码迷,mamicode.com
首页 > 其他好文 > 详细

1使用Struts2

时间:2016-07-13 17:13:00      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

1Struts2实例
Struts2当前最新版本是struts2.1.8版,其下载地址为:
http://struts.apache.org/download.cgi#struts2181
将下载的struts2文件解压,可以看到四个目录,我们将lib目录下的struts2-core-2.1.8.1.jar和xwork-core-2.1.6.jar,commons-logging-1.0.4.jar,freemarker-2.3.15.jar,ognl-2.7.3.jar,commons-fileupload-1.2.1.jar,commons-io-1.3.2.jar
必需的类库复制到Web应用的WEB-INF/lib路径下,如果你的Web应用需要使用Struts2的更多特性,则需要将更多的jar文件复制到Web应用的WEB-INF/lib路径下。




1web.xml的配置
WEB-INF目录下的WEB-INF/web.xml文件是用于配置struts2的核心Filter,下面是web.xml文件的内容:
<?xml version="1.0" encoding="UTF-8"?> 
<web-app 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"> 
<display-name>Struts 2.0 Hello World </display-name> 
<!-- 配置Struts 2框架的核心Filter -->  
<filter> 
<!-- 配置Struts 2核心Filter的名字 -->
<filter-name>struts2</filter-name> 
<!-- 配置Struts 2核心Filter的实现类 -->   
<filter-class> 
org.apache.struts2.dispatcher.FilterDispatcher 
</filter-class> 
</filter> 


