目录
1.2.4 编写业务逻辑Action(LoginAction)
1 struts2入门程序
1.1 下载包
下载struts2的开发包http://struts.apache.org/
1.2 新建项目
1.2.1 新建项目并添加struts2依赖的jar文件
1.2.2 web.xml
在web.xml中配置struts2的核心过滤器(核心过滤器可以在struts2-core-2.5.10.1.jar中org.apache.struts2.dispatcher.filter找到)
1.2.3 struts.xml
在src下新建struts的配置文件,名称为struts.xml并添加dtd的引用(struts2-core-2.5.10.1.jar中struts-2.5.dtd找到)
1.2.4 编写业务逻辑Action(LoginAction)
import com.opensymphony.xwork2.Action;
public class LoginAction implements Action {
//获取表单元素的值:要求必须与表单元素一致
private String userName;
private String userPass;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
@Override
public String execute() throws Exception {
if("admin".equals(userName)&&"admin".equals(userPass)){
return "success";//逻辑名称
}
return "login";
}
}
1.2.5 编写页面login.jsp和index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>用户登录</title>
</head>
<body>
<form action="login.action" method="post">
USERNAME:<input type="text" name="userName"/><br>
PASSWORD:<input type="password" name="userPass"/><br>
<input type="submit" value="LOGIN"/>
</form>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
欢迎你,${userName}!
</body>
</html>
1.2.6 配置struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- package节点:包, struts-default为struts2默认定义的包 -->
<package name="demo1" extends="struts-default">
<!-- name的值应该与请求地址栏去掉.action相同,class的值为业务逻辑Action的全限定类名 -->
<action name="login" class="cn.zzsxt.action.LoginAction">
<!-- name为逻辑名称应该与action中方法的返回值相同,文本节点为需要跳转的物理路径 -->
<result name="success">/index.jsp</result>
<result name="login">/login.jsp</result>
</action>
</package>
</struts>
2 struts2中package详解
2.1 package内元素详解
<package>元素可以把逻辑上相关的一组Action、Result、Intercepter等元素封装起来,形成一个独立的模块,package可以继承其他的package,也可以作为父包被其他的package继承,比如<package name="helloworld" extends="struts-default">中,helloworld这个包就继承了struts-default这个包
2.1.1 package元素属性
package元素:将Action(应用控制器)在逻辑上进行隔离,完成包中功能上的继承
- name:包的名称。必须配置,就是通过name属性完成继承
- extends:要继承的包,后面配置的是被继承的包的名称,值必须为某个包的名字。可选
- namespace:包的命名空间,action请求url的前缀(url的构成部分)包在地址栏的反应
- abstract:定义包为抽象的,也就是不能包含Action的定义。可选,如果一个package是abstract=“true”,该package必须被继承,不能包含action节点
2.1.2 Action元素属性
Action元素:描述javabean(应用控制器,具体处理请求的javabean)
- name : 该javabean的请求路径
- class : javabean的完成限定名(通过反射创建javabean的对象)
- method : 指定的是处理本次请求的方法,如果method省略不写则默认执行方法是execute()方法
2.1.3 result元素属性
result元素 : Action执行完成后需要响应的结果
- name:需要响应的结果逻辑名称
- type:表示响应的结果的类型(ajax响应,通过的跳转响应)
请求转化:
dispatcher(默认值),只能跳转到jsp
chain:跳转到javabean(应用控制器)
重定向:
redirect : jsp
redirectAction : javabean
产生一个流对象:
stream : 通过流对象的方式给客户端做出响应点击此处了解文件上传下载使用到的stream
plainText:响应到客户单的内容为view的源码
2.1.4 param元素属性
param: 参数,给struts2系统中定义的类的属性赋值
- name: 需要赋值的属性名称
2.1.5 struts.xml配置文件示例
<?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>
<!-- 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 -->
<!-- 需要给UserAction注册一个url -->
<package name="user" namespace="/user" extends="struts-default">
<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="userAction_*" class="com.test.action.UserAction" method="{1}">
<!-- 引用拦截器 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>
<result name="error" type="dispatcher">/error.jsp</result>
<result name="input" type="dispatcher">/login.jsp</result>
<!-- 配置Action返回cancel时重定向到Welcome的Action-->
<result name="cancel" type="redirect-action">Welcome</result>
<!-- 异常处理 result表示出现异常时返回的name为success的结果处理 -->
<exception-mapping exception=”java.lang.Exception” result=”success”/>
<!-- 参数设置 name:对应Action中的get/set方法 -->
<param name="url">http://www.sina.com</param>
</action>
<!-- 不同包Action之间的跳转 -->
<!-- <result name="uaction2" type="redirectAction">../user2/userAction3</result> -->
<result name="uaction2" type="redirectAction">
<!-- 注入:服务器启动的时候,会给redirectAction对应的类中的数据赋值 -->
<param name="actionName">userAction3</param>
<param name="namespace">/user2</param>
</result>
<result name="userLogin">/userLogin.jsp</result>
</action>
<!-- 同一个包中跳转 -->
<action name="userAction2" class="com.test.action.UserAction2">
<result name="success" type="redirect">/success.jsp</result>
</action>
</package>
<!—引用国际化文件的base名-->
<constant name=”struts2.custom.i18n.resources” value=”messageResource” />
<package name="user2" namespace="/user2" extends="struts-default">
<!-- 同一个包中跳转 -->
<action name="userAction3" class="com.test.action.UserAction3">
<result name="success" type="plainText">
<param name="location">/success.jsp</param>
<param name="charSet">UTF-8</param>
</result>
</action>
</package>
</struts>
2.2 struts2中方法调用的方式
2.2.1 通配符调用
在以前的学习中,<action>元素的配置,都是用明确的配置,其name、class等属性都是一个明确的值。其实Struts2还支持class属性和method属性使用来自name属性的通配符
通配符调用: *代表的通配符, {n}代表第n通配符对应的值(最为常用)
<global-allowed-methods>regex:.*</global-allowed-methods>
<!-- 通配符的调用 -->
<action name="student-*" class="cn.test.crud.action.StudentAction" method="{1}">
<result name="list">/list.jsp</result>
<result name="success" type="redirectAction">student-list</result>
<result name="error">/error.jsp</result>
<result name="detail">/detail.jsp</result>
</action>
- action使用通配符
<action name="*_*" class="cn.javass.action.action.{1}Action" method="{2}">
<result name="toWelcome">/s2impl/welcome.jsp</result>
</action>
在上面的配置中:
name属性的值中 * 代表长度不为0的任意字符串,因此,它可以响应的action只需要名称中间有一个下划线即可。比如页面可访问的action名称为:HelloWorld_create.action、HelloWorld _update.action等等。
在name属性定义了通配符之后,class属性使用第一个通配符(使用{1}作为占位),method属性使用第二个通配符。如果使用HelloWorld_create.action作为访问的action名称的话,struts.xml中action名称为HelloWorld_create,第一个通配符匹配HelloWorld,第二个通配符匹配create。因此,由cn.javass.action.action.HelloWorldAction的create方法来响应。
- result使用通配符
那么,对于<result>元素,能不能也使用<action>元素的name属性定义的通配符呢?答案是可以的,假如有如下的配置:
<action name="*_*_*_*" class="cn.javass.action.action.{1}Action" method="{2}">
<result name="{3}">/${folder}/{4}.jsp</result>
</action>
- 通配符匹配原则
在使用通配符的时候,也有可能不止一个使用通配符的<action>元素可能匹配这次URL的访问,看以下的配置文件
<action name="HelloWorld_create" class="cn.javass.action.action.HelloWorldAction" method="create2">
<result name="toWelcome">/s2impl/welcome.jsp</result>
</action>
<action name="*_*" class="cn.javass.action.action.{1}Action" method="{2}">
<result name="toWelcome">/s2impl/welcome.jsp</result>
</action>
这时候,如果访问/helloworld/HelloWorld_create.action,Struts2首先会查找是否有精确匹配的<action>元素,这时候无论以上<action>元素以什么顺序出现,Struts2会先找到并使用精确匹配的<action>元素。但是,如果没有精确匹配的<action>元素,则Struts2会找到第一个匹配的使用通配符的<action>元素来使用。
通配符对于那些简单的CRUD的工程或软件原型来说,只要Action的包名、Action的类名、对应的方法名写的有规律的应用,能大大简化配置的工作
2.2.2 方法动态调用
方法动态调用:actionName!methodName. 要求必须开启方法的动态调用,需要设置常量进行开启(将常量struts.enable.DynamicMethodInvocation的值设置为true,默认为false)
<!-- 开启方法的动态调用 ,默认值为false-->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<!-- 方法动态调用:actionName!methodName,前提是开启方法的动态调用-->
<action name="studentAction" class="cn.test.crud.action.StudentAction">
<result name="list">/list2.jsp</result>
<result name="success" type="redirectAction">studentAction!List</result>
</action>
访问地址studentAction!add.action时,将调用studentAction中add方法
2.3 package中属性
下面重点讲解一下namespace和abstract属性:
2.3.1 namespace属性
namespace配置的是包的命名空间,同一个命名空间里面不能有同名的Action,当然不同的命名空间里面是可以有同名的Action的。类似于Java的包的功能,namespace可以有效的防止action重名的冲突,因为配置了namespace后,在访问action的时候就需要添加namespace来作为action的前缀。如果不配置namespace,表示是默认的namespace,那么访问的时候不需要添加namespace前缀。比如HelloWorld的示例,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" />
<constant name="struts.locale" value="zh_CN"/>
<constant name="struts.i18n.encoding" value="gb2312"/>
<package name="helloworld" extends="struts-default">
<action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction">
<result name="toWelcome">/s2impl/welcome.jsp</result>
</action>
</package>
</struts>
观察里面<package>
元素的定义,里面是没有配置namespace
的,因此在访问的时候,是直接在webcontext
下面写要访问的action
的名称的,示例如下:
<form action="/helloworld/helloworldAction.action" method="post"> …… </form>
其中/helloworld
是webcontext
。
如果配置了namespace
,那么访问的时候是必须要添加namespace
前缀的,配置namespace
的时候/
表示namespace
的根。示例如下:
<package name="hello" namespace="/javass" extends="struts-default">
<action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction">
<result name="toWelcome">/s2impl/welcome.jsp</result>
</action>
</package>
那么访问的时候就需要加上namespace
,示例如下:
<form action="/helloworld/javass/helloworldAction.action" method="post">
……
</form>
2.3.2 abstract属性
abstract用来定义包为抽象的,也就是不能包含Action的定义,但是抽象包可以被其他包继承,因此里面可以定义其他包需要的元素,比如ResultType、Interceptor等等。
比如上面HelloWorld示例中继承的struts-default包,它就是个抽象的包,定义示例如下:
<package name="struts-default" abstract="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
</result-types>
<interceptors>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
<interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
<interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
<interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
<interceptor name="deprecation" class="org.apache.struts2.interceptor.DeprecationInterceptor" />
<!-- Basic stack -->
<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
<!-- Sample validation and workflow stack -->
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="basicStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
<!-- Sample file upload stack -->
<interceptor-stack name="fileUploadStack">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample model-driven stack -->
<interceptor-stack name="modelDrivenStack">
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample action chaining stack -->
<interceptor-stack name="chainStack">
<interceptor-ref name="chain"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- Sample i18n stack -->
<interceptor-stack name="i18nStack">
<interceptor-ref name="i18n"/>
<interceptor-ref name="basicStack"/>
</interceptor-stack>
<!-- An example of the paramsPrepareParams trick. This stack
is exactly the same as the defaultStack, except that it
includes one extra interceptor before the prepare interceptor:
the params interceptor.
This is useful for when you wish to apply parameters directly
to an object that you wish to load externally (such as a DAO
or database or service layer), but can't load that object
until at least the ID parameter has been loaded. By loading
the parameters twice, you can retrieve the object in the
prepare() method, allowing the second params interceptor to
apply the values on the object. -->
<interceptor-stack name="paramsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="params">
<param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
<!-- A complete stack with all the common interceptors in place.
Generally, this stack should be the one you use, though it
may do more than you need. Also, the ordering can be
switched around (ex: if you wish to have your servlet-related
objects applied before prepare() is called, you'd need to move
servletConfig interceptor up.
This stack also excludes from the normal validation and workflow
the method names input, back, and cancel. These typically are
associated with requests that should not be validated.
-->
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">^class\..*,^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
<!-- The completeStack is here for backwards compatibility for
applications that still refer to the defaultStack by the
old name -->
<interceptor-stack name="completeStack">
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Sample execute and wait stack.
Note: execAndWait should always be the *last* interceptor. -->
<interceptor-stack name="executeAndWaitStack">
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="execAndWait">
<param name="excludeMethods">input,back,cancel</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultStack"/>
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
</package>
3 namespace访问路径问题
在struts.xml配置文件当中packet有一个属性字段namespace,这里必须详细了解一下,他的作用是可以让不同的packet里面包含相同action名称
一般情况,如果没有namespace属性字段的默认为"",会被最后才搜索
如果有两个相同的package,他们里面有相同的方法,有namespace的action会优先被搜索,在下面的代码当中,有两个package,一个是default,另一个是test1,大家里面都有Hello的action,如果Hello的action被调用,test1会被执行优先于default,意思是,程序会先搜索test1里面的Hello的action,所以这里的结果是会返回Hello2.jsp而不是Hello.jsp
(注意:struts.xml配置文件中的package是由上往下读取的,被继承的package要先于继承的package,意思就是编写这个配置文件时父级别要优先于子级别的package)
另外要主要的是这个namespace所指的在这个web app的根目录下的一个文件路径,namespace="/test"代表在根目录下的/test里面。所以以下的代码表示返回的Hello3.jsp在Web App下的/test/里面
最后还有一个要点就,如下面例子,请求http://localhost:8080/Strut2Namespace/test/Hello会出现404的结果,
如果修改一下,在Hello.jsp前加上"/"代表绝对路径的意思,则能显示Hello.jsp的页面,我们来分析一下这个案例
按照规则,先读取名为test2的package然后然后未能找到Hello的action,则开始读取默认的package,发现有Hello的action,则返回成功页面,Hello.jsp,因为这里默认的路径是"",可以理解为当前访问目录,但在访问目录下根本不能找到这个页面,则报404,如果改成/Hello.jsp,则返回的页面路径从根目录开始找Hello.jsp,这样在根目录下能找到Hello.jsp的页面,则能返回正确的页面,所这里需要这一点