Struts2的学习(5)-使用PrepareInterceptor和Preparable接口

关于PrepareInterceptor
对应的源码分析:com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor

<pre name="code" class="java">public String doIntercept(ActionInvocation invocation) throws Exception {
        // 获取实例
        Object action = invocation.getAction();
        
       
        // 判断Action是否实现了Preparable接口
        if (action instanceof Preparable) {
            try {
                String[] prefixes;
                // 根据当前拦截器firstCallPrepareDo(默认为false)
                // 属性确定prefixes
                if (firstCallPrepareDo) {
                    prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
                } else {
                    prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
                }
                // 若为false,则prefixes为:prepare、prepareDo
                // 调用前缀方法
                PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
            }
            catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Exception) {
                    throw (Exception) cause;
                } else if(cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    throw e;
                }
            }
          // 根据当前拦截器的alwaysInvokePrepare(默认为true)决定是否调用Action的prepare方法
         if (alwaysInvokePrepare) {
                        ((Preparable) action).prepare();
                    }
                }

                return invocation.invoke();
            }
   }

 
   

对上面程序中的PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);进行分析:
<pre name="code" class="java">public String doIntercept(ActionInvocation invocation) throws Exception {
        // 获取实例
        Object action = invocation.getAction();
        
       
        // 判断Action是否实现了Preparable接口
        if (action instanceof Preparable) {
            try {
                String[] prefixes;
                // 根据当前拦截器firstCallPrepareDo(默认为false)
                // 属性确定prefixes
                if (firstCallPrepareDo) {
                    prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
                } else {
                    prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
                }
                // 若为false,则prefixes为:prepare、prepareDo
                // 调用前缀方法
                PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
            }
            catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Exception) {
                    throw (Exception) cause;
                } else if(cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    throw e;
                }
            }
          // 根据当前拦截器的alwaysInvokePrepare(默认为true)决定是否调用Action的prepare方法
         if (alwaysInvokePrepare) {
                        ((Preparable) action).prepare();
                    }
                }

                return invocation.invoke();
            }
   }

 
    

对上面的程序中的    Method method = getPrefixedMethod(prefixes, methodName, action);方法进行分析:
public String doIntercept(ActionInvocation invocation) throws Exception {
        // 获取实例
        Object action = invocation.getAction();
        
       
        // 判断Action是否实现了Preparable接口
        if (action instanceof Preparable) {
            try {
                String[] prefixes;
                // 根据当前拦截器firstCallPrepareDo(默认为false)
                // 属性确定prefixes
                if (firstCallPrepareDo) {
                    prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
                } else {
                    prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
                }
                // 若为false,则prefixes为:prepare、prepareDo
                // 调用前缀方法
                PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
            }
            catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Exception) {
                    throw (Exception) cause;
                } else if(cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    throw e;
                }
            }
          // 根据当前拦截器的alwaysInvokePrepare(默认为true)决定是否调用Action的prepare方法
         if (alwaysInvokePrepare) {
                        ((Preparable) action).prepare();
                    }
                }

                return invocation.invoke();
            }
   }


进行分析后得到的结论:
(1) 若Action实现了Prepare接口,则Struts将尝试执行prepare[ActionMethodName]方法,
prepare[ActionMethodName]不存在,则尝试执行prepareDo[ActionMethodName]方法,若都存在,就都不执行。
(2)若PrepareInterceptor的alwaysInvokePrepare属性为false,则Struts2将不会调用实现了Preparable的Action。
(3)解决前一篇文章的方案是:可以为每一个ActionMethod准备Prepare[ActionMethodName]方法,而抛弃原来的prepare方法;避免PrepareInterceptor的alwaysInvokePrepare属性为false,以避免Struts2框架在用prepare方法。

代码具体实现:
struts配置文件的配置:
</pre><pre name="code" class="html"><?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>
    <!-- 配置struts可以受理的请求的扩展名 -->
    <constant name="struts.action.extension" value="action,do,"></constant>
    <package name="default" namespace="/" extends="struts-default">
        <!-- 修改PrepareInterceptorParamsStack拦截器的 alwaysInvokePrepare属性值为false-->
        <interceptors>
            <interceptor-stack name="atguiguStak">
                <interceptor-ref name="paramsPrepareParamsStack">
                    <param name="prepare.alwaysInvokePrepare">false</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>

        <!-- 配置使用paramsPrepareParamsStack作为默认的拦截器栈 -->
        <default-interceptor-ref name="atguiguStak"></default-interceptor-ref>

        <action name="emp-*" class="com.yu.struts2.app.EmployeeAction" method="{1}">
            <result name="{1}">/{1}.jsp</result>
            <result name="success" type="redirectAction">emp-list</result>
        </action>

    </package>

</struts>

EmployeeAction类改写如下:
package com.yu.struts2.app;

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

public class EmployeeAction implements RequestAware ,ModelDriven<Employee>, Preparable{

    private Dao dao = new Dao();

    public String list(){
        requestMap.put("emps", dao.getEmployees());
        return "list";
    }

    public String delete(){
        dao.delete(employeeId);
        return "success";
    }

    private Employee employee;

    public String save(){
        // 1.获取请求参数:通过定义对应属性的方式
        // 2.调用Dao的save方法
        dao.save(employee);

        return "success";
    }

    public void prepareSave(){
        employee = new Employee();
    }

    public String edit(){
        // 1.获取传入的employeeId:employee.getEmployeeId()
        // 2.根据employeeId获取Employee对象
        //Employee emp = dao.get(employee.getEmployeeId());

        // 3.把栈顶对象的属性转配好,此时栈顶对象时employee
        // 目前的employee对象只有employeeId属性,其他属性为null
        /*
         *  Struts2表单回显时:从值栈栈顶开始查找匹配的属性,若找到就添加到value属性中
         */
//        employee.setEmail(emp.getEmail());
//        employee.setFirstName(emp.getFirstName());
//        employee.setLastName(emp.getLastName());

        // 不能够进行表单的回显,因为经过重写赋值的employee对象不再是栈顶对象
        //employee = dao.get(employee.getEmployeeId());

        // 手动的把从数据库中获取的Employee对象放到值栈的栈顶。
        // 但此时值栈栈顶及第二个对象均为Employee对象,不够完美
        //ActionContext.getContext().getValueStack().push(dao.get(employee.getEmployeeId()));

        return "edit";
    }

    public void prepareEdit(){
        employee = dao.get(employeeId);
    }

    public String update(){
        dao.update(employee);

        return "success";
    }

    public void prepareUpdate(){
        employee = new Employee();
    }

    private Map<String, Object> requestMap;

    @Override
    public void setRequest(Map<String, Object> arg0) {
        // TODO Auto-generated method stub
        this.requestMap = arg0;
    }

    private Integer employeeId;

    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }

    @Override
    public Employee getModel() {
        // 判断是Create还是Edit。
        // 若为Create,则employee = new Employee();
        // 若为Edit,则employee = dao.get(employeeId);
        // 判定标准为是否有employeeId这个参数。若有该参数,则视为Edit;若没有该参数,则视为Create
        // 若通过employeeId来判断,则需要在modelDriven拦截器之前执行一个params拦截器!
        // 而这可以通过使用paramsPrepareParams拦截器栈实现
        // 需要在struts.xml文件中配置使用paramsPrepareParams作为默认的拦截器栈

//        if(employeeId == null){
//            employee = new Employee();
//        }
//        else
//            employee = dao.get(employeeId);
//        
        return employee;
    }

    /*
     * prepare方法的主要作用:为getModel()方法准备model的
     */
    @Override
    public void prepare() throws Exception {
        System.out.println("prepare...");
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值