<!-- 配置Filter拦截的URL --> 
<filter-mapping> 
<filter-name>struts2</filter-name> 
<!-- 配置Struts 2的核心FilterDispatcher拦截所有用户请求 --> 
<url-pattern>/*</url-pattern> 
</filter-mapping> 


<welcome-file-list> 
<welcome-file>index.html</welcome-file> 
</welcome-file-list> 
</web-app> 
每个项目中的web.xml基本上不变。
因为Struts 2将核心控制器设计成Filter,而不是一个普通Servlet。故为了让Web应用加载FilterDispacher,只需要在web.xml文件中配置FilterDispatcher即可。
在web.xml文件中配置了该Filter,还需要配置该Filter拦截的URL。通常,我们让该Filter拦截所有的用户请求,因此使用通配符来配置该Filter拦截的URL。 


2前端页面的编写
下面Web应用目录下建立一个login.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<!-- 提交请求参数的表单 -->
<form action="Login.action" method="post">
<table align="center">
<caption><h3>用户登录</h3></caption>
<tr>
<td>用户名:<input type="text" name="username"/></td>
</tr>
<tr>
<td>密&nbsp;&nbsp;码:<input type="text" name="password"/></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" value="登录"/>
<input type="reset" value="重填" />
</td>
</tr>
</table>
</form>
</body>
</html>
注意该表单被提交后交给login.action处理,因为struts2 Action默认拦截所有后缀为.action的请求。而login就是struts.xml文件中配置的某个<action name="login">的name属性的值。
<input type="text" name="username"/>中的name值于Action中的属性名相对应。


**********如果Action类的属性为某个实体类,那么<input type="text" name="实体类vo.属性名"/>将会把文本框的值赋给实体类的属性。*************


3控制类Action的编写
实现控制器类
struts下的控制器不再像struts1下的控制器需要继承一个Action父类,甚至可以无需实现任何接口,Struts2的控制器就是一个普通的POJO。实际上struts2的Action就是一个包含execute方法的普通的java类,该类里包含了多个属性对应与用户的请求参数,下面是处理login.jsp用户请求的Action类的代码:
package mypack;
public class LoginAction
{
//下面是Action内用于封装用户请求参数的两个属性
   private String username;
   private String password;
//username属性对应的getter方法
   public String getUsername()
   {
   return username;
   }
//username属性对应的setter方法
   public void setUsername(String username)
   {
   this.username = username;
   }
//password属性对应的getter方法
   public String getPassword()
   {
    return password;
   }
//password属性对应的setter方法
public void setPassword(String password)
   {
    this.password = password;
   }
//处理用户请求的execute方法
public String execute() throws Exception {
// 如果用户名为scott,密码为tiger,则登录成功
if (getUsername().equals("scott") && getPassword().equals("tiger")) {
return "success";
} else {
return "error";
}


}
}
上面的Action类是一个普通的java类,该类定义类两个属性:username和password,并为这两个属性提供了对应的setter和getter方法。由于Struts2的拦截器机制,它们负责解析用户的请求参数,并将请求参数赋值给Action对应的属性。该Action将调用自身的execute方法处理用户请求,如果execute方法返回success字符串,根据Action的配置请求将被转发到/welcome.jsp页面;如果execute方法返回error字符串,则请求被转发到/error.jsp页面。




4Action的配置struts.xml
配置Action
为了让上面的Action类能处理用户请求,还需要将该Action配置在struts.xml文件中,struts.xml文件应该放在WEB-INF/classess目录下,下面是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>
<package name="default" extends="struts-default">
<action name="Login"  class="mypack.LoginAction">
<result name="error">/error.jsp</result>
<result name="success">/welcome.jsp</result>
</action>
</package>
</struts>
Action的配置主要放在<action>....</action>之间,上面映射文件定义了name为Login的Action。即:该Action将负责处理传递给login.action URL的客户端请求。<result>...</result>之间放置对Action程序处理结果的应该导向的页面。
这里配置了action,那么在浏览器中访问action的路径为:Http://ip:port/web项目名/Login.action,如果包含这个action的<package>还配置了命名空间,则访问路径为:
Http://ip:port/web项目名/命名空间名称/Login.action
所以我们在前端页面访问后台action的时候要注意浏览器上action的路径。




5核心控制器:FilterDispatcher
FilterDispatcher是Struts 2框架的核心控制器,该控制器作为一个Filter运行在Web应用中,它负责拦截所有的用户请求,当用户请求到达时,该Filter会过滤用户请求。如果用户请求以action结尾,该请求将被转入Struts 2框架处理。
Struts 2框架获得了*.action请求后,将根据*.action请求的前面部分决定调用哪个业务逻辑组件,例如,对于login.action请求,Struts 2调用名为login的Action来处理该请求。Struts 2应用中的Action都被定义在struts.xml文件中,在该文件中定义Action时,定义了该Action的name属性和class属性,其中name属性决定了该Action处理哪个用户请求,而class属性决定了该Action的实现类。


Struts 2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的请求参数解析出来,传入到Action中,并回调Action的execute方法来处理用户请求。




********************
2struts2常量配置:
struts.i18n.encoding,指定解析请求参数时所用的解码集,该属性对于处理中文请求参数非常有用,对于获取中文请求参数值,应该将该属性设置为GBK或GB2312。


struts.objectFactory,指定struts2默认的ObjectFactory Bean,该属性默认值为spring。


struts.objectFactory.spring.autoWire,指定spring框架的自动装配模式,该属性的默认值是name,即根据Bean的name属性自动装配。


struts.multipart.parser,该属性指定处理multipart/form-data的MIME类型请求的框架。该属性支持cos,pell和jakarta等属性值,即分别对应使用cos的文件上传框架,pell上传以及common-fileupload文件上传框架。默认为jakarta。


struts.multipart.saveDir,该属于指定上传文件的临时保存路径。该属性的默认值为javax.servlet.context.tempdir
struts.multipart.maxSize,该属性指定Struct2文件上传中整个请求内容允许的最大字节数。
struts.action.extention,该属性指定需要struts2处理的请求后缀,该属性的默认值是action。如果用户需要制定多个请求后缀,则多个后缀之间以逗号隔开。


struts.configuration.xml.reload,该属性设置当struts.xml文件改变后,系统是否自动重新加载该文件。默认为false。
strtus.custom.i18n.resource,该属性指定struts2应用所需要的国际化资源文件,如果有多个国际化资源文件,则多个资源文件的文件名要以逗号隔开。例如:
<constant name="struts.custom.il8n.resources" value="messageResource"/>


struts.configuration.files,该属性指定struts2框架加载的配置文件,如果需要指定多个默认加载的配置文件,则文件名之间以逗号隔开。该属性的默认值为:
strus-default.xml,struts-plugin.xml和struts.xml。


struts.serve.static.browserCache:该常量设置浏览器是否缓存静态内容。当应用处于开发阶段时,我们希望每次请求都获得服务器的最新响应,则可设置该常量为false。


struts.xml中常量通过<constant.../>元素配置在<struts>....</struts>中。


3包和命名空间
*****包和命名空间*******
Struts2使用包来组织Action,因此将Action定义放在包定义下完成,定义Action通过使用package下的action子元素来完成。
struts2框架中核心组件就是Action,拦截器等,Struts2框架使用包来管理Action和拦截器等,每个包就是多个Action,多个拦截器,多个拦截器引用的集合。


配置package元素的属性:
name属性,这个属性就是该包的唯一标识。


可选的extends属性,extends属性值必须是另一个包的name属性。指定extends属性表示让该包继承另一个包,子包可以从一个或多个包中继承到拦截器,拦截器栈,action等配置。当我们在一个struts1.xml文件中include另一个struts2.xml文件时,如果想将struts1.xml配置的拦截器应用到struts2.xml的action上,可以使用在struts2.xml的extends属性中指定struts1.xml的拦截器所在的包名即可。


namespace是一个可选属性,该属性定义该包的命名空间。abstract该属性是一个可选属性,取值true它指定该包是一个抽象包,抽象包不能包含Action的定义。在指定名称空间时可以带上斜杠/,也可以不带上斜杠/。如:
namespace="kk"或namespace="/kk"都可以。建议使用加上/在Eclipse中,否则会报错找不到该命名空间。当在jsp中请求时命名空间名称前不要带上/。


abstract:该属性时一个可选属性,它指定该包是否是一个抽象包。抽象包不能包含Action定义。


struts2之所以提供命名空间的功能,主要是为了处理同一个Web应用中包含同名的Action,同一命名空间下不能有同名的Action。如果配置package时没有指定namespace属性,则该包下的所有Action处于默认的包空间下,默认的命名空间总是""。
*****当某个包指定了命名空间后,该包下所有的Action处理的URL应该是命名空间+Action名。例如:********
http://localhost:8080/web应用目录名/kk/Login.action
对于系统首先到命名空间下的对应的Action,如果没有找到,则去默认的命名空间下查找。
如果namespace="/"则表示是根命名空间。如果指定了根命名空间,则系统只在根命名空间下查找而不去默认命名空间下查找。


例如,下面我们配置一个包的命名空间为"/kk"
<package name="ff" extends="struts-default" namespace="/kk">
<action name="Login"  class="lee.LoginAction">
<result name="error">/hello.jsp</result>
<result name="success">/welcome.jsp</result>
</action>
</package>
那么在<form>中请求Login.action应该在该action前面加上包名:
<form action="kk/Login.action" method="post">


如果我们写成<form action="/kk/Login.action" method="post">可能会出现404错误它表示在根目录下寻找
kk/Login.action,请求路径变成http://127.0.0.1:8080/kk/Login.action而不是在web的项目目录下这样导致404错误。


struts2-core-2.1.2.jar里定义了struts-default抽象包,该包下包含了大量结果类型定义,拦截器定义,拦截器引用定义等,这些定义是配置普通Action的基础,所以开发者定义的package通常应该继承struts-default包。


实际上所有的struts2插件文件都会提供一个struts-plugin.xml文件,而不同插件的struts-plugin.xml文件会定义另一个插件包,用于被需要使用该开发者继承。如果我们需要使用struts2的某个插件,可能需要struts2插件文件中定义的包。


4Action的动态方法调用
*****使用Action的动态方法调用********
struts1提供了DispatchAction,从而允许一个Action内包含多个控制处理逻辑。struts2也提供了这种包含处理多个处理逻辑的Action.struts2中采用动态方法调用处理这种请求,动态方法调用是指表单元素的action并不是直接等于某个Action的名字,而是以如下形式指定Form的action属性:
action="ActionName!methodName"
其中ActionName指定提交到那个Action,而methodName指定提交到指定的方法。例如:
<form action="kkk/Login!test" method="post">
表请求命名空间kkk下的名为Login的Action下的test方法,注意这里仅仅需要Action的名称,如果写成
kkk/Login.action!test将会报404错。


使用动态方法调用前必须设置struts2允许动态方法调用,开启系统的动态方法调用时通过设置struts.enable.DynamicMethodInvocation常量来完成,设置为"true",将开启动态方法调用。如下所示:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
注意不能设置value为true,true必须用双引号""包括起来。




*****指定method属性及使用通配符******
如果在配置<action .../>元素指定了action的method属性,则可以在Action类调用指定方法,而不是execute方法来处理用户的请求。如:
<action name="login" class="lee.loginAction" method="login"/>
...
</action>
这种方法将Action类的每个处理方法都映射成一个逻辑Action,前提是这些方法具有相似的方法签名:方法的形参列表为空,方法返回值为String。
以下为对应的login方法:
public String login(){
 .....
}




Struts2还支持另一个中动态方法调用:使用通配符方式。在配置<action ..../>元素时,需要指定name,class和method属性,其中name属性可以使用模式字符串(允许*代表一个或多个任意字符),表明该Action可以处理所有能匹配该模式字符串的请求。例如:
<action name="*Action" class="lee.LoginRegistAction" method="{1}">
上面的<action name="*Action"../>元素不是一个普通的Action,而是定义了一系列的逻辑Action,只要用户请求的URL是*Action.action的模式,都可以使用该Action来处理。配置该action还定义的method属性。但该method属性使用了一个表达式{1},该表达式的值就是name属性值中第一个*的值。例如loginAction.action,则调用lee.LoginRegistAction类的login方法。
<action name="*_*" method="{2}" class="action.{1}">,method属性的值为第二个*,class中{1}的值是第一个*号。


struts2中还可以配置全局结果。如:
<global-results>
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
<result.../>可以通过type属性指定结果类型,默认的结果类型为dispatcher。struts2内建的支持结果类型如下:
chain结果类型,Action链式处理的结果类型。
dispatcher,用于指定JSP作为视图的结果类型。
freemarker,用于指定使用FreeMarker末班作为视图的结果类型。
redirect,用于直接跳转到其他URL的结果类型。
redirect-action,用于直接跳转到其他Action的结果类型。
stream,用于向浏览器返回一个InputStream(一般用于文件下载)
velocity,用于指定使用Velocity作为视图的结果类型。
xslt,用于与xml/xslt整合的结果类型。
plainText,用于显示某个页面的原始代码的结果类型。


dispatcher是将请求转发到指定的JSP资源,而redirect是重定向到指定的视图资源。转发和重定向的区别:重定向会丢失所有的请求参数,请求属性当然也丢失了Action的处理结果,相当于调用HttpServletResponse的sendRedirect(String)方法来重定向。


redirect-action与redirect类型非常相似,一样重新生成一个新的请求,但与redirect结果类型的去区别在于:redirect-action使用ActionMapperFactory提供的ActionMapper来重定向请求。当需要一个Action处理结束后,直接将请求重定向到另一个Action时,我们使用redirect-action类型。配置redirect-action结果类型时,可以指定如下两个参数:
actionName,该参数指定重定向的Action名称。
namespace,该属性指定需要重定向的Action所在的命名空间。例如:
<result type="redirect-action">
<!--指定重定向的actionName-->
<param name="actionName">dashboard</param>
<param name="namespace">/secure</param>
</result>


动态结果,例如:
<action name="*_*" class="{1}">
<result>
//{2}对应于第二个*
{2}.jsp
</result>
</action>


为Action指定参数
在struts2中还可以为action指定一个或多个参数。大家还记着struts1.x是如何设置的action参数不? 在struts1.x中可以使用<action>标签的parameter属性为其指定一个action参数,如果要指定多个,就只能通过逗号(,)或其他的分隔符将不同的参数隔开。而在struts2中可以通过<param>标签指定任意多个参数。代码如下: 
<action name="submit"  class="action.MyAction">
<param name="param1">value1</param>
<param name="param2">value2</param>
<result name="save" >/result.jsp</result>
.....
</action>
当然,在action中读这些参数也非常简单,只需要象获取请求参数一样在action类中定义相应的setter方法即可(一般不用定义getter方法)。如下面的代码将读取param1和param2参数的值: 
package action;
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport
{
private String param1;
private String param2;
public String execute() throws Exception
    {
        System.out.println(param1 + param2);
    }
public void setParam1(String param1)
    {
this.param1 = param1;
    }
public void setParam2(String param2)
    {
this.param2 = param2;
    }
 ......

当struts2在调用execute之前,param1和param2的值就已经是相应参数的值了,因此,在execute方法中可以直接使用param1和param2。 


 


5struts.xml中引入其它struts2的配置文件
*********************************
包含其它配置文件
在默认情况下,struts2只自动加载strus-default.xml,struts-plugin.xml和struts.xml。为了避免struts.xml文件过于庞大,我们可以将一个strutsxml配置文件分解为多个配置文件,然后在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>
<!--通过include元素导入其他配置文件-->
<include file="struts-part1.xml"/>
...
</struts>
被包含的struts-part1.xml文件是标准的struts2配置文件,一样包含DTD信息和格式,struts2配置文件的根元素等信息。通常和struts.xml一样也放在WEB-INF/classes路径下。


5ActionSupport基类
************************************
相对于struts1而言,struts2采用了低侵入式的设计,struts2不要求Action类继承人任何的struts2基类,或者实现任何struts2接口。struts2的Action就是一个普通的POJO(通常包含一个无参的execeute方法)。struts2通常直接使用Action来封装HTTP请求参数,因此,Action类还应该包含与请求参数对应的属性,并且这些属性提供对应的setter和getter方法。


Action接口和ActionSupport基类
struts2提供了一个Action接口,这个接口定义了Struts2的Action处理应该实现的规范。下面是一个标准的Action接口的代码:
public interface Action{
//定义Action接口里包含的一些字符串
public static final String ERROR="error";
public static final String INPUT="input";
public static final String LOGIN="login";
public static final String NONE="none‘;
public static final String SUCCESS="success";
//定义用户处理请求的execute()方法
public String execute() throws Exception;
}


ActionSupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。开发者的Action类继承该ActionSupport类,则会大大加快Action的开发。




******************************
6Action中访问Servlet
Action访问Servlet API
Struts2的Action没有与任何Servlet API耦合,Struts2框架提供了一种更轻松的方式来访问Servlet API,Web应用中通常需要访问的Servelt API就是HttpServletRequest,HttpSession和ServletContext,这三个类分别代表JSP内置对象中的request,session和application。
Struts2提供一个ActionContext类,struts2的Action通过该类访问Servlet API,下面是ActionContext类中包含的几个常用的方法:
Object get(Object key),该方法类似于调用HttpServletRequest的getAttribute(String name)方法。
Map getApplication(),返回一个Map对象,该对象模拟了应用ServletContext实例。
static ActionContext getContext(),静态方法,获取系统的ActionContext实例。
Map getParameters(),获取所有的请求参数,类似于调用HttpServletRequest对象的getParameterMap()方法。
Map getSession(),返回一个Map对象,该Map对象模拟了HttpSession实例。
void setApplication(Map application),直接传入一个Mapp实例,该Map实例里的key-value对转换成application的属性名,
void setSession(Map session),直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名,属性值。
如:
ActionContext ctx=ActionContext.getContext();
ctx.getApplication().put("counter",counter);


ServletResponseAware接口
struts2提供了一个ServletResponseAware接口,实现该接口的Action可以直接访问服务器相应的HttpServletResponse实例。例如:
publi class LoginAction implements Action,ServletResponseAware{
private HttpServletResponse reponse;
public void setServletResponse(HttpServletResponse response){
this.response=response;//得到response对象
}
public String execute() throws Exception{
......
}
}


public void setServletResponse(HttpServletResponse response),该方法有一个参数,该参数就代表了Web应用对客户端的响应,实现该方法,就可以在execute方法中访问该HttpServletResponse对象。


public void setServletRequest(HttpServletRequest request),通过该方法即可访问该表用户请求的HttpServletRequest对象。


ServletContextAware接口
pulic void setServletContext(ServletContext context),通过该方法即可访问到代表Web应用的ServletContext对象。




ServletActionContext工具类的静态方法
另外Struts2还提供了ServletActionContext工具类,这个类直接继承了我们上面介绍的ActionContext,它提供了直接与Servlet相关对象访问的功能。这个类包含了如下几个静态方法:
static PageContext getPateContext(),取得Web应用的PageContext对象。
static HttpServletRequest getRequest(),取得Web应用的HttpServletRequest对象。
static HttpServletResponse getResponse(),取得Web应用的HttpServletResponse对象。
static ServletContext getServletContext(),取得Web应用的ServletContext对象。
必须指出的是,虽然可以在Action类中获取HttpServletResponse,但是如果希望通过HttpServletResponse来生成服务器响应是不可能,因为Action只是业务控制器,即如果在Action中书写如下代码:
response.getWriter().println("Hello World");
上面的代码在标准的Servlet中会生成对客户端的响应,但在Struts2的Action中没有任何意义。即使我们在Struts2的Action类中获得了HttpServletResponse对象,也不要尝试直接在Action中对客户端生成响应。






下面是我定义的一个BaseAction类,当我们编写Action类的时候可从BaseAction继承,这样可以方便的使用BaseAction类中的方法。
@SuppressWarnings("serial")
public class BaseAction extends ActionSupport{
/**
     * 获得request
     * 
     * @return-
     */
    public HttpServletRequest getRequest()
    {
        return ServletActionContext.getRequest();
    }
    
    /**
     * 获得response
     * 
     * @return
     */
    public HttpServletResponse getResponse()
    {
        return ServletActionContext.getResponse();
    }
    
    /**
     * 获得session
     * 
     * @return
     */
    public HttpSession getSession()
    {
        return getRequest().getSession();
    }
    
    /**
     * 获得servlet上下文
     * 
     * @return
     */
    public ServletContext getServletContext()
    {
        return ServletActionContext.getServletContext();
    }
}
*******************
7struts2的拦截器
拦截器其实就是AOP(面向切面编程)的编程思想,拦截器允许在Action处理之前或Action处理结束之后,插入开发者自定的代码。在很多时,我们需要在多个Action进行相同的操作,例如权限控制,此处就可以使用拦截器来检查用户是否,用户的权限是否足够(当然也可以借助Spring的AOP框架来完成)。通常,使用拦截器可以完成如下操作:
进行权限控制
跟踪日志
跟踪系统的性能瓶颈(我们可以通过记录每个Action开始处理时间和结束之间,从而取得耗时较长的Action)
struts2也允许将过多个拦截器组合在一起,形成一个拦截器栈,一个拦截器栈可以包含多个拦截器,多个拦截器组成一个拦截器栈,对于struts2系统而言,多个拦截器组成的拦截器栈对外也表现成一个拦截器。拦截器和拦截器栈都是放在<interceptors.../>元素中定义。




