Struts2的默认配置文件是struts.xml,它的最大作用就是配置Action和请求之间的对应关系,并配置逻辑视图名和物理视图资源之间的对应关系,除此之外,struts.xml文件还可以配置Bean、常量以及导入其他配置文件。
struts.xml是联系整个Struts2框架的纽带,通过配置文件将Struts2的核心控制器StrutsPrepareAndExecuteFilter、业务控制器Action以及视图等组件关联在一起,实现相应的功能。所以struts.xml对于Struts2的重要性不言而喻,这篇文章我就讲讲struts.xml。
1.常量
Struts2规定了一些特殊的对整个Struts2应用起作用的常量,通过配置这些常量,可以改变Struts2框架的一些默认行为。
Struts2可以在三种配置文件中对常量进行配置,分别为struts.xml,struts.properties,web.xml。如果在不同的配置文件中配置了相同的常量,则会进行覆盖,常量加载顺序和覆盖顺序相反。
比如在struts.xml中配置了常量A,在web.xml中也配置了A,则web.xml中的A的值会覆盖struts.xml的值。
在struts.xml中使用<constant>标签配置常量。定义常量需要指定两个属性:name和value。
(1)在struts.xml中配置常量
<struts>
<!-- 设置编码,默认为utf-8 -->
<constant name="struts.i18n.encoding" value="utf-8"></constant>
</struts>
(2)在struts.properties中配置常量
struts.i18n.encoding = utf-8
(3)在web.xml中配置常量
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.i18n.encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
关于struts2的常用常量,可以看这篇文章。
ps:推荐在struts.xml中配置常量。在web.xml中配置会让web.xml显得很臃肿,降低可读性。如果配置的常量比较少,则可以在struts.xml中进行配置,便于集中管理,如果配置的常量比较多,则在struts.properties中进行配置,此时可以在web项目中结合使用struts.xml和struts.properties。
2.包
Struts2使用包来组织Action,包使用<package>标签进行定义,每个<package>标签定义了一个包配置。该标签常用属性如下
属性 | 功能 |
---|---|
name | 指定包的名字,该属性是必须的。 |
extends | 指定包继承的其他包,即继承了其他包中的Action。拦截器等定义,该属性是可选的。 |
namespace | 指定包的命名空间,该属性是可选的。 |
abstract | 指定包是否的一个抽象包,抽象包中不能包含Action定义,该属性是可选的。 |
在struts.xml中配置包的示例代码如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 设置编码,默认为utf-8 -->
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<!-- 指定Struts2处于开发阶段,可以进调试 -->
<constant name="struts.devMode" value="true"></constant>
<!-- Struts2的Action都必须配置在package里,此处使用默认package -->
<package name="default" namespace="/" extends="struts-default">
<!-- 定义一个名为user的action,实现类为 com.codeliu.action.UserAction-->
<action name="user" class="com.codeliu.action.UserAction">
<!-- result的name和Action类的execute方法的返回值一一对应,区分大小写 -->
<!-- result标签指明execute方法的返回值和资源视图的映射关系,转向的资源可以是jsp或者另一个action或者其他 -->
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
</struts>
上述代码配置了一个名为default的包,该包继承struts-default包。struts-default是Struts2的默认抽象包,该包下包含大量的结果类型定义、拦截器及引用定义等,这些定义时配置Action的基础,因此定义包时通常继承struts-default包。
注意:
1.一个包下可以配置多个Action。
2.还有一种包叫抽象包,抽象包里不能有Action定义,当一个包设置属性abstract = true的时候,就成了抽象包。
3.struts.xml配置文件是从上往下解析的,所以父包应该定义在子包的前面,即被继承的包要放在继承包的前面,且任意两个包的name不能相同,不然会抛出异常。
4.如果在同一个包中配置了两个name相同的Action,那么后一个Action会覆盖前一个Action。
3.命名空间
<package>标签还有一个属性叫namespace,用于指定该包所对应的命名空间。这是为了更好的管理重名的问题。同一个命名空间下不能有同名的Action,不同的命名空间里可以有相同的Action。
<action>标签是没有namesapce属性的,同一个package下的Action属于同一个命名空间。如果package没有指定namespace,则该包下的所有Action属于默认的命名空间。
比如上面代码中的<package>标签我改成如下
<!-- Struts2的Action都必须配置在package里,此处使用默认package -->
<package name="default" namespace="/codeliu" extends="struts-default">
<!-- 定义一个名为user的action,实现类为 com.codeliu.action.UserAction-->
<action name="user" class="com.codeliu.action.UserAction">
<!-- result的name和Action类的execute方法的返回值一一对应,区分大小写 -->
<!-- result标签指明execute方法的返回值和资源视图的映射关系,转向的资源可以是jsp或者另一个action或者其他 -->
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
</package>
则访问请求的URL就由
localhost:8080/项目名/user.action
变成
localhost:8080/项目名/codeliu/user.action
请求的路径应该符合namespace+Action的形式。
除此之外,还可以设置成根命名空间
namespace = "/"
这样的形式访问的URL和默认的形式一样。
配置命名空间后,Struts2会按照如下顺序搜索Action:
(1)指定命名空间:先查找指定命名空间下是否有对应的Action,如果找到则用此Action处理用户请求。
(2)默认命名空间:如果在指定命名空间下没有找到,则去默认命名空间下查找,找到则用此Action处理用户的请求。
(3)报错:如果指定命名空间和默认命名空间都找不到,则报错。
例如上面的/codeliu/user.action,程序首先去/codeliu命名空间中查找名为user的Action,找到了则用此Action处理用户请求,如果没找到,则去默认命名空间下,如果还没找到,则报错。
默认命名空间和根命名空间的区别:默认命名空间的Action可以处理任何命名空间下的Action请求,而根命名空间里的Action只能处理根命名空间下的请求。比如上面的/codeliu/user.action,如果在指定命名空间下没有此Action,则默认命名空间里的名为user的Action也可以处理这个Action请求。程序如果在指定命名空间里没有找到符合条件的Action,则直接进入默认命名空间,不会去根命名空间。
4.一个struts.xml文件包含其他struts.xml文件
一般在实际开发中,struts.xml都会变得很臃肿,这时候可以通过分解struts.xml,然后在struts.xml中包含其他的struts.xml文件。
在struts.xml中使用<include>标签包含其他struts.xml,比如下面的代码
<struts>
<include file="struts-part1.xml"></include>
<include file="struts-part2.xml"></include>
<include file="struts-part3.xml"></include>
</struts>
注意:包含的每个xml文件也必须是完整的,都必须包含DTD信息、Struts2配置文件的根元素等信息。在<include>引用文件时,是单独解析每个struts.xml文件。