首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

MessageStoreInterceptor 拦截器的应用

2012-11-07 
MessageStoreInterceptor 拦截器的使用本文将详细介绍 MessageStoreInterceptor, 包括 MessageStoreInterc

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"                /> 

由 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" 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);          }      }  }  



热点排行