zoukankan      html  css  js  c++  java
  • struts2基本介绍

    前言


    文本


    Struts2


    Apache SoftWare Foundation Tomcat/Struts1/Struts2/Ibaitas/


    MVC框架:Struts1/Struts2/JSF/WebWork


    Struts2是由Apache软件基金会与webWork的研发团队合作开发
    www.apache.org
    Struts2是一个单控制器的开源免费的框架。



    框架搭建


    1.新建WEBproject导入JAR包 


    antlr-2.7.2.jar  语法解析器
    commons-beanutils-*.jar  commons项目下用来处理Bean的工具包
    commons-chain-*.jar   commons项目下用来处理流程链的
    commons-collections-*.jar commons项目下全部集合处理的工具包
    commons-digester-*.jar  将xml解析成 java对象
    commons-fileupload-*.jar 文件上传的
    commons-io-*.jar 处理IO流
    commons-lang-*.jar 处理普通java对象的
    commons-logging-*.jar commons项目下日志处理工具包
    commons-logging-api-*.jar commons项目下日志处理工具包
    commons-validator-*.jar   commons项目下处理验证
    oro-*.jar 文本文件处理的
    freemarker-*.jar freemarker模版语言相关的
    struts2-core-*.jar Struts2核心包
    xwork-*.jar webwork核心包,包涵非常多command
    ognl-*.jar  Struts2表达式语言

    以上这些包在搭建Struts2框架时必须导入
    其它jar包:

    *-plugin-*.jar 以plugin结束的是其它框架与Struts2整合的插件包


    2.拷贝配置文件


    struts.xml  struts2的配置文件
    web.xml 核心控制器的配置文件
    在2.1.6版本号之前使用的核心控制器 FilterDispatcher

    2.1.6版本号之后org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter



    3.測试框架搭建




    实现Action


    1.实现Action接口实现接口中定义的全部方法


    implements Action
    Action接口中定义了五个字符串常数以及一个 public String execute() throws Exception;
    五个常数:
    SUCCESS-->"success"
    NONE-->"none"
    INPUT-->"input"
    ERROR-->"error"

    LOGIN-->"login"


    2.普通类,必须含有一个无參的返回值为String类型的execute方法


    public class LoginAction2 {
    public String execute(){
    System.out.println("LoginAction2");
    return "success";
    }

    }


    *3.通过继承ActionSupport来实现自己定义Action


    public class LoginAction3 extends ActionSupport{

    @Override
    public String execute() throws Exception {
    System.out.println("LoginAction3--execute");
    return SUCCESS;
    }

    }


    Struts.xml中对于Action的配置


    package标签用来管理Action
    name属性:区分package
    namespace:定义的是package中Action的訪问路径

    extends:配置文件通过继承的方式实现其它配置文件里定义的属性


    <package namespace="/user" name="user" extends="struts-default">
    Action标签用来配置相应的Action实现
    name属性:配置Action的訪问路径
    class属性:配置当前Action标签相应的实现类
    <action name="loginAction" class="" >
    Result标签用来配置Action返回的页面
    name属性:匹配Action的字符串返回值定位相应的返回页面
    type属性:定义页面返回到浏览器的方式
    <result>/success.jsp</result>
    </action>

    </package>




    接收前台页面參数


    1.接收单个參数


    public class LoginAction3 extends ActionSupport{
    //定义一个參数成员变量
    private String userName;
    //提供getter/setter
    public String getUserName() {
    return userName;
    }

    public void setUserName(String userName) {
    this.userName = userName;

    }


    JSP页面:


    <input type="text" name="userName">
    name属性的值必须和Action中成员变量的名称同样

    2.通过对象接收參数


    public class LoginAction2 {
    private User user;
    public User getUser() {
    return user;
    }
    public void setUser(User user) {
    this.user = user;

    }


    JSP页面:
    <input type="text" name="user.userName">

    3.ModelDriven接收參数


    public class LoginAction implements Action,ModelDriven{
    private User user = new User();
    public User getUser() {
    return user;
    }
    public void setUser(User user) {
    this.user = user;
    }
    public Object getModel() {
    return user;
    }
    }

    JSP页面:
    <input type="text" name="userName">
    name属性的值必须和Action中对象的属性名同样

    关于參数接收:
    通常通过继承ActionSupport方式来实现Action
    在接收參数方面,经常使用普通成员变量和对象类型两种
    假设通过Action接收方式接收对象类型參数。必须在创建相应引用时初始化

    Action中使用作用域


    1.通过ActionContext来设置作用域 


    ActionContext对象所表示的是当前Action对象的执行环境
    //通过静态方法获得对象,ActionContext为线程单例
    ActionContext context = ActionContext.getContext();
    //request.setAttribute();
    context.put("requestScope", "req");
    //session
    Map session = context.getSession();
    session.put("sessionScope", "session");
    //ServletContext
    Map app = context.getApplication();
    app.put("app", "application");

    2.通过ServletActionContext对象来设置作用域


    //通过ServletActionContext来获得request对象
    //ServletActionContext单例
    HttpServletRequest request = ServletActionContext.getRequest();
    request.setAttribute("requestScope", "requestScope");
    HttpSession session = request.getSession();
    session.setAttribute("sess", "sessionScope");
    ServletContext context = session.getServletContext();

    context.setAttribute("app", "app");


    3.通过实现ServletRequestAware接口来设置作用域


    //设置HttpServletRequest成员变量接收接口中传递的request參数
    public class TestServletRequest extends ActionSupport implements ServletRequestAware{
    private HttpServletRequest request;
    public void setServletRequest(HttpServletRequest request) {
    this.request = request;
    }

    參数接收过程中的类型转换


    1.自己定义类型转换


    a.參数类型转换类。必须继承StrutsTypeConverter


    public class DateConverter extends StrutsTypeConverter{
    /**
    * 将String类型的參数转换成特定对象类型
    * @param Map context ActionContext 对象
    * @param String[] values 參数数组
    * @param Class toClass
    */
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {

    /**
    * 将特定对象类型转换成String类型
    * @param Map context ActionContext 对象
    * @param Object o 目标对象
    */
    @Override
    public String convertToString(Map context, Object o) {

    b.配置參数接收过程中的配置文件


    局部转换器:针对特定Action,配置文件放置在相应Action同样文件夹下


    Action类名-conversion.properties
    TestParametersAction-conversion.properties
    配置内容:
    Action类中特定对象类型的成员变量名称 = 转换类的全限定名
    birthday = com.zhongx.struts2.day2.DateConverter
    全局转换器:对projectAction中全部特定类型,将配置文件存储在SRC下
    xwork-conversion.properties
    配置内容:
    特定转换的对象类型 = 转换类的全限定名
    java.util.Date = com.zhongx.struts2.day2.DateConverter

    后台验证


    通过继承ActionSupport重写validate方法来实现


    validate方法会在运行execute方法之前先被调用进行输入參数格式校验
    //通过validate方法进行校验
    @Override
    public void validate() {
    System.out.println("validate");
    String name = users.get(0).getUserName();
    int age = users.get(0).getAge();
    if(name==null || "".equals(name)){
    //将错误提示信息设置到错误信息域中
    this.addFieldError("error", "name is null");
    }else if(age>200||age<0){
    this.addFieldError("error", "age is error");
    }else{
    System.out.println("ok");
    }
    }

    一旦错误信息域中有错误提示。那么Struts2默认会查找相应Action配置中
    <result name="input"> 所相应的jsp返回
    <result name="input">/error.jsp</result>
    那么在错误页面:
    通过struts2标签来获取错误信息:
       <s:fielderror><s:param>error</s:param></s:fielderror>

    前台JS校验 Struts2后台校验


    有点: 校验不须要经过server,运行效率高 安全
    缺点: 不安全。easy被用户篡改 校验必须连接server,运行效率低
    建议:前台js校验和后台Struts2校验并用。




    Struts2文件上传下载


    文件上传:


    1.前台jsp页面


    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="pic">

       </form>


       2.后台程序參照TestFileUploadAction



    文件下载


    參照TestFileDownAction



    配置文件
    <action name="fileDownAction" class="com.zhongx.struts2.day3.TestFileDownAction">
    <result name="down">/list.jsp</result>
    配置下载结果类型 type = stream
    <result name="fileDown" type="stream">
    stream类型的结果类型接收两个參数
    inputName 名称的參数是Action中的输入流
    <param name="inputName">downFileInput</param>
    contentDisposition 參数设置文件的展示方式以及下载 时的默认文件名
    <param name="contentDisposition">attachment;fileName=${file}</param>
    </result>
    </action>


    Action中方法的动态调用


    1.通过。+方法名称显示调用
    调用dynaMethodAction中的相应的add方法
    dynaMethodAction!add
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    2.通过配置文件设置调用的方法名称
    通过method属性设置默认调用的方法
    <action name="dynaMethodAction" class="com.zhongx.struts2.day4.TestDynaMethodAction" method="delete">
    </action>
    3.通过*通配符匹配调用方法
    //method中通过动态获得调用的方法的方法名
    //调用过程中dynaMethodAction_方法名称
    <action name="dynaMethodAction_*" method="{1}" class="com.zhongx.struts2.day4.TestDynaMethodAction">
    <result name="ok">{1}_success.jsp</result>

    Struts2的国际化


    Internationalization(i18n)


    1.在src文件夹下新建资源文件


    资源文件名_语言简写_国别简写.properties
    appRes_zh_CN.properties
    文件内容:
    key = value  //user=u7528u6237u540D
    //user = userName
     

    2.将资源文件配置在Struts.xml中


    <constant name="struts.custom.i18n.resources" value="资源文件名"></constant>

    3.获得匹配国家的语言


    占位符
    <s:text name="key"></s:text>
    // <s:text name="user"></s:text>
     
    在浏览器显示时依据浏览器的国别设置获得相应的语言显示

    在书写资源文件时,假设相应国家的语言是非拉丁语系的语言,那么资源文件必须经过Unicode编码
    user=u7528u6237u540D
    手动将资源文件转换成Unicode编码
    native2ascii  命令转换 native2ascii -encoding gbk 输入文件   输出文件


    Struts2的result type


    <result name="" type="xxxx">
    type = dispatcher 默认,从Action到前台页面的转发
      chain      从Action到Action的转发
      redirect      从Action到前台页面的重定向
      redirectAction  从Action到Action的重定向
      stream     向浏览器输出一个InputStream类型的流,一般用作文件下载
      freemarker 向浏览器输出freemarker模版
      velocity 向浏览器输出velocity模版
      xslt 向浏览器输出xml/xslt模版
      plainText 向浏览器原样输出(输出源文件)
      httpheader 控制特定HTTP协议的输出
      

    自己定义的Result type类型


    1.定义type实现类


    public class TestResult implements Result

    2.配置Result type类型


    a.定义type类型而且绑定实现类


    <package name="day4" namespace="/" extends="struts-default">
    <result-types>
    <result-type name="type名称" class="实现类的全限定名称"></result-type>
    </result-types>

    b.使用自己定义的type


    <action name="" class="">
    <result name="" type="自己定义type名称" ></result>

    还能够通过继承StrutsResultSupport来实现自己定义result类型
    实现doExecute方法


    拦截器(Interceptor)



    认识拦截器

    struts-default.xml
    标签
    <interceptors>
    <interceptor name="拦截器名称" class="拦截器的实现类"></interceptor>
    </interceptors>

    Action中应用拦截器
    <action>
    <interceptor-ref name="引入拦截器的名称"></interceptor-ref>
    </action>

    默认Struts.xml中
    <package name="" namespace="" extends="struts-default">
    默认当前包中的 Action继承struts-default中使用的拦截器
    struts-default默认使用
    拦截器栈 defaultStack
    拦截器栈中引入18个经常使用拦截器
    比方 :
    i18n
    fileUpload
    params
    workflow等
    </package>

    自己定义的拦截器


    a.通过实现接口来实现自己定义拦截器



    b.通过继承AbstractInterceptor来实现拦截器


    //通过继承父类的形式来实现拦截器
    public class MyInterceptor3 extends AbstractInterceptor{
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
    String path = invocation.invoke();
    return path;
    }
    }


    配置自己定义拦截器


    a.直接引用
    <package name="day5" namespace="/" extends="struts-default">
    <!-- 配置自己定义的拦截器以及功能实现类 -->
    <interceptors>
    <interceptor name="myInte1" class="com.zhongx.struts2.day5.MyInterceptor1"></interceptor>
    </interceptors>
    <action name="testIntercepter" class="com.zhongx.struts2.day5.TestInterceptorAction">
    <!-- 使用自己定义的拦截器 -->
    <interceptor-ref name="myInte1"></interceptor-ref>
    <result name="ok">/success.jsp</result>
    <result name="success">/index.jsp</result>
    </action>
    </package>
    b.通过配置拦截器栈来引用



    表单反复提交


    问题:同一个表单携带同样的数据被提交多次

    通过Struts2的拦截器   token来处理多次提交问题


    <interceptors>
    <interceptor-stack name="my_stack">
    <interceptor-ref name="token"></interceptor-ref>
    <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>
    </interceptors>

    在Action中使用自己定义的拦截器栈
    <action name="testToken" class="com.zhongx.struts2.day4.TestTokenAction">
    <interceptor-ref name="my_stack"></interceptor-ref>

    <result name="ok">/success.jsp</result>
    <!-- 一旦反复提交。那么token拦截器会返回invalid.token 来查找相应的返回结果-->
    <result name="invalid.token">/error.jsp</result>

    </action>

    在JSP页面


    表单中增加<s:token></s:token>标签来标识是否为同一表单
    <form action="testToken">
      <s:token></s:token>
      username:<input id="name" type="text" name="userName">
      年龄:<input id="age" type="text" name="age">
      <input type="submit" value="submit">

       </form>


    方法级别的拦截器


     继承MethodFilterInterceptor来实现拦截器
    String doIntercept(ActionInvocation)
    配置文件
    <package name="day6" namespace="/" extends="struts-default">
    <!--配置拦截器实现类-->
    <interceptors>
    <interceptor name="methods" class="com.zhongx.struts2.day6.TestMethodInterceptor"></interceptor>
    </interceptors>

    <action name="testMethod" class="com.zhongx.struts2.day6.TestMethodInterceptorAction">
    <!--引入拦截器-->
    <interceptor-ref name="methods">
    <!-- 不被拦截的方法  -->
    <param name="excludeMethods">login</param>
    <!-- 被拦截的方法 -->
    <param name="includeMethods">add,delete,execute</param>
    </interceptor-ref>

    <result name="exe">/success.jsp</result>
    <result name="delete">/delete_success.jsp</result>
    <result name="add">/add_success.jsp</result>
    <result name="login">/login.jsp</result>
    </action>
    </package>


    OGNL和值栈以及Struts2标签


    OGNL(Object Graphic Navigation Language,对象图导航语言)
    方便开发者查找对象,高速的获得对象的属性和相应的值
    OGNL从值栈中获取对象方便,可以高速从复杂类型对象(树形文件夹结构非常深)中获取属性
    在没有Struts2前webWork框架中已经採用了OGNL来获取属性
    使用OGNL必须 导入OGNL.jar



    Action对象,其它对象
    (root区)

    ValueStack (context,context用OGNL訪问必须加#号)
    paramters 包涵HTTP请求參数的对象 
    request  HTTP请求对象
    session   HTTP会话对象
    application  当前应用对象
    attr 包涵作用域对象

    OGNL訪问属性必须结合Struts2标签使用


    基本标签


    获取属性值
    <s:property value="">
    格式化日期
    <s:date name="" format="">
    向作用域设值
    <s:set var="test" value="users[0]" scope="action"></s:set>
    设置路径
    <s:url value="/testAction" ></s:url>
    创建对象
    <s:bean name="com.zhongx.struts2.day1.User" var="uu">
    设置參数
    <s:param name="userName">testBean</s:param>
    </s:bean>
    将对象设置在root区,标签结束对象回收
    <s:push value="users[0]">
    <s:property value="userName"/>
    <s:property value="age"/>
    <s:property value="address.street"/>
    </s:push>
    分支控制
    <s:if test="users[0].age>0">
    </s:if>
    <s:elseif>
    </s:elseif>
    <s:else>
    </s:else>

    迭代标签
    <!-- 
    ?

    表示选出符合条件的全部对象
    ^表示符合条件的第一个对象
    $表示符合条件的最后一个对象
    users.{$#this.age>1}
    -->
    <s:iterator var="u" value="users.{$#this.age>1}" status="status"><br>
    <s:property value="#u.userName"/>
    <!-- 循环下标 -->
    <s:property value="#status.index"/>
    <!-- 循环记录数 -->
    <s:property value="#status.count"/>

    </s:iterator>

    获得值栈
    <s:debug></s:debug>

    UI标签


    <s:head/>
    <s:form>
    <s:textField>
    <s:password>
    <s:select>
    <s:radio>
    <s:checkboxlist>
    <s:textarea>
    <s:submit>
    <s:reset>

    <s:form action="">
    <s:textfield name="name"></s:textfield>
    <s:password name="password"></s:password>
    <s:select name="city" list="{'北京','上海','广州'}" ></s:select>
    <s:select name="city" list="users" listKey="age" listValue="userName" ></s:select>
    <s:radio name="sex" list="#{'m':'男','n':'女'}"></s:radio>
    <s:checkboxlist  name="in" list="{'beij','shangh'}" ></s:checkboxlist>
    <s:checkboxlist  name="in" list="users" listKey="age" listValue="userName"></s:checkboxlist>
    <s:textarea cols="5px" rows="5px"></s:textarea>
    <s:submit value="submit"></s:submit>
    <s:reset value="reset"></s:reset>
    </s:form>

    Struts2中使用Json


    1.从Action中传递一个Json对象到前台JS中


    a.导入Json相应的依赖库
    json-lib-*.jar
    struts2-json-plugin-*.jar
    b.通过Ajax发送请求到处理Action
    action中提供一个返回对象类型的成员变量而且提供getter/setter方法
    private User user;
    c.配置Action
    通过继承json-default来继承result type="json"
    <package name="json" namespace="/" extends="json-default">
    <action name="testJsonAction" class="com.zhongx.struts2.day6.TestJsonAction">
    <result type="json"></result>
    </action>
    </package>

    通过这样的方式会将对象类型的成员变量以Json形式返回给页面的回调函数


    2.从前台JS传递一个Json类型的字符串到后台Action

    參照testJson2.jsp


      TestJsonAction2.java




    异常(Exception)


    何为异常:
    怎么处理异常
    try{}catch(){}
    当前方法中能解决的,就捕获解决
    throw
    当前方法解决不了,交给调用者处理

    JavaEE中处理异常


    throw DAO---->DaoException
    ClassNotFoundException
    IOException
    SQLException
    NetWorkAdapterException
    throw Biz---->DaoException
    业务异常
    UserNotExistException
    UserOrPasswordException


    try{}catch(){} Action--->DaoException
     UserNotExistException
     UserOrPasswordException


    UI   提供友好提示

    异常分类


    两大类
    check Exception
    编译时,编译器会检查程序
     ClassNotFoundException
     IOException
     SQLException
     
    RuntimeException
    执行过程中。检查的异常 
    NullPointerException
    ClassCastException
    IndexOutOFboundsException

    检查异常是在程序中必须处理


    自己定义异常


    extends Exception
    採用
    extends RuntimeException

    Struts2中Action的异常处理


    1.在Action中trycatch
    try{
    //调用biz处理业务
    User user = userBiz.queryUserByName(name, password);
    }catch(DaoException e){
    依据不同异常返回不同页面
    return "error";
    }catch(UserNotExistException e){
    this.addFieldError("message", "user not exist");
    依据不同异常返回不同页面
    return "input";
    }catch(PasswordErrorException e){
    this.addFieldError("message", "password is error");
    return "input";
    }

    2.声明式异常处理


    将全部异常配置在Struts.xml中,Action中不做不论什么处理
    <action name="loginAction" class="com.zhongx.bank.action.LoginAction">
    配置异常对象以及发生异常跳转的 相应页面
    exception属性:配置异常的全限定名称
    result:配置异常发生时相应跳转的result结果
    <exception-mapping 
    exception="com.zhongx.bank.exception.DaoException"
    result="error"
    ></exception-mapping>
    <exception-mapping 
    exception="com.zhongx.bank.exception.UserNotExistException"
    result="input"
    ></exception-mapping>
    <exception-mapping 
    exception="com.zhongx.bank.exception.PasswordErrorException"
    result="input"
    ></exception-mapping>

    <result name="success">/manager.jsp</result>
    <result name="input">/login.jsp</result>
    <result name="error">/error.jsp</result>
    </action>

    页面获取异常信息


    从值栈中获取,异常信息存放在值栈中Action对象中
    <s:property value="exception.message" s:property/>
    重定向不能获取到异常信息

    Filter与Interceptor 差别?


    1.Filter在运行流程时,採用方法回调来实现流程调用
     Interceptor在运行流程中採用的是反射实现
    2.拦截目标不同。Filter拦截全部请求,Interceptor拦截特定Action的请求

    3.Filter在运行目标Action之前拦截。Interceptor在Action运行前后都拦截


    自己定义Struts1


    commons-digester.jar解析XML
    实现XML标签到对象的转换
    1.依据目标XML的结构定义解析规则文件
    參照rule.xml
    2.创建集合对象接收封装解析的XML
    ModelConfig config = new ModelConfig();
    Digester digester = DigesterLoader.
    createDigester(ActionServlet.class.getClassLoader().getResource("com/zhongx/struts/rule.xml"));
    //将存储集合对象传入
    digester.push(config);
    //解析目标 XML
    digester.parse(ActionServlet.class.

    getClassLoader().getResourceAsStream("mystruts.xml"));


    Struts1和Struts2差别


    1.核心控制器实现不同


    2.Action的实现方式不同


    3.參数接收方式不同


    4.后台验证实现不同


    5.Action中绑定值到视图的实现方式不同


    6.框架支持的页面显示技术不同


    7.页面运行的表达式语言不同


    8.Action运行流程不同


    9.Action的线程安全方面不同

     
     
     



    总结











    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    结对编程项目作业4
    团队编程项目进度
    团队编程项目作业2-团队编程项目代码设计规范
    现代软件工程 阅读笔记
    个人编程作业1-GIT应用
    结对编程项目作业2-开发环境搭建过程
    结对编程项目作业2-结对编项目设计文档
    课后作业-阅读任务-阅读提问
    《团队-科学计算器-模块测试过程》
    团队-科学计算器-模块开发过程
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4675214.html
Copyright © 2011-2022 走看看