struts2的Action(四)

实现Action

Action是struts2应用的核心,开发中需要大量的Action类,并在struts.xml中配置Action。Action中包含了对用户请求的处理逻辑,Action类也被称为业务控制逻辑器。

struts2采用低侵入式设计,它不要求Action类继承任何的struts的基类或者实现任何struts接口。struts2的Action类是普通的POJO类(通常应该带一个无参的方法),从而有很好的代码复用性。

struts2通常直接使用Action来封装HTTP参数,因此,,Action类还应该包含于请求参数对应的实例变量,并且为这些实例变量提供相应的setter和getter方法。

比如用户请求包含productName和productDesc两个请求参数,Action类应该提供productName和productDesc两个实例变量来封装用户请求参数,并且为productName和productDesc提供对应的setter和getter方法。下面是处理该请求的Action类的代码片段:

//处理用户请求的Action类,只是一个POJO,无需继承任何基类,或实现任何接口
public class Product {
    //提供实例变量来封装HTTP请求参数
    private Integer productId;
    private String productName;
    private String productDesc;
    private double productPrice;
    //相应的setter和getter方法
    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductDesc() {
        return productDesc;
    }

    public void setProductDesc(String productDesc) {
        this.productDesc = productDesc;
    }

    public double getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(double productPrice) {
        this.productPrice = productPrice;
    }
    //Action类默认处理用户请求的方法:execute方法
    public String execute(){
       ...
       //返回处理结果字符串
       return resultStr;
    }

虽然Action需要处理的请求包含productName和productDesc等HTTP请求参数,Action类也可以不包含它们对应的实例变量。因为系统是通过对应的setter和getter方法来处理请求参数的,而不是通过实例变量来处理请求参数的。即Action类里包含对应实例变量与否不重要,重要的是需要包含void setProductName(String productName)和String getProductName()方法。

Action类里的实例变量不仅可以用来封装请求参数,还可以用来封装处理结果。如果希望将服务器提示的“注册成功”或其他信息在下一个页面输出,就可以在Action类中增加一个tip实例变量,并为之提供对应setter和getter方法,

//封装服务提示的tip实例变量
private String tip;
//tip对应的setter和getter方法
public String getTip(){
   return tip;
}
pubic void setTip(String tip){
   this.tip = tip;
}
//Action包含的注册控制逻辑
public String register() throws Exception{
   ActionContext.getContext().getSession().put("user",getUsername());
   setTip("欢迎你!" + getUsername() + "你已经注册成功!");
   return SUCCESS;
}

可以在下一个页面中使用struts2标签来输出该实例变量的值。加载JSP页面中输出tip实例变量值得代码片段如下:

<s:property value="tip"/>

系统不严格区分Action里哪个实例变量用于封装请求参数,哪个实例变量用于封装处理结果。如果用户的HTTP请求包含名为tip的请求参数,则系统会调用void setTip(String tip)方法,通过这种方式,名为tip的请求参数就可以传给Action实例;如果Action类里没有包含对应的方法,则名为tip的请求参数将无法传入该Action。

在JSP页面中输出Action的实例变量值时,也不区分该实例变量是用于封装请你参数还是处理结果。因此,struts2标签既可以输出Action的处理结果也可以输出HTTP请求参数值。

Action接口和Action基类

为规范Action类开发,struts2提供了一个Action接口,给接口定义了struts2的Action处理类应该实现的规范:

public interface Action {
    //定义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";
    //定义处理用户请求的execute方法
    public String execute() throws Exception;

}

Action接口里定义了一个execute方法,该接口的规范定义了Action类应该包含一个execute方法,该方法返回一个字符串。该接口还定义了5个字符串常量,用于统一execute方法的返回值。一般Action类处理用户请求后,有人喜欢返回welcome字符串,有人喜欢返回success字符窜… …这样不利于统一关联,故Action接口定义了这5个字符串常量:ERROR、

INPUT、LOGIN和SUCCESS,分别代表特定含义。但是,如果开发者希望用自己的字符串作为逻辑视图名,还是可以被允许的,但这并不利用后期维护。

struts2还为Action接口提供一个实现类ActionSupport,其包含相关方法等见图

AcitonSupport是个默认的Action实现类,该类里有很多默认方法,包括获取国际化信息的方法、数据校验的方法、默认的处理用户请求的方法等。它是struts2默认的Action处理类,如果让开发者的Action处理类继承ActionSupport类,会大大简化Action的开发。

Action访问Servlet API

struts2的Action没有与任何Servlet API耦合,从而能轻松地测试该Action。但是Web应用的控制器经常都是要求访问Servlet API的,例如跟踪HTTPSession状态等,通常Web应用要访问的Servlet API有HttpServletRequest、HttpSession、ServletContext等,这三个接口分别代表JSP内置对象中的request、session和application。

与Servlet API解耦的访问方式 :

为了避免与 Servlet API 耦合在一起, 方便 Action 做单元测试, Struts2 对 HttpServletRequest, HttpSession 和 ServletContext 进行了封装, 构造了 3 个 Map 对象来替代这 3 个对象, 在 Action 中可以直接使用 HttpServletRequest, HttpServletSession, ServletContext 对应的 Map 对象来保存和读取数据.

struts2提供了ActionContext类,ActionContext 是 Action 执行的上下文对象, 在 ActionContext 中保存了 Action 执行所需要的所有对象, 包括 parameters, request, session, application 等.

获取 HttpSession 对应的 Map 对象:

public Map getSession()

获取 ServletContext 对应的 Map 对象:

public Map getApplication()

获取请求参数对应的 Map 对象:

public Map getParameters()

获取 HttpServletRequest 对应的 Map 对象:

public Object get(Object key): ActionContext 类中没有提供类似 getRequest() 这样的方法来获取 HttpServletRequest 对应的 Map 对象. 要得到 HttpServletRequest 对应的 Map 对象, 可以通过为 get() 方法传递 “request” 参数实现。

完整方法如下:

与 Servlet 耦合的访问方式:

用ActionContext访问Servlet API不是直接获得Servlet API的实例。为在Action中直接访问Servlet API,struts2提供如下接口:

|>ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例。

|>ServletRequestAware:实现该接口的Action可以直接访问用户请求的HttpServletRquest实例。

|>ServletResponseAwre:实现该接口的Action可以直接访问服务器响应的HttpServletResponse实例。

另外,struts2还提供一个ServletActionContext工具类直接访问Servlet API,

借助ServletActionContext类可以在Action中访问Serlevt API,并可以避免Action类需要实现XxxAware接口,但该Action依然与Servlet API直接耦合,测试时需要有 Servlet 容器, 不便于对 Action 的单元测试,一样不利于高层次的解耦。

Action的动态方法调用

这篇写Action相关,本来应该还涉及到Action的基本配置,但前面一篇讲开发流程时基本介绍到,这里不再赘言,直接看Action的动态方法调用。

很多时候要求一个Action内包含多个控制处理逻辑。比如对同一个表单,用户可能要通过登录或注册两个不同提交按钮来提交同一个表单系统需要使用Action不同方法来处理用户请求,这就需要让同一个Action里包含多个控制处理逻辑。

”登录”按钮使用登录逻辑处理请求,“注册”按钮使用注册逻辑处理请求。可采用DMI(Dynamic Method Invocaton,动态方法调用)来处理请求。动态方法调用中表单元素的action并不是直接等于某个Action的名字,而是按如下形式来指定表单的action属性。

fun(){
<!--action属性为actionName!methodName的形式-->
target.action="action!methodName";
}

如我们可以将JSP页面“注册”按钮的代码写成:

<!--注册按钮没有任何动作,但单击该按钮时触发regist函数-->
<input type"submit" value="注册" onClick="regist();">

regist函数JavaScript代码:

function regist(){
   //获取页面的第一个表单
   targetForm = document.forms[0];
   targetForm.action = "login!regist";
}

最后一行代码就是说将该表单提交给login Action的regist方法处理。LoginRegistAction类的代码如下:

public class LoginRegistAction extends ActionSupport{
   //封装用户请求参数的两个成员变量
   private String username;
   private String password;
   //封装处理结果的tip成员变量
   private String tip;
   //省略setter和getter方法
   ...
   //Action包含的注册控制逻辑
   public String register() throws Exception{
      ActionContext.getContext().getSession().put("user",getUsername());
   setTip("欢迎你!" + getUsername() + "你已经注册成功!");
   return SUCCESS;
   }
   //Action默认包含的控制逻辑
   public String execute() throws Exception{
      if(getUsername().equals("Jujiu")&&getPassword().equals("1357afy"))
      {
         ActionContext.getContext().getSession().put("user",getUsername());
         setTip("欢迎你!" + getUsername()+"你已经注册成功!");
         return SUCCESS;
       }
   }
}

默认调用execute方法,当用户单击登录,系统将表单提交给LoginActionAction默认方法,当用户单击“注册”按钮,该表单的action会被修改为:login!regist,系统将提交给login Action(即LoginRegistAction)的regist方法处理。这种方式可以使一个Action包含多个逻辑处理,并通过为表单元素指定不同action属性来提交给action的不同方法。

使用动态方法调用,其中的方法如regist方法的声明和系统默认的execute方法除了方法名不一样外,其他如形参列表、返回值类型都应完全相同。

使用动态方法调用前需要设置struts2运行动态方法调用,即设置struts.enable.DynamicMethodInvocation常量的值为true。DMI方式存在安全缺陷。不建议常用。

method属性指定方法和通配符使用

可以使用中的method属性将一个Action类配置成多个逻辑Action,让Action调用指定方法。

<struts>
  <package name="helloWorld" extends="struts-default">

