struts2配置文件之——web.xml文件
任何一个mvc框架都离不开web.xml文件的配置,web.xml文件是所有Java Web应用程序都需要的核心文件。
Struts2框架需要在web.xml中配置它的核心控制器——StrutsPrepareAndExecuteFilter。用于对框架进行初始化,以及处理所有请求。
使用struts2框架的web.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
StrutsPrepareAndExecuteFilter作为一个Filter在web应用中运行,它负责拦截所有用户请求,当用户请求到达时,该Filter会过滤用户请求。如果用户请求以".action"结尾,该请求将被输入struts2框架进行处理。
Struts2配置文件之——Action
在Struts2框架中控制器是由两个部分组成的。核心控制器用于拦截用户请求,对请求进行处理。业务控制器调用相应的Model类实现业务处理,返回结果。
提示: 普通的java类也可以作为Action类,只要该类含有一个返回字符串的无参的public方法即可。
在struts.xml里配置Action如下图:
<?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>
<!--创建一个default包,继承自Struts2的struts-default包 -->
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="cn.ssh.ch08.LoginAction">
<!-- 结果为"success"时,跳转 至success.jsp页面-->
<result name="success">/success.jsp</result>
<!-- 结果为"error"时,跳转 至fail.jsp页面-->
<result name="error">/fail.jsp</result>
<!-- 结果为"input"时,跳转 至login.jsp页面-->
<result name="input">/login.jsp</result>
</action>
</package>
</struts>
在配置文件中将一个请求的URI,也就是action的名字对应到一个Action类,当一个请求匹配某个Action的名字时,框架就会使用这个Action类处理请求。action元素的name属性是必须的,表示action的名字,用于匹配请求的URI。class属性表示Action类的全限定类名。
<form action="login.action" method="post">
用户名:<input name="name"/><br>
密 码:<input type="password" name="password" /><br>
<input type="submit" value="登录">
</form>
上面这个这段代码,表单提交到login.action,它会先去到struts.xml配置文件里找name为login的action元素。然后去到class属性它对应的Action类。Action类返回一个处理后的逻辑字符串,然后又回到struts.xml配置文件里,检测哪个result元素的name属性和返回的字符串是一样的,就返回它所配置的对应的页面。
Struts2配置文件之——result元素
result元素的作用就是实现结果视图的调用,并决定视图以哪种形式展现给客户端。Action类在处理完用户请求后,会返回一个简单字符串,框架根据这个字符串选择对应的Result,因此我们将其称为逻辑视图名。逻辑视图名称由result元素的name属性来表示。result元素的值用来指定这个逻辑视图对应的物理视图资源的位置。逻辑视图名称只有与物理视图资源联系在一起,才能发挥作用,所以我们必须在配置文件中设置二者之间的对应关系。
struts2应用的执行过程 :
① web容器接收请求,把请求交给在web.xml中配置的Struts2框架的核心控制器StrutsPrepareAndExecuteFilter。
② 由StrutsPrepareAndExecuteFilter确定请求对应的Action,即业务控制器
③ 框架根据Action返回的结果字符串,由 StrutsPrepareAndExecuteFilter选择对应的result,将结果呈现给用户。
一个典型的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>
<constant name=" " value=" "/>
<package name=" " namespace=" " extends=" ">
<action name=" " class=" "
<result name=" "></result>
</action>
</package>
</struts>
<constant>元素用于配置常量,通过常量的配置,可以改变Struts2框架的一些行为,从而满足不同需求。name属性表示常量名,value属性表示常量值 。
处理中文乱码时,可以通过在struts.xml中配置常量的方式来解决。
<constant name="struts.i18n.encoding" value="UTF-8"/>
struts2中可配置的常量都 可以在struts2-core-2.3.16.3jar下的org/apache/struts2/default.properties文件中找到。
<package>元素 : struts2框架把action,result等组织在一个名package的逻辑单元中,从而简化了维护工作,提高了重用性。每个包中都包含了将要用到的action,result等的定义。与java中的包类似,与java包不同的是,struts2中的包可以继承已经定义好的包,从而继承原有的包的定义,包括action,result等的配置,也可以添加自己包的配置。
pacakage属性分析:
name:name属性是必须的,且只能是唯一的,用来指定包的名称
extends:指定要扩展的包,和java的extends关键字相似
namespace: 可选属性,定义该包中的action的命名空间。如果没有设置该属性,action放入默认命名空间中。struts2框架使用action的名称和它所在的包的命名空间来标识一个action。默认的命名空间用" "表示 ,也可以使用" / "定义一个根命名空间。二者是有区别的,当请求Web应用程序根路径下的action,框架在根命名空间中查找对应的action,如果在根路径下未找到,则再到默认的命名空间中去查找。
struts拆分配置文件:
Struts2可以将一个配置文件拆分为多个配置文件,但是默认只加载WEB-INF/classes下的struts.xml文件。将拆分过的文件整合在一起,使用include元素将其他配置文件包含进来。
<struts>
<include file="struts-user.xml"/>
<include file="struts-user.xml"/>
<!---省略其他配置->
</struts>
被包含的xml文件会被保存在WEB-INF/classes下,它们与struts.xml结构完全一样。系统加载struts.xml后会自动的加载所包含的所有配置文件。
struts-default.xml : 它是struts2框架默认的配置文件,为框架提供默认设置,这个配置文件会自动加载,struts-default包就是在struts-default.xml文件中定义。
struts-plugin.xml : struts2插件使用的配置文件。不开发插件,不需要编写这个配置文件。
Action的配置:
在这之前 ,我们先说说Action的主要作用,它的主要作用有以下三个:
1. 为给定请求封装需要做的实际工作,调用特定的业务处理类
2. 为数据的转移提供场所
3. 帮助框架决定由哪个结果呈现请求响应,也就是跳转相应的页面
Action的method属性:
使用method属性可以在同一个Action中处理不同的请求。假设我们现在要做用户登录和注册的功能,如果一个请求对应一个Action,那么我们就要编写两个Action,这样比较繁琐,我们可以在一个Action中编写不同的方法,处理不同的请求
<action name="login" class="cn.action.UserAction" method="login">
<result>/page/manage.jsp</result>
<result name="input">/page/login.jsp</result>
<result name="error">/page/fail.jsp</result>
</action>
<action name="register" class="cn.action.UserAction" method="register">
<result>/page/success.jsp</result>
<result name="input">/page/register.jsp</result>
<result name="error">/page/fail.jsp</result>
</action>
上面代码中配置了两个Act ion,它们的name属性不同,但是指向的是同一个类,Struts2在接收请求后通过method属性来确定执行同一个Action类中的哪一个方法。如果请求的是login.action,就会调用login()方法,请求的是register.action,就会调用register()方法。如果要在Action类中添加新的方法,只需要修改配置文件中的设置就可以了。使用method属性可以指定任意方法处理请求,只要该方法和execute()方法具有相同的格式。
Struts2在根据action元素的method属性查找执行方法时有两种途径:
① 查找和method属性值完全一样的方法
② 查看doMethod()形式的方法
拿上面的代码来说,请求login.action且method属性值为login时,struts2框架会首先在UserAction中找login()方法,找不到则会去找doLogin()方法。
为了减少Action配置的数量,还可以使用动态方法进行处理。
动态方法调用是指表单元素的action并不是直接等于某个action的名称,而是通过在Action的名称中使用"(!)"来标识要调用 的方法名称,格式为 actionName!methodName.action。
<action name="user" class="action.UserAction">
<result name="login">/page/manage.jsp</result>
<result name="register">/page/register.jsp</result>
<result name="login_input">/page/login.jsp</result>
<result name="error">/page/fail.jsp</result>
</action>
当请求user!login.action时,框架会调用UserAction的login()方法,当请求user!register.action时,框架将调用UserAction的regigster()方法。
但是动态的方法调用可能会带来安全隐患,通过URL可以执行Action中的任意方法,所以在确定使用动态方法调用时,应该保证Action中的所有方法都 是普通的,开放的方法。Struts2框架是默认禁止动态方法调用的,如果想要启用的话,可以通过DynamicMethodInvocation属性设置
在struts.xml文件中,配置下面的代码,启用动态方法调用
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
如果同一Action的不同方法要处理的请求使用相同的配置(Result等),则使用动态方法调用。
如果不同方法的调用需要不同的配置,那么就要使用action元素的method属性,为同一个Action配置多个名称,但使用method属性会导致配置文件中在在大量的Action配置。使用method属性比使用动态方法调用要更安全。
Action配置之通配符:
我们在配置action元素时,要指定name,class和method属性,其中name属性支持通配符,在class,method属性中可以使用表达式。使用通配符的方式是另一种形式的动态方法调用 ,通配符用星号(*)表示,用于配置0个到多个字符。
<action name="*User" class="action.UserAction" method="{1}">
<result name="success">/page/{1}_success.jsp</result>
<result name="input">/page/{1}.jsp</result>
<result name="error">/page/error.jsp</result>
</action>
上面这段代码,name属性中使用星号,代表这个Action可以匹配所有以User结尾的URI,如loginUser.action,resgiterUser.action
,method属性使用了表达式{1},这个表达式的值就是name属性值中第一个*的值,当请求为loginUser.action时,通配符匹配的是
login,那么这个值将替换{1},method的值是login,请求会由UserAction的login()方法执行。
配置默认的Action:
配置默认的Action通过<default-action-ref../>元素完成。每个package元素下只能有一个默认Action.它指定的name属性要为当 前package,子package,父package三者中的一个Action name,如果在某一个继承树上的各package中分别定义了多个
<default-action-ref../>,则搜索顺序为:由子package到父package寻找,找到即停止。
<struts>
<package name="default" extends="struts-default">
<default-action-ref name="defaultAction"/>
<action name="defaultAction">
</action>
</package>
</struts>
在配置文件,如果将action元素的class属性省略了,会默认使用ActionSupport类,ActionSupport类实现了Action接口,并给出了
execute()方法的默认实现 。
struts.xml文件配置之Result :
result元素主要完成逻辑视图和物理视图资源的映射。Result配置主要有两部分组成:一部分是Result,所代表的实际资源的位置,另一部分是Result的类型,由result元素的type属性进行设定。
result之常用结果类型:
1. dispatcher类型:
dispatcher类型是默认的结果类型,struts2在内部使用Servlet API的RequestDispatcher来转发请求。它是通过转发来完成页面的跳转。
<?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>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<package name="default" namespace="/" extends="struts-default">
<action name="*User" class="action.UserAction"
type="dispatcher /redirect /redirectAction>
<result name="success">/page/{1}_success.jsp</result>
<result name="input">/page/{1}.jsp</result>
<result name="error">/page/error.jsp</result>
</action>
</package>
</struts>
2.redirect类型:
redirect表示重定向,与dispatcher类型的主要差别在于,使用dispatcher结果类型是将请求转发到指定的视图资源,所以请求中包含的数据仍然还是存在的,而redirect结果类型是在内部使用HttpServletResponse对象的sendRedirect()方法将请求重定向到指定的URL,请求中包含的参数,属性,Action实例及Action封装的属性将全部丢失。
3. redirectAction类型:
redirectAction类型与redirect很像,都是使用HttpResponse的sendRedirect()方法将请求重定向至指定的URL。但redirectAction类型主要用于重定向到另一个Action。当请求处理完成后,需要在另一个Action中继续处理请求时,就要使用rdirectAction类型重定向到指定的Action。redirect类型常用于执行对一个具体的资源(如视图)的请求,而 redirectAction则主要用于执行一个Action的请求。
Result之动态结果:
动态结果就是在指配置时,你不知道执行后的结果是哪一个,只有在运行时才知道哪个结果作为视图显示给用户,即在配置时使用表达式,在运行时,由框架根据表达式的值来确定要使用哪个结果。
举例:用户角色有管理员,普通用户,用户登录时根据用户的角色决定用户能够浏览的资源。登录依然由UserAction来处理,
普通用户可访问的资源由OrdinaryUserAction。 ,管理员可以访问的资源由ManagerAction处理。
如下面的代码:
public class UserAction extends ActionSupport{
private String nextDispose;
//省略其他属性和getter,setter方法
/**
* execute方法,当Struts2处理用户请求时,在默认配置下调用的方法
*/
public String login(){
//省略处理代码
if(user.isManager()) {
nextDispose="manager";
}else{
nextDispose="common";
}
return SUCCESS;
}
strtus.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>
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="action.UserAction">
<result type="redirectAction">${nextDispose}</result>
<result name="error">/page/error.jsp</result>
</action>
<action name="common" class="action.OrdinaryUserAction">
<!--省略代码-->
</action>
<action name="manager" class="action.ManagerAction">
<!--省略代码-->
</action>
</package>
</struts>
在上面代码中,使用${nextDispose}来获取Action中nextDispose属性的值,这个值要在运行时才能知道,框架在运行时解析出
它的值。然后将请求重定向到指定的Action,要注意的是,使用${属性}名语法访问的属性一定要在Action中存在,并且Action要提供这个属性的getter方法。
Result配置之全局结果:
我们上面配置的结果都在action元素的内部,这些结果不能被其他的Action使用。在某些情况下,多个Action可能需要访问同一个结果,这时就需要配置全局结果来满足多个Action共享一个结果的要求。全局结果也在包中定义,这个包中所有Action都可以共享这个结果。
<?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>
<package name="default" namespace="/" extends="struts-default">
<global-results>
<result name="error">/page/error.jsp</result>
<result name="login" type="redirect">/page/login.jsp</result>
</global-results>
<action name="login" class="cn.action.UserAction" method="login">
<result>/page/manage.jsp</result>
<result name="input">/page/login.jsp</result>
<result name="error">/page/fail.jsp</result>
</action>
<action name="register" class="cn.action.UserAction" method="register">
<result>/page/success.jsp</result>
<result name="input">/page/register.jsp</result>
<result name="error">/page/fail.jsp</result>
</action>
</package>
</struts>
全局结果同样使用result元素配置,与action配置result元素的区别在于,全局结果需要在global-results元素中嵌套result元素。如果在Action中的result元素名称与全局结果的名称相同时,Action中的result元素会覆盖全局result结果。也就是说,当Action处理用户请求结束后,会首先在本Action中的result结果中搜索与逻辑视图名称对应的结果,只有在Action中无法找到与逻辑视图对应的结果时,才会去全局结果中寻找并执行。