xmlns="
xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="
struts2
--org.apache.struts2.dispatcher.FilterDispatcher
-->
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
说明:
注释掉的部分为以前2.1.4版本中用的核心filter类。
StrutsPrepareAndExecuteFilter类的init方法将会读取类路径下默认的配置文件struts.xml,并以javabean形式存放在内存中,以后struts2对用户的每次请求将使用内存中数据,而不是重读struts.xml文件。
步骤六、发布测试。
简要分析执行流程:
当输入.../login.jsp访问jsp页面填写完相关信息并提交给login.action时,它会首先被在web.xml中配置的过滤器监听到,过滤器会去查找strust.xml文件,并结合namespace查找名为login的action,查找到此action便交给其处理,LoginAction内部会执行execute方法,并返回结果result(result也是参照的struts.xml中action下的result配置)。
关于表单传参,主要是参照的action中的方法名,而非属性名。
7.开启struts2自带的开发模式常量
在以前的开发中,当修改一些配置时总是不能及时地更新到服务器,我们总会重新部署或重启来更新改变的内容,在struts2中可以通过一个常量来达到此目的。
即在struts.xml中的元素下增加如下内容:
这样配置后,当配置文件修改保存时就会及时更新到服务器中。
其它一些常量:
--指定WEB应用的编码集,相当于调用HttpServletRequest.setCharacterEncodint方法,如果使用了velocity或freemarker,它也用于指定输出的编码格式-->
--指定请求后缀为.action,指定多个请求后缀用逗号分隔-->
--设置浏览器是否缓存静态内容,建议:
开发阶段关闭,运行时开启-->
--当struts.xml配置文件修改后,系统是否重新加载该文件,开发阶段打开此功能-->
--开发提示:
出错时打印更详细的信息-->
--指定请求的后缀可以是.do或.action-->
注意:
在struts2.1.6版本中存在一个bug:
即配置了struts.i18n.encoding常量也不能解决中文乱码问题,原因是此版本在获取请求参数后才调用了setCharacterEncoding()方法进行编码设置。
解决此bug的方法是配置一个filter,并在doFilter方法中增加如下代码:
request.setCharacterEncoding(“UTF-8”);在以后的2.1.8版本中解决了此问题及2.1.6中存在的其它bug,建议新项目使用2.1.8版本。
8.vo传参模式
Copy上面的myStruts2项目,改名为myStruts2Vo项目。
作如下修改:
在LoginAction中有两个字段:
username,password。
把此两个属性重构到com.asm.vo.User类中,然后在LoginAction中提供User对象及相应的get/set方法。
现在需要注意的是在login.jsp中会有如下的修改:
户名:
密码:
关键就是改掉name属性值。
其它基本无变动。
后话:
假如此此User对象并不能和Model层的相应对象完全对应,我们还应借助此User对象在Action中构建出Model层的相应对象,这样,在exectue方法中便能通过构建的Model对象作为参数与Model层交互。
9.ModerDriven传参模式
Copy上面的myStruts2Vo项目,改名为myStruts2Model项目。
重点是修改LoginAction,修改后的主要内容如下:
packagecom.asm;
importcom.asm.vo.User;
importcom.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ModelDriven;
publicclassLoginActionimplementsAction,ModelDriven{
privateUseruser=newUser();
publicStringexecute()throwsException{
if(user.getUsername().equals("struts2")){
return"loginSuccess";
}else{
return"loginFailure";
}
}
publicUsergetModel(){
returnuser;
}
}
说明:
它实现了ModelDriven接口,并使用了泛性机制(必须),因此要求jdk1.5以上。
现在需要注意的是在login.jsp中name属性值为User中两个字段,和第一个实例一样。
说明:
此方式一般不会使用,在此略作了解。
10.为什么要使用struts2代替struts1.x
(1)struts2的execute方法中的参数不会依赖于servletAPI,实现了也servlet解耦,是一种无侵入式的设计。
(2)struts2提供了拦截器,利用拦截器可以进行AOP编程,实现权限拦截等功能。
(3)struts2提供了类型转换器,我们可以很容易地对请求参数转换成需要的类型。
(4)提供了同种表现层技术支持,如JSP、freeMarker、velocity等
(5)可以对指定的方法进行校验,可以轻松地实现表单校验功能
(6)提供了全局范围、包范围和action范围的国际化资源文件管理实现。
二、struts.xml配置及例程
1.配置文件的优先级
在struts2中一些配置(比如常量)可以同时在struts-default.xml(只读性),strtus-plguin.xml(只读性),struts.xml,struts.properties和web.xml文件中配置,它们的优先级逐步升高,即是说后面的配置会覆盖掉前面相同的配置。
2.配置形式
下面以对struts.i18n.encoding=UTF-8的配置为例进行说明:
在struts.xml配置形式如下:
在struts.properties的配置形式如下:
struts.i18n.encoding=UTF-8
在web.xml中配置如下:
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts.i18n.encoding
UTF-8
说明:
官方声称配置了此常量可以解决中文乱码问题,但实事上并不能达到目的,在前面的三个项目中,如果我们在表单中输入中文,其结果是会出现乱码。
解决此问题参看[一.7的注意]。
这是struts2.1.6中的一bug,它的下一版2.1.8已解决此问题。
3.package配置相关
属性名
是否必须
说明
Name
是
Package的唯一标识,不允许同名
Extends
否
指定要继承的包
Namespace
否
指定名称空间
Abstract
否
声明包为抽象否
下面我们建立struts2package项目来进行package相关测试:
说明:
在上面的配置文件中所用到的Test1Action和Test2Action这两个Action都只是继承了com.opensymphony.xwork2.ActionSupport类,而ActionSupport默认返回的就是“success”,所以当点击上面的链接分别转到了forward目录下的test1.jsp和test2.jsp。
下面重点来看这个package元素的namespace属性及action的name属性,它们共同定义了action所映射到的实质文件。
上图展示了链接地址和action的对应关系,所以当我们要想访问一个action所关联到的jsp文件时,应该用namespace+action的name关于它的内容测试可以参考struts2package项目。
补充:
通常情况下,action元素的name是属性值是不能出现“/”的,所以希望通过action中name属性来实现多级映射,需要在sturts.xml中增加如下属性:
这样配置后就可以再action的name元素中使用“/”了。
比如:
/forward/test3.jsp
然后输入/test3/test3.action">test3
链接地址就可以访问了
强调:
namespace默认值“”,即不配置namespace属性。
它的意思是:
如果action不能进行完整路径匹配,则会来此namespace下进行匹配,比如:
.../test/test/test.action,如果参照namespace及action的name不能找到也之完全对应的action,它会再到依次追溯到上级目录中查找,即是说它会以…/test/test.action这样的路径来对应namespace和action的name进行查找。
如果返回到最终的目录仍找不到,它就会到namespace="/"对应的包下查找名为test的action,如果仍找不到,它就会去默认的namespace下查找名为test的action,如果找到则执行此action。
另外,namespace也可以配置成namespace="/"。
它代表配置为项目的根。
总结action的名称探索顺序:
完全对应、逐步追溯到上级目录查找、"/"下查找、默认namespace下查找。
为什么要提出namespace,主要是避免多人共同开发项目出现名字冲突。
如果不使用namespace,多个人所写的action中可能出现重名的现象,这样当项目合并时就会出现冲突。
而有了namespace可以在项目开发时由项目经理给每一个人分不同的namespace,这样每个开发人员只需要保证自己所写的action不同名即可。
namespace引发的链接问题:
当我们为action配置了namespace时,访问此action的形式总会是如下形式:
.../webappname/xxx/yyy/ActionName.action而当此action成功执行跳转到某个jsp页面时,如想在此jsp页面写链接,一定要写绝对路径,因为相对路径是相对.../webappname/xxx/yyy/,而如果以后我们修改了action的namespace时,相对路径又要变,所以链接不能写成相对路径。
以下介绍绝对路径的写法:
通常用myeclip