struts2入门到精通教程

来源:互联网 发布:js验证用户名 编辑:程序博客网 时间:2024/04/27 22:16

为什么要使用struts2以及Servlet的缺点

servlet的缺点:

   1、写一个servlet需要在web.xml文件中配置8行,如果一个系统中servlet很多,则会导致       web.xml文件中的内容很多   2、在项目中很多人编辑一个web.xml文件会出现版本冲突的问题   3、在一个servlet中方法的入口只有一个,如果在servlet中写很多方法,这些方法应该传递参数,根据每次       请求的参数不一致来判断执行哪个方法   4、servlet中的方法都有两个参数request,response,这两个参数具有严重的容器依赖性,所以在       servlet中写的代码是不能单独测试的   5、现在写一个servlet,为注册servlet           ResigterServlet{               public void doPost(){                1、权限的操作            2、获取表单中的数据            3、文件的上传的功能            4、表单上的元素进行验证            5、保存一个用户           }           }    6、如果在表单中的元素很多,在servlet中要想获取表单中的数据,那么在servlet的方法中必要有大量的        request.getParameter代码    7、在一个servlet的属性中声明一个数据,会存在线程安全的问题

Servlet的优点:

因为是最低层的mvc,所以效率比较高

struts2中action是否安全

struts2的action的说明:
1、action是多实例的,每请求一次将会创建一个对象
2、是不存在线程安全的问题的

servletde 重构

第一步:写一个监听器在tomcat初始化的时候执行

public class ActionListener implements ServletContextListener{    /**     * tomcat销毁的时候执行     */    @Override    public void contextDestroyed(ServletContextEvent arg0) {        // TODO Auto-generated method stub        /**         * 在tomcat销毁的时候,清空application域中的所有的action的配置         */        arg0.getServletContext().setAttribute("actions", null);    }    /**     * tomcat初始化的时候执行     */    @Override    public void contextInitialized(ServletContextEvent arg0) {        /**         * 1、创建一个map         * 2、把key,value放入到map中         * 3、把map放入到application域中         */        Map<String, String> map = new HashMap<String, String>();        map.put("userAction", "cn.itcast.sh08.action.UserAction");        arg0.getServletContext().setAttribute("actions", map);    }}

第二步:写一个ActionServlet:

在访问地址http://localhost8080//userAction.action的时候将这个url地址发送到Actionservlet中,然后解析这个url地址,

/**         * 1、获取url         * 2、对url进行解析,把"userAction"的部分解析出来         * 3、获取到application         * 4、从application中把map提取出来         * 5、根据"userAction"从map中把value提取出来         * 6、利用java的反射机制进行调用         */        //itcastsh08_super_servlet/userAction.action        String uri = request.getRequestURI();        /**         * 把uri传递进去,解析出来userAction         */        String actionName = StringUtils.parse(uri);        /**         * 通过key:userAction,得到value:userAction的类名         */        Map<String, String> map = (HashMap<String, String>)this.getServletContext().getAttribute("actions");        String actionClassName = map.get(actionName);        try {            /**             * 得到了请求的action所对应的execute方法             */            Class classt = Class.forName(actionClassName);            String httprequest = "javax.servlet.http.HttpServletRequest";            Class requestClass = Class.forName(httprequest);            String httpresponse = "javax.servlet.http.HttpServletResponse";            Class responseClass = Class.forName(httpresponse);            Method method = classt.getMethod("execute",requestClass,responseClass);            String result = (String)method.invoke(classt.newInstance(),request,response);            request.getRequestDispatcher(result).forward(request, response);        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        } 

这里的StringUtils是用来获取userAction的

struts.xml详解

关于包的name的作用

 <package name="system" namespace="/" extends="struts-default">:其中的name=“”的作用是用来区分不同模块功能下的不同包( package代表一个模块,name为模块的名称,而且值是唯一的)

关于extend的功能

 extends="struts-default"实际上是把package中name为"struts-default"的包中的所有的功能如果想要使用某一个包的action,可以使用继承<package name="aa" namespace="/world" extends="helloworld"></package>这里面extend="这里面是某一个包的名字"<package name="helloworld" namespace="/base" extends="struts-default">    <action name="helloWorldAction" class="cn.itcast.sh08.struts2.action.HelloWorldAction">        <result name="index">index.jsp</result>    </action>

关于命名空间:

    1、上述的namespace和url有关系    2、如果namespace为"/"            那么在url中项目名称后面紧接着跟action中name的名称        namespace="/"        http://localhost:8088/itcastsh08_struts2_package_namespace/helloWorldAction.action    3、如果namespace为"/base"        http://localhost:8088/itcastsh08_struts2_package_namespace/base/helloWorldAction.action    4、如果namespace为"/base"         itcastsh08_struts2_package_namespace/helloWorldAction.action                   该url是请求不到的         itcastsh08_struts2_package_namespace/base/helloWorldAction.action                 该url可以请求到         itcastsh08_struts2_package_namespace/base/a/helloWorldAction.action                                       也可以请求到 ,查找规则:                  1、先找base/a下的helloWorldAction                  2、再查找base下的helloWorldAction    5、在url中加了几层命名空间,则在转向到jsp页面时,jsp的路径也会加几个命名空间的名字的路径            base/a/helloWorldAction.action            base/a/b/index.jsp    6、如果采用上述的命名空间的形式,命名空间有什么的名称,在webroot下就应该建立什么样的文件夹

关于两个配置文件struts.xml和struts-default.xml

1、这两个配置文件都是在服务器启动的时候加载的2、这两个配置文件都放在了classpath的根目录     struts.xml文件放在了src的根目录     struts-default.xml文件是在struts2核心包的根目录下3、struts.xml文件是供程序员使用的   struts-default.xml文件是运行struts2低层的xml文件4、先加载struts-default.xml文件,后加载struts.xml文件5、因为dtd都一样,如果出现相同的元素,后者覆盖前者

关于result

<result name="list" >/admin/jsp/userAction/list.jsp</result>        <result name="toList" type="redirectAction">user_list</result>        一般用的就两种,result中间的是jsp页面这样的是转发的方式,或者是user_list这表示重定向,重新请求一个方法

关于include的使用

include保证了可以有很多个xml文件<struts>    <include file="struts-helloworld.xml"></include></struts>在企业里最好保证人手一份xml文件,这样不会出现冲突的问题

关于action的几种写法

action的写法   1、就是一个最简单的javabean        public class HelloWorldAction {            public String execute(){                System.out.println("hello world");                return "index";            }        }   2、让一个action实现接口Action        public class HelloWorld2Action implements Action{            /**             * 如果实现了Action接口,应该把方法写在execute里             */            public String execute(){                System.out.println("hello world");                return SUCCESS;            }        }        <result>index.jsp</result>    3、让一个类继承ActionSupport        ActionSupport中含有一些功能:           1、国际化           2、表单验证        如果让一个action类继承了ActionSupport就能直接使用ActionSupport中的国际化、表单验证等功能    4、如果在action的配置中这样配置:         <action name="helloWorld3Action">            <result>index.jsp</result>        </action>        那么在struts-default.xml文件中有一句话将起作用:           <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />        这个时候将执行ActionSupport中的execute方法

通配符的映射

 1、第一种情况   url:      http://localhost:8088/itcastsh08_struts2_action/helloWorldAction.action                 配置文件:      <package name="helloworld" namespace="/" extends="struts-default">        <action name="helloWorldAction" class="cn.itcast.sh08.struts2.action.HelloWorldAction">            <result name="index">index.jsp</result>        </action>      </package>         如果采用该结构,只能执行helloWorldAction中的execute方法   2、第二种情况        在配置文件的action标签中可以指定method属性        <action name="userAction" method="saveUser"             class="cn.itcast.sh08.struts2.action.UserAction">            <result>index.jsp</result>        </action>        url:http://localhost:8088/itcastsh08_struts2_methodpattern/userAction.action        这个时候,将请求userAction中method属性的值指定的方法:saveUser       缺点:               如果在UserAction中出现很多个方法,因为每一个方法配置一个action,所以有几个方法就得配置几个action   3、第三种情况        <package name="method2" namespace="/m2" extends="struts-default">            <action name="userAction" class="cn.itcast.sh08.struts2.action.UserAction">                <result>index.jsp</result>            </action>        </package>        url:            http://localhost:8088/itcastsh08_struts2_methodpattern/m2/userAction!deleteUser.action        UserAction中的其中的一个方法和userAction!deleteUser中的叹号后面的内容一样        为动态调用该方法    4、请求UserAction中的saveUser方法:            要求:a_add.action,b_add.action,c_add.action都可以请求    5、配置文件        <action name="*_add" method="{1}" class="cn.itcast.sh08.struts2.action.UserAction">            <result>index.jsp</result>        </action>    6、请求UserAction和PersonAction中的pattern方法        <action name="*_pattern" method="pattern" class="cn.itcast.sh08.struts2.action.{1}">            <result>index.jsp</result>        </action>    7、配置文件中        <package name="method6" namespace="/" extends="struts-default">            <action name="UserAction_*" method="{1}" class="cn.itcast.sh08.struts2.action.UserAction">                <result>{1}.jsp</result>            </action>        </package>    8、配置文件中        <action name="*_*" method="{2}" class="cn.itcast.sh08.struts2.action.{1}">            <result>{2}.jsp</result>        </action>        统配的程度越高,匹配的范围越大,越容易出问题
我通常情况下用的是这样的
    <action name="user_*" method="{1}" class="cn.itcast.sh08.struts2.action.userAction"><result name=“list”>list.jsp</result></action>    jsp页面请求的方式类似于user_list,method表示的是list,list是action中的list方法,result中的name中的list表示的是action中list方法中的return list

先介绍如何使用valueStack储存数据以及其储存数据的结构图

struts2的值栈valueStack (存储值)

前言

在servlet中解决数据的存储和显示
把一个数据放在request,session,application域中,在页面上利用ognl表达式就可以显示出来

概述

    1、ValueStack是一个接口,在struts2中使用OGNL表达式实际上是使用实现了ValueStack接口的类OgnlValueStack,这个类是OgnlValueStack的基础。    2、ValueStack贯穿整个action的生命周期。每一个action实例都拥有一个ValueStack对象。其中保存了当前action对象和其他相关对象。

内存图

这里写图片描述

组织结构

这里写图片描述

从图上可以看出OgnlValueStack和我们有关的内容有两部分:即OgnlContext和CompoundRoot。所以把这两部分搞清楚很重要。

valueStack总体结构图

这里写图片描述

说明:
1、上图是ognl完整的数据结构图,可以清晰得看出数据的组成。
2、Context中的_root和ValueStack中的root(对象栈)里的数据结构和值是一样的。
3、这就意味着我们只需要操作OgnlContext就可以完成对数据的存和取的操作。
4、ValueStack内部有两个逻辑的组成部分:
a)ObjectStack
Struts会把动作和相关的对象压入到ObjectStack中。
b)ContextMap
Struts会把一些映射关系压入到ContextMap中

获取valueStack的三种方式

ValueStack valueStack = ActionContext.getContext().getValueStack();    ValueStack valueStack2 = ServletActionContext.getContext().getValueStack();    ValueStack valueStack3 = (ValueStack)ServletActionContext.getRequest().getAttribute("struts.valueStack");

valueStack的内存结构:

 root:对象栈 context:OgnlContext      _root:对象栈      _values:map栈

对象栈的操作

 1、把数据放入到对象栈中    valueStack.push  放入到对象栈的栈顶    valueStack.getRoot().add("aaaa");  放入到了对象栈的栈底    ActionContext.getContext().getValueStack().set("aaa", "asfd");  把一个map放入到了对象栈的栈顶    valueStack.getRoot().add(0,"aaaa"); 放入到了对象栈的栈顶2、从对象栈中把数据提取出来    ActionContext.getContext().getValueStack().getRoot().get(0);    ActionContext.getContext().getValueStack().peek();       获取对象栈的栈顶的元素3、移除栈顶元素     ActionContext.getContext().getValueStack().getRoot().remove(0);     ActionContext.getContext().getValueStack().pop();

map栈的操作

 1、可以把一个对象放入到map栈中的reuqest域中    ServletActionContext.getRequest().setAttribute("aaa", "aaa");2、可以把一个对象放入到map栈的application域中    ServletActionContext.getServletContext().setAttribute("aaaa", "aaaa");3、可以把一个对象放入到map栈中    ActionContext.getContext().put("aaa", "aaaa");

如何将值放在valueStack

/*     * 把数据放入对象栈中的第一种方式     */    public String addDataToObjectStack_1(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 把字符串添加到了CompoundRoot的第一个位置,我们把第一个位置称为对象栈的栈顶         */        valueStack.push("aaaaa");        return "";    }    /*     * 把数据放入对象栈中的第二种方式     */    public String addDataToObjectStack_2(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 把字符串添加到了对象栈中         */        valueStack.getRoot().add("aaaa");        return "";    }    /*     * 把数据放入对象栈中的第三种方式     */    public String addDataToObjectStack_3(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 把字符串添加到了对象栈中         *    把一个map放入到了对象栈的栈顶,"aaa"作为key,"asfd"作为value         */        ActionContext.getContext().getValueStack().set("aaa", "asfd");        return "";    }    /**     * 从对象栈中把数据提取出来的方式     *    第一种方式     */    public String addDataFromObjectStack_1(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 提取栈顶的元素         */        ActionContext.getContext().getValueStack().getRoot().get(0);        return "";    }    /**     * 从对象栈中把数据提取出来的方式     *    第二种方式     */    public String addDataFromObjectStack_2(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 提取栈顶的元素         */        ActionContext.getContext().getValueStack().peek();        return "";    }    /*     * 把对象栈的栈顶的元素移除     */    public String removeDataFromObjectStack_1(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 移除栈顶的元素         */        ActionContext.getContext().getValueStack().getRoot().remove(0);        return "";    }    /*     * 把对象栈的栈顶的元素移除     */    public String removeDataFromObjectStack_2(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        /**         * 移除栈顶的元素         */        ActionContext.getContext().getValueStack().pop();        return "";    }    /**     * 把一个key,value键值对放入到request域中     */    public String putObjectToRequest(){        ServletActionContext.getRequest().setAttribute("aaa", "aaa");        ValueStack valueStack = ActionContext.getContext().getValueStack();        return "";    }    /**     * 把一个key,value键值对放入到application域中     */    public String putObjectToApplication(){        ServletActionContext.getServletContext().setAttribute("aaaa", "aaaa");        ValueStack valueStack = ActionContext.getContext().getValueStack();        return "";    }    /**     * 把一个key,value直接放在map栈中     */    public String putDataToMapStack_1(){        ValueStack valueStack = ActionContext.getContext().getValueStack();        ActionContext.getContext().put("aaa", "aaaa");        return "";    }

ognlContext组织结构(第一部分 数据存储主要在这里面)

_values(这里介绍如何把值放在map中的request application以及session中)
从上述可以看出,OgnlContext实际上有一部分功能是Map。所以可以看出_values就是一个Map属性。而运行一下下面的代码就可以看到:
//在request域中设置一个参数ServletActionContext.getRequest().setAttribute("req_username","req_username");//在request域中设置一个参数ServletActionContext.getRequest().setAttribute("req_psw", "req_psw");//在session域中设置一个参数ActionContext.getContext().getSession().put("session_username", "session_username");//在session域中设置一个参数ActionContext.getContext().getSession().put("session_psw", "session_psw");在_values的map中:主要存储的地方是        application     在 ApplicationMap        request 在       RequestMap        action  在       自己写的action        session 在       SessionMap

