`
心动音符
  • 浏览: 339913 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

MessageStoreInterceptor 拦截器的使用

 
阅读更多
本文将详细介绍 MessageStoreInterceptor, 包括 MessageStoreInterceptor 的作用, operationMode 参数的取值, 应用举例和源码分析.
  MessageStoreInterceptor 拦截器能保证 actionMessage 在 redirect 后不会丢失.  struts.xml 文件的部分配置如下:
<interceptors>  
     <interceptor-stack name="storeMessage">  
    <interceptor-ref name="defaultStack" />  
    <interceptor-ref name="store">  
         <param name="operationMode">AUTOMATIC</param>  
    </interceptor-ref>  
     </interceptor-stack>  
</interceptors>  
  
<default-interceptor-ref name="storeMessage" /> 

问题:
  • 1. MessageStoreIntercetor 的作用是什么?
  • 2. operationMode 可以取哪些值?  每个值都有什么作用?
  • 3. MessageStoreIntercetor 的主要应用场景是什么?
  • 4. MessageStoreIntercetor 工作的原理怎样?

1. MessageStoreInterceptor 的配置在 struts-default.xml 文件中可以找到:
<interceptor   
  name="store"              
  class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> 

由 MessageStoreInterceptor 的 API 可以知道: 若 Action 类实现了 ValidationAware 接口, MessageStoreInterceptor 拦截器可以把和该 Action 相关的 messages, errors 和 field errors(下称 "消息") 保存到 session 中(默认放在 Action 中, 而 Action 在 request 中). 以使可以跨请求访问 messages, errors 和 field errors.
2. 从文档上知道 operationMode 的合法取值有: NONE, STORE, RETRIEVE 和 AUTOMATIC. 其中 NONE 为默认值.
①. STORE: MessageStoreInterceptor 拦截器会把 "消息" 放入 session 域中.
②. RETRIEVE: MessageStoreInterceptor 拦截器会把 "消息" 从 session 中取出来, 放入 Action 中.      
③. AUTOMATIC: MessageStoreInterceptor 拦截器会把 "消息" 从 session 中取出来, 放入 Action 中.  而且若响应结果的类型的 redirect, Action 中的 "消息" 会被放入 session 中.              
④. NONE: 什么都不做.
3. 使用场景: 添加新的员工后, 重定向到员工显示页面, 并显示 "员工添加成功" 的消息.
现举例说明: 
1). 项目目录结构:



2). 代码:
index.jsp:
<a href="emp!list.action" mce_href="emp!list.action">List Emps</a><br><br>  
<a href="emp.action" mce_href="emp.action">Add Emp</a> 


显示所有的员工信息: 点击: List Emps 到 EmpAction 的 list 方法.
EmpAction.java
import java.util.List;  
  
import com.opensymphony.xwork2.ActionSupport;  
import com.opensymphony.xwork2.ModelDriven;  
import com.opensymphony.xwork2.Preparable;  
  
public class EmpAction extends ActionSupport implements ModelDriven<Emp>, Preparable{  
  
    private static final long serialVersionUID = 1L;  
      
    private EmpDao empDao = new EmpDao();  
      
    private List<Emp> emps = null;  
      
    private Emp emp;  
      
    @SuppressWarnings("static-access")  
    public String list() throws Exception {  
        System.out.println("list...");    
        emps = empDao.getAll();  
        return "list";  
    }  
      
    @SuppressWarnings("static-access")  
    public String add(){  
        empDao.addEmp(emp);  
        addActionMessage("Save User Success!");  
        return "reload";  
    }  
  
    @Override  
    public Emp getModel() {  
        return emp;   
    }  
  
    @Override  
    public void prepare() throws Exception {  
          
    }  
      
    public void prepareAdd() throws Exception {  
        emp = new Emp();  
    }  
  
    public List<Emp> getEmps() {  
        return emps;  
    }  
  
    public void setEmps(List<Emp> emps) {  
        this.emps = emps;  
    }  
  
    public Emp getEmp() {  
        return emp;  
    }  
  
    public void setEmp(Emp emp) {  
        this.emp = emp;  
    }  
}  


然后转到 /WEB-INF/content/emp-list.jsp
struts.xml:
<package name="simpleit" namespace="/" extends="struts-default">  
      
    <interceptors>  
        <interceptor-stack name="storeMessage">  
            <interceptor-ref name="defaultStack" />  
            <interceptor-ref name="store">  
                <param name="operationMode">AUTOMATIC</param>  
            </interceptor-ref>  
        </interceptor-stack>  
    </interceptors>  
  
    <default-interceptor-ref name="storeMessage" />  
      
    <action name="emp" class="org.simpleit.eg.EmpAction">  
        <result name="success">/WEB-INF/content/emp-add.jsp</result>  
        <result name="list">/WEB-INF/content/emp-list.jsp</result>  
        <result name="reload" type="redirect">/emp!list.action</result>  
    </action>  
      
</package>  

emp-list.jsp:
<s:actionmessage/>    
<table>  
    <tr>  
        <th>Name</th>  
        <th>Email</th>  
    </tr>  
      
    <s:iterator value="emps" var="emp">  
        <tr>  
            <td>${emp.name }</td>  
            <td>${emp.email }</td>  
        </tr>  
    </s:iterator>  
      
</table>  

添加新员工: 点击 index.jsp 页面的 Add Emp 连接, 将把页面转到 /WEB-INF/content/emp-add.jsp
emp-add.jsp:
<s:form action="emp!add.action">  
    <s:textfield name="name" label="Name"></s:textfield>  
    <s:textfield name="email" label="Email"></s:textfield>  
    <s:submit value="Submit"></s:submit>  
</s:form>

点击 "Submit" 按钮, 将执行 EmpAction 的 add() 方法, 然后 重定向 到 emp!list.action, 再转发到 emp-list.jsp, 在 emp-list.jsp 页面上可以通过 <s:actionmessage/> 标签显示消息.
其它代码:
Emp.java
public class Emp {  
      
    private String name;  
      
    private String email;  
      
    public Emp() {}  
      
    public Emp(String name, String email) {  
        this.name = name;  
        this.email = email;  
    }  
      
    public String getName() {  
        return name;  
    }  
      
    public void setName(String name) {  
        this.name = name;  
    }  
      
    public String getEmail() {  
        return email;  
    }  
      
    public void setEmail(String email) {  
        this.email = email;  
    }   
}  


EmpDao.java
public class EmpDao {  
  
    private final static List<Emp> emps = new ArrayList<Emp>();  
      
    static{  
        emps.add(new Emp("Tom", "Tom@sina.com"));  
        emps.add(new Emp("Jerry", "Jerry@sina.com"));  
    }  
      
    public static List<Emp> getAll(){  
        return emps;  
    }  
      
    public static void addEmp(Emp emp){  
        emps.add(emp);  
    }  
}  


4. 源码分析: 

        先总结下 "添加员工" 的操作流程: 提交表单, 执行 EmpAction 的 add() 方法, 在 add() 方法中通过 addActionMessage("Save User Success!"); 存放消息, 然后重定向到 list() 方法, 再在页面上通过标签显示消息. 重定向到 list() 方法后依然能够得到在 add() 方法中得到的消息, 就是 MessageStoreInterceptor 拦截器的功劳!
打开 MessageStoreInterceptor 的源代码:
public String intercept(ActionInvocation invocation) throws Exception {  
  
    before(invocation);  
    String result = invocation.invoke();  
    after(invocation, result);  
  
    return result;  
}  

在执行 invoke 方法之前会调用 before() 方法, 执行 invoke() 方法之后调用 after() 方法.
提交表单后, 执行 add() 方法, 然后 MessageStoreInterceptor 拦截器的 after() 方法会被调用:
protected void after(ActionInvocation invocation, String result) throws Exception {  
    //获取 operationMode 参数   
    String reqOperationMode = getRequestOperationMode(invocation);  
     
    //获取响应类型是否为重定向   
    boolean isRedirect = invocation.getResult() instanceof ServletRedirectResult;  
      
    if (STORE_MODE.equalsIgnoreCase(reqOperationMode) ||  
            STORE_MODE.equalsIgnoreCase(operationMode) ||  
            (AUTOMATIC_MODE.equalsIgnoreCase(operationMode) && isRedirect)) {  
                  
        //获取 Action 实例   
          Object action = invocation.getAction();  
        if (action instanceof ValidationAware) {  
            // store error / messages into session   
            Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);  
            ValidationAware validationAwareAction = (ValidationAware) action;  
              
            //把 Action 实例中的 "消息" 放入 session 域中   
            session.put(actionErrorsSessionKey, validationAwareAction.getActionErrors());  
            session.put(actionMessagesSessionKey, validationAwareAction.getActionMessages());  
            session.put(fieldErrorsSessionKey, validationAwareAction.getFieldErrors());  
        }  
        else {  
            LOG.debug("Action ["+action+"] is not ValidationAware, no message / error that are storeable");  
        }  
    }  
}  

在执行 list() 方法之前 before() 方法会被调用:
protected void before(ActionInvocation invocation) throws Exception {  
    String reqOperationMode = getRequestOperationMode(invocation);  
  
    if (RETRIEVE_MODE.equalsIgnoreCase(reqOperationMode) ||  
            RETRIEVE_MODE.equalsIgnoreCase(operationMode) ||  
            AUTOMATIC_MODE.equalsIgnoreCase(operationMode)) {  
  
        Object action = invocation.getAction();  
        if (action instanceof ValidationAware) {  
            // retrieve error / message from session   
            Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);  
            ValidationAware validationAwareAction = (ValidationAware) action;  
  
            LOG.debug("retrieve error / message from session to populate into action ["+action+"]");  
  
            //从 session 中获取 "消息"   
            Collection actionErrors = (Collection) session.get(actionErrorsSessionKey);  
            Collection actionMessages = (Collection) session.get(actionMessagesSessionKey);  
            Map fieldErrors = (Map) session.get(fieldErrorsSessionKey);  
               
            //把 "消息" 放入 Action 中    
            if (actionErrors != null && actionErrors.size() > 0) {  
                Collection mergedActionErrors = mergeCollection(validationAwareAction.getActionErrors(), actionErrors);  
                validationAwareAction.setActionErrors(mergedActionErrors);  
            }  
  
            if (actionMessages != null && actionMessages.size() > 0) {  
                Collection mergedActionMessages = mergeCollection(validationAwareAction.getActionMessages(), actionMessages);  
                validationAwareAction.setActionMessages(mergedActionMessages);  
            }  
  
            if (fieldErrors != null && fieldErrors.size() > 0) {  
                Map mergedFieldErrors = mergeMap(validationAwareAction.getFieldErrors(), fieldErrors);  
                validationAwareAction.setFieldErrors(mergedFieldErrors);  
            }  
            session.remove(actionErrorsSessionKey);  
            session.remove(actionMessagesSessionKey);  
            session.remove(fieldErrorsSessionKey);  
        }  
    }  
}  



  • 大小: 8.2 KB
分享到:
评论

相关推荐

    Struts2拦截器及其用法详细说明

    - XML配置:在`struts.xml`文件中,使用`&lt;interceptor&gt;`元素定义拦截器,`&lt;interceptor-stack&gt;`元素组合多个拦截器,`&lt;package&gt;`元素下的`interceptors`属性指定拦截器栈。 ```xml &lt;!-- 可以添加其他内置或...

    SpringBoot拦截器原理解析及使用方法

    拦截器的使用为开发人员提供了灵活的请求处理方式,可以方便地在请求到达控制器之前和之后加入自定义的逻辑。掌握拦截器的使用,对于开发安全、高效、易于维护的Web应用是非常有帮助的。在实际开发中,合理设计拦截...

    struts2拦截器的使用方法

    ### Struts2拦截器的使用方法 #### 一、Struts2拦截器概述 Struts2框架中的拦截器(Interceptor)是一种重要的机制,用于在Action执行前后进行一系列处理,比如参数验证、数据预处理等。它能够帮助开发者更加灵活...

    请求拦截器和响应拦截器.docx

    请求拦截器和响应拦截器 请求拦截器和响应拦截器是 Axios 库中提供的一种机制,用于在发送请求之前和响应数据...使用请求拦截器和响应拦截器可以统一处理所有请求和响应数据,简化代码,提高代码的可维护性和可读性。

    struts1.2拦截器使用插件

    3. **配置拦截器栈**:在`struts-config.xml`中,可以使用`&lt;interceptor-stack&gt;`标签定义拦截器栈,栈中的拦截器会按照定义的顺序执行。 4. **插件使用**:Struts1.2提供了一些预定义的拦截器插件,例如`...

    微信小程序请求拦截器 ,响应拦截器

    微信小程序请求拦截器 ,响应拦截器,结合微信小程序二次封装request 一起使用

    struts2 拦截器的使用(继承抽象拦截器)

    这篇博客文章“struts2 拦截器的使用(继承抽象拦截器)”探讨了如何通过继承Struts2的抽象拦截器来创建自定义拦截器。 首先,让我们理解拦截器的基本概念。在Struts2中,拦截器是基于Java的动态代理机制实现的,...

    WebService之自定义拦截器(server+client)

    在IT行业中,Web服务是应用程序之间进行通信的一种标准方法,而WebService之自定义拦截器的实现,无论是...通过理解并熟练掌握CXF框架下的拦截器使用,开发者可以更好地驾驭Web服务,实现更高效、更安全的应用程序。

    CXF使用EndpointImpl发布WebService加入拦截器

    本篇文章将深入探讨如何使用CXF的`EndpointImpl`类来发布一个WebService,并加入拦截器。 首先,我们要理解`EndpointImpl`是CXF框架用于构建和配置Web服务端点的核心类。通过实例化这个类,我们可以自定义服务的...

    拦截器的使用示例Interceptor

    通过`addInterceptors(InterceptorRegistry registry)`方法添加自定义的拦截器,然后使用`registry.addInterceptor(interceptor)`方法将拦截器实例注册到注册表中。配置完成后,拦截器会按照添加的顺序依次执行。 5...

    CXF3.0+Spring3.2 自定义拦截器

    6. **调试和测试拦截器**:为了确保拦截器按预期工作,你需要了解如何在CXF中启用日志输出,这通常通过设置日志级别和使用如`java.util.logging`或`log4j`这样的日志框架来实现。 7. **异常处理**:自定义拦截器...

    mybatis拦截器实现通用权限字段添加的方法

    本文将详细介绍如何使用MyBatis拦截器来实现通用权限字段添加,达到灵活、可靠、可维护的数据库操作。 MyBatis拦截器是什么 MyBatis拦截器是一个接口,用于拦截MyBatis的Executor对象,以便在执行SQL语句之前或...

    自定义拦截器的实现以及拦截器的详细配置

    在Java Web开发中,拦截器(Interceptor)是一个重要的概念,特别是在使用MVC框架如Struts2时。拦截器可以理解为一种预处理和后处理机制,它在请求到达控制器之前和离开控制器之后进行操作,例如日志记录、权限检查...

    mybatis 分页拦截器及拦截器配置

    通过使用分页拦截器,我们可以将分页逻辑封装起来,使得在编写Mapper接口和Mapper XML文件时,无需关心具体的分页细节。 MyBatis中的拦截器(Interceptor)是基于Java的动态代理机制实现的,它可以拦截执行SQL的...

    uni-app 请求拦截器

    在uni-app中,我们可以使用`uni.$http`提供的拦截器功能,它包含两个部分:请求拦截器(request interceptor)和响应拦截器(response interceptor)。请求拦截器主要在请求发送前执行,而响应拦截器则在接收到...

    MyBatis拦截器:给参数对象属性赋值的实例

    `OpeInfoInterceptor`类就是这样一个拦截器,它使用了`@Intercepts`注解来指定拦截的目标。`@Signature`注解用来精确定义拦截的方法,这里是`Executor`类的`update`方法,接收`MappedStatement`和`Object`两个参数。...

    拦截器解决中文乱码问题

    "拦截器解决中文乱码问题"这个主题,主要关注的是如何通过使用拦截器(Interceptor)这一技术手段来预防或解决乱码现象。拦截器是Spring MVC框架中的一个重要组件,它可以对HTTP请求进行预处理和后处理,从而在数据...

    理解拦截器用于在某个方法或字段被访

    【理解拦截器】 拦截器是面向切面编程(AOP)的一个重要概念,它允许在方法或字段被访问之前或之后插入额外的操作。这提供了一种灵活的方式,可以在不修改原有代码的情况下,增强或控制程序的行为。在Web开发框架如...

Global site tag (gtag.js) - Google Analytics