看了很多关于struts.xml常用配置的文章,都大同小异,但感觉都不是很全,下面选一篇不错的文章补充一下。
1.使用<include>标签重用配置文件
在Struts2中提供了一个默认的struts.xml文件,但如果package、action、interceptors等配置比较多时,都放到一个struts.xml文件不太容易维护。
因此,就需要将struts.xml文件分成多个配置文件,然后在struts.xml文件中使用<include>标签引用这些配置文件。这样做的优点如下:
a. 结构更清晰,更容易维护配置信息。
b. 配置文件可以复用。
如果在多个Web程序中都使用类似或相同的配置文件,那么可以使用<include>标签来引用这些配置文件,这样可以减少工作量。
假设有一个配置文件,文件名为newstruts.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="demo" extends="struts-default" >
<action name="submit" class="action.MoreSubmitAction">
<result name="save" >
/result.jsp
</result>
<result name="print">
/result.jsp
</result>
</action>
</package>
</struts>
则struts.xml引用newstruts.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>
<include file="newstruts.xml"/>
<package name="test" extends="struts-default">
</package>
</struts>
大家要注意一下,用<include>引用的xml文件也必须是完成的struts2的配置。实际上<include>在引用时是单独解析的xml文件,而不是将被引用的文件插入到struts.xml文件中。
2.常量配置
通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成。
<?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>
<!--指定Web应用的默认编码集,相当于调用 HttpServletRequest的setCharacterEncoding方法。-->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!--该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发, 但在产品发布阶段应将该属性设置为false。 -->
<constant name="struts.i18n.reload" value="false"/>
<!--该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。 -->
<constant name="struts.custom.i18n.resources" value="applicationResource"/>
<!--该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。-->
<constant name="struts.action.extension" value="action, do" />
<!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭。-->
<constant name="struts.serve.static.browserCache " value="true" />
<!--当struts 2的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开。-->
<constant name="struts.configuration.xml.reload" value="false" />
<!--该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。
该属性的默认值为struts- default.xml,struts-plugin.xml, struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。 -->
<constant name="struts.configuration.files" value="struts-default.xml,struts-plugin.xml,struts.xml"/>
<!--指定加载struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration,开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。 -->
<constant name="struts.configuration" value="org.apache.struts2.config.DefaultConfiguration"/>
<!--含有Actions的完整连续的package名称。 -->
<constant name="struts.continuations.package" value=""/>
<!-- 应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。
该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。 -->
<constant name="struts.devMode" value="true" />
<!--该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。-->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<!--该属性指定视图标签默认的视图主题,该属性的默认值是xhtml,可以为simple,xhtml或ajax。 -->
<constant name="struts.ui.theme" value="xhtml"/>
<package name="test" extends="struts-default">
</package>
</struts>
这里只是列出一部分常用的,其他常量如果有需要可以查看官方文档。
3.包(Package)配置
Struts2框架中核心组件就是Action、拦截器等,Struts2框架使用包来管理Action和拦截器等。每个包就是多个Action、多个拦截器、多个拦截器引用的集合。
Package的名字必须是唯一的。 package可以扩展, 当一个package扩展自另一个package时该package会在本身配置的基础上加入扩展的package 的配置。 父package必须在子package前配置。
name:package名称extends: 继承的父package名称
abstract: 设置package的属性为抽象的 抽象的package不能定义action 值true:false
namespace: 定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
3.1 命名空间配置
考虑到同一个Web应用中需要同名的Action,Struts2以命名空间的方式来管理Action,同一个命名空间不能有同名的Action。
Struts2通过为包指定namespace属性来为包下面的所有Action指定共同的命名空间。
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- struts2的action必须放在一个指定的包空间下定义 -->
<package name="default" extends="struts-default">
<!-- 定义处理请求URL为login.action的Action -->
<action name="login" class="org.qiujy.web.struts2.action.LoginAction">
<!-- 定义处理结果字符串和资源之间的映射关系 -->
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
<package name="my" extends="struts-default" namespace="/manage">
<!-- 定义处理请求URL为login.action的Action -->
<action name="backLogin" class="org.qiujy.web.struts2.action.LoginAction">
<!-- 定义处理结果字符串和资源之间的映射关系 -->
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
如上配置了两个包:default和my,配置my包时指定了该包的命名空间为/manage。
对于包default:没有指定namespace属性。如果某个包没有指定namespace属性,即该包使用默认的命名空间,默认的命名空间总是""。它处理的URL为:
http://localhost:8080/userlogin_struts2/login.action
对于包my:指定了命名空间/manage,则该包下所有的Action处理的URL应该是“命名空间/Action名”。如上名为backLogin的Action,它处理的URL为:
http://localhost:8080/userlogin_struts2/manage/backLogin.action
3.2.Action配置
A. 在默认情况下,Struts2会调用动作类的execute方法。但有些时候,我们需要在一个动作类中处理不同的动作。也就是用户请求不同的动作时,执行动作类中的不同的方法。
为了达到这个目的,可以在<action>标签中通过method方法指定要指行的动作类的方法名,并且需要为不同的动作起不同的名子(也称为别名)。如下面代码所示:
<?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="demo" extends="struts-default" >
<action name="test" class="action.MyAction">
</action>
<action name="my" class="action.MyAction" method="my">
</action>
</package>
</struts>
上面代码的两个动作的class属性都指向同一个类,name为这个类起了两个动作别名:test和my。在动作my中,使用了method属性指定要要运行的方法名为my。
在MyAction类中必须要有my方法,代码如下:package action; import com.opensymphony.xwork2.ActionSupport; public class MyAction extends ActionSupport { public String execute() throws Exception { // 处理test动作的代码 } public String my() throws Exception { // 处理my动作的代码 } }
除了在struts.xml中配置别名,还可以通过请求参数来描述指定动作(并不需要在struts.xml中配置)。请求参数的格式如下:
http://localhost:8080/contextPath/actionName!method.action
比如请求MyAction的my方法URL为:http://localhost:8080/contextPath/my!my.action
(2) Action 通配符
假设有有配置如下:
<package name="actions" extends="struts-default" namespace="/actions">
<action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}">
<result>/Student{1}_success.jsp</result>
</action>
<action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}">
<result>/{1}_{2}_success.jsp</result>
<!-- {0}_success.jsp -->
</action>
</package>
{1}、{2}表示第一第二个占位符 , *为通配符
总结:使用通配符,将配置量降到最低。
<a href="<%=context %>/actions/Studentadd">添加学生</a> Result: /Studentadd_success.jsp
<a href="<%=context %>/actions/Studentdelete">删除学生</a>Result: /Studentdelete_success.jsp
不过,一定要遵守"约定优于配置"的原则。
<a href="<%=context %>/actions/Teacher_add">添加老师</a>Result: /Teacher_add_success.jsp
<a href="<%=context %>/actions/Teacher_delete">删除老师</a>Result: /Teacher_delete_success.jsp
<a href="<%=context %>/actions/Course_add">添加课程</a>Result: /Course_add_success.jsp
<a href="<%=context %>/actions/Course_delete">删除课程</a>Result: /Course_delete_success.jsp
通过action name的通配匹配,获得占位符,可以使用占位符放在result和method、class中替代匹配的字符。
(3)为action指定参数
在struts2中还可以为action指定一个或多个参数。大家还记着struts1.x是如何设置的action参数不?
在struts1.x中可以使用<action>标签的parameter属性为其指定一个action参数,如果要指定多个,就只能通过逗号(,)或其他的分隔符将不同的参数隔开。
而在struts2中可以通过<param>标签指定任意多个参数。代码如下:
<action name="submit" class="action.MyAction">
<param name="param1">value1</param>
<param name="param2">value2</param>
<result name="save" >
/result.jsp
</result>
</action>
当然,在action中读这些参数也非常简单,只需要象获取请求参数一样在action类中定义相应的setter方法即可(一般不用定义getter方法)。
如下面的代码将读取param1和param2参数的值:
package action;
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport
{
private String param1;
private String param2;
public String execute() throws Exception
{
System.out.println(param1 + param2);
}
public void setParam1(String param1)
{
this.param1 = param1;
}
public void setParam2(String param2)
{
this.param2 = param2;
}
}
当struts2在调用execute之前,param1和param2的值就已经是相应参数的值了,因此,在execute方法中可以直接使用param1和param2。
3.3 选择result类型
在默认时,<result>标签的type属性值是“dispatcher”(实际上就是转发,forward)。开发人员可以根据自己的需要指定不同的类型,如redirect、stream等。如下面代码所示:
这此result-type可以在struts2-core-2.0.11.1.jar包或struts2源代码中的struts-default.xml文件中找到,在这个文件中找到<result-types>标签,所有的result-type都在里面定义了。代码如下:
<result name="save" type="redirect">/result.jsp</result>
<result-types>
<!--用来处理Action链, 处理的结果值为下一个转向的action-->
<result-type name="chain"
class="com.opensymphony.xwork2.ActionChainResult"/>
<!--用来转向页面,通常处理JSP,默认是dispatcher-->
<result-type name="dispatcher"
class="org.apache.struts2.dispatcher.ServletDispatcherResult"
default="true"/>
<!--处理FreeMarker模板-->
<result-type name="freemarker"
class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<!--用来控制特殊的Http行为-->
<result-type name="httpheader"
class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<!--重定向到一个URL-->
<result-type name="redirect"
class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<!--重定向到一个Action-->
<result-type name="redirectAction"
class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<!--向浏览器发送InputSream对象,通常用来处理文件下载-->
<result-type name="stream"
class="org.apache.struts2.dispatcher.StreamResult"/>
<!--处理Velocity模板-->
<result-type name="velocity"
class="org.apache.struts2.dispatcher.VelocityResult"/>
<!--处理XML/XLST模板-->
<result-type name="xslt"
class="org.apache.struts2.views.xslt.XSLTResult"/>
<!--显示原始文件内容,例如文件源代码-->
<result-type name="plainText"
class="org.apache.struts2.dispatcher.PlainTextResult" />
</result-types>
3.4全局results
有很多时候一个<result>初很多<action>使用,这时可以使用<global-results>标签来定义全局的<result>,代码如下:
<struts>
<package name="demo" extends="struts-default">
<global-results>
<result name="print">/result.jsp</result>
<result name="input">/error.jsp</result>
</global-results>
<action name="submit" class="action.MoreSubmitAction">
</action>
<action name="my" class="action.MoreSubmitAction" method="my">
</action>
</package>
</struts>
如果<action>中没有相应的<result>,Struts2就会使用全局的<result>。
3.5.拦截器配置
Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
(1)实现拦截器类
假设当浏览者需要请求执行某个操作时,应用需要先检查浏览者是否登录,以及是否有足够的权限来执行该操作,拦截器类如下:
package org.qiujy.common;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* 权限检查拦截器
*
* @author qiujy
* @version 1.0
*/
public class AuthorizationInterceptor extends AbstractInterceptor {
/*
* 拦截Action处理的拦截方法
*
*/
public String intercept(ActionInvocation invocation) throws Exception {
Map session = invocation.getInvocationContext().getSession();
String userName = (String) session.get("userName");
if (null != userName && userName.equals("test")) {
System.out.println("拦截器:合法用户登录---");
return invocation.invoke();
} else {
System.out.println("拦截器:用户未登录---");
return Action.LOGIN;
}
}
}
(2)定义拦截器,拦截器栈:
<package name="my" extends="struts-default" namespace="/manage">
<interceptors>
<!-- 定义拦截器 -->
<interceptor name="拦截器名" class="拦截器实现类"/>
<!-- 定义拦截器栈 -->
<interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器一"/>
<interceptor-ref name="拦截器二"/>
</interceptor-stack>
</interceptors>
......
</package>
(3)使用拦截器:
定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截Action了。拦截器的拦截行为将会在Action的exceute方法执行之前被执行:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="my" extends="struts-default">
<interceptors>
<!-- 定义权限控制拦截器 -->
<interceptor name="authority"class="org.qiujy.common.AuthorizationInterceptor"/>
</interceptors>
<!-- 定义全局处理结果 -->
<global-results>
<!-- 逻辑名为login的结果,映射到/login.jsp页面 -->
<result name="login">/login.jsp</result>
</global-results>
<action name="listall"class="org.qiujy.web.struts2.action.UserAction" method="listAllUser">
<result name="success">/listall.jsp</result>
<!-- 使用拦截器 -->
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="authority"/>
</action>
</package>
</struts>