1.使用<include>标签重用配置文件
在Struts2中提供了一个默认的struts.xml文件,但如果package、action、interceptors等配置比较多时,都放到一个struts.xml文件不太容易维护。
因此,就需要将struts.xml文件分成多个配置文件,然后在struts.xml文件中使用<include>标签引用这些配置文件。这样做的优点如下:
a. 结构更清晰,更容易维护配置信息。
b. 配置文件可以复用。
如果在多个Web程序中都使用类似或相同的配置文件,那么可以使用<include>标签来引用这些配置文件,这样可以减少工作量。
假设有一个配置文件,文件名为newstruts.xml,代码如下:
- <?xmlversion="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>
- <packagename="demo"extends="struts-default">
- <actionname="submit"class="action.MoreSubmitAction">
- <resultname="save">
- /result.jsp
- </result>
- <resultname="print">
- /result.jsp
- </result>
- </action>
- </package>
- </struts>
<?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文件的代码如下:
- <?xmlversion="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>
- <includefile="newstruts.xml"/>
- <packagename="test"extends="struts-default">
- </package>
- </struts>
<?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文件中完成。
- <?xmlversion="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方法。-->
- <constantname="struts.i18n.encoding"value="UTF-8"/>
- <!--该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发, 但在产品发布阶段应将该属性设置为false。 -->
- <constantname="struts.i18n.reload"value="false"/>
- <!--该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。 -->
- <constantname="struts.custom.i18n.resources"value="applicationResource"/>
- <!--该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。-->
- <constantname="struts.action.extension"value="action, do"/>
- <!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭。-->
- <constantname="struts.serve.static.browserCache "value="true"/>
- <!--当struts 2的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开。-->
- <constantname="struts.configuration.xml.reload"value="false"/>
- <!--该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。
- 该属性的默认值为struts- default.xml,struts-plugin.xml, struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。 -->
- <constantname="struts.configuration.files"value="struts-default.xml,struts-plugin.xml,struts.xml"/>
- <!--指定加载struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration,开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。 -->
- <constantname="struts.configuration"value="org.apache.struts2.config.DefaultConfiguration"/>
- <!--含有Actions的完整连续的package名称。 -->
- <constantname="struts.continuations.package"value=""/>
- <!-- 应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。
- 该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。 -->
- <constantname="struts.devMode"value="true"/>
- <!--该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。-->
- <constantname="struts.enable.DynamicMethodInvocation"value="false"/>
- <!--该属性指定视图标签默认的视图主题,该属性的默认值是xhtml,可以为simple,xhtml或ajax。 -->
- <constantname="struts.ui.theme"value="xhtml"/>
- <packagename="test"extends="struts-default">
- </package>
- </struts>
<?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必须放在一个指定的包空间下定义 -->
- <packagename="default"extends="struts-default">
- <!-- 定义处理请求URL为login.action的Action -->
- <actionname="login"class="org.qiujy.web.struts2.action.LoginAction">
- <!-- 定义处理结果字符串和资源之间的映射关系 -->
- <resultname="success">/success.jsp</result>
- <resultname="error">/error.jsp</result>
- </action>
- </package>
- <packagename="my"extends="struts-default"namespace="/manage">
- <!-- 定义处理请求URL为login.action的Action -->
- <actionname="backLogin"class="org.qiujy.web.struts2.action.LoginAction">
- <!-- 定义处理结果字符串和资源之间的映射关系 -->
- <resultname="success">/success.jsp</result>
- <resultname="error">/error.jsp</result>
- </action>
- </package>
- </struts>
<!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方法指定要指行的动作类的方法名,并且需要为不同的动作起不同的名子(也称为别名)。如下面代码所示:
- <?xmlversion="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>
- <packagename="demo"extends="struts-default">
- <actionname="test"class="action.MyAction">
- </action>
- <actionname="my"class="action.MyAction"method="my">
- </action>
- </package>
- </struts>
<?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方法,代码如下:
- <preclass="java"name="code">package action;
- import com.opensymphony.xwork2.ActionSupport;
- public class MyAction extends ActionSupport
- {
- public String execute() throws Exception
- {
- // 处理test动作的代码
- }
- public String my() throws Exception
- {
- // 处理my动作的代码
- }
- }</pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- package action;
- import com.opensymphony.xwork2.ActionSupport;
- publicclass MyAction extends ActionSupport
- {
- public String execute() throws Exception
- {
- // 处理test动作的代码
- }
- public String my() throws Exception
- {
- // 处理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>
<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>标签指定任意多个参数。代码如下:
- <actionname="submit"class="action.MyAction">
- <paramname="param1">value1</param>
- <paramname="param2">value2</param>
- <resultname="save">
- /result.jsp
- </result>
- </action><spanstyle='font-family: "Microsoft YaHei"; background-color: rgb(255, 255, 255);'></span>
<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;
- publicclass MyAction extends ActionSupport
- {
- private String param1;
- private String param2;
- public String execute() throws Exception
- {
- System.out.println(param1 + param2);
- }
- publicvoid setParam1(String param1)
- {
- this.param1 = param1;
- }
- publicvoid setParam2(String param2)
- {
- this.param2 = 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都在里面定义了。代码如下:
- <resultname="save"type="redirect">/result.jsp</result>
<result name="save" type="redirect">/result.jsp</result>
- <result-types>
- <!--用来处理Action链, 处理的结果值为下一个转向的action-->
- <result-typename="chain"
- class="com.opensymphony.xwork2.ActionChainResult"/>
- <!--用来转向页面,通常处理JSP,默认是dispatcher-->
- <result-typename="dispatcher"
- class="org.apache.struts2.dispatcher.ServletDispatcherResult"
- default="true"/>
- <!--处理FreeMarker模板-->
- <result-typename="freemarker"
- class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
- <!--用来控制特殊的Http行为-->
- <result-typename="httpheader"
- class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
- <!--重定向到一个URL-->
- <result-typename="redirect"
- class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
- <!--重定向到一个Action-->
- <result-typename="redirectAction"
- class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
- <!--向浏览器发送InputSream对象,通常用来处理文件下载-->
- <result-typename="stream"
- class="org.apache.struts2.dispatcher.StreamResult"/>
- <!--处理Velocity模板-->
- <result-typename="velocity"
- class="org.apache.struts2.dispatcher.VelocityResult"/>
- <!--处理XML/XLST模板-->
- <result-typename="xslt"
- class="org.apache.struts2.views.xslt.XSLTResult"/>
- <!--显示原始文件内容,例如文件源代码-->
- <result-typename="plainText"
- class="org.apache.struts2.dispatcher.PlainTextResult"/>
- </result-types>
<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>
- <packagename="demo"extends="struts-default">
- <global-results>
- <resultname="print">/result.jsp</result>
- <resultname="input">/error.jsp</result>
- </global-results>
- <actionname="submit"class="action.MoreSubmitAction">
- </action>
- <actionname="my"class="action.MoreSubmitAction"method="my">
- </action>
- </package>
- </struts>
<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;
- }
- }
- }
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)定义拦截器,拦截器栈:
- <packagename="my"extends="struts-default"namespace="/manage">
- <interceptors>
- <!-- 定义拦截器 -->
- <interceptorname="拦截器名"class="拦截器实现类"/>
- <!-- 定义拦截器栈 -->
- <interceptor-stackname="拦截器栈名">
- <interceptor-refname="拦截器一"/>
- <interceptor-refname="拦截器二"/>
- </interceptor-stack>
- </interceptors>
- ......
- </package>
<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)使用拦截器:
- <palign="left"><spanstyle="color: teal;"></span></p><preclass="html"name="code"><palign="left"><spanstyle="color: teal;"></span></p><preclass="html"name="code"><!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <packagename="my"extends="struts-default">
- <interceptors>
- <!-- 定义权限控制拦截器 -->
- <interceptorname="authority"class="org.qiujy.common.AuthorizationInterceptor"/>
- </interceptors>
- <!-- 定义全局处理结果 -->
- <global-results>
- <!-- 逻辑名为login的结果,映射到/login.jsp页面 -->
- <resultname="login">/login.jsp</result>
- </global-results>
- <actionname="listall"class="org.qiujy.web.struts2.action.UserAction" method="listAllUser">
- <resultname="success">/listall.jsp</result>
- <!-- 使用拦截器 -->
- <interceptor-refname="defaultStack"/>
- <interceptor-refname="authority"/>
- </action>
- </package>
- </struts></pre><br>
- <p><spanstyle="color: teal;"></span></p>
- <pre></pre>
- <pre></pre>
- <p><spanstyle="background-color: rgb(255, 255, 255);"><spanstyle="font-family: Microsoft YaHei; font-size: 12px;"><spanstyle="line-height: 19px;"></span></span></span></p>
- <pre></pre>
- <div></div>
- <div></div>
- </pre>
- <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
<!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用 -->
<include file="struts-default.xml"></include>
<!-- package提供了将多个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
-->
<package name="com.kay.struts2" extends="struts-default" namespace="/test">
<interceptors>
<!-- 定义拦截器
name:拦截器名称
class:拦截器类路径
-->
<interceptor name="timer" class="com.kay.timer"></interceptor>
<interceptor name="logger" class="com.kay.logger"></interceptor>
<!-- 定义拦截器栈 -->
<interceptor-stack name="mystack">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器 每个Action都会自动引用
如果Action中引用了其它的拦截器 默认的拦截器将无效 -->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!-- 全局results配置 -->
<global-results>
<result name="input">/error.jsp</result>
</global-results>
<!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
name:action名称
class: 对应的类的路径
method: 调用Action中的方法名
-->
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!-- 引用拦截器
name:拦截器名称或拦截器栈名称
-->
<interceptor-ref name="timer"></interceptor-ref>
<!-- 节点配置
name : result名称 和Action中返回的值相同
type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!-- 参数设置
name:对应Action中的get/set方法
-->
<param name="url">http://www.sina.com</param>
</action>
</package>
</struts> -
从struts2.1开始,struts2不再推荐使用Codebehind作为零配置插件,而是改为使用Convention插件来支持零配置,和Codebehind相比,Convention插件更彻底,该插件完全抛弃配置信息,不仅不需要是使用struts.xml文件进行配置,甚至不需要使用Annotation进行配置,而是由struts2根据约定自动配置。零配置并不是没有配置,而是通过约定大于配置的方式,大量通过约定来调度页面的跳转而使得配置大大减少。所以,首先应该了解下convention-plugin的约定:
- <spanstyle="font-family: Microsoft YaHei;"><!--设置Convention插件定位视图资源的根路径,默认为/WEB-INFO/content -->
- <constantname="struts.convention.result.path"value="/WEB-INF/content/"/>
- <!--如果设置为false,则可以将视图页面放置Action对应的目录(无需放入WEB-INFO/content) -->
- <constantname="struts.convention.result.flatLayout"value="true"/>
- <!--Convention搜索Action类的类名后缀,默认为Action -->
- <constantname="struts.convention.action.suffix"value="Action"/>
- <!--是否禁止通过包扫描Action,默认是false -->
- <constantname="struts.convention.action.disableScanning"value="false"/>
- <!--设置即使没有@Action注释,是否依然创建Action映射。默认值为false -->Create action mappings, even if no @Action is found
- <constantname="struts.convention.action.mapAllMatches"value="false"/>
- <!--设置是否所有实现com.opensymphony.xwork2.Action的Action都创建Action映射,默认是true -->
- <constantname="struts.convention.action.checkImplementsAction"value="true"/>
- <!--设置Convention映射的Action所在包的默认父包。默认值是convention-default -->
- <constantname="struts.convention.default.parent.package"value="convention-default"/>
- <!--设置映射Action时,是否将Action的name属性值转换为所有字母小写,默认值是true -->
- <constantname="struts.convention.action.name.lowercase"value="true"/>
- <!--设置映射Action时指定name属性值各单词之间的分隔符。默认值为中画线(“-”) -->
- <constantname="struts.convention.action.name.separator"value="-"/>
- <!--默认包路径包含action,actions,struts,struts2的所有包都会被struts作为含有Action类的路径来搜索 -->
- <constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
- <!--指定禁止从Action的根包里搜索Action。默认值为false -->
- <constantname="struts.convention.package.locators.disable"value="false"/>
- <!--如果指定了该常量,Convention只会以该常量值开始的包中搜索Action类 -->
- <constantname="struts.convention.package.locators.basePackage"value=""/>
- <!--指定排除在搜索Action之外的包。默认值为org.hibernate.* ... -->
- <constantname="struts.convention.exclude.packages"value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
- <!--指定Convention映射的Result时默认支持的结果类型。默认值为dispatcher,velocity,freemarker -->
- <constantname="struts.convention.relative.result.types"value="dispatcher,velocity,freemarker"/>
- <!--设置是否重定向到斜线(/)。例如用户请求/foo,但/foo不存在时,如果设置该常量为可重定向到/foo/。默认值是true -->
- <constantname="struts.convention.redirect.to.slash"value="true"/></span>
<!--设置Convention插件定位视图资源的根路径,默认为/WEB-INFO/content --> <constant name="struts.convention.result.path" value="/WEB-INF/content/"/> <!--如果设置为false,则可以将视图页面放置Action对应的目录(无需放入WEB-INFO/content) --> <constant name="struts.convention.result.flatLayout" value="true"/> <!--Convention搜索Action类的类名后缀,默认为Action --> <constant name="struts.convention.action.suffix" value="Action"/> <!--是否禁止通过包扫描Action,默认是false --> <constant name="struts.convention.action.disableScanning" value="false"/> <!--设置即使没有@Action注释,是否依然创建Action映射。默认值为false -->Create action mappings, even if no @Action is found <constant name="struts.convention.action.mapAllMatches" value="false"/> <!--设置是否所有实现com.opensymphony.xwork2.Action的Action都创建Action映射,默认是true --> <constant name="struts.convention.action.checkImplementsAction" value="true"/> <!--设置Convention映射的Action所在包的默认父包。默认值是convention-default --> <constant name="struts.convention.default.parent.package" value="convention-default"/> <!--设置映射Action时,是否将Action的name属性值转换为所有字母小写,默认值是true --> <constant name="struts.convention.action.name.lowercase" value="true"/> <!--设置映射Action时指定name属性值各单词之间的分隔符。默认值为中画线(“-”) --> <constant name="struts.convention.action.name.separator" value="-"/> <!--默认包路径包含action,actions,struts,struts2的所有包都会被struts作为含有Action类的路径来搜索 --> <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/> <!--指定禁止从Action的根包里搜索Action。默认值为false --> <constant name="struts.convention.package.locators.disable" value="false"/> <!--如果指定了该常量,Convention只会以该常量值开始的包中搜索Action类 --> <constant name="struts.convention.package.locators.basePackage" value=""/> <!--指定排除在搜索Action之外的包。默认值为org.hibernate.* ... --> <constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/> <!--指定Convention映射的Result时默认支持的结果类型。默认值为dispatcher,velocity,freemarker --> <constant name="struts.convention.relative.result.types" value="dispatcher,velocity,freemarker"/> <!--设置是否重定向到斜线(/)。例如用户请求/foo,但/foo不存在时,如果设置该常量为可重定向到/foo/。默认值是true --> <constant name="struts.convention.redirect.to.slash" value="true"/>
下面开始了解一下Convention如何使用
1.将struts-Convention-plugin-2.1.6.jar文件复制到WEB-INF/lib路径下
2. struts-Convention-plugin如何扫描我们的Action类的呢
1)对于Convention插件而言,它会自动搜索位于action,actions,struts,struts2包下的所有java类,对于所有实现了com.opensymphony.xwork2.Action的java类以及所有类名以Action结尾的java类都会当成Action类来处理。
- <spanstyle="font-family: Microsoft YaHei;"><constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
- 可以通过设置struts.convention.package.locators属性来修改这个配置。如:
- <constantname="struts.convention.package.locators"value="web,action"/></span>
<constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/> 可以通过设置struts.convention.package.locators属性来修改这个配置。如: <constant name="struts.convention.package.locators" value="web,action" />
则定义了在项目中,包路径包含web和action的将被视为Action存在的路径来进行搜索。
Com.ustb.web.* 或者 com.ustb.action.*都将被视为含有Action的包路径而被搜索。
2)struts.Convention.exclude.packges::指定不扫描哪些包下的java类,位于这些包结构下的java类将不会自动映射成Action;
3) struts.convention.action.packages:Convention插件以该常量指定包作为根包来搜索Action类。Convention插件除了扫描action,actions,struts,struts2四个包的类以外,还会扫描该常量指定的一个或多个包,Convention会试图从中发现Action类。4) struts.convention.package.locators.basePackag: 扫描的基包,也即是,只有这个包的子包才被Struts2 Convention Plugin扫描。
4.映射Action的name时,遵循如下两步规则:
1)如果该Action类名包含Action后缀,将该Action类名的Action后缀去掉。否则不做任何处理。
2)将Action类名的驼峰写法(每个单词首字母大写、其他字母小写的写法)转成中画线写法(所有字母小写,单词与单词之间以中画线隔开)
如:LoginAction映射的Acion的name属性为login,GetBooks映射的Action的name的属性为get-books,AddEmployeeAction映射的Action的name属性为add-employee5. Convention如何确定URL的具体资源
1)默认情况下,Convention总会到WEB应用的WEB-INF/content路径下定位物理资源,定位资源的约定是:actionRUL+resultCODE+suffix。当某个逻辑视图找不到对应的试图资源时,Convention会自动视图使用ActionURL+suffix作为物理视图资源。
如:actions.fore.LoginAction 返回success字符串时,Convention优先考虑使用WEB-INF/content/fore目录下的login-success.jsp作为视图资源。如果找不到该文件,login.jsp也可作为对应的试图资源。如果返回input字符串,Convention会将WEB-INF/content/fore里面查找login-input.jsp
2) 去掉类名的Action部分,然后将将每个分部的首字母转为小写,用’-’分割。
如:UserAction->user UserDetailAction ->user-detail。结合上面的。对于com.ustb.web.user.detail.UserDetailAction,映射的 url就是/WEB-INF/content/user/detail/user-detail.jsp3)struts支持.jsp .html .htm .vm格式的文件。下面是actiong和结果模版的映射关系:
URL Result File that could match Result Type /hello success /WEB-INF/content/hello.jsp Dispatcher /hello success /WEB-INF/content/hello-success.htm Dispatcher /hello success /WEB-INF/content/hello.ftl FreeMarker /hello-world input /WEB-INF/content/hello-world-input.vm Velocity /test1/test2/hello error /WEB-INF/content/test/test2/hello-error.html Dispatcher 当然,简单的通过默认的方式来进行配置不能完全满足实际项目的需要。所幸,convention的零配置是非常灵活的。
通过@Action注释
对如下例子:- package com.example.web;
- import com.opensymphony.xwork2.Action;
- import com.opensymphony.xwork2.ActionSupport;
- publicclass HelloAction extends ActionSupport {
- @Action("action1")
- public String method1() {
- return SUCCESS;
- }
- @Action("/user/action2")
- public String method2() {
- return SUCCESS;
- }
- }
方法名 默认调用路径 默认映射路径 method1 /hello!method1.action . /WEB-INF/content/hello.jsp method2 /hello!method2.action. /WEB-INF/content/hello.jsp 通过@Action注释后
方法名 @Action注释后调用路径 @Action注释 后映射路径 method1 /action1!method1.action. /WEB-INF/content/action1.jsp method1 /user/action2!method2.action /WEB-INF/content/user/action2.jsp
通过@Actions注释- package com.example.web;
- import com.opensymphony.xwork2.ActionSupport;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- publicclass HelloAction extends ActionSupport {
- @Actions({
- @Action("/different/url"),
- @Action("/another/url")
- })
- public String method1() {
- return “error”;
- }
我们可以通过:/different/url!method1.action 或 /another/url!method1.action 来调用method1 方法。
对应的映射路径分别是/WEB-INF/content/different/url-error.jsp; /WEB-INF/content/another/url-error.jsp
可能误导了大家,一个方法被@Action注释后,只是多了一种调用方式,而不是说覆盖了原来的调用方式。比如对于如下例子:- package com.example.web;
- import com.opensymphony.xwork2.ActionSupport;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- publicclass HelloAction extends ActionSupport {
- @Action("/another/url")
- public String method1() {
- return “error”;
- }
我们调用method1方法可以通过两种方式:
1 /hello!method1.action 映射 url:/WEB-INF/content/hello-error.jsp
2 /another/url!method1.action 映射 url:/WEB-INF/content/another/url-error.jsp
可见,两种方式均可对method1方法进行调用,唯一的区别就是,两种调用的映射是不一样的,所以,想跳转到不同的界面,这是一个非常好的选择。
通过@Namespace 注释- package com.example.web;
- import com.opensymphony.xwork2.ActionSupport;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- @Namespace("/other")
- publicclass HelloWorld extends ActionSupport {
- public String method1() {
- return “error”;
- }
- @Action("url")
- public String method2() {
- return “error”;
- }
- @Action("/different/url")
- public String method3() {
- return “error”;
- }
- }
通过 /other/hello-world!method1.action 访问method1 方法。
通过 /other/url!method2.action 访问method2 方法
通过 /different /url!method3.action 访问method3 方法
与@Action 注释不同的是,该注释覆盖了默认的namespace(这里是’/’),此时再用hello!method1.action 已经不能访问method1 了.
@Results和@Result
1 全局的(global)。
全局results可以被action类中所有的action分享,这种results在action类上使用注解进行声明。- package com.example.actions;
- import com.opensymphony.xwork2.ActionSupport;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- import org.apache.struts2.convention.annotation.Result;
- import org.apache.struts2.convention.annotation.Results;
- @Results({
- @Result(name="failure", location="/WEB-INF/fail.jsp")
- })
- publicclass HelloWorld extends ActionSupport {
- public String method1() {
- return “failure”;
- }
- @Action("/different/url")
- public String method2() {
- return “failure”;
- }
- }
当我们访问 /hello -world !method1.action 时,返回 /WEB-INF/fail.jsp
当我们访问 /hello -world !method2.action 时,返回 /WEB-INF/fail.jsp
当我们访问 /different/url!method2.action 时,返回 /WEB-INF/fail.jsp
2 本地的(local)。
本地results只能在action方法上进行声明。- package com.example.actions;
- import com.opensymphony.xwork2.ActionSupport;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- import org.apache.struts2.convention.annotation.Result;
- import org.apache.struts2.convention.annotation.Results;
- publicclass HelloWorld extends ActionSupport {
- @Action(value="/other/bar",results={@Result(name = "error", location = "www.baidu.com",type="redirect")})
- public String method1() {
- return “error”;
- }
- }