struts2中内建的大量的拦截器,这些拦截以name-class对的形式配置在 struts-default.xml文件中,其中name是拦截器的名字,就是拦截器的唯一标识。class则指定该拦截器的实现类。


一旦定义了拦截器和拦截器栈之后,就可以使用这个拦截器或拦截器栈来拦截Action了,拦截器或拦截器栈的拦截行为将会在Action的execute方法执行之前被执行。


配置拦截器
在struts.xml文件中定义拦截器只需要为拦截器指定一个拦截器名,就完成拦截器定义。定义拦截器使用<interceptor.../>元素来定义。拦截器一般写在<package>中,如:
<interceptors>
<interceptor name="拦截器" class="拦截器实现类"/>
如果还需要在配置拦截器时传入拦截器参数,则需要在<interceptor.../>元素中使用<param.../>子元素。如:
<interceptor name="拦截器" class="拦截器的实现类"/>
<param name="参数名">参数值</param>
</interceptor>
</interceptors>
还可以把多个拦截器组成一个拦截器栈。定义拦截器栈使用<interceptor-stack.../>元素,拦截器栈是由多个拦截器组成的,因此需要在<interceptor-stack.../>元素中使用<interceptor-ref.../>元素来定义多个拦截器引用。如:
<interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器1"/>
<interceptor-ref name="拦截器2"/>
</interceptor-stack>


在<action..>...</action>中使用拦截器时通过<interceptor-ref.../>元素,在Action中使用拦截器的配置语法与配置拦截器栈时引用拦截器的语法一样。如:
<action >
<interceptor-ref name="拦截器1"/>
...
</action>


<interceptor-ref name="defaultStack"/>是系统默认的拦截器栈。


配置默认拦截器
当配置一个包时,可以为其指定默认的拦截器,如果该包中的Action没有显式的指定拦截器,则默认的拦截器将会起作用。如果我们为包中的Action显式应用了某个拦截器,则默认的拦截器不会起作用。如果该Action需要使用该默认拦截器,则必须手动配置该拦截器的引用。
配置默认拦截器使用<default-interceptor-ref name="拦截器名或拦截器栈名"/>元素,该元素作为<package.../>元素的子元素使用。


书写拦截器
如果用户要开发自己的拦截器类,应该实现com.opensymphony.xwork2.interceptor.Intercptor接口。该接口的定义如下:
public interface Interceptor extends Serializable
{
//销毁该拦截器之前的回调方法
void destroy();
//初始化该拦截器的回调方法
void init();
//拦截器实现拦截的逻辑方法
String intercept(ActionInvocation invocation)throws Exception;
}
该接口包含了3个方法:
init(),在该拦截器被实例化之后,在该拦截器执行拦截器之前,系统将回调该方法。对于每个拦截器而言,其init()方法只执行一次。该方法的方法体主要用于初始化资源。如数据库连接。


