第3章 Struts2开发 本章导读 Struts2框架是Apache开源社区原有的Struts框架和Open Symphony社区WebWork2框架的合并版本,它集成了这两大流行的MVC框架各自的优点,主要以WebWork的设计思想为核心,提供了更加灵活的控制层和组件实现技术。 本章要点  Struts2的体系结构  Struts2的安装与配置  Struts2框架的主要配置文件 3.1Struts2结构 3.1.1Struts2体系结构 Struts2框架提供了更灵活的控制层和组件实现技术,Struts2框架主要的功能组件有Action组件、拦截器组件、国际化本地资源包以及XML配置文件等。图3.1为Struts2框架的体系结构图。 图3.1Struts2体系结构 (1) HttpServletRequest代表了浏览器客户端的一次HTTP请求和服务器程序处理结果的一次HTTP响应输出。 (2) ActionMapper其实是HttpServletRequest和Action调用请求的一个映射,它屏蔽了Action对于Request等Java类的依赖。Struts2中它的默认实现类是DefaultActionMapper,ActionMapper很大的用处可以根据自己的需要来设计url格式,它自己也有Restful的实现,具体可以参考文档的docs\actionmapper.html。 (3) FilterDispatcher代表Struts2框架的过滤器组件,是Struts2的核心控制器,负责拦截所有的客户端请求,通过web.xml文件被加入到Web应用当中,当有客户端请求到达时,它就会进行拦截,然后将根据配置文件将请求转发给相应的业务逻辑控制器进行处理。Struts2框架包含一系列的标准过滤器组件链,该组件链主要由 ActionContextCleanUp和核心过滤器组件FilterDispatcher构成。ActionContextCleanUp主要应用在整合SiteMesh框架。 (4) Action是Struts2的业务逻辑控制器,负责处理客户端的请求并将处理结果输出给客户端。 (5) ActionProxy是Action的代理,由ActionProxyFactory创建,它本身不包括Action实例,DefaultActionProxy是默认的ActionProxy代理。ActionProxy作用是如何取得Action,ActionProxy 创建一个ActionInvocation的实例,同时ActionInvocation通过代理模式调用Action。但在调用之前 ActionInvocation会根据配置加载Action相关的所有Interceptor。该组件在Struts2框架中发挥着非常重要的作用。它是action和xwork中间的一层。 正因为ActionProxy的存在导致Action调用更加简洁。 (6) ActionInvocation 是Xworks 中Action 调度的核心。ActionInvocation 是一个接口,它的作用是如何执行Action,拦截器的功能就是在ActionInvocation中实现的。DefaultActionInvocation是Webwork 对ActionInvocation的默认实现。 (7) Interceptor代表Struts2框架的拦截器组件,利用拦截器进行AOP编程(面向切面编程),实现权限验证等功能。 (8) Template是开发人员自己开发的各个部分的程序,Struts2支撑多种表现层的技术,如 JSP、FreeMarker等。 (9) ConfigurationManager提供对客户端应用程序配置文件的访问,也就是Struts2中配置文件的解析器。 (10) Struts.xml文件是Struts2框架的配置文件,主要负责配置业务逻辑控制器Action,以及用户自定义的拦截器等,是Struts2各个组件之间的纽带。 3.1.2工作流程 一个请求在Struts2框架中的基本流程如图3.2所示。 图3.2Struts2工作流程 (1) 首先浏览器端发送一个HttpServletRequest请求。 (2) 核心控制器StrutsPrepareAndExecuteFilter根据请求决定调用合适的Action。 (3) Struts2的拦截器链自动对请求进行相关应用的拦截,如validation(数据验证)或文件的上传下载等功能。 拦截器的调度流程大致为: ActionInvocation初始化时,根据配置文件的设置,加载Action相关的所有Interceptor,然后通过ActionInvocation.invoke方法调用Action实现。 (4) 回调Action的execute方法,该execute方法先获取用户请求参数,然后执行某种数据库的操作,既可以将数据保存到数据库,也可以从数据库中查询数据。实际上,Action只是一个控制器,它会调用业务逻辑组件来处理用户的请求。 (5) Action的execute方法将处理的结果存入Stack Context中,并返回一个字符串,核心控制器StrutsPrepareAndExecuteFilter将根据返回的字符串跳转到指定的视图资源,该视图资源将会读取Stack Context中的信息,并在浏览器生成响应数据。这些响应数据可以是HTML页面、图像、各种格式的文档等,并且所支持的视图技术也非常多,如JSP、Velocity、FreeMarker等模板技术。 在实际中,使用Struts2框架开发用户登录功能,需要用户创建一个登录界面login.jsp,一个系统主页面index.jsp,一个Action类LoginAction.java,一个拦截器类LoginInterceptor.java,另外需要对配置文件web.xml、struts.xml进行相应的设置。那么该模块的实际工作过程如图3.3所示。 图3.3实际模块的工作过程 用户在浏览器中输入http://localhost:8080/Test/login.jsp地址,调用login.jsp文件,在登录界面上填写相应的用户名和密码,然后提交请求给Action类处理,Struts2框架根据配置文件web.xml里的设置对请求进行过滤,符合要求就交给Struts2框架,Struts2框架会根据配置文件struts.xml调用相应的Action类LoginAction.java来处理,如果该Action类定义了拦截器,那么就拦截请求,调用LoginInterceptor.java对用户名、密码等信息进行验证,然后再将控制权转移回Action类LoginAction.java,如果处理结果为成功,则转向系统主页面index.jsp,否则转回登录页面login.jsp重新输入值。 3.1.3安装与配置 使用Struts2框架进行web开发或者运行Struts2的程序就必须先配置好Struts2的运行环境。首先配置JDK环境变量,然后安装web服务器,可以选择Tomcat作为运行的服务器。然后安装Struts2框架的JAR文件包。 方式1当开发工具不支持Struts2框架时,需要开发人员手工下载JAR包并添加到项目中去。 登录http://struts.apache.org/网站下载Struts2完整版struts2.5all.zip,将下载的zip文件解压缩,打开其文件夹,里面包含以下4个目录(见图3.4)。 图3.4Struts2.5目录 不同版本的Struts2框架系统库,它们的核心库文件的文件名略有差别,Struts2.5版本主要有以下几个文件夹:  apps目录下的文件为DEMO示例,是学习Struts2非常有用的资料。  docs目录下的文件为系统的帮助文件。  src 为Struts2框架源代码文件所在的目录。  lib包含Struts2框架的核心类库,以及Struts2的第三方插件类库。 打开Struts2开发包的lib文件夹,把struts2core2.5.jar 、log4japi2.5.jar、ognl3.1.4.jar、commonslogging1.1.3.jar、freemarker2.3.23.jar、commonsio2.4.jar、commonslang2.4.jar、javassist3.20.0.GA.jar、commonsfileupload1.3.1.jar拷贝到项目的\WebRoot\WEBINF\lib目录下。如果需要在Web应用中使用Struts2的更多特性,则需要将相应的JAR文件复制到Web应用的WEBINF/lib目录下即可。 方式2当开发工具支持Struts2框架时,可以采用菜单项的方式安装Struts2框架的JAR包。本书使用Myeclipse2015作为开发工具,添加Struts2框架的步骤如下: (1) 建立一个Web项目。打开Myeclipse2015建立一个Web项目,命名为“Struts2Test”,如图3.5所示。 图3.5新建Web项目 (2) 加载Struts2类库。 用鼠标右击项目名,在弹出的菜单项上选择【MyEclipse】(见图3.6),然后选择【Project Facets[Capabilities]】菜单,最后选择【Install Apache Struts (2.x) Facet】,弹出如图3.7所示对话框。 选择配置文件中对文件类型的过滤,*.action表示将对扩展名是.action的文件进行过滤; *.do表示将对扩展名是.do的文件进行过滤; /*表示将对所有的文件进行过滤。 然后单击【Next】按钮,出现如图3.8所示对话框,选择要添加的Struts2类库文件,默认是Core,单击【Finish】按钮完成。 Struts2框架加载成功后,将该项目名展开,可以看到该项目下导入了很多Struts2类库,如图3.9所示。 图3.6加载Struts 2类库 图3.7选择过滤文件类型 注意: web.xml文件存储在WEBINF目录下,struts.xml存储在classes目录下,lib下存储的是所必需的类库包,如Struts2核心类库包等。 图3.8选择Struts2类库 图3.9加载后的包文件 3.2配置文件web.xml Struts2框架能够为程序提供良好的管理机制,这样开发人员就能够脱离繁杂的管理工作而专心于业务。然而框架并不可能知道开发人员的业务,只有开发人员把自己的业务通过配置文件注册给框架,框架才知道自己要管理的资源是什么。Struts2框架中的配置文件web.xml由框架自动加载,对其自身进行配置。 3.2.1文件的作用 Struts2框架就是通过web.xml配置了核心控制器,核心控制器也就是过滤器,对用户请求和处理程序响应的内容进行处理。 在Struts2中,开发人员可以自定义过滤器,要求所有过滤器必须实现java.Serlvet.Filter接口,这个接口中含有3个过滤器类必须实现的方法:  init(FilterConfig): Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。  doFilter(ServletRequest,ServletResponse,FilterChain): 完成实际的过滤操作,当用户请求与过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法,返回响应之前也会调用此方法。FilterChain参数用于访问过滤器链上的下一个过滤器。  destroy(): Servlet容器在销毁过滤器实例前调用该方法,这个方法可以释放Servlet过滤器占用的资源。 定义好过滤器后,需要在web.xml中进行配置。web.xml文件存放在项目中WebRoot/WEBINF的文件夹下。根据版本不同,里面的内容也有所不同。低版本的web.xml代码如下: struts 2 org.apache.struts2.dispatcher.FilterDispatcher struts 2 /* 而对于Struts2.1.6 及以上版本的框架,web.xml代码如下: struts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter struts2 *.action 从上述的例子可以看出,不同版本的web.xml文件主要有两处不同的地方: (1) 文件头中Javaee变成小写。 (2) org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 核心控制器的类名发生了变化,由原来的org.apache.struts2.dispatcher.FilterDispatcher变成org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter。 3.2.2常用属性 下面详细介绍web.xml文件中常用的一些属性。 这段代码是普通的XML文档定义,定义了当前的文件版本是2.5 版本,通过xmlns引入了命名空间http://java.sun.com/xml/ns/javaee,通过xmlns:xsi 定义了xml遵循的标签规范,通过xsi:schemaLocation定义xmlschema的地址,也就是xml书写时需要遵循的语法,由两部分组成,前面部分就是命名空间的名字,后面是xsd(xmlschema)的地址。 接下来是对核心控制器的定义,也可以是用户自定义的过滤器,基本语法格式如下: 过滤器名 过滤器对应类 参数名称 参数值 过滤器名 URL关联方式 核心控制器的定义包含以下基本的元素:  元素表示对过滤器进行定义。  元素是元素的子元素,表示过滤器的名字,该名字用来对其具体的类进行调用。  元素也是元素的子元素,表示过滤器具体的类存放的路径。  元素表示初始化参数的定义,其子元素表示参数名称,表示定义的参数值。  元素指定让Struts2框架来处理用户的哪些请求(URL)。  子元素表示过滤器的名字,与前面元素的子元素的名字一致。  表示过滤器的URL映射规则。过滤器必须和特定的URL关联才能发挥作用。 当用户发送一个请求后,web.xml中配置的Struts2核心控制器就会过滤该请求。过滤器的映射规则有3种: (1) 完全匹配,例如下面代码: 过滤器名 xxx.action (2) 路径匹配,例如下面代码匹配了根路径下的全部请求: 过滤器名 /* (3) 扩展名匹配,例如下面代码匹配了所有扩展名为.action的文件: 过滤器名 *.action 如果用户的请求是以.action结尾,过滤器就会进行过滤,将该请求转入Struts2框架处理。Struts2框架接收到*.action请求后,将根据*.action请求前面的“*”来决定调用哪个业务。 另外,配置过滤器时,还可以指定一系列的初始化参数,主要的参数: (1) config: 该参数的值是一个以英文逗号“,”隔开的字符串,每个字符串都是一个XML配置文件。Struts2框架将自动加载该属性指定的系列配置文件。如果没有指定该属性则默认使用strutsdefault.xml、strutsplugin.xml、struts.xml这三个配置文件。下面代码指定Struts2框架自动加载mystruts2.xml文件。 config mystruts2.xml (2) actionPackages,用来配置Struts2框架默认加载的Action包结构。参数的值是一个字符串类型的包空间,如果有多个包空间,可以用英文“,”符号隔开,这样,Struts2框架将扫描指定的包空间下的所有Action类。 例如: actionPackages com.test.action 这样Struts2就会去com.test.action包下面找所有实现了Action的类。 (3) configProviders: 如果用户需要实现自己的ConfigurationProvider类,用户可以提供一个或多个实现了ConfigurationProvider接口的类,然后将这些类的类名设置成该属性的值,多个类名之间以英文逗号“,”隔开。 例如: configProviders com.struts2.test.web.MyConfigurationProvider (4) 配置Struts2常量,每个元素配置一个Struts2常量,其中子元素指定了常量name,而子元素指定了常量value。在这里配置的常量等价于在struts.properties文件中配置的属性。 truts.enable.DynamicMethodInvocation false 3.2.3案例 案例1批量设置请求编码。 为了避免提交数据的中文乱码问题,需要在每次使用请求之前设置request.setCharacterEncoding("gb2312")编码格式,这样确实很麻烦。Filter可以批量拦截修改servlet的请求和响应。下面编写EncodingFilter.java文件,代码见例3.1。 例3.1EncodingFilter.java package com; public class EncodingFilter implements Filter { public void init(FilterConfig config) throws ServletException { } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("gb2312"); chain.doFilter(request, response); } } 类EncodingFilter实现了Filter接口,Filter接口中定义的三个方法都要在EncodingFilter中实现,其中doFilter()的代码实现主要的功能: 为请求设置gb2312编码,执行chain.doFilter()会继续下面的操作。转换成对应HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。 为了让filter发挥作用还需要在web.xml进行配置。见例3.2。 例3.2web.xml 部分代码 EncodingFilter com.EncodingFilter EncodingFilter /* Filter标签用来定义过滤器,filtermapping标签告诉服务器把哪些请求交给过滤器处理,这里的“/*”表示所有请求,这样,所有的请求都会先被EncodingFilter拦截,并在请求里指定gb2312字符编码。 案例2用filter控制用户访问权限。 出于信息安全和其他一些原因的考虑,项目中的一些页面要求用户满足了一定条件之后才能访问。例如让用户输入账号和密码,如果输入的信息正确就在session里做一个成功的标记,这里的成功标志就是session中的username有值,其后在请求保密信息的时候判断session中是否有已经登录成功的标记,存在则可以访问,不存在则禁止访问。假设要保护的页面是admin/index.jsp 编写SecurityFilter.java,控制用户访问权限。代码见例3.3和例3.4。 例3.3SecurityFilter.java package com; public class SecurityFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(); if (session.getAttribute("username") != null) { chain.doFilter(request, response); } else { res.sendRedirect("../failure.jsp"); } } 例3.4web.xml 部分代码 SecurityFilter com.SecurityFilter SecurityFilter /admin/* 定义SecurityFilter过滤器,让它过滤匹配/admin/*的所有请求,/admin/路径下的所有请求都会接受SecurityFilter的检查 因为Filter本来设计成为多种协议服务,http协议仅仅是其中一种,将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。得到了http请求之后,可以获得请求对应的session,判断session中的username变量是否为null,如果不为null,说明用户已经登录,就可以调用doFilter继续请求访问的资源。如果为null,说明用户还没有登录,禁止用户访问,并使用页面重定向跳转到failure.jsp页面显示提示信息。因为/failure.jsp的位置在/admin/目录的上一级,所以加上两个点才能正确跳转到failure.jsp,两个点“..”代表当前路径的上一级路径。 3.3配置文件struts.properties 3.3.1文件作用 Struts2提供了很多可配置的属性,通过这些属性的设置,可以改变框架的行为,从而满足不同的Web应用的需求。这些属性可以在struts.properties文件中进行设置,该文件是Struts2框架的全局属性文件,也是自动加载的文件。 配置文件struts.properties是标准的Java 属性文件格式,使用“#”号作为注释字符,该文件是由一系列的keyvalue对组成,每个key就是一个Struts2的属性,该key对应的value就是一个Struts2的属性,该文件位于classpath下,通常放在Web应用程序的/WEBINF/classes目录下。struts.properties文件里的代码见例3.5。 例3.5struts.properties ###指定加载Struts2配置文件管理器,默认为org.apache.struts2.config.DefaultConfiguration ### 开发者可以自定义配置文件管理器,该类要实现Configuration接口,可以自动加载struts2配置文件。 # struts.configuration=org.apache.struts2.config.DefaultConfiguration ### 设置默认的locale和字符编码 # struts.locale=en_US struts.i18n.encoding=UTF-8 ### 指定struts的工厂类 # struts.objectFactory = spring ### 指定spring框架的装配模式 ### 装配方式有: name, type, auto, and constructor (name 是默认装配模式) struts.objectFactory.spring.autoWire = name ### 该属性指定整合spring时,是否对bean进行缓存,值为true or false,默认为true 。 struts.objectFactory.spring.useClassCache = true ### 指定类型检查 #struts.objectTypeDeterminer = tiger #struts.objectTypeDeterminer = notiger ### 该属性指定处理 MIME-type multipart/form-data,文件上传 # struts.multipart.parser=cos # struts.multipart.parser=pell struts.multipart.parser=jakarta # 指定上传文件时的临时目录,默认使用 javax.servlet.context.tempdir struts.multipart.saveDir= struts.multipart.maxSize=2097152 ### 加载自定义属性文件 (不要改写struts.properties!) # struts.custom.properties=application,org/apache/struts2/extension/custom ### 指定请求url与action映射器,默认为#org.apache.struts2.dispatcher.mapper.DefaultActionMapper #struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper ### 指定action的后缀,默认为action struts.action.extension=action ### 被 FilterDispatcher使用 ### 如果为 true 则通过jar文件提供静态内容服务。 ### 如果为 false 则静态内容必须位于 /struts struts.serve.static=true ### 被 FilterDispatcher使用 ### 指定浏览器是否缓存静态内容,测试阶段设置为false,发布阶段设置为true。 struts.serve.static.browserCache=true ### 设置是否支持动态方法调用,true为支持,false不支持。 struts.enable.DynamicMethodInvocation = true ### 设置是否可以在action中使用斜线,默认为false不可以,想使用需设置为true。 struts.enable.SlashesInActionNames = false ### 是否允许使用表达式语法,默认为true。 struts.tag.altSyntax=true ### 设置当struts.xml文件改动时,是否重新加载。 ### - struts.configuration.xml.reload = true ### 设置struts是否为开发模式,默认为false,测试阶段一般设为true。 struts.devMode = false ### 设置是否每次请求,都重新加载资源文件,默认值为false。 struts.i18n.reload=false ###标准的UI主题 ### 默认的UI主题为xhtml,可以为simple、xhtml或ajax struts.ui.theme=xhtml ###模板目录 struts.ui.templateDir=template #设置模板类型。可以为ftl、vm或jsp struts.ui.templateSuffix=ftl ###定位velocity.properties 文件。默认velocity.properties struts.velocity.configfile = velocity.properties ### 设置velocity的context。 struts.velocity.contexts = ### 定位toolbox。 struts.velocity.toolboxlocation= ### 指定web应用的端口。 struts.url.http.port = 80 ### 指定加密端口 struts.url.https.port = 443 ### 设置生成url时,是否包含参数。值可以为: none、get或all struts.url.includeParams = get ### 设置要加载的国际化资源文件,以逗号分隔。 # struts.custom.i18n.resources=testmessages,testmessages2 ### 对于一些web应用服务器不能处理HttpServletRequest.getParameterMap() ### 像 WebLogic、Orion和OC4J等,须设置成true,默认为false。 struts.dispatcher.parametersWorkaround = false ### 指定freemarker管理器 #struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager ### 设置是否对freemarker的模板设置缓存 ### 效果相当于把template拷贝到 WEB_APP/templates。 struts.freemarker.templatesCache=false ### 通常不需要修改此属性。 struts.freemarker.wrapper.altMap=true ### 指定xslt result是否使用样式表缓存。开发阶段设为true,发布阶段设为false。 struts.xslt.nocache=false ### 设置struts自动加载的文件列表。 struts.configuration.files=struts-default.xml,struts-plugin.xml,struts.xml ### 设定是否一直在最后一个slash之前的任何位置选定namespace。 struts.mapper.alwaysSelectFullNamespace=false 3.3.2常用属性 该文件中包含很多属性,下面进行介绍: struts.configuration: 该属性指定加载Struts2配置文件的文件管理器。默认值是org.apache.struts2.config.DefaultConfiguration。 struts.locale: 设置Web应用的默认Locale。 struts.i18n.encoding: 设置Struts2应用编码的默认使用字符集,如需获取中文请求参数值,应该将该常量值设置为GBK或者GB2312。 struts.objectFactory: 该属性默认值是spring,设置Struts2默认的ObjectFactory Bean。 struts.objectFactory.spring.autoWire: 设置Spring框架的自动装配模式,该属性默认值是name,即默认根据Bean的name进行自动装配。 struts.objectFactory.spring.useClassCache: 该属性指定整合Spring框架时,是否缓存Bean实例,该属性只允许使用true和false两个属性值,默认值是true,通常不建议修改该属性的值。 struts.objectTypeDeterminer: 该属性指定Struts2的类型检测机制,通常支持tiger和notiger两个属性值。 struts.multipart.parser: 该属性指定处理multipart/formdata的MIME类型(文件上传)请求的框架,该常量支持cos、pell和jakarta等常量值,即分别对应使用cos的文件上传框架、pell上传及commonfileupload文件上传框架。该属性的默认值为jakarta。如果需要使用cos或者pell的文件上传方式,则应该将对应的JAR文件复制到Web应用中。例如,使用cos上传方式,则需要自己下载cos框架的JAR文件,并将该文件放在WEBINF/lib路径下。 struts.multipart.saveDir: 该属性的默认值是javax.servlet.context.tempdir,该属性指定上传文件的临时保存路径。 struts.multipart.maxSize: 该属性设置Struts2文件上传中整个请求内容允许的最大字节数。 struts.custom.properties: 该属性指定Struts2应用加载用户自定义的属性文件,该属性文件配置的常量不会覆盖struts.properties文件中配置的常量。如果需要加载多个自定义属性文件,多个自定义属性文件的文件名应以英文逗号“,”隔开。 struts.mapper.class: 指定将HTTP请求映射到指定Action的映射器,Struts2提供了默认的映射器: org.apache.struts2.dispatcher.mapper.DefaultActionMapper。默认映射器根据请求的前缀与Action的name属性完成映射。 struts.action.extension: 该属性指定需要Struts2处理的请求后缀,默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号“,”隔开。 struts.serve.static: 该属性设置是否通过JAR文件提供静态内容服务,该属性只支持true和false属性值,该属性的默认属性值是true。 struts.serve.static.browserCache: 该属性设置浏览器是否缓存静态内容。当应用处于开发阶段时,如果希望每次请求都获得服务器的最新响应,则可设置该属性为false。 struts.enable.DynamicMethodInvocation: 该属性设置Struts2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。 struts.enable.SlashesInActionNames: 该属性设置Struts2是否允许在Action名中使用斜线,该属性的默认值是false。如果希望允许在Action名中使用斜线,则可设置该属性为true。 struts.tag.altSyntax: 该属性指定是否允许在Struts2标签中使用表达式语法,因为通常都需要在标签中使用表达式语法,故此属性应该设置为true,该属性的默认值是true。 struts.devMode: 该属性设置Struts2应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。 struts.i18n.reload该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发,但在产品发布阶段应将该属性设置为false。开发阶段将该属性设置了true,将可以在每次请求时都重新加载国际化资源文件,从而可以让开发者看到实时开发效果; 产品发布阶段应该将该属性设置为false,是为了提供响应性能,每次请求都需要重新加载资源文件会大大降低应用的性能。 struts.ui.theme: 该属性指定视图标签默认的视图主题,该属性的默认值是xhtml。 struts.ui.templateDir: 该属性指定视图主题所需要模板文件的位置,该属性的默认值是template,即默认加载template路径下的模板文件。 struts.ui.templateSuffix: 该属性指定模板文件的后缀,该属性的默认属性值是ftl。该属性还允许使用ftl、vm或jsp,分别对应FreeMarker、Velocity和JSP模板。 struts.configuration.xml.reload: 该属性设置当struts.xml文件改变后,系统是否自动重新加载该文件。该属性的默认值是false。 struts.velocity.configfile: 该属性的默认值为velocity.properties。该属性指定Velocity框架所需的velocity.properties文件的位置。 struts.velocity.contexts: 该属性指定Velocity框架的Context位置,如果该框架有多个Context,则多个Context之间以英文逗号“,”隔开。 struts.velocity.toolboxlocation: 该属性指定Velocity框架的toolbox的位置。 struts.url.http.port: 该属性指定Web应用所在的监听端口。该属性通常没有太大的用途,只是当Struts2需要生成URL时(例如url标签),该常量才提供Web应用的默认端口。 struts.url.https.port: 该属性类似于struts.url.http.port常量的作用,区别是该常量指定的是Web应用的加密服务端口。 struts.url.includeParams: 该属性指定Struts2生成URL时是否包含请求参数。该属性接受none、get和all三个值,分别对应于不包含、仅包含GET类型请求参数和包含全部请求参数。 struts.custom.i18n.resources: 该属性指定Struts2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号“,”隔开。 struts.dispatcher.parametersWorkaround: 该属性的默认值是false。对于某些Java EE服务器,不支持HttpServlet Request调用getParameterMap()方法,此时可以设置该常量值为true来解决该问题。对于WebLogic、Orion和OC4J服务器,通常应该设置该常量为true。 struts.freemarker.manager.classname: 该属性指定Struts2使用的FreeMarker管理器。该属性的默认值是org.apache.struts2.views.freemarker.FreemarkerManager,这是Struts2内建的FreeMarker管理器。 struts.freemarker.wrapper.altMap: 该属性只支持true和false两个值,默认值是true,通常无须修改该常量值。 struts.xslt.nocache: 该属性指定是否关闭XSLT Result的样式表缓存。当应用处于开发阶段时,该常量通常被设置为true; 当应用处于产品使用阶段时,该常量通常被设置为false。 struts.configuration.files: 该属性指定Struts2框架默认加载的配置文件,如果需要指定多个默认加载的配置文件,则多个配置文件的文件名之间以英文逗号“,”隔开。默认值是strutsdefault.xml,strutsplugin.xml,struts.xml,所以Struts2框架默认加载struts.xml文件。 实际应用中,struts.properties不推荐使用,因为所有的设置都可以通过struts.xml里的常量来实现。 3.4配置文件struts.xml 3.4.1文件作用 配置文件struts.xml是Struts2框架的核心配置文件,主要用于配置和管理开发人员编写的Action,以及Action包含的result定义、Bean的配置、常量的配置、包的配置和作用于action的拦截器的配置等。 该文件通常放在Web应用程序的WebINF/classes目录下,将被Struts2框架自动加载。struts.xml文件的基本结构如下所示: /success.jsp /error.jsp 前3行是XML的头,定义了基本信息。文件的根元素是标签,其他标签都是包含在它里面的,很多元素都是可以重复定义的,以配置不同的内容。 3.4.2常用属性 1. 包配置(package) Struts2框架使用包来管理Action和拦截器等,每个package就是多个Action、多个拦截器、多个拦截器引用的集合,从而简化维护工作,提高了代码的重用性。另外,package元素可以扩展其他的包,从而“继承”原有包的所有定义,也可以添加自己的包特有的配置,以及修改原有包的部分配置。 Package元素的常用属性如表3.1所示。 表3.1Package的常用属性 属性名必选/可选说明 name必选指定包名,这个名字将作为引用该包的键。注意,包的名字必须是唯一的,在一个struts.xml文件中不能出现两个同名的包。 extends可选允许一个包继承一个或多个先前定义的包。 abstract可选将其设置为true,可以把一个包定义为抽象的。抽象包不能有action定义,只能作为“父”包被其他包所继承。 namespace可选将保存的action配置为不同的命名空间。 例如: 配置一个名为stu的包的代码如下: 2. 命名空间的配置(namespace) Struts2以命名空间的方式来管理Action,主要针对大型项目Action重名的问题,因为不在同一个命名空间的Action可以使用相同的Action名字,同一个命名空间不能有同名的Action。代码见例3.6。 例3.6命名空间示例部分代码 /foo.jsp /moo.jsp /foo2.jsp 当发起/moo.action请求时,框架会在根命名空间“/”中查找moo.action,如果没找到再到默认命名空间下查找。在此例中,Mypackage中存在moo.action,因此执行cn.com.web. LoginActionTwo类。 如果发起/accp/foo.action请求时,框架会在/accp命名空间查找foo.action,找到后执行cn.com.web.LoginActionThree类。 如果发起/accp/bar.action请求时,框架会在/accp命名空间下查找bar.action,没有找到,那么转到默认命名空间下查找,此时查找bar.action文件,执行cn.com.web.LoginAction类。 3. Action的配置 Action主要配置action类的调用,Struts2框架的核心功能是Action,开发好action后,需要在struts.xml中进行配置,action元素配置action的物理路径以及映射路径,用来告诉Struts2框架,针对某个URL的请求应该交给哪个action类进行处理。详细的属性在第4章介绍。 /success.jsp /error.jsp name表示action 的名字,Struts2框架根据action 的名字查找相应的类,调用时class表示action类具体存放的物理路径。 4. 包含配置(include) 利用include元素,可以将一个struts.xml配置文件分割成多个配置文件,然后在struts.xml中使用include元素引入其他配置文件。比如一个网上购物程序,可以把用户配置、商品配置、订单配置分别放在3个配置文件user.xml、goods.xml和order.xml中,然后在struts.xml中将这3个配置文件引入: 5. 常量配置(constant) 通过struts.xml文件中的常量配置,可以指定Struts2框架的属性,其实这些属性也可以在其他配置文件中指定,例如在web.xml配置文件的元素中可以指定常量,也可以在 struts.properties文件中定义属性来实现。反过来,struts.properties配置文件中的所有属性都可以通过标记配置在struts.xml中: 6. Bean的配置 Struts2框架是一个具有高度可扩展性的框架,其大部分的核心组件都不是以直接编码的方式写在代码中的,而是以可配置的方式来管理Struts2的核心组件,这样,就使得这些核心组件具有可插可拔的功能,降低了代码的耦合度。 当开发人员需要扩展该框架的核心组件,或者替换Struts2的核心组件时,只需要提供自己的组件实现类,并将该组件实现类部署在struts.xml中就可以。 使用元素在struts.xml文件中定义Bean,通常有如下两个作用。 (1) 创建该Bean的实例,将该实例作为Struts2框架的核心组件使用。 (2) Bean包含的静态方法需要注入一个值。 例如下面的struts.xml文件中的Bean配置,该Bean实现了ObjectFactory接口,实现类是MyObjectFactory。配置代码片段如下: bean元素有如下几个属性:  class: 必填属性,它指定Bean实例的实现类。  type: 可选属性,它指定Bean实例实现的Struts2的规范,该规范通常是通过某个接口来体现,因此该属性的值通常是一个Struts2接口。如果需要将Bean实例作为Struts2组件来使用,则应该指定该属性的值。  name: 可选属性,该属性指定Bean实例的名字,对于有相同type类型的多个Bean,它们的name属性不能相同。  scope: 可选属性,该属性指定Bean实例的作用域,属性值只能是default、singleton、request、session或者thread之一。  static: 可选属性,该属性指定Bean是否使用静态方法注入,通常而言,当指定了type属性时,该属性值不应该指定为true。  optional: 可选属性,该属性指定该Bean是否是一个可选的Bean。 3.4.3案例 案例3这是一个比较完整的struts.xml文件,里面演示了各种元素的使用方法与用途,并进行了详细的注释。代码见例3.7。 例3.7struts.xml 参数值* 参数值* 参数值* 参数值 参数值* ? 映射资源 参数值* 异常处理资源 参数值* 参数值* 映射资源 参数值* 参数值* 异常处理资源 参数值* * ...* ? 思考与练习 (1) 简述Struts2体系结构? (2) 命名空间是什么?怎样配置? (3) Struts.xml文件有什么作用?