_root(第二部分)

这里写图片描述

从图中可以看出_root实际上CompoundRoot类,从类的组织结构图中可以看出,这个类实际上是继承了ArrayList类,也就是说这个类具有集合的功能。而且在默认情况下,集合类的第一个为ValueStackAction,也就是我们自己写的action。

ognl表达式(显示操作标签)

使用方法:

 1、引入标签库    <%@ taglib prefix="s" uri="/struts-tags" %>        标签库的位置在struts2-core-2.3.1.2.jar包中的META-INF/struts-tags.tld   2、s:debug            是一个超级链接,当点击该超级链接的时候,valueStack中的内容显示出来了   3、访问valueStack中的数据       1、如果要访问map栈中的数据,加"#"       2、如果要访问对象栈中的数据,直接访问属性即可   4、s:property标签                     说明:          1、是一个输出标签          2、如果不写value属性,输出栈顶的元素          3、如果执行了下面的代码                Person person = new Person();                person.setPid(1L);                person.setName("王二麻子");                //把person对象放入到了栈顶                ActionContext.getContext().getValueStack().push(person);                       把对象放入到栈顶,其属性会直接暴漏出来,在页面上可以直接访问其属性                <s:property value="name"/>                    其页面上的对象栈中的属性的名称来自于方法          4、如果一个对象在对象栈中,那么该对象如果有set或者get方法,例如:               getAaa(){                 return "xxx";               }                那么aaa会作为属性的名称,xxx会作为属性的值保存在对象栈中          5、如果对象栈中出现相同的属性,则会从上向下找,直到找到就停止了          6、如果把一个对象放入到request域中               ServletActionContext.getRequest().setAttribute("person", person);                页面上可以                <s:property value="#request.person.name"/>                <s:property value="#request.person.getName()"/>          7、如果把一个对象放入到各种域中                ServletActionContext.getServletContext().setAttribute("a_app", "a_app");                在页面上可以利用                   <s:property value="#attr.a_app"/>从各种域中查找相应的key值          8、可以利用parameters输出表单中的内容                <s:property value="#parameters.a[0]"/>   5、s:iterator标签        1、当value属性不写,则默认迭代栈顶的元素        2、value属性指向了要迭代的集合List,Set,Map,[]        3、当前正在迭代的元素在栈顶        4、var属性的值表示正在遍历的元素,该值在map栈中        5、status属性表示正在遍历的那一行的状态            int getCount() 返回当前迭代的元素个数            int getIndex() 返回当前迭代元素的索引            boolean isEven() 返回当前迭代元素的索引是否是偶数            boolean isOdd()  返回当前迭代元素的索引是否是奇数            boolean isFirst()  返回当前迭代元素是否为第一个元素            boolean isLast()  返回当前迭代元素是否为最后一个元素        6、使行变色

ognl表达式(UI标签)

使用方法

1、在页面上可以写struts2的标签,但是浏览器是不识别struts2标签的2、当在页面上写完struts2标签的时候,struts2内核会对标签进行翻译成html标签,在翻译的过程中会多增加很多内容            <s:form action="">                <s:textfield name="username" value="111"></s:textfield>            </s:form>            翻译成html:            <table class="wwFormTable">                <tbody>                    <tr>                        <td class="tdLabel"></td>                    <td>                        <input id="_username" type="text" value="111" name="username">                    </td>                    </tr>                </tbody>            </table>3、修改方案:          在服务器启动的时候,struts2内部会去org/apache/struts2下面加载一个properties文件:default.properties文件          一些参数的说明:          struts.i18n.encoding=UTF-8  默认的编码          struts.action.extension=action,,  默认的扩展名          struts.devMode = false   开发模式              默认值为false   改了配置文件以后必须重新启动            值为true       改了配置文件以后,struts2内部会自动检查,重新加载          struts.ui.theme=xhtml  ui的主题                 可以把xhtml的值改成4、改变default.properties文件中的配置        在xml文件中,有一个元素为constant,为常量元素,该元素的作用就是为了改变default.properties文件中的值          <constant name="struts.devMode" value="true"/>    开发模式          <constant name="struts.ui.theme" value="simple"/>  简单样式5、两个比较重要的标签      s:select          value属性    指向集合的位置          listKey   option中的value          listValue  option标签的内容          headerKey  第一个option的value          headerValue  第一个option的内容      s:checkboxlist            属性同上            必须有name属性6、ui标签的好处:     1、在页面上如果使用struts2的ui标签,不用再写过滤器进行编码的处理     2、使用struts2的ui标签对于数据的回显示很方便的     3、一般情况下,在页面上需要对数据进行回显,则数据放在对象栈中            ActionContext.getContext().getValueStack().push(person1);     4、页面上可以根据struts2标签中的name属性进行回显           <s:textfield name="name"></s:textfield>     5、如果把数据放入到了map栈中,则页面上必须根据value进行回显     6、在s:form标签的各种元素中:           s:textfield           s:textarea           s:password           ....            如果要想用value属性进行回显,也就是说value属性内容要跟ognl表达式                value="%{ognl表达式}"