destroy(),该方法与init()方法对应。在拦截器实例被销毁之前,系统将回调该拦截器的destroy方法,该方法用于销毁在init()方法里打开的资源。


intercept(ActionInvocation invocation),该方法是用户需要实现的拦截器动作,就像Action的execute方法一样,intercept方法会返回一个字符串作为逻辑视图。如果该方法直接返回了一个字符串,系统将会跳转到该逻辑视图对应的实际视图资源,不会调用被拦截的Action。该方法ActionInvocation参数包含了被拦截的Action的引用,可以通过调用该参数的invoke方法,将控制权转给下一个拦截器或转给被拦截的Action。


struts2还提供了一个com.opensymphony.xwork2.interceptor.AbstractInterceptor类,该类提供了一个init和destroy的空实现,这样我们无需实现这两个方法,自定义拦截器更加简单。


例如:
public class MyInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception{
.....


String result=invocation.invoke();
return result;
}
}


8struts2的properties配置文件
struts2的配置还可以使用struts.properties来配置。当struts.properties和struts.xml同时存在时,优先使用struts.properties文件中的属性且两个文件都被使用。


*************
Struts配置文件中用Spring注入
在struts的配置文件中我们有时配置了如下两个常量,如果我们配置了struts.objectFactory=spring,那么在进行<action...></action>的配置时,<action>元素的class属性可以直接书写类的名称(注意类名的第一个字母换成小写否则会报错)而不用将包名.类名写全。Spring会自动根据我们提供的类名将相应的类注入进来。(因为第二句的autoWire=type,默认为name则Spring会自动根据名称来注入)。即使有Spring进行注入进来,给出<action>元素给出了全限定包名.类名也是可以的。
struts.objectFactory=spring
struts.objectFactory.spring.autoWire=type
在struts.xml中为:
<struts>
...
<constant name="struts.objectFactory" value="spring"/>
<constant name="struts.objectFactory.spring.autoWire" value="type"/>
</struts>


****************
struts2的valuestack
ValueStack这个对象贯穿整个Action的生命周期(每个Action类的对象实例会拥有一个ValueStack对象)。当Struts 2接收到一个.action的请求后,会先建立Action类的对象实例,并且将Action类的对象实例压入ValueStack对象中(实际上,ValueStack对于相当一个栈),而ValueStack类的setValue和findValue方法可以设置和获得Action对象的属性值。
Struts 2中的某些拦截器正是通过ValueStack类的setValue方法来修改Action类的属性值的。


当Action设置了某个属性值后,struts2将这些属性值全部封装在一个叫struts.valuestack的请求属性里。在JSP页面中输出需要的信息可以通过如下代码来获取包含全部输出信息的ValueStack对象。
request.getAttribute("struts.valuestack");
从数据结构上看,ValueStack有点类似于Map的结构,但它比Map结构更加强大。Action中所有的属性都被封装到了ValueStack对象中,Action中的属性名可以理解为ValueStack中的值的name。
JSP页面中获得ValueStack对象:
ValueStack vs=(ValueStack)request.getAttribute("struts.valuestack");
vs.findValue("blogs");


Action中获得ValueStack对象:
ValueStack vs1 = ActionContext.getContext().getValueStack();
  value1 = (String) vs1.findValue("value");
