Struts2是一个在WebWork框架基础上发展起来开源MVC框架。html
StrutsPrepareAndExecuteFilter本质上是一个过滤器,配置在web容器中,该过滤器做为Struts框架的启动项,将符合扩展名要求的请求转发给Struts框架处理,将处理结果返回给浏览器。java
对于那些符合扩展名要求的请求,StrutsPrepareAndExecuteFilter直接将其转发给Struts框架,没有沿着过滤器链向下传递,因此配置在其后的过滤器不起做用。那些不符合扩展名要求的请求将沿过滤器链正常执行。web
StrutsPrepareAndExecuteFilter(为便于表述,如下称做struts启动项)将符合扩展名要求的请求转发到Struts框架中,首先生成一个ActionMapping,该ActionMapping表明了须要调用的Action对象,基于ActionMapping返回一个ActionProxy,proxy经过配置管理器查询配置文件struts.xml,返回一个ActionInvocation对象,由Invocation对象具体调用action中的方法。在action方法调用前以及调用后都会执行一系列拦截器,最后将响应结果反馈给浏览器。数组
Action是Struts2框架的控制器,将请求分发给响应的业务逻辑。每请求一次,建立一个对象。浏览器
建立Action对象时推荐继承ActionSupport,由于ActionSupport实现了不少接口,继承该类能够拥有国际化、数据验证等功能。Struts2也支持不继承任何类的POJO对象,只能实现一些简单的功能,如表单注入,实现类型转化、数据验证、拦截器、国际化、文件上传等特殊功能时必须继承ActionSupport。安全
在请求url中加入方法名以访问Action中指定方法的机制。
高版本的Struts禁用了动态Action,可使用通配符,动态地调用action中的方法:服务器
struts.xml是Action对象的默认配置文件。
格式:session
<struts> <package name="resultList"extends="struts-default"abstract="true"> <global-results> <result name="">/xxx.jsp</result> </global-results> </package> <include file="newFile.xml"></include> <contant name="struts.devMode"value="true"></constant> <package name="packageName"extends="struts-default"> <global-results> <result name="">xxxx</result> </global-results> <action name="url*"class="完整包名{1}"> <result name="res" type="">/xxx.jsp</result> <result name=""type="redirect"> <param name="location">/xxx.jsp</parame> <param name="key">value</param> </result> <result name=""type="redirectAction"> <param name="actionName">actionName</param> <param name="key">value</param> </result> </action> </package>
</struts>
标签说明:数据结构
为不一样的模块设定不一样的配置文件,最后集中到默认的配置文件struts.xml中。app
设定struts框架的属性。
name:设定一个名称,当action对象返回的字符串与该名称值相同时,返回对应的文件(如jsp、html)给浏览器,name默认值为success。返回文件采用以“/”开头相对于项目的路径形式。
type:设定页面跳转的类型:
在Action中定义与表单输入同名的属性,底层自动调用setter方法将输入注入到属性中。
建立一个封装了表单输入的类,在Action中引用该类的对象,并为对象提供getter/setter方法。要求表单输入必须指明所属的对象,实现方式将表单输入的名称定义为“obj.name”,obj是Action中封装对象的引用变量。
底层实现过程:域模型为表单输入指明了所属的对象,Action对象建立完成之后,调用getter方法,若是存在对象,则返回,不存在,
接着调用setter方法建立对象,对象建立完成之后,调用对象中的setter方法为对象属性赋值。
若是表单输入能够被封装到一个类的多个对象中,那么可使用域模型将输入注入到向Action对象的List集合中,实现以下:
在表单输入中使用List集合引用变量与下标给表单输出指定所属的对象:
<input type="text"name="list[0].name">
Action对象实现ModelDriven接口中的getModel方法,getModel方法负责接收表单输入,将输入注入到实体对象中,并返回实体对象不须要在表单输入中指明将要注入的对象,即表单输入名称前再也不加对象的引用变量。
Struts2提供了Map类型的request、session、application,经过ActionContext对象获取,首先获取ActionContext对象:
ActionContext context = ActionContext.getContext();
获取request、session、application对象的通用方法,以request为例:
Map<Object Object> request=context.get("request");
获取session对象的专有方法:
Map<Object,Object> session=context.getSession();
获取application对象的专有方法:
Map<Object,Object> application=context.getApplication();
Struts提供了一个ServletActionContext类,利用该类的静态方法能够获取request\session\application对象:
HttpServletRequest request=ServletActionContext.getRequest(); HttpSession session=request.getSession(); ServletContext servletContext=ServletActionContext.getServletContext();
一个线程,一个ActionContext;一个Action,一个ActionContext,ActionContext是线程安全的。
对应于OGNL的根,使用OGNL表达式能够直接获取其中的数据。数据结构:
ActionContext context = ActionContext.getContext();
ValueStack valueStack = context.getValueStack();
valueStack.push(Object obj);//将数据放到栈顶 valueStack.set(Object key,Object value);//若是顶层存在Map集合,则放入Map集合中;不存在,建立一个,再将数据放入其中
valueStack.peek();// 获取栈顶元素 valueStack.pop();// 获取并删除该栈顶元素
若是栈中的对象包含多个属性,获取属性值时不须要经过对象引用的形式,能够直接使用属性名,系统从栈顶开始检索,找到第一个属性名称相同的属性,将其值返回。
4.request、session、application(Map类型的集合):在OGNL中,采用#request.key获取属性值。
5.parameters:存放请求参数,经过#parameters.name获取请求参数的值。
6.attr:不指定属性的范围,能够经过#attr.key获取属性的值,检索顺序request、session、application。
7.action对象:获取其中的数据<s:property value="#action.varName"/>。
Object Graph Navigation Language,能够自动导航对象的结构,访问对象,为对象赋值。
OGNL的核心是OGNL上下文,OGNL上下文至关于一个Map类型的容器,能够存储任何类型的数据。OGNL分层次,有一个区域是OGNL的根,能够直接访问根中数据,访问其余区域的数据须要在前面加“#”。
当指定内容有可能被执行环境当作字符串时,告知指定内容是OGNL表达式。
@完整类名@属性名::访问静态变量。
@完整类名@method():访问静态方法。
Struts默认状况下不容许访问静态方法,如需访问须要在配置文件中作以下设置:
<constant name="struts.ognl.allowStaticMethodAccess"value="true"/>
访问java.lang.Math中的静态方法,能够由@java.lang.Math@method()简写为@@method()。
arr[index]:获取数组指定索引位置的元素。
arr.length:获取数组的长度。
获取集合中知足条件的对象,针对行的操做,返回一个集合。
操做方法:
建立拦截器对象时,若是直接实现Interceptor接口,需实现其中的三个方法,而这三个方法在实际中并非所有须要的。AbstractInterceptor是一个抽象类,实现了Interceptor接口,实现了init、destroy方法,所以自定义拦截器对象时,继承该方法,只实现intercept方法便可。
拦截器对象的生命与引用分离,先声明,后引用。
在不作其余特殊设定的状况下,使用了自定义的拦截器,系统默认的拦截器失效。因为系统默认的拦截器比较重要,实现重要功能不可缺乏,所以应该将系统默认的拦截器包含进去,而且放在其余自定义拦截器前面。
分别定义与引用多个拦截器。
----------------拦截器声明------------------------ <interceptors> <interceptor name="interceptor01"class=""/> <interceptor name="interceptor02"class=""/> </interceptors> ----------------拦截器引用------------------------ <action> <interceptor-ref name="defaultStack"/> <interceptor-ref name="interceptor01"/> <interceptor-fef name="interceptor01"/> </action>
将多个拦截器集中在拦截器栈中,引用拦截器栈。拦截器栈至关于拦截器集合。
----------------拦截器声明------------------------ <interceptors> <interceptor name="interceptor01"class=""/> <interceptor name="interceptor02"class=""/> <interceptor-stack name="myStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="interceptor01"/> <interceptor-fef name="interceptor01"/> </interceptor-stack> </interceptors> ----------------拦截器引用------------------------ <action> <interceptor-ref name="myStack"/> </action>
将拦截器集中在默认拦截器中,对包中全部的Action有效。
----------------拦截器声明------------------------ <interceptors> <interceptor name="interceptor01"class=""/> <interceptor name="interceptor02"class=""/> <interceptor-stack name="myStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="interceptor01"/> <interceptor-fef name="interceptor02"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"/>
直接继承AbstractInterceptor建立的拦截器对全部方法都进行拦截,继承MethodFilterInterceptor建立的拦截器能够指定拦截的方法。
引用方式:
<interceptor-ref name="interceptor01"class=""> <param name="includeMethods">methodName01,methodName02</param>//指定拦截的方法 <param name="excludeMethods">methodName01,methodName02</param>//指定不拦截的方法 </interceptor-ref>
Struts内置了许多类型转化器,主要是将字符串转化为基本数据类型及其包装类,将字符串转化为日期。系统默认的日期格式是yyyy-MM-dd HH:mm:ss,当输入的字符串符合该格式时,自动转化为日期。
public class MyDateConverter extends DefaultTypeConverter { @Override public Object convertValue(Object value, Class toType) { // TODO Auto-generated method stub return super.convertValue(value, toType); } }
该方法分为两部分,有时执行两次:
、
发生类型转换异常,会返回值input,须要在配置文件中定义input对应的返回页面。input只在抛出TypeConversionException时才返回,所以须要在自定义类型转换器中抛出该异常,能够先判断表单输入的格式是否是容许的格式,若是不是容许格式,抛出该异常。
文件命名方式ActionClassName-conversion.properties,放在Action包中,属性文件内容:
属性名=类型转换器全限定性类名
文件命名方式xwork-conversion.properties,放在src目录下,属性文件内容:
属性类型(如java.util.Date)=类型转换器全限定性类名
修改类型验证返回的提示信息,建立ActionClassName.properties文件,放在Action包中,内容:
invalid.fieldvalue.fieldname=数据验证失败提示信息
ActionSupport实现了Validatable接口,对其中的方法validate只是空实现,所以手动编写验证器时,继承ActionSupport类,重写validate方法。手动验证器默认对对象内的全部方法都进行验证。
public class MyValidator extends ActionSupport{ public void validate(){ if(xxxxxx)//验证若是未经过 this.addFieldError("字段名","显示的错误提示信息"); } }
验证文件的命名规则:
ActionClassName-validation.xml:对Action对象中全部方法都进行验证。
ActionClassName-AliasName(配置中的名称)-validation.xml:只对指定的方法进行验证。
验证文件的编写:
<validators> <field name="fieldName"> <field-validator type="requiredstring"> <message>验证未经过时输出的信息</message> </field-validator> </field> <validators>
验证未经过时,Action返回值“input”,所以须要在<action>标签内部配置返回值为“input”时的返回页面。
若是为同一个方法同时定义了多个数据验证方式,执行的优先级:基于XML的针对方法的验证>基于XML的针对对象的验证>手动编写的针对方法的验证>手动编写的针对对象的验证。
引用:
<%@taglib prefix="s" uri="/struts-tags"%>
主要标签:
1.<s:debug/>:在页面中显示ActionContext中的内容。
2.<s:property value=""/>:
3.<s:property value="#request.name"/>:
4.<s:set name=""value="''"scope=""/>:赋值语句,字符串必须在内层使用‘',外层使用"",未指定做用域时放在context。
5.<s:iterator value=""/>:将遍历对象放到值栈栈顶。
6.<s:property value="'s' in #list/>:判断某个数据是否在列表中,相应地,还有不存在判断not in。
7.<s:push value=""/>:将数据压入栈中,以便之后访问,该标签不稳定,减小使用。
首次访问表单页面,若是该页面采用了令牌机制,token拦截器生成一个随机数,将这个随机数在浏览器与服务器端各保存一份。首次提交表单时,token拦截器对比两个参数,相同,完成提交,而后服务器单方面修改该随机数,不通知浏览器。浏览器再次提交,两个参数值不相同,token拦截器返回invalid.token值,跳转到该值对应的页面,请求未到达Action对象,这样就防止了重复提交。
使同一个事物适应多种国际环境,就叫作国际化,在Web应用程序开发中就是使页面可以按照多种语言来显示。
Struts提供了一个拦截器I18N,该拦截器会自动获取与国际化相关的请求参数,根据参数值选取相应地资源文件为程序内部的变量赋值,赋值完成后,页面按赋值结果显示。这个请求参数是request_locale,将其追加到URL后面,并按照格式request_locale=language_country赋值。
实现国际化须要使用Struts标签创建页面。
国际化的实现依赖于资源文件,一种语言一个资源文件,资源文件的命名决定了其做用范围,共有三种命名方式:
全局范围资源文件,对整个应用都有效。baseName能够自定义,放在scr目录下,在配置文件中配置:
<constant name="struts.sustom.i18n.resources"value="baseName"/>
包范围资源文件。
Action范文资源文件,放在包内。
在资源文件中定义动态参数:keyName={0},valueContext,其中占位符从0开始。
在java文件中,采用如下形式为动态参数赋值:
String str=this.getText("key",String[] args);
其中args是一个数组,为资源文件中的占位符赋值,这样就能够理解为何不使用*,并且从0开始了。
<s:text name="key"> <s:param><s:property value=""></s:param>//为第一个占位符赋值 <s:param><s:property value=""></s:param>//为第二个占位符赋值 </s:text>
<s:param>标签用做传递参数,<s:property>用来取值。
<s:i18n name="资源文件名相对于src的路径"> -------指定资源------- </s:i18n>