拦截器interceptor

拦截器的目的:

    如果在一个业务逻辑方法中设计到的逻辑相当复杂,可以把这些业务分离开:       例如:保存用户            1、启动日志            2、检查权限            3、文件的上传            4、保存用户          如果用传统的方法做,以上4点都在同一个方法中,这样耦合性很强

目标:

          把这四方面的内容分开,完全松耦合

不用拦截器实现步骤:

1、准备页面:        在页面中准备一个文本框,该文本框在一个表单中2、准备action                          在action中有一个方法:saveUser                          在action中准备一个属性,该属性是为了获取文本框的值                          在saveUser中做如下的工作:                对该属性的值进行判断,如果值为"admin",输出"save user"                                                         如果值不为"admin",输出"没有权限进行访问"

用拦截器实现的步骤:

1、准备页面2、准备action    public class InterceptorAction extends ActionSupport{        public String saveUser(){            ActionContext.getContext().put("message", "save user");            return "privilege";        }    }    说明:该action的saveUser方法和权限没有任何联系3、创建一个拦截器     public class PrivilegeInterceptor implements Interceptor{        @Override        public String intercept(ActionInvocation arg0) throws Exception {            /**                * 接受页面的参数进行判断             */            String username = ServletActionContext.getRequest().getParameter("username");            if("admin".equals(username)){                return arg0.invoke();            }else{                ActionContext.getContext().put("message", "权限不足,没有办法访问");                return "privilege";            }        }     }  4、配置        <interceptors>            <!--                 声明一个拦截器             -->            <interceptor name="privilege" class="cn.itcast.sh08.struts2.interceptor.PrivilegeInterceptor"></interceptor>            <!--                 声明了一个拦截器栈             -->            <interceptor-stack name="privilegeStack">                <!--                     引用默认的拦截器栈                 -->                <interceptor-ref name="defaultStack"></interceptor-ref>                <!--                     引用自己创建的拦截器                 -->                <interceptor-ref name="privilege"></interceptor-ref>            </interceptor-stack>        </interceptors>        <default-interceptor-ref name="privilegeStack"></default-interceptor-ref>

拦截器的意义以及其参数解析