或者
ValueStack vs2 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
  value2 = (String) vs2.findValue("value");
findValue是ValueStack对象的方法:Object findValue(String expr)  
setValue是ValueStack对象的方法:void setValue(String expr, Object value)  


************
在<action ..../>的配置中,method属性指定了该action所要执行的方法名称,如果要执行action中的execute方法则就在<action.../>中不制定method属性。




************
如果web项目找不到javax.servlet包下面的类,则将servlet-api.jar和jsp-api.jar放到WEB-INF/lib目录下,这两个包在tomcat的lib下可以找到




******************


web.xml关于webAppRootKey的定义
默认情况下webAppRootKey属性的值为webapp.root(就是说系统会把“web目录的路径”压入一个叫webapp.root的系统变量,也就是说我们可以在以后的properties文件设置中,使用${webapp.root.webtools}来代替“web目录的路径”,此例为tomcat/webapp/webtools)


因为一个tomcat下面可能部署了多个基于spring、log4j的应用,webapp.root会产生冲突错误(也就是说不知道webapp.root具体代表那个应用的路径了),所以我们可以为具体应用具体配置,而不使用默认值。


如下:
 <context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>webapp.root.webtools</param-value>
 </context-param>




***************
tomcat server.xml的<Context>元素:
<Context>代表了运行在<Host>上的单个Web应用,一个<Host>可以有多个<Context>元素,每个Web应用必须有唯一的URL路径,这个URL路径在<Context>中的属性path中设定。 <Context path="/3cs" docBase="D:\tomcat7\wtpwebapps\3cs5" debug="0" reloadable="true"/>  


<Context>元素的属性:
 一: path:指定访问该Web应用的URL入口。这样请求的url为http://localhost:8080/path
 二: docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径,如果Web应用采用开放目录结构,则指定Web应用的根目录,如果Web应用是个war文件,则指定war文件的路径。
 三: reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载Web应用。



1使用Struts2

标签:

原文地址:http://blog.csdn.net/bin71722/article/details/51889620

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!