`

Struts2 Action和Action配置

 
阅读更多

 

一. Action实现类

1. Action

Struts2的核心功能是action,对于开发人员来说,使用struts2框架,主要的编码工作就是编写Action类。

Struts2的Action类就是普通POJO。

Action类的属性通常是用来接收请求参数和返回页面数据的。

属性需要设置setXxx方法和getXxx方法,分别用来设置和获取属性的值。

最普通的Action类需要一个public String execute() throws Exception,该方法返回一个逻辑字符串。

 

为了规范用户开发Action类,Struts2框架提供了一个Action接口,该接口中提供了Action的通用规范模范。

该接口com.opensymphony.xwork2.Action的定义:

public interface Action{
    public static final string SUCCESS="success";
    public static final string NONE="none";
    public static final string ERROR="error";
    public static final string INPUT="input";
    public static final string LOGIN="login";
    public String execute() throws Exception;
}

 

该接口定义的5个常量的意义:

SUCCESS 表示动作执行成功,并应该把相应的结果视图显示给用户。
NONE 表示动作执行,但不应该把任何结果视图显示给用户。
ERROR 表示动作执行不成功,并应该把相应的报错视图显示给用户。
INPUT 表示输入验证失败,并应该把用户输入的那个表单重新显示给用户。
LOGIN 表示动作没有执行(用户没有登录),并应该把登录视图显示给用户。

 

当然,Struts2  Action类不一定要实现Action接口,也可以编写一个普通的Java类作为Action,只要该类提供一个返回String的无参的public方法,如下所示:

public String xxx()

 

在实际开发中,Action类很少直接实现Action接口,通常都是从com.opensymphony.xwork2.ActionSupport类继承。ActionSupport实现了Action接口和Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable的接口,提供了输入验证、错误信息存取,以及国际化的支持,选择从ActionSupport继承,可以简化action的开发。

一下是ActionSupport类的部分内容:

public class ActionSupport implments Action,Validateable,ValidateableAware,TextProvider,LocaleProvider,Serializable{
    public void addActionError(String anErrorMessage){}
    public void addActionMessage(String aMessage){}
    public void addFieldError(String fieldName,String errorMessage){}
    public void input(){}
    public void execute(){}
    public void validate(){}
    public void getText(String aTextName){}
}

struts2框架中每一个Action是一个工作单元。Action负责将一个请求对应到一个Action的处理上去,当一个Action类和一个请求相匹配,该Action类的处理方法就会被Struts2框架调用。

 

2. 间接访问Servlet API(与Servlet API解耦)(访问Map类型)

(1)非IoC方式(不常用)

Struts2框架中,Action与Servlet API相分离,这种低耦合Action不方便访问Session,ServletContext等对象。

Struts2框架提供ActionContext类。通过该类可以访问Servlet API。

ActionContext是Action的上下文对象。其中保持了action执行所需的一组对象,包括parameters,request,session,application和locale等。

ActionContext类定义了如下方法,用于获取HttpServlet,HttpSession和ServletContext对应的Map对象

ActionContext类的常用方法:

方法名称 说明
static ActionContext getContext() 获得当前线程的ActionContext对象。
Map getApplication() 获取封装了ServletContext的Map对象。
Map getSession()

获取封装了HttpSession的Map对象。

Map getParameters() 返回一个包含所有HttpServletRequest参数信息的Map对象。类似于HttpServletRequest的getParameterMap()方法。
Object get(Object key) 通过key来寻找当前ActionContext中的值。相当于getAttributes方法。
void put(Object key,Object value) 向当前ActionContext对象中存入键值对信息。相当于setAttributes方法。
void setApplication(Map application) 设置ServletContext的值。
void setSession(Map session) 设置Session的值。

 

(2)IoC方式(最推荐使用该方法)

接口名称 说明
RequestAware

 

实现该接口方法  void setRequest(java.util.Map map)

Action中需要有一个private Map对象。

 

SessionAware

实现该接口方法  void setSession(java.util.Map map)

Action中需要有一个private Map对象。

ApplicationAware

 

实现该接口方法  void setApplication(java.util.Map map)

Action中需要有一个private Map对象。

 

 

 

3. 直接访问Servlet API(与Servlet API耦合(访问真实类型)

(1)非IoC方式(不常用)

Struts2提供org.apache.struts2.ServletActionContext类来获得Servlet API。在ServletActionContext类中有以下静态方法,可以直接得到Response,ServletContext,Response对象:

public static HttpServletRequest getRequest()

public static ServletContext getServletContext()

public static HttpServletResponse getResponse()

 

通过ServletActionContext定义的常量和ActionContext的get方法也可以直接得到相应的Servlet对象。

ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST)  得到HttpServletRequest对象。

ActionContext.getContext().get(ServletActionContext.SERVLET_CONTEXT)  得到ServletContext对象。

ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE)  得到HttpServletResponse对象。

 

 

(2)IoC方式(不常用

通过IoC方式访问Servlet API,就必须在Action中实现相应的接口,这些接口是:

接口名称 说明
ServletContextAware

实现该接口的Action可以直接访问ServletContext对象。

Action需要实现该接口的方法:void setServletContext(javax.servlet.ServletContext servletContext)

Action中需要有一个private ServletContext对象。

ServletRequestAware

实现该接口的Action可以直接访问HttpServletRequest对象。

Action需要实现该接口的方法:void setServletRequest(javax.servlet.HttpServletRequest  srequest)

Action中需要有一个private HttpServletRequest对象。

ServletResponseAware

实现该接口的Action可以直接访问HttpServletResponse对象。

Action需要实现该接口的方法:void setServletResponse(javax.servlet.HttpServletResponse  response)

Action中需要有一个private HttpServletResponse对象。

SessionAware

实现该接口的Action可以直接访问HttpSession对象。

Action需要实现该接口的方法:void setSession(java.util.Map map)

Action中需要有一个private Map对象。

 

 

 

二. Action配置

1. 基本配置

开发Action类后,就需要配置action映射,以告诉struts2框架,针对某个URL的请求应该对应哪个Action类进行处理。Struts.xml中的每一个action元素就是一个action映射。

action完整的属性如表所示:

属性

是否必须

说明

name

action的名字,匹配请求URI

class

Action类的完整类名

method

执行Action时调用的方法

converter

应用于action的类型转换器的完整类名

 

例:

 

<action name="login" class="com.xxx.action.LoginAction">
    <result>/success.jsp</result>
    <result name="error">/error.jsp</result>
</action>

 

 

说明:

(1)Actionname属性必需,其他属性可选。默认情况下在name属性不允许出现斜杠(/)的。

如果需要在名字中使用斜杠(/),则需要配置struts2的struts.enable.SlashesInActionNames属性,来打开这个功能。

例:<action name="com/manager" class="com.xxx.BookManager" />

struts.xml文件配置片段:

<constant name="struts.enable.SlashesInActionNames" value="true" />

 

(2)在为action取名时,名字中尽量不要使用点号(.)(例如create.user)连接字符(-)(例如:my-action),否则会出现一些莫名其妙的问题。

其实我们不用去记忆名字中不允许出现哪些字符,只要按照通常的命名习惯去为action取名就可以了,顶多在名字中使用一下下划线(_)(例如:my_action),这样是可以保证不会出现问题。

 

 

2. 使用method属性

在软件开发中,经常会用到CRUD操作,CRUDcreate(创建)Read/Retrieve(读取)Update(更新)Delete(删除)的首字母的缩写。例如:在一个用户管理系统中,对用户有四种操作:添加用户、浏览用户、编辑用户和删除用户,分别对应CRUD的四种操作。在具体实现时,为了节省action类的数量,通常是在一个action类中编写四个方法来实现CRUD操作。

 

public String loginUser() throws Exception{} //查询用户

public String addUser() throws Exception{} //添加用户

public String updateUser() throws Exception{} //修改用户

public String deleteUser() throws Exception{} // 删除用户

 

在执行action时,默认调用方法是execute()

在配置action时,通过action元素的method属性来指定处理方法。所指定的方法必须遵循与execute方法相同的格式。

 

struts.xml文件中,对同一个action类配置不同的别名,并使用method属性,如下所示:

 

<action name="reg" class="UserAction" method="addUser">
    <result name="success" type="redirect">index.jsp</result>
    <result name="input">reg.jsp</result>
</action>
<action name="login" class="UserAction" method="loginUser">
    <result name="success">index.jsp</result>
    <result name="input">reg.jsp</result>
</action>
<action name="update" class="UserAction" method="updateUser">
    <result name="success">index.jsp</result>
    <result name="input">reg.jsp</result>
</action>
<action name="delete" class="UserAction" method="deleteUser">
    <result name="success">index.jsp</result>
    <result name="input">reg.jsp</result>
</action>
 

 

使用method属性的注意点

 

Struts2在根据action元素的method属性查找方法时有两种途径:

(1)查找与method属性值完全一致的方法

(2)查找doMethod()形式的方法。

例,

当请求reg时,struts2首先查找addUser()方法,如果找不到,则继续查找doAddUser() 方法。这种特性是从WebWork继承而来的,而WebWork提供这种特性,一方面是为了兼容旧版本WebWork遗留的功能,另一方面是因为一些方法别名的需要,例如,defaultJava的关键字,不能作为方法名,你可以使用doDefault作为方法名,在配置时,可以使用method=“default”.

 

这种特性同样也适用于动态方法调用,例如,请求/users! addUser.action,struts2会依次查找addUser()doAddUser()方法。

 

 

3. Action动态方法调用

动态方法调用(Dynamic Method Invocation,DMI)可以不要任何配置,而直接调用Action中的非execute()方法。

<action>action属性中使用感叹号( ! )来标识要调用的方法名,请求URIaction属性值的格式为:

Action名称!方法名称.action

Action名称!方法名称

 

例:配置了如下的Action

<action name=“users” class=“com.xxx.UserAction” >…..</action>

 

当请求/users!addUser.action时,将调用UserActionaddUser()方法;

当请求/users!updateUser.action时,将调用UserActionupdateUser()方法;

 

 

DMI的实现本质是,其实现代码扫描action名字中的“!字符,如果找到,则欺骗框架来调用“!字符后的方法。

虽然调用的是其它方法,但是它使用的仍然是execute方法的配置,包括验证。框架相信它正在调用的是Action类的execute()方法。

 

struts2中使用DMI有两个要注意的问题:

首先,DMI可能会带来安全隐患,由于通过URL可以执行action中的任意方法,恶意的用户会利用这一特性来执行一些敏感的方法,即使你不想这些方法被执行。所以在确定使用DMI时,你应该确保Action中的方法都是普通、开放的方法;否则,你应该加上安全控制。

其次,DMI与通配符方法有所重叠。

 

由于上述两个原因,struts2提供了一个属性配置,用于关闭DMI

struts.xml的配置片段:

<constant name="struts.enable.DynamicMethodInvocation" value="false">

 

method属性配置与动态方法调用的使用情况:

a. 如果同一个Action的不同方法使用的是相同的配置(同样的拦截器引用,同样的result映射),那么可以使用动态方法调用。

b. 如果不同的方法调用需要配置不同的拦截器引用、不同的result映射,那么可以使用action元素的method属性,为同一个Action配置多个别名。

 

 

4. Action 通配符映射

有时Action中方法的调用满足一定的规律。则可以适当使用通配符以减少配置代码。

例:
<action name="*Crud" class=“com.xxx.Crud" method="{1}">

editCrud.Action的引用将调用edit方法,deleteCrud.Action的引用将调用delete 方法。
{1}
表示匹配第一个*

 

通配符即星号(*),用于匹配0个或多个字符。在配置action时,可以在action元素的name属性中使用星号(*)来匹配任意的字符。

 

通配符中几个特殊的标记,如下所述:

*:可以匹配0个或多个任意字符,但是不包括正斜杠”/”

**:可以匹配0个或多个任意字符,包括正斜杠”/”在内

\:反斜杠,转义字符。

因为*不能匹配正斜杠,所以前面/editSubscription/add不会被匹配上。

 

action mapping中,被通配符所匹配的值可以用符号{N}来访问,其中N19的数,用来表示代替第N个被匹配上的值,说通俗点就是第N*号所表示的内容。

 

例:

通配符表达式是/edit*/add*/confirm*,它匹配上了/editOrder/addItem/confirmResult。则

{1}就代表Order{2}就代表Item{3}就代表Result

 

Struts2对通配符的检索规则:

如果配置文件中包含多种通配符的使用,Struts2按照如下规则检索Action

(1)如果能够找到name属性值与请求的Action名完全一致的<action>时,则匹配该<action>元素,而不会匹配使用通配符的配置。

(2)如果没有找到完全一致的匹配时,则按照匹配文件的匹配顺序依次匹配。最先符合的<action>将会匹配。所以<action name="*">的形式放在最后面,以防止这种形式被最先匹配。

 

 

 

三. 默认Action

Struts2框架允许使用默认Action

struts.xml中配置:

 

<package name="default" extends="struts-default">
    <default-action-ref name="DefaultAction" />    指定默认Action的名称为DefaultAction
    <action name="defaultaction" class="DefaultAction">    配置DefaultAction
        <result name="success">/default.jsp</result>
    </action>
</package>
 

默认Action的作用:当用户请求找不到对应的<action>元素时,系统将调用默认Action来接收用户请求。

说明:若没有默认Action,则当请求不存在action时,struts2会出现错误。

应用:实现美化的404页面,在访问不存在请求时直接跳转到首页。等。

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics