interceptor色々

今回のプロジェクトで自作したInterceptorをメモ。
まずはActionの@Executeメソッドが呼ばれた場合にログを出力する。

public class ActionLoggerInterceptor extends AbstractInterceptor {

    /** serialVersionUID */
    private static final long serialVersionUID = 1L;

    private static Log log = LogFactory.getLog(ActionLoggerInterceptor.class);

    public Object invoke(MethodInvocation invocation) throws Throwable {

        SessionDto sessionDto = SingletonS2Container.getComponent(SessionDto.class);
        
        Method method = invocation.getMethod();
        String className = ClassUtil.getShortClassName(method.getDeclaringClass());

        Execute exec = method.getAnnotation(Execute.class);

        if (null != exec) {

            StringBuilder buf = new StringBuilder();
            if (null != sessionDto.loginAuthDto) {
                String userId =
                    !StringUtils.isEmpty(sessionDto.loginAuthDto.loginId)
                        ? sessionDto.loginAuthDto.loginId
                        : "-";
                buf.append("[" + userId + "] ");
            }
            buf.append(className + "#" + method.getName() + "()");

            log.info(buf.toString());
        }

        return invocation.proceed();
    }
}

SessionDtoはインスタンスフィールドにしてDIしてもらうようにしたかったんだけど、CoolDeployの環境だと思ったように動かなかったのでコンテナから取得するようにしている。ここは要調査。

続いて、セッションにログイン認証情報が存在しない場合にログイン画面へ戻す場合。

public class LoginCheckInterceptor extends AbstractInterceptor {

    private static final long serialVersionUID = 1L;

    public Object invoke(MethodInvocation invocation) throws Throwable {

        SessionDto sessionDto = SingletonS2Container.getComponent(SessionDto.class);

        if (null == sessionDto
            || null == sessionDto.loginAuthDto
            || null == sessionDto.loginAuthDto.loginId) {

            ActionMessages errors = new ActionMessages();
            errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
                "errors.login.auth.not.found",
                null));

            ActionMessagesUtil.addErrors(RequestUtil.getRequest().getSession(), errors);
            return "/login/?redirect=true";

        }

        return invocation.proceed();
    }

}

最後はStrutsのTokenを使ったチェック。

public class TokenCheckInterceptor extends AbstractInterceptor {

    private static final long serialVersionUID = 1L;

    public Object invoke(MethodInvocation invocation) throws Throwable {

        TokenCheck tokenCheck =
            invocation.getMethod().getAnnotation(TokenCheck.class);

        if (null != tokenCheck) {
            HttpServletRequest request = RequestUtil.getRequest();
            if (!TokenProcessor.getInstance().isTokenValid(request, true)) {

                ActionMessages errors = new ActionMessages();
                errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
                    "errors.login.auth.not.found",
                    null));

                ActionMessagesUtil.addErrors(RequestUtil
                    .getRequest()
                    .getSession(), errors);
                return "/login/?redirect=true";

            }
            TokenProcessor.getInstance().saveToken(request);
        }

        return invocation.proceed();
    }
}

TokenCheckアノテーションは自作。Tokenチェックに引っ掛かった場合はログイン画面へ遷移する。これに関して参考にさせて頂いたのは以下のサイト。
トークンをアノテーションでいじってみる。 - コンピュータクワガタ
前も書いた気がするけど、アノテーションとinterceptorを組み合わせると大抵のことはどうにかなってしまうんだけど、あんまり使い過ぎると保守する人とかが何がどのタイミングで行われているかを把握しづらくなってしまう。何をどこまでやるかはちゃんと議論をしないとダメだなぁ、自戒を込めて。