     <action name="login" class="com.afy.LoginRegist">
        <result name="details">
          /WEB-INF/pages/welcome.jsp
        </result>
     </action>

    <action name="regist" class="com.afy.LoginRegist" method="regist">
      <result name="details">
         /WEB-INF/pages/welcome.jsp
      </result>
     </action>

 </package>
</struts>

这里定义login和regist两个逻辑Action,处理类都是LoginRegist,处理逻辑由method方法指定,login的Action对应的处理逻辑是默认的execute方法,而regist的Action对应的处理逻辑是指定的regist方法。相应的JavaScript代码改为:

function regist(){
   //获取页面的第一个表单
   targetForm = document.forms[0];
   targetForm.action = "regist";
}

我们发现多个< action…/>中的定义大部分相同,造成冗余,此时可以考虑使用通配符方式。在配置< action…/>,指定name属性时使用模式字符串(用“*”代表一个或多个任意字符),可以在class、method属性及< result…/>子元素中使用表达式{N}的形式代替前面第N个星号所匹配的子串。

<struts>
  <package name="helloWorld" extends="struts-default">

     <action name="*Action" class="com.afy.LoginRegist" method=“{1}”>
        <result name="details">
          /WEB-INF/pages/welcome.jsp
        </result>
     </action>

 </package>
</struts>
时间: 2024-10-20 16:05:01

struts2的Action(四)的相关文章

SSH框架-Struts2基础-Action

Struts2的目录结构: 解压apps目录下的struts2-blank.war: 仿照这个最基本的项目,拷贝相关文件: 1.拷贝apps/struts2-blank/WEB-INF/classes/struts.xml到我们的项目中的src目录(因为src编译完成后会自动放在classes目录): 2.拷贝类库apps/struts2-blank/WEB-INF/lib/*.jar到自己项目的WebRoot/WEB-INF/lib下. 3.拷贝apps/struts2-blank/WEB-I

Struts2中Action通配符的配置

1.在我的一篇文章中,介绍了Struts2中Action的动态调用方法:http://blog.csdn.net/u012561176/article/details/44347429 但是那样子还不是最简单的,最简单的是使用通配符,将配置量降到最低,但是这个也比较难已理解,在使用通配符时,一定要遵守"约定优于配置"的原则. 2.接下来介绍一下通配符,使用星号(*)表示所有,{数字}表示第几个通配符,例如: *Action,那么{1}就表示第一个星号(*),如果是 *_* 的话,那

Struts2中Action接收参数的方法主要有以下三种:

Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数(最原始的方式):     a.定义:在Action类中定义属性,创建get和set方法:     b.接收:通过属性接收参数,如:userName:     c.发送:使用属性名传递参数,如:user1!add?userName=jim: 2.使用DomainModel接收参数:     a.定义:定义Model类,在Action中定义Model类的对象(不需要new),创建该对象的get和set方法

struts2的action是线程安全的,struts1的action不是线程安全的真正原因

为什么struts2的action是线程安全的,struts1的action不是线程安全的? 先对struts1和struts2的原理做一个简单的讲解 对于struts1 ,当第一次**.do的请求过来时,在内存中的actionmapping中找到相对应的action,然后new出这个action放在缓存中,当第二次一样的请求过来时,还是找的这个action,所以对于struts1来说,action是单实例的 ,只有一个,如果在action中定义变量,就要非常小心了,因为并发问题,可能带来灾难性

Struts2中Action取得表单数据的几种方法

Struts2中Action取得表单数据的几种方法 Struts2中Action获得表单数据的几种方法struts2 Action获取表单传值 1.通过属性驱动式JSP: <form action="sys/login.action" method="post"> <input type="text" name="username"> <input type="submit"

在Struts2的Action中取得请求参数值的几种方法

把参数放到作用域里面去. 如:action 中: request.setAttribute("参数名","值");   页面上:  request.getAttribute("参数名"); request.getParameter()方法完全可以获得URL参数,检查下是否参数名写错 你使用的是不是BaseAction.如果就是server.getRequest().getParameter() 看看你的控件是不是 name 属性!如果id的话就获

struts2的action从request获取参数值的几种方式

使用jquery框架的ajax能够方便的向后台传递参数,以$.post为例,参数有2种方式字符串和键值对: $.post(url, "name=aty&age=25")和$.post(url, {"name":"aty","age":25}).显然,使用json的方式比使用字符串拼接要方 便.对于后台的action来说,这2种方式是等价的,而且jquery也提供了param.serialize.serialize能够实

【Struts2】★☆之struts2对Action提交方法进行验证

[Struts2]★☆之struts2对Action提交方法进行验证 在实际的开发项目中,我们通常采用的是js对我们输入的值进行验证,例如,用户名的长度,密码长度,等等.但是这样做,不好之处就是我们可以通过人为的将开发者的验证js注掉,这样就导致验证失败,对后台安全性是一个很大的威胁,在采用struts2进行开发时,我们可以采用框架内置的校验器,对我们的Action进行校验.本文所讲诉的就是如何使用重写struts2中的ActionSupport里面的validate方法对输入值进行校验. ok

Struts2中Action接收参数的方法

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt112 Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数:     a.定义:在Action类中定义属性,创建get和set方法:     b.接收:通过属性接收参数,如:userName:     c.发送:使用属性名传递参数,如:user1!add?userName=Magci: 2.使用DomainModel接收参数: