struts 2008. 7. 30. 15:59

struts2] Interceptor

                             Interceptor

개념
  - 액션 단위의 작업을 수행할 때 기존 액션 처리 전과 후에 추가적인 작업을 지원하기 위한 방법을 제공

flow
  - FliterDispatcher 실행후 Interceptor 호출 -> Action -> Interceptor -> FilterDispatcher

종류
  - param : 요청파라미터를 액션에 저장
  - prepare : 액션이 Preparable 인터페이스를 구현하였다면 prepre()메소드 호출
  - model-driven : 액션이 ModelDriven인터페이스를 구현하였다면 getModel() 메소드 호출


간단한 interceptor활용 예

1. struts 환경구성
     - struts.xml에 action 및 interceptor정의
      -struts.properties 정의


* struts.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC '-//Apache Software Foundation//DTD Struts Configuration 2.0//EN'
'http://struts.apache.org/dtds/struts-2.0.dtd'>
<struts>
    <package name="defalut" extends="struts-default" namespace="">
   
       <interceptors>
         <interceptor name="MyInterceptor" class="interceptors.MyInterceptor"></interceptor>
       </interceptors>
           
    <action name="f3">
         <result>/ex1/form3.jsp</result>
     </action>
      
    <action name="form3" class="ex1.FormAction3">
      <interceptor-ref name="prepare"/><!--1첫째수행됨, 사용자가 원하는 객체를 생성 -->
      <interceptor-ref name="modelDriven"/><!--2번째 수행됨, 위의 객체를 ValueStack에 적재 -->
      <interceptor-ref name="params"/><!-- 3번째 수행됨,ValueStack에 가장 위에 있는 객체에 파라미터를 저장 -->
      <result>/ex1/res3.jsp</result>
    </action>
     
    <action name="myInter" class="ex1.InterTestAction">
        <interceptor-ref name="MyInterceptor"/>
        <interceptor-ref name="logger"/>
        <result>/ex1/res4.jsp</result>
    </action>
      
    </package>
</struts>

* struts.xml
# To change this template, choose Tools | Templates
# and open the template in the editor.
struts.i18n.reload=true
struts.devMode=true
struts.configuration.xml.reload=true
struts.continuations.package=org.apache.struts2.showcase
struts.custom.i18n.resources=globalMessages
struts.url.http.port=9000
struts.action.extension=action
struts.serve.static=true
struts.serve.static.browserCache=false
struts.mulipart.maxSize=2097252

* form3.jsp
     - struts.xml에 정의한 action name인 f3.action 실행시 form3.jsp페이지 호출
     - form3.jsp호출후 action안에 정의한 interceptor실행
           interceptor실행순서  :  prepare -> modelDriven -> params
     - interceptor가 모두 수행되면 action 실행

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<body>
  <s:form action="form3" method="post" theme="simple">
    Name : <s:textfield name="name"/><br/>
    Phone : <s:textfield name="phone"/><br/>
    <s:submit value="Send"/>
  </s:form>
</body>


*FormAction3.java
     - interceptor에 정의한 params에 의해서 폼으로 부터 넘겨온 파라미터값을 valuestack에 올림
     - 따라서 Action클래스가 불려질때 form으로 부터 파라미터값들이 넘어옴

package ex1;

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

public class FormAction3 implements Preparable,ModelDriven{
   String msg;
   Personal p;
   
   public String getMsg() {
    return msg;
   }
   public void setMsg(String msg) {
    this.msg = msg;
   }
   public Personal getP() {
    return p;
   }
   public void setP(Personal p) {
    this.p = p;
   }
   
   public String execute() throws Exception{
    msg = p.getName()+" 정보를 DB저장 완료"; 
             //interceptor 에서 이미 객체를 valuestrack올렸기때문에 여기서 p.getName()으로 호출이 가능
    return "success";
   }
   
   public void prepare() throws Exception {
    /*
     * prepare는 내가 원하는 객체를 생성하는것이 목적
     * execute()가 불려지기 전에 prepare()메서드가 먼저 불려진다.
     */
    p = new Personal();
   }
   @Override
   public Object getModel() {
     /*
      * 여기서 반환되는 객체가 ValueStack에 올라간다.
      * */
    return p;
   }
 }


*res3.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  내용 : <s:property value="msg"/>
</body>
</html>



*MyInterceptor.java
      - interceptor를 사용자가 만들어서 아래와 같은 방법으로 사용할수있다.
      - 사용자가 만들시에는 AbstractInterceptor 클래스를 상속받아야하고 intercept(ActionInvocation ai)
         메서드를 재정의 하면된다.


package interceptors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor{

 private  static Log log = LogFactory.getLog(MyInterceptor.class);
 @Override
 public String intercept(ActionInvocation ai) throws Exception {
   
   log.info("실행전");
   String res = ai.invoke();  // 16행
   /*
    * 현재 인터셉터가 마지막 인터셉터라면 이때  Action이 호출된다.
    * 결국 invoke()메서드를 중심으로 해서 16행전을 [전처리부] 16행 이후를 후처리부라 한다.
    * */
   log.info(res+"실행후");
  return res;
 }
}


*InterTestAction.java
   - 테스트용 action 클래스

package ex1;

public class InterTestAction {
  private String msg;

  public String getMsg() {
   return msg;
  }
 
  public String execute() throws Exception{
   msg = "Just Do It";
   return "success";
  }
}