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();
}
这样做就不用参数的传递了,只要在同一个线程中就可以了
- struts2入门到精通教程
- mybatis入门到精通教程
- XStream入门到精通教程
- 汇编语言程序教程:从入门到精通!
- 汇编语言程序教程:从入门到精通!
- 汇编语言程序教程:从入门到精通!
- JavaScript教程--从入门到精通(一)
- JavaScript教程--从入门到精通
- JavaScript教程--从入门到精通(1)
- jJavaScript教程--从入门到精通(2)
- jJavaScript教程--从入门到精通(2)
- JavaScript教程--从入门到精通(3)
- JavaScript教程--从入门到精通(4)
- JavaScript教程--从入门到精通(5)
- JavaScript教程--从入门到精通(6)
- JavaScript教程--从入门到精通(7)
- JavaScript教程--从入门到精通(8)
- JavaScript教程--从入门到精通(9)
- android 扬声器和听筒切换兼容5.0以上版本
- Java中的静态类以及嵌套类
- bzoj 1113: [Poi2008]海报PLA
- Flink中的一些核心概念
- 类大小的计算
- struts2入门到精通教程
- Spring3.1集成Quartz,让你的任务执行随心所欲
- HDU 1297 Children’s Queue
- 关于接口,继承,内部类的一些测试
- Java线程池——FutureTask
- iOS内存话题: 实例变量造成的循环引用
- STL之常用算法
- php里面的MySql
- 为啥你手机还用不上安卓6.0?