在前面的 Struts2.2 CURD Dem o 中,我们整体理顺了 Strut s2.2 的基本流程,这里我们以这个 Demo 来说明一下配置文件里节点表示的意义。
Struts 中的配置文件:
文件 |
可选项 |
位置 |
用途 |
no |
/WEB-INF/ |
Web 部署描述符包含所有必需框架组件 |
|
yes |
/WEB-INF/classes/ |
主要配置 , 包含结果 / 视图类型 , 操作映射、拦截器 , 等等 |
|
yes |
/WEB-INF/classes/ |
框架属性 |
|
yes |
/WEB-INF/lib/struts2-core.jar |
缺省配置,由 Struts 提供 |
|
yes |
/WEB-INF/classes/ |
默认的宏 velocity.properties 所引用 |
|
struts-plugin.xml |
yes |
At the root of a plugin JAR |
可选插件配置文件,格式同 struts 一样。 |
struts-plugin.xm |
yes |
/WEB-INF/classes/ |
覆盖默认的速度配置 |
一、 Web.xml:
Web.xml 文件大家应该很熟悉,因为每个 web 程序都会有这个文件,而 Struts2 在使用时,需要在这个文件中进行配置 FilterDispatcher, 该过滤器类初始化 Struts 框架和处理所有的要求。并且这个过滤器可以包含一些初始化参数等。
<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"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>com.mycompany.myapp.actions</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- ... --> </web-app>
而标签一般不需要在这里配置,因为标签已经包含在 struts-core.jar ,容器会自动找到它。如果配置,则方式如下:
<!-- ... --> </welcome-file-list> <taglib> <taglib-uri>/s</taglib-uri> <taglib-location>/WEB-INF/struts-tags.tld</taglib-location> </taglib> </web-app>
二、 Struts.xml
管理元素:
1、 Constant 节点
通过在 struts.xml 中对 Constant 节点的配置来提供一种改变框架默认行为的机制:
设置文件上传大小限制(单位字节)
<constant name="struts.multipart.maxSize" value="29661132" />
允许开发模式以提供更方便的调试功能
<constant name="struts.devMode" value="true" />
国际化设置
<constant name="struts.custom.i18n.resources" value="guest" />
该节点在 Struts.xml 中的配置可以等价于 在 struts.properties 中的 struts.devMode = true 和在 web.xml 中的
<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"> <filter> <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> <init-param> <param-name>struts.devMode</param-name> <param-value>true</param-value> </init-param> </filter> ... </web-app>
2、package节点
Struts 中的 package 可以理解为 java 中的包,可以将一组业务相关的 actions 、 results 、 result types 、 interceptors 划分在一起与其他业务进行分组。当然它也有子包的概念,如果有子 package ,则父 package 必须在子 package 前配置。
Name :唯一标识
Namespace :默认的命名空间为空字符串,要是加上非空字符串如“ test ”,访问时,就改为了“ /test/delete.action ” 这里需要多说一点是 Struts 官方文档特别强调一点是 namespace are not a path ,即如果有一个 namespace 为“ /barspace/myspace /bar.action ”, struts 会到“ /barspace/myspace ”下去找 bar.action 如果找不到,会直接返回到默认的 namespace(“”) 中去找。
extends="struts-default" 通常每个包都应该继承 struts-default 包,因为 Struts2 很多核心的功能都是拦截器来实现。如:从请求中把请求参数封装到 action 、文件上传和数据验证等等都是通过拦截器实现的。 struts-default 定义了这些拦截器和 Result 类型。因此,当包继承了 struts-default 才能使用 struts2 提供的核心功能。
<package name="default" extends="struts-default" namespace="/">
3、 include 节点:
文档中提到一个策略叫“分而治之”,配置文件也是,可以将部门配置写入到其他的配置文件(格式也需要与 struts.xml 中一样)中去,最后引入。
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <include file="Home.xml"/> <include file="Hello.xml"/> <include file="/util/POJO.xml"/> <include file="/com/initech/admin/admin-struts.xml"/> </struts>
请求处理元素:
1 、 Interceptor 节点:
拦截器允许您定义的代码执行之前或之后执行的动作方法。 (“ 过滤器 ” 模式 ) 。拦截器是一种强大的工具在开发应用程序。有许多 , 许多用例对拦截器 , 包括验证、属性、安全性、日志记录和分析。
多个拦截器可以作为一个拦截器堆栈,例如如果要检查客户端证书、时间等信息,所有的这些可以做成部分功能相同的拦截器堆栈。
拦截器和拦截器堆栈可以混合使用;
<interceptors> <!-- 定义拦截器 name:拦截器名称class:拦截器类路径--> <interceptor name="timer" class="com.kay.timer"></interceptor> <!-- 定义拦截器栈 --> <interceptor-stack name="appDefault"> <interceptor-ref name="timer"></interceptor-ref> <interceptor-ref name="defaultStack"> <param name="exception.logEnabled">true</param> <param name="exception.logLevel">ERROR</param> </interceptor-ref> </interceptor-stack> </interceptors> <!-- 定义默认的拦截器 每个Action都会自动引用 如果Action中引用了其它的拦截器 默认的拦截器将无效 --> <default-interceptor-ref name="appDefault" /> <action name="hello" class="com.kay.struts2.Action.LoginAction"> <!-- 引用拦截器name:拦截器名称或拦截器栈名称--> <interceptor-ref name="timer"></interceptor-ref> <result name="success" type="dispatcher">/talk.jsp</result> </action>
2 、 action 节点:
Action 是 Struts2 的基本工作单元, Action 通过一个标识符与处理程序映射,当一个请求匹配 action 的 name 时, Struts2 容器决定调用哪个 Action 来处理用户请求。
每个 Action 可以指定多个 result 、 ExceptionHandler 、 Intercepter 。但是只能指定一个 name 。在应用程序中, name 属性会去掉 Host , Application 和后缀等信息,得到 Action 的名字。
在 Struts2 中,一个指向 Action 的链接通常由 Struts 标签产生,这个标签只需要指定 Action 的名字, Struts 框架会自动添加后缀等扩展。
<s:form action="Hello"> <s:textfield label="Please enter your name" name="name"/> <s:submit/> </s:form>
在定义 Action 的 name 时,最好使用英文字面和下划线,而不要使用“ . ”和“ / ” ;
<action name="index" class="com.iflytek.action.ListEmployeeAction"> <result name="success">/page/employeeList.jsp</result> </action>
Action 标签中如果没用置顶 method ,则默认是 execute ,否则就可以指定到 Action 类中的不同方法。 Method 上的通配符使用,很多时候 , 一组 Action 映射将共享一个共同的模式( delete 、 add 、 update )。例如 , 你所有的编辑动作可以用单词 “ 编辑 ”, 并调用编辑方法操作类,这时就可以使用通配符。
<action name="*User" class="com.iflytek.model" method="{1}">
当我们没有指定 Action 的 class 属性的时候,我们默认使用 com.opensymphony.xwork.ActionSupport , ActionSupport 有两个方法 input 和 execute ,每个方法都是简单的返回 SUCCESS 。
使用如下代码可以实现刷新的效果
<s:form> <s:textfield label="Please enter your name" name="name"/> <s:submit/> </s:form>
通常情况下,请求的 Action 不存在的情况下, Struts2 框架会返回一个 Error 页面:“ 404 - Page not found ”,如果我们不想出现一个控制之外的错误页面,我们可以指定一个默认的 Action ,在请求的 Action 不存在的情况下,调用默认的 Action ,通过如下配置可以达到要求:
<package name="Hello" extends="action-default"> <default-action-ref name="UnderConstruction"/> <action name="UnderConstruction"> <result>/UnderConstruction.jsp</result> </action> ...
默认通配符
<action name="*" > <result>/{1}.jsp</result> </action>
每个 Action 将会被映射到以自己名字明明的 JSP 上。
通配符:
<action name="/edit*" class="org.apache.struts.webapp.example.Edit{1}Action"> <result name="failure">/mainMenu.jsp</result> <result>edit_{1}.jsp</result> </action>
上面匹配的结果将替换{ 1 }
* :将匹配零个或多个字符不包括斜杠 (/) 字符。
** :将匹配零个或多个字符包括斜杠 (/) 字符。
当然还支持正则等,这个这里就不描述了
注意如果使用正则需要在配置:
<constant name="struts.enable.SlashesInActionNames" value="true"/> <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/> <constant name="struts.patternMatcher" value="regex" />
3、 result 节点:
定义Action的结果视图,name表示结果视图名称,默认为success,type为结果视图类型,默认为dispathcher
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";
A 、设置默认返回类型:
<result-types> <result-type name="dispatcher" default="true" class="org.apache.struts2.dispatcher.ServletDispatcherResult" /> </result-types>
B 、多个返回类型:
<action name="Hello"> <result>/hello/Result.jsp</result> <result name="error">/hello/Error.jsp</result> <result name="input">/hello/Input.jsp</result> <result name="*">/hello/Other.jsp</result> </action>
在 name = " * " 不是一个通配符模式 , 它是一个特殊的名称 , 是唯一选择的如果没有找到一个精确的匹配。
C 、全局返回类型:
通常 , 结果是嵌套在 Action 中。但是一些结果适用于多种 Action 。在一个安全的应用程序 , 客户端可能会试图访问一个页面没有被授权 , 许多 Action 可能需要访问一个“登录”的页面。
<global-results> <result name="error">/Error.jsp</result> <result name="invalid.token">/Error.jsp</result> <result name="login" type="redirectAction">Logon!input</result> </global-results>
D 、动态返回类型:
<struts> .... <package name="somePackage" namespace="/myNamespace" extends="struts-default"> <action name="myAction" class="com.project.MyAction"> <result name="success" type="redirectAction">otherAction?id=${id}</result> <result name="back" type="redirect">${redirectURL}</result> </action> <action name="otherAction" class="com.project.MyOtherAction"> ... </action> </package> .... </struts>
public class MyAction extends ActionSupport { private int id; private String redirectURL; ... public String execute() { ... if (someCondition) { this.redirectURL = "/the/target/page.action"; return "back"; } this.id = 123; return SUCCESS; } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public String getRedirectURL() { return this.redirectURL; } public void setRedirectURL(String redirectURL) { this.redirectURL= redirectURL; } ... }
result 的 type :
1 、 Chain : 用来处理 Action 链
2 、 Dispatcher : 用来转向页面,通常处理 JSP( 默认值 )
3 、 FreeMarker : 处理 FreeMarker 模板
4 、 HttpHeader : 用来控制特殊的 Http 行为
5 、 Redirect : 重定向到一个 URL
6 、 Redirect-Action : 重定向到一个 Action
7 、 Stream : 向浏览器发送 InputSream 对象,通常用来处理文件下载
8 、 Velocity :处理 Velocity 模板
9 、 XLS :处理 XML/XLST 模板
10 、 PlainText :显示原始文件内容,例如文件源代码
11 、 S2PLUGINS:Tiles : 结合 Tile 使用
4 、 Unknown Handlers 节点:
<bean type="com.opensymphony.xwork2.UnknownHandler" name="handler1" class="com.opensymphony.xwork2.config.providers.SomeUnknownHandler"/> <bean type="com.opensymphony.xwork2.UnknownHandler" name="handler2" class="com.opensymphony.xwork2.config.providers.SomeUnknownHandler"/> <unknown-handler-stack> <unknown-handler-ref name="handler1" /> <unknown-handler-ref name="handler2" /> </unknown-handler-stack>
错误处理元素:
Exception 节点:
Struts 的异常映射是一个比较强大的特性,其核心就是在异常期间抛出的动作方法可以自动捕获并映射到一个预定的结果中。
默认的异常映射是在默认的拦截器中进行激活的,可以看看下面的 strusts-default.xml
... <interceptors> ... <interceptor name="exception" class="com.opensymphony.xwork.interceptor.ExceptionMappingInterceptor"/> ... </interceptors> <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servlet-config"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="debugging"/> <interceptor-ref name="profiling"/> <interceptor-ref name="scoped-model-driven"/> <interceptor-ref name="model-driven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="static-params"/> <interceptor-ref name="params"/> <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> ...
<struts> <package name="default"> ... <global-results> <result name="login" type="redirect">/Login.action</result> <result name="Exception">/Exception.jsp</result> </global-results> <global-exception-mappings> <exception-mapping exception="java.sql.SQLException" result="SQLException"/> <exception-mapping exception="java.lang.Exception" result="Exception"/> </global-exception-mappings> ... <action name="DataAccess" class="com.company.DataAccess"> <exception-mapping exception="com.company.SecurityException" result="login"/> <result name="SQLException" type="chain">SQLExceptionAction</result> <result>/DataAccess.jsp</result> </action> ... </package> </struts>
ValueStack 中的 value
<h2>An unexpected error has occurred</h2> <p> Please report this error to your system administrator or appropriate technical support personnel. Thank you for your cooperation. </p> <hr/> <h3>Error Message</h3> <s:actionerror/> <p> <s:property value="%{exception.message}"/> </p> <hr/> <h3>Technical Details</h3> <p> <s:property value="%{exceptionStack}"/> </p>
三、 struts.properties :
在该文件中,可以设置一些参数,使得 struts 适合你的要求,例如编码等,下面列出一个默认的配置:
### Struts default properties ###(can be overridden by a struts.properties file in the root of the classpath) ### ### Specifies the Configuration used to configure Struts ### one could extend org.apache.struts2.config.Configuration ### to build one's customize way of getting the configurations parameters into Struts # struts.configuration=org.apache.struts2.config.DefaultConfiguration ### This can be used to set your default locale and encoding scheme # struts.locale=en_US struts.i18n.encoding=UTF-8 ### if specified, the default object factory can be overridden here ### Note: short-hand notation is supported in some cases, such as "spring" ### Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here # struts.objectFactory = spring ### specifies the autoWiring logic when using the SpringObjectFactory. ### valid values are: name, type, auto, and constructor (name is the default) struts.objectFactory.spring.autoWire = name ### indicates to the struts-spring integration if Class instances should be cached ### this should, until a future Spring release makes it possible, be left as true ### unless you know exactly what you are doing! ### valid values are: true, false (true is the default) struts.objectFactory.spring.useClassCache = true ### ensures the autowire strategy is always respected. ### valid values are: true, false (false is the default) struts.objectFactory.spring.autoWire.alwaysRespect = false ### if specified, the default object type determiner can be overridden here ### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger" ### Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here ### Note: By default, com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer is used which handles type detection ### using generics. com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer was deprecated since XWork 2, it's ### functions are integrated in DefaultObjectTypeDeterminer now. ### To disable tiger support use the "notiger" property value here. #struts.objectTypeDeterminer = tiger #struts.objectTypeDeterminer = notiger ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data # struts.multipart.parser=cos # struts.multipart.parser=pell struts.multipart.parser=jakarta # uses javax.servlet.context.tempdir by default struts.multipart.saveDir= struts.multipart.maxSize=2097152 ### Load custom property files (does not override struts.properties!) # struts.custom.properties=application,org/apache/struts2/extension/custom ### How request URLs are mapped to and from actions #struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper ### Used by the DefaultActionMapper ### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do ### The blank extension allows you to match directory listings as well as pure action names ### without interfering with static resources. struts.action.extension=action,, ### Used by FilterDispatcher ### If true then Struts serves static content from inside its jar. ### If false then the static content must be available at <context_path>/struts struts.serve.static=true ### Used by FilterDispatcher ### This is good for development where one wants changes to the static content be ### fetch on each request. ### NOTE: This will only have effect if struts.serve.static=true ### If true -> Struts will write out header for static contents such that they will ### be cached by web browsers (using Date, Cache-Content, Pragma, Expires) ### headers). ### If false -> Struts will write out header for static contents such that they are ### NOT to be cached by web browser (using Cache-Content, Pragma, Expires ### headers) struts.serve.static.browserCache=true ### Set this to false if you wish to disable implicit dynamic method invocation ### via the URL request. This includes URLs like foo!bar.action, as well as params ### like method:bar (but not action:foo). ### An alternative to implicit dynamic method invocation is to use wildcard ### mappings, such as <action name="*/*" method="{2}" class="actions.{1}"> struts.enable.DynamicMethodInvocation = true ### Set this to true if you wish to allow slashes in your action names. If false, ### Actions names cannot have slashes, and will be accessible via any directory ### prefix. This is the traditional behavior expected of WebWork applications. ### Setting to true is useful when you want to use wildcards and store values ### in the URL, to be extracted by wildcard patterns, such as ### <action name="*/*" method="{2}" class="actions.{1}"> to match "/foo/edit" or ### "/foo/save". struts.enable.SlashesInActionNames = false ### use alternative syntax that requires %{} in most places ### to evaluate expressions for String attributes for tags struts.tag.altSyntax=true ### when set to true, Struts will act much more friendly for developers. This ### includes: ### - struts.i18n.reload = true ### - struts.configuration.xml.reload = true ### - raising various debug or ignorable problems to errors ### For example: normally a request to foo.action?someUnknownField=true should ### be ignored (given that any value can come from the web and it ### should not be trusted). However, during development, it may be ### useful to know when these errors are happening and be told of ### them right away. struts.devMode = false ### when set to true, resource bundles will be reloaded on _every_ request. ### this is good during development, but should never be used in production struts.i18n.reload=false ### Standard UI theme ### Change this to reflect which path should be used for JSP control tag templates by default struts.ui.theme=xhtml struts.ui.templateDir=template #sets the default template type. Either ftl, vm, or jsp struts.ui.templateSuffix=ftl ### Configuration reloading ### This will cause the configuration to reload struts.xml when it is changed struts.configuration.xml.reload=false ### Location of velocity.properties file. defaults to velocity.properties struts.velocity.configfile = velocity.properties ### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext struts.velocity.contexts = ### Location of the velocity toolbox struts.velocity.toolboxlocation= ### used to build URLs, such as the UrlTag struts.url.http.port = 80 struts.url.https.port = 443 ### possible values are: none, get or all struts.url.includeParams = none ### Load custom default resource bundles # struts.custom.i18n.resources=testmessages,testmessages2 ### workaround for some app servers that don't handle HttpServletRequest.getParameterMap() ### often used for WebLogic, Orion, and OC4J struts.dispatcher.parametersWorkaround = false ### configure the Freemarker Manager class to be used ### Allows user to plug-in customised Freemarker Manager if necessary ### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager #struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager ### Enables caching of FreeMarker templates ### Has the same effect as copying the templates under WEB_APP/templates struts.freemarker.templatesCache=false ### Enables caching of models on the BeanWrapper struts.freemarker.beanwrapperCache=false ### See the StrutsBeanWrapper javadocs for more information struts.freemarker.wrapper.altMap=true ### maxStrongSize for MruCacheStorage for freemarker struts.freemarker.mru.max.strong.size=100 ### configure the XSLTResult class to use stylesheet caching. ### Set to true for developers and false for production. struts.xslt.nocache=false ### Whether to always select the namespace to be everything before the last slash or not struts.mapper.alwaysSelectFullNamespace=false ### Whether to allow static method access in OGNL expressions or not struts.ognl.allowStaticMethodAccess=false ### Whether to throw a RuntimeException when a property is not found ### in an expression, or when the expression evaluation fails struts.el.throwExceptionOnFailure=false ### Logs as Warnings properties that are not found (very verbose) struts.ognl.logMissingProperties=false ### Caches parsed OGNL expressions, but can lead to memory leaks ### if the application generates a lot of different expressions struts.ognl.enableExpressionCache=true
其他文件一般在项目中都很少去涉及,除非特定的需求,所以就不在往下说了,具体可以查阅官方的文档。