ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • struts2 :: Interceptor(인터셉터)
    IT/Java & JSP & FW 2012. 4. 30. 16:45

    Action은 params 인터셉터와 setter로 사용자가 넘기는 요청 파라미터의 값을 받는다.


    Interceptor는 사용자의 요청이 Action에 도달하기 전에 가로 채 Action 실행 전 후에 다른 실행 코드를 넣을 수 있는 객체이며 어떤 경우 Action이 실행되지 않을 수 있게도 한다. 또한 한 개 이상의 Action에 공통적으로 사용할 수 있는 로그인 여부 체크, 이중 Submit 방지, Security Checking, Logging, Action 수행시간을 점검하여 병목현상을 확인 할 수 있는 Bottleneck Checking 등과 같은 일반적인 기능을 캡슐화 할 수 있는 방법을 제공한다. 

    (AspectJ, Spring에서 제공하는 AOP와 비슷하다)


    Struts2에는 개발에 자주 사용될만한 인터셉터를 미리 정의해 주었는데 다음과 같은 것들이 있다.

    (struts2-core-2.0.14.jar 파일의 struts-default.xml에 정의)


    아래 인터셉터는 struts.xml에서 별도의 interceptors에 정의할 필요 없이 사용 가능하다.


    <!—특정이름의 파라미터를 다른 이름의 파라미터로 재정의 

    <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>


    <!—이전 Action의 속성을 현재 Action으로 복사 

    <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>


    <!—모든 형변환 에러를 Action에 필드 레벨의 에러 메시지로 추가 

    <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>


    <!—HttpSession을 자동으로 생성 

    <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />


    <!—몇가지의 디버깅 화면을 제공 

    <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />


    <!—Action을 백그라운드로 설정 

    <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>


    <!-- Action이나 다른 Interceptor 실행중 발생한 예외들을 저장한 Map을 result에 저장 

    <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>


    <!—파일업로드를 지원한다 

    <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>


    <!—사용자 세션의 Locale을 저장한다 

    <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>


    <!—Action 실행 전후에 “Starting execution stack for action”, “Finishing execution stack for action”과 같은 메시지를 로그로 출력한다 

    <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>


    <!—Action이 ModelDriven을 구현했다면 Action의 getModel() 메소드를 실행해서 그 결과를 ValueStack의 최상단에 PUSH 한다 

    <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>


    <!—Prepare를 구현한 Action에서 prepare() 메소드를 호출한다. 

    <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>


    <!—Action이 ScopedModelDriven을 구현한 경우 설정한 scope에 저장된 Model을 검색해서 Action의 setModel()을 호출해서 검색된 모델을 Action에 세팅한다. 

    <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>


    <!—요청파라미터를 Action의 프로퍼티에 세팅한다 

    <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>


    <!—struts.xml 파일에 정의된 파라미터를 Action에 세팅한다 

    <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>


    <!—session scope 또는 application scope에 Action의 상태를 저장한다 

    <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>


    <!—HttpServletRequest, HttpServletResponse를 Map을 통해서 접근할 수 있도록 한다 

    <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>


    <!—Action이 실행되는 시간을 로그로 출력 

    <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>


    <!-- Action에서 현재 토큰의 유효성을 체크한다. 폼의 중복 Sunmit을 방지한다 

    <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>


    <!—token interceptor와 동일, 그러나 유효하지 않은 토큰의 경우 Submit된 데이터를 Sesison에 저장 

    <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>


    <!—action-validation.xml에 정의된 validator를 이용하여 유효성을 검사 

    <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>


    <!-- Action에서 validate()를 호출하고 에로가 발생하면 INPUT result를 리턴한다 

    <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>


    <!—Action이 ValidatoraAware인터페이스를 구현한 경우 ACtion에서 발생한 메시지를 HttpSession에 세팅한다 

    <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />


    <!—체크되지 않은 체크박스를 ‘false’(변경가능함)로 파라미터에 넣어준다 

    <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />


    <!—사용자가 올바른 role을 가지고 있을 때만 Action이 실행된다 

    <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />


    Struts1과는 달리 Struts2 에서 Action은 더 이상 싱글톤(Singleton)이 아니라 매 요청마다 새로 생성되어 각 상태를 가질 수 있다. 실제 Action은 그 자체가 빈(Bean)이 되어 요청 파라미터들을 프로퍼티로써 세팅 하거나 도메인 오브젝트를 프로포티로 가질 수 있다.


    그러나 인터셉터는 다르다 어떤 Action에 설정된 Interceptor는 그 Action의 전처리, 후처리를 하기 위해 한개의 인스턴스가 존재하여 생성되어 항상 떠 있어 요청이 실행되면 새로운 Action인스턴스가 생성되어 인터셉터를 통과한다고 보면 된다. 따라서 인터셉터는 상태가 없는 것이다.


    인터셉터 여러개의 세트를 Interceptor Stack이라 하는데 특별히 스택이라 부르는 이유는 인터셉터 3개를 넣는다고 하면 먼저 인터셉터1이 들어가고 인터셉터2, 인터셉터3이 차례로 스택에 들어간다. 그리고 마지막으로 Action이 실행되고 후처리에서는 반대로 인터셉터3, 인터셉터2, 인터셉터1이 실행되어 나온다.

    1. HTTP요청 -> FilterDispatcher

    2. FilterDispatcher에서 ActionMapper의 도움으로 Struts2의 액션 요청(.action)인지 판단

    3. 액션 요청(Action Request)일 경우 액션 프록시(ActionProxy)로 요청을 위임

    4. 액션 프록시(ActionProxy)는 환경설정 관리자를 통해 작업정보를 받고 액션 인보케이션(ActionInvocation)을 생성 후 작업을 위임

    5. 액션 인보케이션(ActionInvocation)에서 액션 실행 전 인터셉터 호출

    6. 액션 인보케이션(ActionInvocation)에서 액션 호출 후 리절트(result) 값을 리턴 받음

       6-1. Action에서 PreResultListener를 add 했다면 그것을 수행 

       (ActionInvocation 인자가 넘어가기 때문에 흐름을 제어할 수 있다. 예를 들어, 이미 수행된  액션의 리절트 코드를 바꿔버릴 수 있다.);

    7. 리턴받은 리절트 값에 해당하는 struts.xml의 매핑된 리절트를 찾고 랜더링

    8. 액션 인보케이션에서 역순으로 인터셉터 호출

    9. 응답 생성 

    public interface Interceptor extends java.io.Serializable {
    void init();
    void destroy();
    String interceptor(ActionInvocation invocation) throws Exception;
    }

    init(), destroy() 메소드가 있는 것들은 대부분 매번 인스턴스를 만드는 것이 아니라 미리 인스턴스를 띄워놓고 서비스하는 용도이다. 서블릿이나 필터가 그러한 예이며 인터셉터도 마찬가지다. 인터셉터에 특별한 초기화가 없는 경우 init(), destroy()는 의미가 없으므로 이 Interceptor 인터페이스를 구현해 놓은 추상클래스인 AbstractInterceptor를 상속받아 인터셉터를 만들면 된다.

    public abstract class AbstractInterceptor implements Interceptor {
    public void init(){}
    public void destroy(){}
    public abstract String intercept(ActionInvocation invocation) throws Exception;
    }

Designed by Tistory.