1.全局的逻辑控制器为一个过滤器,负责过滤所有的请求。该过滤器引用的API类为 org.apache.struts2.disapatcher.FilterDispatcher
2.MVC:页面请求(jsp)——>逻辑控制器(Filter)——>业务控制器(Action)——>业务逻辑组件——>业务处理/DAO
3.struts2的配置文件放在classpath下。
4.struts2的类型转换:
a.继承DefaultTypeConverter,
覆盖父类的public Object convertValue(Map context, Object value, Class toType)方法
b.继承StrutsTypeConverter,
覆盖父类的public Object convertFromString(Map context, String[] values, Class toClass)
该方法负责转换从页面传递过来的数据。
覆盖父类的public String convertToString(Map context, Object o)
该方法负责将Action中处理好的数据转换成相应格式的字符串。
5.struts2的数据验证:
a.使用编码方式进行验证。业务控制器Action继承ActionSupport类,重写public void validate()方法。
在该方法中进行数据验证。若Action中处理业务的方法为test,则可以编写public void validateTest()
方法,来对test方法的数据进行验证。(系统在进行validateTest方法后,会接着执行validate方法,然后
才执行相应的业务代码。)
若严重出错,则可以调用addFieldError或者调用addActionError方法,增加相应的错误提示信息。
b.使用配置xml文件进行验证。验证文件的名字为:×××Action-validation.xml。验证的方式包含字段验证和非字段验证。
其中字段验证表示对某个字段进行某些类型的验证。非字段验证表示用某个类型的验证来验证,某个字段。两种方式
底层实现一样,只是表现方式不同,字段验证方式比较直观。
验证的类型有一下几种:required,requiredstring,int,date,double,expression,fieldexpression
email,url,visitor,conversion,stringLength,regex(正则表达式)。
对验证类型可以指定shourt-circuit参数为true,来执行短路验证。
如果Action中执行业务的方法为test,则可以通过编写×××Action-test-validation.xml方法来对test方法的数据进行
验证。且执行完test方法的私有验证文件后,还会执行默认的验证文件×××Action-test-validation.xml的验证。
c.struts2进行客户端的验证。首先需要使用struts2的标签库,且标签库的theme属性不能为simple,然后设置标签的
validate属性为true。
注意:struts2的客户端验证依赖于服务器的验证配置文件。
6.struts2的拦截器。struts2的拦截器是struts2的核心,其底层实现使用了Java的反射机制与动态代理。在struts2的配置文件中
为一个Action引入了一个拦截器,则配置的默认拦截器不会被调用,需要手工配置到该Action中。
实现struts2拦截器的方法:
a.实现Interceptor接口,并实现init,destrory以及intercept方法。
b.继承AbstractInterceptor类,覆盖intercept方法。
c.继承MethodFilterInterceptor类,覆盖intercept方法。该类可以对特定的方法进行拦截。
拦截器栈可以包含拦截器和拦截器栈。
7.文件的上传和下载:
a.使用apache组织开发的commons-fileupload和commons-io包,并且按需要配置fileUpload拦截器和相应的上传参数,
比如上传文件的类型,上传文件的大小。多文件的上传可以使用js代码来在页面修改上传文件的列表,在Action中
则用三个列表分别来保存文件对象(file),文件名(fileName),以及文件类型(fileContentType)。
b.文件下载使用流进行读取:return ServletActionContext.getServletContext.getResourceAsStream("文件名")
并将Action的结果返回类设定为stream,即流。按需要配置相应的参数。
8.struts2的国际化。struts2国际化的底层实现用到了Java基础类库中的Locale(地区)和ResourceBundle(消息资源)两个类。
struts2的国际化主要用在一下几个地方:
a.jsp页面:使用struts2的标签时,指定标签的key属性(对应消息资源文件中的key)。
使用<s:text name="key">
<s:param></s:param>
</s:text>
标签取得消息资源信息。
还可以用<s:i18n name="basename"></s:i18n>标签来指定特定的消息资源文件。
b.Action中:调用getText(key)或者getText(key,args)方法取得消息资源文件中的消息资源。
c.xml验证文件中:指定message元素的key属性(对应消息资源文件中的key)。(怎么传参数?)
d.类型转换过程中:通过查看xwork包的源代码可以找到:ge.properties文件中可以找到如下的键值对:
xwork.default.invalid.fieldvalue=Invalid field value for field "{0}".
在消息资源文件中重新指定该键值对即可。
另外在struts.properties中设定键值对struts.i18n.encoding=GBK,可以解决中文乱码问题。
9.struts2的异常处理。在Action中,我们的业务逻辑处理方法都对抛出异常进行了声明。具体的异常对应具体的处理结果。
在action配置中:
<action >
<result name="exception"></result>
<exception-mapping result="exception" exception="具体的异常类型"></exception-mapping>
</action>
还可以配置全局的异常处理:
<global-exception-mappings>
<exception-mapping result="" exception=""></exception-mapping>
</global-exception-mappings>
struts2的其他东西:
1.对于struts.xml中的package:
a.设置<package abstract="true">,则表明该包中没有action的配置,只定义一个基础公共的组件。
b.package的namespace可以将不同的请求路径分隔开,在多人合作项目中用到比较多。当接收到一个请求,
若在当前的namespace中没有相应的请求地址,则会到默认的namespace中去寻找匹配的地址。
2.模型驱动机制(ModelDriven),将一个Action中的各个参数封装成为一个JavaBean(类似struts1.x中的
ActionForm)。需要实现ModelDriven<T>接口,并实现getModel方法。当一个Action实现ModenDriven接口后,
该Action会被ModenDrivenInterceptor拦截,进行相应的参数设置。
3.防止表单的重复提交:在jsp的表单中设置<s:token name="***"></s:token>标签。并且在相应的Action
中设置token拦截器和名为invalid.token的返回结果。相应出错信息的key为struts.message.invalid.token。
配置该key,来实现国际化。
4.struts2中Action与Servlet容器的耦合。主要有三种方式:
a.实现ServletRequestAware或ServletResponseAware接口。并提供对request或者response熟悉的设置方法。
b.使用ActionContext(但不能获得response对象)。改方法方便单元测试。
c.使用ServletActionContext。ServletActionContext是ActionContext的子类。
首选使用ActionContext,其次ServletActionContext。
5.整合多个struts配置文件,在struts2的配置文件中使用include元素包含其他的配置文件。用于多模块开发。
6.可以在web.xml中对struts2的核心过滤器FilterDispatcher设置初始化参数(不推荐使用)。
7.动态方法调用(DynamicMethodInvocation).
a.action配置中指定:<action name="×××" method="">
b.在客户端即页面指定:<s:form action="method!actionName">
c.使用通配符:<action name="*Login" class="com.action.LoginAction" method="{1}">,
若Action的url为helloLogin,则调用LoginAction的hello来处理业务。此种方法简化了配置,但是
使得程序不明了,不提倡使用该方法。
8.struts2的结果类型。在struts2-core包中,有几种struts2已经配置好的结果类型。
其中默认的类型为dispatcher,此外还有:redirectAction,chain,freemaker,httpheader,redirect,
redirectAction,stream,velocity,xslt,plainText。
9.struts2与spring的整合。导入struts2-spring-plugin包,在web.xml中设置spring的监听器,
spring监听器对应的API类为:org.springframework.web.context.ContextLoaderListener。
struts2-spring-plugin包为我们将struts2的对象工厂设置为spring的IoC容器,其代码为:
<struts>
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<!-- Make the Spring object factory the automatic default -->
<constant name="struts.objectFactory" value="spring" />
<package name="spring-default">
<interceptors>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
</interceptors>
</package>
</struts>
很明显,将struts.objectFactory定位为org.apache.struts2.spring.StrutsSpringObjectFactory
其余的工作就交给spring的IoC容器去做了。
另外:当我们需要增加spring的配置文件时,需要在web.xml中设定contextConfigLocation参数。代码如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>其他的spring配置文件名,用逗号隔开</param-value>
</context-param>
需要注意的一些地方
1.存储fieldError的是一个LinkedHashMap<String,ArrayList>;而actionError则存储在一个ArrayList中。
ActionSupport中的getFieldError方法返回的是一个新的集合。该集合是原fieldError集合的一个副本。
在struts2的源代码中返回的是:new LinkedHashMap(internalGetFieldError),即一个新的集合对象。
所以执行代码:this.getFieldErrors.put("username","ErrorMsg");不会影响原fieldError集合的数据。
2.若一个Action注册了PreResultListner,则会在该Action返回的时候调用相应结果验证的逻辑代码。
3.struts2-core包中的default.properties和struts-default.xml文件保存了一些struts2默认的配置。
可以在自己的struts配置文件中对相应的配置进行覆盖或重新设值。比如修改请求的后缀名:在struts.properties
中加入:struts.action.extension = do
则将struts2请求的后缀名修改成了struts1中的do后缀名的形式。
4.在配置文件中配置struts.multipart.saveDir来设定上传文件时的临时文件的存储位置。需要定期清理该路径下的文件。
一、总体的应用思路
1、在web.xml中配置struts2的servlet,将对此应用的请求拦截下来,转发给FilterDispatcher。
2、在struts.xml中通过constant配置struts2的设置(如指定用spring根据对象set方法给对象进行依赖注
入等)
3、在struts.xml中配置总的package;
配置需要的interceptor,设置默认的interceptor;
配置global results。
配置子package中都会用到的action,如异常action。
配置global exceptions(指定当发生某种异常时result的去向)
include子struts配置文件。
4、在子struts-**.xml中配置各自的具体package(继承自总包)及其中的action。
多个子struts-**.xml中的action的名字可以是一样的。
如都有save这个action,但是可以通过命名空间来知道调用的是哪个action。
在action指定调用哪个类的哪个方法。多个action可以公用一个类,只要指定不同的方法即可。
5、在jsp中通过form的action属性和namespace属性告诉struts我们具体调用的是
哪个命名空间下的哪个action。
6、action中需要与前台jsp交互的数据。只要在action类中定义相应的属性(和前台的标签name一致)
即可。后台向前台传数据时,前台会自动通过get***得到数据。前台向后台传数据时,struts会自动
调用set**方法设置数据给后台的action类。
二、最近项目中的struts2具体应用总结
1、web.xml中配置见以前的总结文章(就是配置一个struts2的servlet(指定了struts的配置文件位置),
和一些字符转换和中文乱码的配置)。在本次应用中,在struts2的前面我们还配置了一个filter,
将我们需要的东西(如请求路径)按照我们需要的格式setAttribute到request中去。
2、struts.xml
<struts>
//配置struts2的一些参数(也可以通过struts.properities配置)
//指定struts2中的使用spring提供的对象工厂创建(这样创建的对象其属性就自动注入了)
<constant name="struts.objectFactory" value="spring"/>
//指定根据名字自动匹配spring中的bean,如在某个action类或者interceptor类中定义了一个对象及其
set/get方法,这样我们就会根据spring配置文件中和这个set***匹配的名字的bean来setter注入他
<constant name="struts.objectFactory.spring.autoWire" value="name"/>
//国际化编码方式
<constant name="struts.i18n.encoding" value="UTF-8"/>
//国际化支持的资源文件(所谓国际化就是说我们按照命名规则,给面向各个国家的资源文件分别定
义,然后通过<s:text name="**.**"/>的方式,struts会自动根据操作系统的国际化类型选择那个资
源文件来加载。)
<constant name="struts.custom.i18n.resources" value="i18n.Message,i18n.errors"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.mapper.class"
value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper"/>
//action默认的扩展名。也就是说我们调用的action会在后面自动加上.do
<constant name="struts.action.extension" value="do"/>
<constant name="struts.enable.SlashesInActionNames" value="false"/>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.mapper.alwaysSelectFullNamespace" value="true"/>
<constant name="struts.configuration.xml.reload" value="true"/>
//定义一个总包,继承自struts-default
<package name="webtools" extends="struts-default">
//装配几个我们用到的拦截器/拦截器栈
<interceptors>
//定义一个判断是否登陆的拦截器,在每个操作之前都要判断是否登陆
<interceptor name="LoginCheck"
class="com.watchdata.mepay.web.interceptor.LoginCheckInterceptor">
</interceptor>
//定义一个权限拦截器,在每个操作之前都要判断是否有此权限(取出此用户的权限列表比较)
<interceptor name="PermissionCheck"
class="com.watchdata.mepay.web.interceptor.PermissionCheckInterceptor"/>
<interceptor-stack name="LoginCheckStack">
<interceptor-ref name="LoginCheck"/>
//加入默认拦截器,因为struts的很多功能都是通过这些拦截器实现的。
<interceptor-ref name="defaultStack"/> //也可以是拦截器栈
</interceptor-stack>
<interceptor-stack name="LoginAndPermissionCheckStack">
<interceptor-ref name="LoginCheckStack"/>
<interceptor-ref name="PermissionCheck"/>
</interceptor-stack>
</interceptors>
//设置本应用默认使用的拦截器(栈)
<default-interceptor-ref name="LoginAndPermissionCheckStack"/>
//设置全局结构,相当于全局变量呗。全局都承认的结果转向
<global-results>
<result name="Exception" type="chain">exceptionAction</result>
<result name="login" >/login.jsp</result>
<result name="nopermission">/main/permissionDeny.jsp</result>
</global-results>
//全局异常:当发生某个异常时对应那个结果。如:发生WebRuntimeException异常--->
到Exception结果,而Exception是个全局结果--->chain类型的exceptionAction--->
转到下面定义的exceptionAction--->最后转到了/exception/exception.jsp
<global-exception-mappings>
<exception-mapping exception="WebRuntimeException" result="Exception"/>
<exception-mapping exception="Exception" result="Exception"/>
</global-exception-mappings>
<action name="exceptionAction" class="com.watchdata.mepay.web.action.ExceptionAction">
<result>/exception/exception.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
//通过include找到子struts配置
<include file="struts/struts-admin.xml"></include>
<include file="struts/struts-group.xml"></include>
<include file="struts/struts-role.xml"/>
<include file="struts/struts-permission.xml"></include>
。。。。。。。。。。。。。。。。。。。
</struts>
3、struts.xml include的子配置
<struts>
//配置子包,继承自前面定义的webtools,定义命名空间/group。定义此命名空间下的action。
不同的包/子配置中可能存在相同名字的action,如都有save,delete等,但是根据他们的命名空间
不同来区分是group的delete还是admin的delete。
而在jsp中调用action时也要指明调用那个命名空间下的action
如:<s:form action="save" namespace="/group" 。。。。。。。>
<package name="group" namespace="/group" extends="webtools">
//多个action可以调用的是一个类,通过method的指定来确定调用类中的哪个方法
//由于指定了使用spring的工厂,所以在创建com.watchdata.mepay.web.action.GroupAction时
会将其中的set**,自动注入
<action name="add"
class="com.watchdata.mepay.web.action.GroupAction" method="add">
<result name="input">/Group/addGroup.jsp</result>
</action>
<action name="save"
class="com.watchdata.mepay.web.action.GroupAction" method="save">
<result name="input">/Group/addGroup.jsp</result>
//chain类型,表明继续调用名字为list的action
<result name="list" type="chain">list</result>
</action>
<action name="edit"
class="com.watchdata.mepay.web.action.GroupAction" method="edit">
<result name="input">/Group/editGroup.jsp</result>
<result name="list" type="chain">list</result>
</action>
</package>
</struts>
4、struts2的表现层(标签):
4.1、判断标签:
//test=""中是一个条件语句,可以带有action中定义的函数如:getFieldErrors(),此例是通过判断是否
//发生错误来决定错误显示表格是否显示style="display:none"
<table id="errTable" width="99%" border="0" cellpadding="0" cellspacing="0" class="Middle"
<s:if test="getFieldErrors()==null||getFieldErrors().size()==0">
style="display:none"
</s:if>
>
4.2、文本显示标签
<s:text name="msgs.group.add" />
//显示标签:显示资源文件中指定的名字为msgs.group.add的字符串
4.3、文本框标签
<s:textfield name="group.groupName" size="45" />
//name表示此标签对应于action中的那个属性。这里指的是对应action中group(复杂类型)对象的groupName属性,后台到前台和前台到后台时,都会自动的注入此值
4.4、多选框列表标签
<s:checkboxlist list="roleList" name="roleId" listKey="roleId" listValue="roleName" />
//list:指定了此多选框列表中显示的多选框项(和选不选中无关),在前台直接定义,后者在后台给一个list类型的值。
//name:对应后台选中值数组。选中的值存入到这个数组中。所以其类型应该和listKey中的类型一致。
//listKey:指定选中项传那个值(roleList中bean的一个属性)
//listValue:指定多选框的显示(roleList中bean的一个属性)
对应的action如:
public class GroupAction extends BaseAction
{
private List<Role> roleList;//Role中有roleId、roleName
private Long[] roleId;
......................
}
4.5、set标签:把一个值赋给一个变量
<s:set name="stateList"
value="#{1:getText('msgs.group.active'),0:getText('msgs.group.suspend')}"></s:set>
4.6、select标签
<s:select name="group.state" list="stateList"></s:select>
list:列表中显示的项
name:选中项对应action中的属性
4.6、submit标签
<s:submit value="%{getText('msgs.btn.submit')}" cssClass="button"></s:submit>
Struts 2是在WebWork2基础发展而来的。
注意:struts 2和struts 1在代码风格上几乎不一样。
Struts 2 相比Struts 1的优点:
1、在软件设计上Struts 2 没有像Struts 1那样跟Servlet API 和 struts API 有着紧密的耦合。Struts 2的应用可以不依赖于Servlet API和Struts API 。
2、Struts 2 提供了拦截器,利用拦截器可以进行AOP编程。
3、Struts 2 提供了类型转换器。
4、Struts 2 提供支持多种表现层技术,如:JSP 、 freeMarker等。
5、Struts 2 的输入校验可以指定方法进行校验。
6、Struts 2 提供了全局范围、包范围和Action范围的国际化资源文件管理实现。
Struts 2 体系结构 :
1、Web浏览器请求一个资源。
2、过滤器Dispatcher查找方法,确定适当的Action。
3、拦截器自动对请求应用通用功能,如验证和文件上传操作。
4、Action的execute方法通常用来存储和重新获得信息。
5、结果被返回到浏览器。
搭建Struts 2 开发环境
1、找到开发Struts 2的应用需要用到的jar包。
2、编写Struts 2的配置文件。
3、在web.xml中加入Struts 2 MVC启动框架配置。
开发Struts 2 最少用到的jar文件:
Struts-core-2.x.x.jar : Struts 2 框架的核心类库
xwork-2.x.x.jar : XWork类库,Struts 2 在其上构建
ognl-2.6.x.jar : Object Graph Navigation Language , Struts 2 框架通过其读写对象的属性。
freemarker-2.3.x.jar : Struts 2 的UI标签的模版使用 Freemarker编写。
commons-logging-1.1.x.jar : ASF出品的日志包。
commons-fileupload-1.2.1.jar : 文件上传组件。
Struts 2 各种中文件详解:
1、struts.xml文件
struts.xml需要存放在WEB-INF/classes下,模板如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
</struts>
Struts.xml是 Struts 2 的核心配置文件,主要用于配置开发人员编写的action。
2、web.xml文件
在Struts 2中,Struts框架是通过Filter启动的,他在web.xml中的配置如下:
<!-- 配置Struts2 核心 Filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文件struts.xml完成初始化操作。
注意:struts 2 读取到 struts.xml的内容后,以javabean形式存放在内存中,以后Struts 2对用户的每一次请求处理将使用内存中的数据。
Filter 过滤器是用户请求和处理程序之间的一层处理程序。它可以对用户请求和处理程序响应的类容进行处理,通常用于权限、编码转换等场合。
3、ActionSupport 类
ActionSupport 类为 Action 提供了一些默认实现,主要包括预定义常量、从资源文件中取文本资源、接收验证错误信息和验证的默认实现。
Struts 2 数据验证及验证框架的应用:
1、数据校验
Action 继承了 ActionSupport 类 ,而该类实现了 Action 、Validateable 、 ValidationAware 、TextProvider、LocaleProvider、Serializable 接口。
在Validateable 接口定义了一个 validate() 方法 , 在用户自定义 Action 类中重写该方法就可以实现 验证功能。
public class LoginAction extends ActionSupport{
private String username ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
if ( ! username.equals("HelloWorld"))
{
Map request = (Map) ActionContext.getContext().get("request") ;
request.put("name", getUsername()) ;
return SUCCESS;
}
else return ERROR ;
}
public void validate()
{
//如果名字为空,则把错误信息天骄的Action类的fileError
if (this.getUsername() == null || this.getUsername().trim().equals(""))
{
addFieldError("username" , "名字不能为空") ;
}
}
}
在类中定义了校验方法后,该方法会执行系统的 execute() 方法之前执行。如果执行该方法后,Action类的fieldError中已经包含了数据校验错误信息,将把请求转发到input逻辑视图处,所以在 Action配置中也要配置一下。
<action name = "LoginAction" class = "com.cnblogs.jbelial.login.LoginAction" >
<!-- 定义3个逻辑视图和物理资源之间的映射 -->
<result name = "input">/login.jsp</result>
<result name = "error">/error.jsp</result>
<result name = "success">/main.jsp</result>
</action>
注意:
result中的name属性有下:
1、success : 表示请求处理成功,该值也是默认值。
2、error :表示请求处理失败。
3、none :表示请求处理完成后不跳转到任何页面。
4、input :表示输入时如果验证失败应该跳转到什么地方。
5、login :表示登录失败后跳转的目标。
2、Struts 2 验证框架的应用
Struts 2 提供了大量的数据校验器,包括表单域校验器和非表单域校验器。
(1)必填字符串校验器
该校验器的名字是 requiredstring 其校验规则定义文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<field name = "username">
<!-- 需要验证的字段的字段名 -->
<field-validators type = "requiredstring">
<!-- 去空格 -->
<param name = "trim">true</param>
<!-- 错误提示信息 -->
<message>请输入用户名</message>
</field-validators>
</field>
</validators>
文件命名:ActionName-validation.xml:其中ActionName 就是需要校验的用户自定义的Action 类的名字。而且该文件应该与Action 类文件放置在同一路径下。
(2)必填校验器
该校验器的名字就是 required 。该校验器与requiredstring 的差别就是 可以有空字符串。配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要验证的字段的字段名 -->
<field name = "username">
<field-validators type = "required">
<!-- 错误提示信息 -->
<message>请输入用户名</message>
</field-validators>
</field>
</validators>
(3)整数校验器
该校验器的名字为 int ,该校验器要求字段的整数值必须在一定范围内。配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要验证的字段的字段名 -->
<field name = "number">
<field-validators type = "int">
<!-- 数值的最小值 -->
<param name = "min">50</param>
<!-- 数值的最大值 -->
<param name = "max">100</param>
<!-- 错误提示信息 -->
<message>大小必须在50至100之间</message>
</field-validators>
</field>
</validators>
(4) 日期校验器
该校验器的名字是 date , 该校验器要求字段的日期值必须在指定范围类,所以也有 min 和 max 参数。配置格式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要验证的字段的字段名 -->
<field name = "date">
<field-validators type = "date">
<!-- 时间的最小值 -->
<param name = "min">1900-01-01</param>
<!-- 时间的最大值 -->
<param name = "max">9999-01-01</param>
<!-- 错误提示信息 -->
<message>时间必须在1900-01-01至9999-01-01之间</message>
</field-validators>
</field>
</validators>
(5) 邮件地址校验器
该校验器的名称是 email ,该校验器要求字段的字符如果非空,就必须是合法的邮件地址。格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<validators>
<!-- 需要验证的字段的字段名 -->
<field name = "email">
<field-validators type = "email">
<!-- 错误提示信息 -->
<message>邮箱地址无效</message>
</field-validators>
</field>
</validators>
(6) 网址校验器
该校验器的名称是 url , 该校验器要求字段的字符如果非空,就必须是合法的URL地址 。 格式 和 (5)邮箱校验器 类似。
(7) 字符穿长度校验器
该校验器的名称是 stringlength ,该校验器要求字段的字符长度必须在指定的范围之间 ,所以它有 minLength 和 maxLength 两个参数。它的个数如 (3)整数校验器 类似。
(8) 正则表达式校验器
该校验器的名称是 regex ,它检查被校验字段是否匹配一个正则表达式。
3、Struts 2 拦截器:
Struts 2 框架的绝大部分功能是通过拦截器来完成的,当FilterDispatcher拦截到用户请求后,大量拦截器将会对用户请求进行处理,然后调用用户自定义的Action 类中的方法来处理请求。
拦截器的配置:
在struts.xml文件中来定义的,使用<interceptor.../>元素,格式如下:
<interceptor name = "拦截器名" class = "拦截器实现的类">
<param name = "参数名">参数值</param>
</interceptor>
其中<param.../>可以省略,但在有的时候就需要为其传入拦截器参数。
有时候一个Action要配置不只一个拦截器,往往多个拦截器一起使用来进行过滤。这时候就要配置几个拦截器组成的拦截器栈。定义拦截器栈用
<interceptor-stack.../>,格式如下:
<interceptor-stack name = "拦截器栈名">
<interceptor-ref name = "拦截器一"></interceptor-ref>
<interceptor-ref name = "拦截器二"></interceptor-ref>
<interceptor-ref name = "拦截器三"></interceptor-ref>
</interceptor-stack>
注意:在配置拦截器栈时,用到的拦截器必须是已经存在的拦截器。拦截器栈也可以引用拦截器栈。
拦截器实现类:
Struts 2 提供了一些接口或类供程序员自定义拦截器。如:com.opensymphony.xwork2.interceptor.Interceptor 接口。该接口中有三个方法:
void init () :用于初始化资源。
String intercept (ActionInvocation invocation) :用于实现拦截的动作。
destroy () :用于销毁在init()方法中打开的资源。
一、 构建struts2框架的基本配置
1、 创建项目
2、 导入struts2的五个基本jar包: commons-logging-1.0.4.jar:日志包、freemarker-2.3.13.jar、ognl-2.6.11.jar、struts2-core-2.1.6.jar:核心包、xwork-2.1.2.jar:webWork的核心包,struts2也依赖于它、commons-fileupload-1.2.1.jar
3、 配置项目下的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
4、 在src目录下创建struts2的配置文件struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="struts2" extends="struts-default">
<action name="login" class="com.test.action.LoginAction">
<result name="success">/result.jsp</result>
</action>
</package>
</struts>
注:package里的extends与类的继承相似,struts-default是struts2里已经存在的包 action里的name与页面里表单里的action的值
5、 在com.test.action包下建相应的Action类
public class LoginAction extends ActionSupport {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@SuppressWarnings("unchecked")
public String execute() throws Exception {
if ("hello".equals(this.getUsername().trim())
&& "world".equals(this.getPassword().trim())) {
@SuppressWarnings("unused")
Map map=ActionContext.getContext().getSession();
map.put("user","valid");
return "success";
}
else{
this.addFieldError("username","username or password error");
return "failer";
}
}
public void validate() {
if (null == this.getUsername() || "".equals(this.getUsername().trim())) {
this.addFieldError("username", "username required");
}
if (null == this.getPassword() || "".equals(this.getPassword())) {
this.addFieldError("password", "password required");
}
}
}
注:继承ActionSupport类,实现Action类
二、 struts2类型转换
序:类型转换就是客户端用户输入的参数转化为服务器端java的对象,不管用户输入什么样的内容,到客户端都是以字符串的形式存在。
1、 某个Action类或类对象的属性需要类型转换,则要写一个.properties的属性文件,使其能找到完成类型转换的类,有两种方式:
第一种是局部属性文件,即在action包下创建,命名规则为action类名-conversion.properties,在属性文件里是以key与value对形式存在,key是struts2要转换的属性名,value是转换这个属性的类。当用户要转换多个属性里可以换行加多个
第二种是全局属性文件,即在src根目录下创建一个名为xwork-conversion.properties的属性文件(名字不可以更改),在里面写配置信息。形式是:要转换类的路径=作为转换器的类路径
2、 创建类型转换的类
转换类继承StrutsTypeConverter类,分别实现它里是面的convertToString(Map context, Object o)与convertFromString(Map context, String[] values, Class toClass)两个抽象方法,代码如下:
public class PointConverter2 extends StrutsTypeConverter {
public Object convertFromString(Map context, String[] values, Class toClass) {
Point point = new Point();
String[] paramValues = values[0].split(",");
int x = Integer.parseInt(paramValues[0]);
int y = Integer.parseInt(paramValues[1]);
point.setX(x);
point.setY(y);
return point;
}
public String convertToString(Map context, Object o) {
Point point = (Point) o;
int x = point.getX();
int y = point.getY();
String result = " [ x= " + x + ", y=" + y + "]";
return result;
}
}
三、 struts2校验
序:输入校验是验证用户输入的信息是否合法是否有效。输入校验是建立在类型转换的基础之上的。若验证有错则显示提示信息。输入校验的流程是:首先,类型转换,然后校验,若都没错则执行execute()方法,,若出错,则跳转到”input”指向的页面。假若类型转换不成功也要进行校验。
1、类型转换,如果类型转换失败系统有默认的错误提示信息,改变这种系统的错误提示信息有两种,就是有创建全局或局部的属性文件,首先全局的是在classes目录下写属性文件message.properties,内容是xwork.default.invalid.fieldvalue={0} error的键值对,在struts.xml中的配置是<constant name="struts.custom.i18n.resources" value="message"></constant>,其次局部的是在action包下创建“Action类名.properties”属性文件,内容格式:invalid.fieldvalue.属性名=要现实的信息。
2、校验,struts2提供的多种校验方式:
⑴是在action中重写validate()方法,在其内对各个参数进行校验,校验代码如下:
public void validate() {
if (null == username || username.length() < 6 || username.length() > 10) {
this.addActionError("username invalid");
}
if (null == password || password.length() < 6 || password.length() > 10) {
this.addActionError("password invalid");
} else if (null == repassword || repassword.length() < 6
|| repassword.length() > 10) {
this.addActionError("repassword invalid");
} else if (!password.equals(repassword)) {
this.addActionError("two password not the same");
}
if (age < 1 || age > 130) {
this
.addActionError("\u8f93\u5165\u5e74\u9f84\u5e94\u8be5\u57280\u5c81\u5230120\u5c81\u4e4b\u95f4");
}
if(null==birthday){
this.addActionError("birthday invalid");
}
if(null==graduation){
this.addActionError("graduation invalid");
}
if (null != birthday && null != graduation) {
Calendar c1 = Calendar.getInstance();
c1.setTime(birthday);
Calendar c2 = Calendar.getInstance();
c2.setTime(graduation);
if (!c1.before(c2)) {
this.addActionError("birthday should before graduation");
}
}
注:错误提示信息由action级别的,也有field级别的,field级别的,应在
<s:fielderror cssStyle="color:red" />标签内显示,action只需改field为action即可。可以用多种方式添加错误提示信息,可以在validate()方法中加入this.addActionError("password invalid");或this.addFieldError("password", "password invalid");以增加错误提示信息。
⑵是最常用的xml校验方式,即在action包下创建名称为“Action类名-validation.xml”文件,系统运行是会自动寻找该文件进行校验,其格式参照第三章。这是对整个类的全局校验方式,如果action类中有多个校验方法,则用文件名为”Action类名-方法名-validation.xml”的校验文件对action类的某个方法进行校验。Xml内容格式与全局是一样的。
⑶还以用js在客户端进行验证,使用方法是在struts2标签form中加入onsubmit=”return validate();”,待验证的每个struts标签中都加入一个唯一标志id,通过id获得提交的属性值。具体使用方法参照第三章。
四、 struts2校验框架
对上述校验的细化,可相对第四章。
五、 拦截器
1、创建拦截器类(这是一个验证用户是否登录的实例):
public class AuthInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
Map map = invocation.getInvocationContext().getSession();//得到execute()中保存在session中的值
if (map.get("user") == null) {
return Action.LOGIN;//若为空则返回登录页面,需在struts.xml中配置
} else {
return invocation.invoke();//若成功则到达指定页面
}
}
}
注:session在action类(execute方法)中已经写入,即
@SuppressWarnings("unused")
Map map=ActionContext.getContext().getSession();
map.put("user","valid");
2、 配置struts.xml
Struts.xml中配置拦截器:
<interceptor name="auth" class="com.test.interceptor.AuthInterceptor">
</interceptor>
//应用拦截器:
<interceptor-ref name="auth"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
若验证用户没登录则跳转到登录页面,在struts.xml中配置全局action:
<global-results>
<result name="login" type="redirect">/login2.jsp</result>
</global-results>
注:注意一定要加入<interceptor-ref name="defaultStack"></interceptor-ref>默认拦截器栈,否则出错。
六、 文件上传下载
A 上传
1、 导入两个jar包:commons-io-1.3.2.jar和commons-fileupload-1.2.1.jar
2、 文件上传jsp页面:
表单代码:
<s:form action="upload" theme="simple" enctype="multipart/form-data"
method="post">
<table align="center" border="1" width="50%">
<tr>
<td>
file
</td>
<td id="more">
<s:file name="file"></s:file>
<input type="button" value="Add More.." onclick="addMore()">
</td>
</tr>
<tr>
<td>
<s:submit value="submit"></s:submit>
</td>
<td>
<s:reset value="reset"></s:reset>
</td>
</tr>
</table>
</s:form>
js代码:
<script type="text/javascript">
function addMore(){
var td=document.getElementById("more");
var br=document.createElement("br");
var input=document.createElement("input");
var button=document.createElement("input");
input.type="file";
input.name="file";
button.type="button";
button.value="Remove";
button.onclick =function(){
td.removeChild(br);
td.removeChild(input);
td.removeChild(button);
}
td.appendChild(br);
td.appendChild(input);
td.appendChild(button);
}
</script>
3、 上传文件的Action类核心代码:
public class UploadAction extends ActionSupport {
private List<File> file;//上传多个文件用集合泛型
private List<String> fileFileName;//文件名
private List<String> fileContentType;//文件类型
public List<File> getFile() {
return file;
}
public void setFile(List<File> file) {
this.file = file;
}
public List<String> getFileFileName() {
return fileFileName;
}
public void setFileFileName(List<String> fileFileName) {
this.fileFileName = fileFileName;
}
public List<String> getFileContentType() {
return fileContentType;
}
public void setFileContentType(List<String> fileContentType) {
this.fileContentType = fileContentType;
}
@Override
public String execute() throws Exception {
for (int i = 0; i < file.size(); i++) {
InputStream is = new FileInputStream(file.get(i));
// String root = ServletActionContext.getRequest().getRealPath(
// "/upload");
// String path="D://";
String
path=this.getClass().getResource("/").getPath();//得到d:/tomcat/webapps/工程名WEB-INF/classes/路径
path=path.substring(1,
path.indexOf("WEB-INF/classes"));//从路径字符串中取出工程路劲
path=path+"/upload";
File destFile = new File(path, this.getFileFileName().get(i));//在目的路径下医院文件名创建文件
OutputStream os = new FileOutputStream(destFile);
byte[] buffer = new byte[400];
int length = 0;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);//写入硬盘
}
is.close();
os.close();
}
return SUCCESS;
}
}
4、 struts.xml文件上传配置
<action name="upload" class="com.test.action.UploadAction">
<result name="success">/uploadResult.jsp</result>
<result name="input">/upload.jsp</result>
<interceptor-ref name="fileUpload">
<param name="maximumSize">4096000</param>
<param name="allowedTypes">application/vnd.ms-powerpoint</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
5、 上传结果显示页面
username:<s:property value="username"/><br>
password:<s:property value="password"/><br>
file:<s:property value="fileFileName"/>
B 下载
1、超链接jsp下载页面
<s:a href="download.action">download</s:a>
2、下载核心代码action类
public class DownloadAction extends ActionSupport {
public InputStream getDownloadFile(){
return ServletActionContext.getServletContext().getResourceAsStream("/upload/struts.ppt");
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
3、 struts.xml配置
<action name="download" class="com.test.action.DownloadAction">
<result name="success" type="stream">
<param name="contentType">application/vnd.ms-powerpoint</param>
<param name="contentDisposition">filename="struts.ppt"</param>
<param name="inputName">downloadFile</param>
</result>
</action>
七、 struts2国际化
详细请参照第七章
Struts2的处理流程如下:
1.用户请求对Web应用执行某个动作后,Web浏览器将要求某些资源的请求发送到Web服务器。
2.服务器小程序过滤器调度程序接到请求后,分析请求,然后确定调用相应的动作,提供资源。
3.在Action被执行之前,经配置后把一些常见功能(如验证、工作流或者文件上传)作用到请求上的一组拦截器上,可自动作用到该请求上。
4.Action类的一个新实例被创建,然后执行动作方法,用于把信息存储到数据库,或从数据库获取信息。
5.结果显示输出——无论输出的是HTML、图像、PDF还是其他某种格式。
6.然后,请求按照相反顺序通过拦截器传送。返回的请求允许执行其他的处理或者清理操作。
7.最后,容器把输出发送到浏览器。
Struts2与Struts相比的的特点
1.struts2所用到的技术就是webwork的技术,它所用到的表达式语言是ognl语言,这是种非常强大的对象导航语言。(ognl-2.6.11.jar)
2: struts2中不使用actionform管理表单,在struts2中用的action,整合了strtus中的action和actionform
3.在struts2中是通过标签来对表单和实体bean进行管理的,在struts2中提供了一套标签非常灵活。
构建Struts2应用的步骤:
1. 将所需Struts2的 jar包拷贝到WEB工程的/WEB-INF/lib目录下。
2. 配置web.xml文件,增加Struts2的映射。web.xml文件配置如下:
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- <filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml中定义了一个struts2的FilterDispathcer(拦截器:Struts2 技术的核心)的filter, FilterDispatcher用来初始化struts2并且处理所有的Web请求。
3. 编写Action类,DAO,bean类,整合Hibernate,Spring框架。
Struts.xml中的配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!--设置编码方式,通常设置为中文编码-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="globalMessages"/>
<!-- 上传文件大小 -->
<constant name="struts.multipart.maxSize" value="5242880" />
<!—避免Team工作时系统资源的争夺 -->
<include file="struts-example.xml"/>
<include file="struts-login.xml"/>
...
<include file="struts-personal.xml"/>
<package name="default" extends="struts-default">
<interceptors>
<interceptor class="com.cumt.web.filter.LoginInterceptor" name="loginInterceptor" />
<interceptor-stack name="CheckLogin">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="loginInterceptor" />
</interceptor-stack>
</interceptors>
<!-- 这里放全局的 -->
<global-results>
<result name="login">/loginError.jsp</result>
<result name="error">/error.jsp</result>
<result name="index" type="redirect">Index.action</result>
<result name="addLeader" type="redirect">/public/addLeader.jsp</result>
<result name="addDepartment"
...
</global-results>
<action name="Index" >
<result name="success">/main.jsp</result>
<interceptor-ref name="CheckLogin" />
</action>
</package>
</struts>
Struts-login.xml中的配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="login" namespace="" extends="default">
<action name="Login*" method="{1}" class="LoginAction">
<result name="input">/login.jsp</result>
<result type="redirectAction">Index</result>
</action>
</package>
</struts>
4. Struts2的类型转换,输入校验,核心拦截器,国际化,标签库以及对Spring,Hibernate,JSF的整合以后有时间还会做一个总结,大家可以参看这样一本书:
最后给大家推荐本书三扬科技编著,电子工业出版社出版:《开发者突击:Struts2核心技术与JavaEE框架整合开发实战》
一、struts1
Bean需要继承ActionForm,Struts1会给你封装form,而且需要配置到struts1的配置文件中。<form-beans></form-beans>,还需要在action中引用,<action name=”usr”> 继承DispatchAction可以自己编写自己的方法,在配置文件中加个paramter,可指定方法名的字段
步骤:
1. 导包
2. 配置web.xml,配置ActionServlet,设置初始化参数config value=struts-config.xml
3. 编写实现了Action的类
4. 编写继承Action的类。重写其方法或自己写方法。编写domain,需继承ActionForm
5. 配置struts-config.xml
a) 配置bean
b) 配置action
多方法请求,继承DispatcherAction,此类在strut1的扩展包中.
二、struts2
Struts2的request
Struts2会将属性信息放到值栈 中去。而且页面中获取的request对象已经经过struts2包装。类似与在Tomcat中,访问的jsp页面取出的request是被tomcat包装过。Struts2的实现是经过struts2的核心过滤器后,重新包装了它的request
Struts2不是把Action的属性放在request中,而是直接把自己的Action放进去,然后在自己get
1、通过属性驱动来封装对象
2.2.3可以把未初始化的对象自动初始化。
2、通过模型驱动
在Action中实现ModelDriver接口,重写getMode方法,先初始化接收的对象
3、可获得原生的ServletAPI
1.通过ServletActionContext.getRequest()/ getSession()
2.可通过注入方式获取,需实现ServletRequestAware/ServletSessionAware
4、非IOC方式,实现RequestAware,实现的方法返回map
可通过ActionContext.getContext().getParameters()
Result结果类型
plantText注意IE必须设置头
redirect 参数可以由${name}取出 默认从request中取<param name=”xxx” > ${xx}</parma>
,而#{session.xx}是获取非根对象
Redirect与redirectAction的区别:
redirectAction继承redirect参数不一样
redirectAction:参数
actionName
namespace
supressEmptyParamters控制空参数
dispatch:必须是一个JSP或html资源
chain:必须转发到一个action资源,共享属性值
参数:actionName :
namespace : /xxx
异常的处理。
<exception-mapping />
Struts2的类型转换
自动转换
COS上传下载(见徐文海文件上传下载)
Struts2自带上传
1. 声明一个File类型的成员变量,需要与字段名相同img
2. 必须实现保存功能.在execute中利用FileUtils.copyFile
3. 必须要再实现另一个变量来转梦保存文件名 imgFileName
4. 必须再实现一个变量来获得文件类型 imgContentType
Struts2的get方式乱码解决方式:
写过滤器,重写request的getPramaterMap();
多文件上传: 都是数组类型也可以使List
1. 声明文件 File[] file;
fileFileName
fileContextType
文件下载
Result类型stream
参数
inputName 作为action的属性
contentType image/jpeg
contentDisposition attachment/filename=”xx.pdf”
contentSize 缓冲大小
拦截器
一、步骤
1. 书写实现Interceptor接口的类
2. 实现interceptor方法,返回值
3. 配置文件中配置
4. 配置哪个action拦截
<Interceptors> Minterceptor name=”fist” class=””>
b) 在Action配置中使用拦截器
5. 获取session
ActionContext.getContext().getSession()
Invocation.getInvocationContext().getSession();
二、配置了拦截器的影响:默认拦截器失效将会失效(例如:参数获取不到)
影响的解决:引用系统的拦截器。如果需要上传,则引用系统的上传拦截器,等等。
三、 配置默认拦截器:即使不引用也可以执行的拦截器。配置default-interceptor-ref 会对本包的action起作用。
四、 配置拦截器栈:可包含多个拦截器。
<interceptors>
<interceptor name=”first” class=”” />
<interceptor-stack name=”complex”>
<interceptor-ref name=”first” />
<interceptor-ref name=”defaultStack” />”
</interceptor>
</interceptors>
Interceptor 的实现方法
Public String interceptor(ActionInvocation invo) {
}
五、 拦截器栈会创建一次拦截器的默认构造,另外每配置的action都会创建一次,如果把拦截器放在栈中,则只会创建一次。
六、拦截方法的拦截器: MethodFilterInterceptor
·使用param标签设置excludeMethods过滤排除某方法不拦截
includeMethods谁配置谁起作用,includeMethods优先
Struts2的标签,OGNL表达式
1.OGNL以某个对象作为根
2.%不是脚本的变为脚本 ,类似js的eval
<s:url value=”%{#request.url}” />
3.$表示 用在xml
4. @调用静态的方法,默认为java.lang.Math配合 struts.ognl.allowStaticMethodAccess 为true
5.#号
1.用于其他范围内的取,
2.声明Map或List。{{‘a’,’b’,c}},#{‘a’:’AAA’,’b’:’BBB’}
3.投影过滤{#{’name’:’wj’,’age’:40},#{’name’:’other’,’age’:99}} #a1.{?this.age>90}
^#第一个 $#最后一个
标签
Uri=”/struts-tags”
<s:property value=”xxxx” /> àJSTL 里的<c:out/>
<s:a action=”xxx” />
<s:iterator value=”xxx” var==”x” /> à <c:forEach />
<s:action name=”xx.action”/>包含action资源
struts2处理json
1、布置JSON插件
2、继承json-default包
3、修改result 的Type=json
4、使用注解@JSON(NAME=”XXX”)改名,@JSON(serialized=fasle)不输出
注意循环调用
使用JsonConfig jc = new JsonConfig();
Js.setExcludes(new String[]{“addr”,”addr.user”});
JsonObect o = JsonObject.from(u,jc);
自定义类型转换器
两种方式:局部和全局,局部为某个Action
1. 继承父类的opensym. DefaultTypeConvertor
可双向转换
2. 配置
a). 局部的
需在Action所在的包中放置XXXAction-convertion.properties,然后配置文件 这个Action的属性birthday=DateTypeConverter.,这样就转换好了
b). 全局类型转换器
将上述的properties放在classpath根下,更名为xwork-conversion.propertis.
将上面的字段换成需转换的类型如java.util.Date
输入校验
方式:
1. 手工编写方式
XML配置方式
校验内容:
Action所有方法
Action中某个方法
步骤:
1. 继承ActionSuppor类
2. 重写validate方法
3. 在方法在判断如果不符合,使用addFieldError方法输出信息(对所有方法进行验证),此操作会往fieldErrors集合中添加错误信息,如果集合中包含错误信息,会请求转发input的result
4. 第3步的输出可在input的转发页面上使用struts2的标签输出<s:fielderror/>
5. 如果想对某个方法进行校验,可以修改第三步的validate为validateXxx方法,其他的步骤一样。
XML验证:
1. 继承ActionSupport类
2. 新建XXXAction-validation.xml,放在action所在的包
3. 配置xml, <validators><field name=”username>
<field-validator type=”requiredstring”>//必须 的,是校验器
<param name=”trim”>true</parrm>
<message>用户名不能为空</message>
</field-validator>
</field>
/validators>
4. 校验器是在struts的包中,校验器:
Regex expiress <![CDATA[^1[358]\d{9}$]]>
requiredstring trim必填
required不能为null
stringlength maxLength/minLength 符合长度
int 整型 min max
double 双精度浮点 min max
fieldexpression OGNL表达示
url网址
date min max
conversion 类型转换校验器
visitor 校验复合属性
expression OGNL
5. 对Action的方法校验:ActionClassName-ActionName-validation.xml
验证的流程:
1. 获得参数,进行类型转换,封装到Action的属性中去。
2. 在类型转换期间如果发生异常,则把异常信息保存到ActionContext中,conversionError拦截器会把它添加到fieldErrors里,不管类型转换是否成功,都会进入下一步。
3. 系统通过反射调用action中的validateXxx方法。
4. 再调用action中的validate方法
5. 如果fieldErrors中有值,则进入input视图,否则执行action中的视图
Struts2使用OGNL进行类型转换。提供基本和常用对象的转换器。
Struts2使用“ValueStack”技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。
temp:#ActionContext储存了整个访问周期中的request,session,application
1、FilterDispatcher的处理流程
1、处理HttpServletRequest,如果思上传的请求,对request进行包装
2、查找该请求路径是否有对应的Action,有的话把该路径包装成一个ActionMapping对象
#ActionMapping对象中含有name,method,namespace,params,result等属性(holds the action mapping information)
3、交给Dispatcher类的serviceAction(request, response,servletContext,mapping)方法处理
2、Dispatcher类的处理过程
1、分别实例化几个储存request,session,application的信息的Map对象
3、Struts2中的拦截器
DispatcherFilter拦截器
ActionAutowiringInterceptor拦截器
ParametersInterceptor拦截器
ServletConfigInterceptor拦截器
4、几个辅助接口
SessionAware-通过Map来提供对所有session属性的访问
ServletRequestAware-提供对HttpServletRequest对象的访问
RequestAware-通过Map来提供对所有request属性的访问
ApplicationAware-通过Map来提供对所有application属性的访问
ServletResponseAware-提供对HttpServletREsponse对象的访问
ParameterAware-通过Map来提供所有request String和表单数据的访问
PrincipalAware-提供对PrincipleProxy对象的访问;该对象实现了HttpServletRequest对象的有关pringcile和role的方法,但是它提供了一个 Proxy,因此所有的实现都是独立于Action的。
ServletContextAware-提供对ServletContext对象的访问
5、struts2的扩展自定义拦截器
自定义拦截器实现Interceptor接口或者继承AbstractInterceptor
ActionInvocation对象可以用来访问运行时环境,以及Action本身;上下文(包括了Web应用的请求参数,session参数,用户Local等);Action 的执行结果;还有那些调用Action的方法并判断Action是否已被调用。
6、缩小Action的配置文件的牛X配置
前提:struts.enable.SlashesInActionNames = true;
URL模式:/{module}/{entity}/{action}.action
配置文件:
<action name="*/*/*" method="{3}" class="com.infoq.action.{1}.{2}action">
<result name="view">/{1}/update{2}/jsp</result>
<result name="list">/{1}/list{2}.jsp</result>
</action>
使用超强通配符
1,struts2的form表单里面和url里面的传值以及Action所继承的父类都可以自动set属性注入action中,及继承的action中。
2,凡是url和form表单传值,在action方法中,取值都要用到request.getParameter(),才能取得到值。用request取值,主要是看list1.action?where=0&hhString=t'还是list1.jsp?where=0&hhString=t'。就在jsp和action中这个页面用request可以取到值。action方法最终是找到action对应的类,所以在对应的类及继承类都可以取到页面传过来的参数方法的传值通过方法里面设置request,setAttribute()方法参数来传到页面上去。
3,怎么从页面获取action类中的值?
方法一:
使用OGNL表达式。你可以使用struts自带的标签,他们都支持OGNL,比如s:property,该标签对ognl栈里面所有的值都可以相应的获取到,不只是值栈里面的东西
<s:property value="value.name"/>:它会自动调用getValue().getName()方法。
方法二:
当然是使用JSP本身的性质了。通过request和session来获取值。获取request有四种方法:使用Struts2 Aware拦截器,使用RequestAware拦截器,使用ActionContext类,使用ServletActionContext类。在action中通过request和session。setAttribute()方法,页面get就行了。
总结:
在访问action的时候,struts2的那个核心过滤器会产生action的环境, 然后把action压入ognl根对象ValueStack的栈顶,即struts2自动会帮我们把Action中的属性及对象及继承对象保存在request.setAttribute()中,不只是action中的属性,比如我们Action中list查询的集合对象,我们可以自己设置,才能取得到值。也可以把他保存在Action中的成员变量中(没有就新建一个)。而在jsp中我们都要先设置,
<s:property value="hhString"/>
<%=request.getAttribute("hhString")%
${requestScope.listCategorys}
而<s:property>在检索属性的时候, 是从栈顶往下逐一扫描, 以扫描到的第一个属性为准(这里说的属性是javaBean的属性,而非private字段).! 所以可以经过action而跳转到的jsp页面上是可以直接访问到action的属性的!
4,,Action每次调用一次就实例化一次。里面有bean对象类型的,也会自动new对象,有继承的也会自动new,自动set值,在jsp页面取值时就用对象.属性。但是要用struts2标签,不然没有用,用html标签不支持,除非在value中加个s:property
<input type="hidden" name="val" value="<s:property value='where1'/>"/>
action中的属性在页面取值就直接是属性。
<s:property value="name"/>
5,页面的自动注入值,可以都不用struts2标签,直接用html和name属性对的就行了
6,action实现Action只是为了execute方法的正确,和扩展的其他的方法的引用,可以不实现也可以成功,但是struts2推荐实现该接口,实现了会有更多的方便方法提供。
7,<action name="save">
<result>/index.jsp</result>
</action>
如果没有对action指定class,默认是ActionSupport,没有指定method默认就是exetute方法,没有指定result的name属性,默认是success;
没有配置type默认是forword请请转发
8,listCategorys作为成员变量是保存在值栈中的,故可以直接去,而我们收到设置的request,attr,parameters(在隐藏域传值和url传值时),session,application等五个
的值是保存在content map中的,取值用#request.设置的值,相当于<%=requst.getAttribute()%>,struts2标签是基于<%=%>基本的jsp页面取值的.
9,OGNL//值栈和context Map谁的范围大?ognl上下文不存在谁大谁小。只是ActionContext,valueCotext两个里面都放了对象。
先看下流程:form中的action-->web.xml(过滤请求)-->struts.xml文件(找到对应的Action类,有时交给spring处理目的都一样,iocnew出对象)--》
-->new 出Action对象(把该对象放在context map中,只是这个对象很特殊,故放在值栈中,值栈中的对象可以直接引用,放在其他context map中的对象则要加#,
就是值栈不是context map中的一部分,都可以用#(有request范围字段)取到值),-->当new Action对象的时候对Action里面的成员变量(属性)进行初始化,set值属性是对象,再new对象,
再在bean中set初始化,如果页面什么都不输入,还是会new对象,会做这一步,只是取值的时候为null。
10,Action创建的对象及子对象都放在值栈中,注意Map对象的renquest,session等
Action的对象字段只有在需要的时候,才会初始化。没用到不会new。
当struts2接受到.action的请求后,会创建Action对象,在调用方法前??把Action类的属性放到valueStack的顶层节点。
值栈(根)对象也可以通过EL表达式取到值。${}.
OGNL表达式需要配合struts2标签才能使用,否则没用。
$用于i18n和struts配置文件获取传值,#用于获取ActionContext的值就是对象(#后面肯定有request,session等再.值)。%将原来的文本串解析为ognl,取出值栈中的对象,对于本来就是的无效,MAP中的key解析为value
也就是%都可以随便加的
不是传过来的值,request就不要用parameter方法
11,//OGNL context包括值栈和context map上下文。当struts2接受一个请求是,会迅速创建ActionContext(Map类型),valueCotext(List类型)和action对象,
获取action中scope(request等)对象
四种方法:1Map request = ActionContext。getContext().get(“request”);(Map request实际是存在request中的)2,实现RequestAware接口,提供set,get方法,让容器给我们ioc注值
3,HttpServletRequest request = ServletActionContext.getRequest();.getSession()4,实现ServletRequestAware接口,让日期ioc注值
12,值栈中的值可以在struts.xml文件中用${}取值出来。
type表示里面的action方法,可以和上一个共享action共享一个context Map上下文。和默认的轻轻转发有啥区别?
用重定向redirect则要在result结果中?附加参数,附加参数如果是中文会乱码,EL表达式失效,要用param.username形式。forword也是可以共享同一值栈的。
13传值:只有两种方法一种是url一种是form提交,执行完之后要到另外一个页面的时候要设置是请请转发还是重定向。
url是在jsp或者action方法后面加参数或者param。一种是form提交()隐藏域,或者action注入值即文本域里面的值注入到Action中。
struts2标签不能嵌套使用
1:<s:a href="model_JobHistory.action?mid=<s:property value="#job[1]"/>&jobid=<s:propertyvalue="#job[0]"/>">出错?strus2本身标签也不能嵌套。2。我把<s:a> 修改为 html<a></a>就可以了、
可改为:1用url标签
<s:url id="idUrl" action="model_JobHistory">
<s:param name="mid" value="%{#job[1]}"></s:param>
<s:param name="jobid" value="%{#job[0]}"></s:param>
</s:url>
<s:a……
这种值传不过去
<s:a href="listBusy.kemp">
<s:param name="where" value="where"/>
<s:param name="currentPage" value="currentPage"/>
<s:param name="pagerMethod" value="'last'"/>
尾页</s:a>
:2: <s:a href="lookArticle.action?article.id=%{#us.id}" onclick="browsNum(%{#us.id})" >
这两种都是url传值,可以相互替换。就是传多个参数的时候用第二种不方便
相当于jsp的<a href="save.jsp?user=<%=user%>&where=<%=where%>">
struts2不支持s:标签嵌套el表达式,
valueStack里面的值用的ognl表大式,只在struts2标签里面有效,struts2标签的value不接受任何的<%%>,或者el表达式。
Struts 2支持以下几种表达式语言:
1. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言
2. JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;
3. Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;
4. Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。
Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
1. 支持对象方法调用,如xxx.doSomeSpecial();
2. 支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')或@tutorial.MyConstant@APP_NAME;
3. 支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;
4. 访问OGNL上下文(OGNL context)和ActionContext;
5. 操作集合对象。
OGNL的用法
OGNL是通常要结合Struts 2的标志一起使用,如<s:property value="xx" />等。大家经常遇到的问题是#、%和$这三个符号的使用。下面我想通过例子讲述这个问题:
首先新建名为Struts2_OGNL的Web工程,配置开发环境。之前很多朋友在使用Struts 2的过程中都遇到乱码问题。当然乱码问题由来已久,而且涉及多方面的知识,所以并非三言两语可以说明白,而且互联网上也已经有很多这方便的文章,大家可以Google一下。不过,如果你在开发的过程,多注意一下,避免乱码问题也不难。乱码多数是由于编码与解码所使用的方式不同造成的,所以我建议大家将编码方式都设为“utf-8”,如<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>。另外,在配置web.xml时使用ActionContextCleanUp过滤器(Filter),如下面代码所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts 2 OGNL</display-name>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ActionContextCleanUp
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
清单1 WebContent/WEB-INF/web.xml
“#”主要有三种用途:
1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:
名称
作用
例子
parameters
包含当前HTTP请求参数的Map
#parameters.id[0]作用相当于request.getParameter("id")
request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName相当于request.getAttribute("userName")
session
包含当前HttpSession的属性(attribute)的Map
#session.userName相当于session.getAttribute("userName")
application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName相当于application.getAttribute("userName")
attr
用于按request > session > application顺序访问其属性(attribute)
#attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止
2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100};
3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
下面让我们它们的具体写法,首先是Action类代码:
package tutorial.action;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;
import tutorial.model.Book;
import com.opensymphony.xwork2.ActionSupport;
public class OgnlAction extends ActionSupport implements ServletRequestAware, SessionAware, ServletContextAware {
private static final long serialVersionUID = 1L;
private HttpServletRequest request;
private Map<String, String> session;
private ServletContext application;
private List<Book> books;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@SuppressWarnings("unchecked")
public void setSession(Map session) {
this.session = session;
}
public void setServletContext(ServletContext application) {
this.application = application;
}
public List<Book> getBooks() {
return books;
}
@Override
public String execute() {
request.setAttribute("userName", "Max From request");
session.put("userName", "Max From session");
application.setAttribute("userName", "Max From application");
books = new LinkedList<Book>();
books.add(new Book("978-0735619678", "Code Complete, Second Edition", 32.99));
books.add(new Book("978-0596007867", "The Art of Project Management", 35.96));
books.add(new Book("978-0201633610", "Design Patterns: Elements of Reusable Object-Oriented Software", 43.19));
books.add(new Book("978-0596527341", "Information Architecture for the World Wide Web: Designing Large-Scale Web Sites", 25.19));
books.add(new Book("978-0735605350", "Software Estimation: Demystifying the Black Art", 25.19));
return SUCCESS;
}
}
清单2 src/tutorial/action/OgnlAction.java
以上代码分别在request、session和application的范围内添加“userName”属性,然后再在JSP页面使用OGNL将其取回。我还创建了Book对象的列表用于演示“用于过滤和投影(projecting)集合”的功能,至于Book的代码大家可以在我前一文章《在Struts 2中实现CRUD》看到。
下面是Ognl.jsp的代码,内容如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts OGNL Demo</title>
</head>
<body>
<h3>访问OGNL上下文和Action上下文</h3>
<p>parameters: <s:property value="#parameters.userName" /></p>
<p>request.userName: <s:property value="#request.userName" /></p>
<p>session.userName: <s:property value="#session.userName" /></p>
<p>application.userName: <s:property value="#application.userName" /></p>
<p>attr.userName: <s:property value="#attr.userName" /></p>
<hr />
<h3>用于过滤和投影(projecting)集合</h3>
<p>Books more than $35</p>
<ul>
<s:iterator value="books.{?#this.price > 35}">
<li><s:property value="title" /> - $<s:property value="price" /></li>
</s:iterator>
</ul>
<p>The price of "Code Complete, Second Edition" is: <s:property value="books.{?#this.title=='Code Complete, Second Edition'}.{price}[0]"/></p>
<hr />
<h3>构造Map</h3>
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
<p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
</body>
</html>
清单3 WebContent/Ognl.jsp
以上代码值得注意的是“<s:property value="books.{?#this.title=='Code Complete, Second Edition'}.{price}[0]"/>”,因为“books.{?#this.title=='Code Complete, Second Edition'}.{price}”返回的值是集合类型,所以要用“[索引]”来访问其值。
最后是Struts 2的配置文件struts.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="Struts2_OGNL_DEMO" extends="struts-default">
<action name="Ognl" class="tutorial.action.OgnlAction">
<result>/Ognl.jsp</result>
</action>
</package>
</struts>
清单4 src/struts.xml
发布运行应用程序,结果如下所示:
清单5 示例运行结果1
“%”符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:
<hr />
<h3>%的用途</h3>
<p><s:url value="#foobar['foo1']" /></p>
<p><s:url value="%{#foobar['foo1']}" /></p>
清单6 演示%用途的代码片段
刷新页面,结果如下所示:
清单7 示例运行结果2
“$”有两个主要的用途
1. 用于在国际化资源文件中,引用OGNL表达式,例子请参考《在Struts 2.0中国际化(i18n)您的应用程序》
2. 在Struts 2配置文件中,引用OGNL表达式,如
<action name="AddPhoto" class="addPhoto">
<interceptor-ref name="fileUploadStack" />
<result type="redirect">ListPhotos.action?albumId=${albumId}</result>
</action>
清单8 演示$用途的代码片段
总结
OGNL是一种功能很大的表达式语言,熟悉它可以使我们的开发变得更快捷。
相关推荐
struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全struts2 总结工程大全...
本总结将深入探讨Struts2的核心概念、关键功能和实用技术,以帮助开发者全面理解并熟练运用这一框架。 一、Servlet模板 在Struts2中,Servlet模板是一种处理请求和响应的方式。它通过拦截器链对请求进行处理,然后...
在本项目总结中,我们将深入探讨Struts2的核心特性、工作原理以及如何在实际项目中应用。 一、Struts2框架基础 1. 动态方法调用(Dynamic Method Invocation,DMI):Struts2允许通过URL直接调用Action类的方法,...
【Velocity语法以及整合struts2总结】 Velocity是一个开源的Java模板引擎,它是Apache软件基金会的Jakarta项目的一部分。Velocity将HTML代码与业务逻辑分离,使得开发者可以专注于内容和设计,而不用关心数据如何...
【JSP到Struts2总结】 JSP(Java Server Pages)是基于Java技术的一种服务器端网页编程技术,用于创建跨平台、跨Web服务器的动态网页。JSP网页由HTML、JavaScript、Java程序片段(scriplet)和JSP标记(tag)组成。...
struts2 总结入门学习文档 教你如何白手起家搭建Struts2开发环境、编写第一个struts2应用helloworld、属性介绍、接口、拦截器介绍、struts2标签等。93页
根据提供的文件信息,我们可以整理出关于Struts2框架的一些关键知识点。尽管原文中的信息较为零散且不完整,但还是可以从中提炼出一些有价值的内容。接下来,我们将详细探讨这些知识点。 ### Struts2简介 Struts2...
Struts2是一个强大的MVC(Model-View-Controller)框架,是Java EE应用程序开发中的重要组成部分。它在Struts1.x的基础上进行了大量的改进和优化,提供了更高效、更灵活的架构设计,使得开发者能够更容易地构建和...
本笔记将全面总结Struts2的核心概念、主要功能以及实际开发中的应用。 一、Struts2概述 Struts2是Apache软件基金会下的一个开源项目,它继承了Struts1的优点并解决了其存在的问题,如性能和灵活性。Struts2的核心是...
Struts2是一个强大的MVC框架,它提供了许多功能来简化Web应用开发,包括类型转换、属性访问、文件上传以及拦截器等。以下是基于标题和描述的详细知识点: **一、局部类型转换** 在Struts2中,我们可以自定义类型...
Struts2,servlet模板,反射、xml解析、过滤器,IoC方式