5. Adding functionality with interceptors

5.1 How interceptors are called

  • Interceptors는 action 과 result의 실행 전, 후에 특정한 작업을 처리할 수 있다.
  • Interceptors는 action 실행후에는 실행전에 수행된 순서의 역으로 수행된다.
  • interceptors의 그룹을 stack으로 지정하여 사용 할 수 있다

5.2 Using the prepackaged interceptors

  • 교재 page 115~116 참고. 설명이 쭈~욱 나와있습니다.

5.2.1 Utility interceptors

Timing your actions

  • action 수행 시간을 알 수 있다.

public String intercept(ActionInvocation invocation) throws Exception {
    long startTime = System.currentTimeMillis();
    String result = invocation.invoke();
    long executionTime = System.currentTimeMillis() - startTime;
    ... log the time ...
}

The AroundInterceptor

  • before() 와 after()가 정의되어 있음, 많은 interceptor들의 base class 역할을 함

public abstrac class AroundInterceptor implements Interceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        before(invocation);
        result = invocation.invoke();
        after(ivocation, result);

        return result;
    }

    protected abstract void after(ActionInvocation dispatcher, String result) throws Exception;

    protected abstract void before(ActionInvocation invocation) throws Exception;
}

Logging action executions

  • action 앞 뒤에서 log를 남김.

protected void after(ActionInvocation invocation, String result) throws Exception {
    logMessage(invocation, FINISH_MESSAGE);
}

protected void before(ActionInvocation invocation) throws Exception {   
    logMessage(invocation, START_MESSAGE);
}

5.2.2 Setting parameters

setting properties from the request parameters


    <ww:textfield label="Foo" name="foo"/>

  • ParametersInterceptor sets the properties of the action from the request parameters.

if (parameters != null) {
    final OgnlValueStack stack =
        ActionContext.getContext().getValueStack();

    for (Iterator iterator = parameters.entrySet().iterator();
        iterator.hasNext();) {
        Map.Entry entry = (Map.Entry) iterator.next();
        
        stack.setValue(entry.getKey().toString(), entry.getValue());
    }
}

  • request parameters의 key와 value들을 꺼내어 OgnlValueStack에 넣음
  • OGNL(Object Graph Navigation Language)
  • action의 setFoo() 설정
  • ParametersInterceptor를 사용, default-webwork.xml에 params로 설정되어 있음

Setting properties from the configuration

  • xwork.xml 파일에 설정. 항상 일정한 값을 갖는다.
  • StaticParametersInterceptor를 사용, default-webwork.xml에 static-params로 설정되어 있음

<action name="exampleAction" class="example.ExampleAction">
    <param name="firstName">John</param>
    <param name="lastName">Doe</param>
</action>

Setting properties on your action from a chained action

  • ChainingInterceptor를 사용
  • action chain을 구현할때 사용한다. 이전에 수행된 액션의 속성들을 현재 액션에서도 사용할 수 있게 해준다
  • 7장 "Using results"에서 소개함

Getting at the HTTP-specific objects when you need them

  • ServletConfigInterceptor를 사용하여 Action에서 HttpServletRequest나 HttpServletResponse에 대해 접근할 수 있도록 해준다

Handling file uploads

  • FileUploadInterceptor를 사용하여 파일업로드를 처리한다

5.2.3 Defining workflow

Using the default workflow

  • DefaultWorkflowInterceptor : validation을 수행하고, 에러 발생시 error result를 반환한다.

Preparing your actions

  • PrepareInterceptor사용. com.opensymphony.xwork.Preparable interface를 구현한 Action일 경우 prepare 메소드를 실행한다

Making your actions ModelDriven

  • ModelDrivenInterceptor사용. action이 ModelDriven을 implement하고 있다면 getModel()을 호출해 준다. 4.6 참조.

Preventing duplicate form posting using form tokens

  • TokenInterceptor/TokenSessionInterceptor 사용,
  • 똑같은 submission이 두 번 오면, 두번째 온다는 것을 detect해서 에러를 내든지 첫번째 submission의 결과를 다시 보여주든지 하게 할 수 있다.
  • 15.6장 참조.

Excuting long-running actions without making the user wait

  • ExecuteandWaitInterceptor : action 수행하는 동안 백그라운드로 처리하고, action 수행 끝나면 그 결과를 보낸다. 15.7 참조.

5.3 Using prepackaged interceptor stacks

  • interceptor stack : interceptor들의 묶음
  • 보통 interceptor 단독으로 사용되지는 않고 stack으로 묶어 특정 순서로 사용할 수 있다.
  • webwork-default.xml에 기본적으로 정의되어 있다.
  • page 126~127 참고

5.4 Building your own interceptors

  • 개발자가 인터셉터를 생성하여 action실행시에 적용할 수 있다.

5.4.2 Looking at an example custom interceptor

  • AuthenticationInterceptor: checks the user logon

public class AuthenticationInterceptor implements Interceptor {
    public static final String USER = "user";
   
    public void destroy() {
    }

    public void init() {
    }

    public String intercept (ActionInvocation actionInvocation) throws Exception {
        Map session = actionInvocation.getInvocationContext().getSession();
        User user = (User) session.get(USER);
        if (user == null) {
            return Action.LOGIN;
        } else {
            Action action = actionInvocation.getAction();
            if (action instanceof UserAware) {
                ((UserAware)action).setUser(user);
            }
            return actionInvocation.invoke(); //action 수행
        } 
    }
}

  • global-results 설정

<global-results>
    <result name="login" type="redirect">/login!default.action</result>
    <result name="invalid.token">/invalidToken.jsp</result>
</global-results>

  • Login action

public class Login extends ActionSupport implements SessionAware, UserDAOAware {
    Map session;
    User user;
    private UserDAO userDAO;

    public void setSession(Map session) {
        this.session = session;
    }

    public String execute() throws Exception {
        user = userDAO.findByCredentials(user.getUsername(), user.getPassword());
        if (user == null) {
            return INPUT;
        } else {
            session.put(AuthenticationInterceptor.USER, user);
            return SUCCESS;
        }
    }

    public String doDefault() throws Exception() {
        return INPUT;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setUserDAO(UserDAO dao) {
        this.userDAO = dao;
    }
}

  • 사용자 정의 interceptor 적용 순서
    • interceptor 작성
    • xwork.xml에 interceptor 선언
    • 해당 interceptor를 적용하고자 하는 action의 선언부분에 interceptor-ref 설정

5.5 Interceptors vs. servlet filters

문서에 대하여

  • 이 문서의 내용은 Webwork In Action 교재를 스터디 하면서 정리한 내용 입니다.
  • 최초작성자 : 김정식
  • 최초작성일 : 2007년 9월 21일
  • 이 문서는 오라클클럽 자바 웹개발자 스터디 모임에서 작성하였습니다.
  • 이 문서를 다른 블로그나 홈페이지에 퍼가실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^\^