拦截器的意义在于:可以把一些和业务逻辑没有关系的代码放入到拦截器中,做到这些代码和业务逻辑的松耦合概念:        1、拦截器:实质上是一个类,实现了Interceptor接口的一个类        2、拦截器栈:把很多个拦截器集中在一起就是拦截器栈        3、struts2有一个默认的拦截器栈,该栈在struts-default.xml文件中的struts-default包中            结构为:                <package name="struts-default">                    <interceptors>                        //声明一个拦截器                        <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>                        //声明一个拦截器栈                        <interceptor-stack name="defaultStack">                            //引用上面声明的拦截器                            <interceptor-ref name="exception"/>                            <interceptor-ref name="alias"/>                            <interceptor-ref name="servletConfig"/>                            <interceptor-ref name="i18n"/>                            <interceptor-ref name="prepare"/>                            <interceptor-ref name="chain"/>                            <interceptor-ref name="debugging"/>                            <interceptor-ref name="scopedModelDriven"/>                            <interceptor-ref name="modelDriven"/>                            <interceptor-ref name="fileUpload"/>                            <interceptor-ref name="checkbox"/>                            <interceptor-ref name="multiselect"/>                            <interceptor-ref name="staticParams"/>                            <interceptor-ref name="actionMappingParams"/>                            <interceptor-ref name="params">                              <param name="excludeParams">dojo\..*,^struts\..*</param>                            </interceptor-ref>                            <interceptor-ref name="conversionError"/>                            <interceptor-ref name="validation">                                <param name="excludeMethods">input,back,cancel,browse</param>                            </interceptor-ref>                            <interceptor-ref name="workflow">                                <param name="excludeMethods">input,back,cancel,browse</param>                            </interceptor-ref>                        </interceptor-stack>                    </interceptors>                    //让struts2内部执行默认的拦截器栈或者拦截器                    <default-interceptor-ref name="defaultStack"/>                </package>       4、拦截器的执行顺序:                按照拦截器栈从上到下执行,执行完拦截器以后,再执行action,例如:                  <interceptor-stack name="privilegeStack">                    <interceptor-ref name="defaultStack"></interceptor-ref>                    <interceptor-ref name="privilege"></interceptor-ref>                  </interceptor-stack>                 先执行默认的拦截器栈,后执行privilege                 <interceptor-stack name="privilegeStack">                    <interceptor-ref name="privilege"></interceptor-ref>                    <interceptor-ref name="defaultStack"></interceptor-ref>                  </interceptor-stack>                  先执行privilege,后执行默认的拦截器栈

属性驱动(可用但不常用)

解决的问题就是在jsp页面写一个表单,通过name就可以在action中获取jsp页面中表单的值

属性驱动:
1、目的:在action中声明一些属性,这些属性能够获取到表单中的值
2、步骤:
1、在action中声明一些属性,属性的名称和页面上name属性的名称一致
2、这些属性在action中必须有setter和getter方法
3、原理:
在浏览器提交一个url请求时,先创建一个action,并且把action放入到对象栈中,这个时候
action的属性会出现在对象栈中,然后经过一个拦截器ParametersInterceptor拦截器
做的事情:
1、获取页面上表单中的name和value的值
2、把上述的name和value的值封装成一个map
3、根据valueStack.setValue(name,value);来把页面上的值设置到对象栈的name属性中

模型驱动 (常用)

模型驱动和属性驱动是的区别

区别:模型驱动是先建立一个bean将所有的字段封装进去,而属性驱动是直接在action中写字段,然后实现get和set方法属性驱动:    1、创建一个javabean,javabean中的属性和页面中表单中的name属性的内容保持一致    2、在action里实现一个接口ModelDriven<Person>    3、在action中声明一个属性,并且创建该属性的对象        private Person modle = new Person();    4、在action中有一个方法:        @Override        public Person getModel() {            // TODO Auto-generated method stub            return this.modle;        }        该方法返回模型驱动对象模型驱动的原理:    模型驱动经过两个拦截器:      1、ModelDrivenInterceptor          1、得到action          2、由action强制转化成ModelDriver          3、由ModelDriver.getModel()获取模型对象          4、把模型对象放入到栈顶      2、ParameterInterceptor            把form表单的数据封装到相应的对象栈中的属性中

threadlocal解析(重要)

在ActionContext类中
static ThreadLocal actionContext = new ThreadLocal();
//把context放入到当前线程中
public static void setContext(ActionContext context) {
actionContext.set(context);
}
//从threadlocal中把context提取出来
public static ActionContext getContext() {
return (ActionContext) actionContext.get();
}

这样做就不用参数的传递了,只要在同一个线程中就可以了

1 0
原创粉丝点击