DefaultActionSupport

Anyframe Web에서는 Action 클래스에서 공통적으로 적용되는 기능에 대한 Template 클래스로 DefaultActionSupport를 제공한다.

DefaultActionSupport의 기능을 그대로 가지면서 Struts의 DispatchAction과 같이 동작할 수 있는 DefaultDispatchActionSupport 도 함께 제공하고 있다.

DefaultActionSupport


DefaultActionSupport는 Spring 연동을 위한 DefaultAction Class를 상속받고 있으며 패키지는 anyframe.web.struts.common.action 이다. 주요 기능은 다음과 같다.
  • Anyframe 서비스(Spring 기반)와의 쉬운 연동 지원
  • 선언적인 Synchronized Token 처리 지원
  • 공통 Exception 처리
  • 공통 로깅 지원
다음은 DefaultActionSupport의 구조이다.

DefaultActionSupport의 execute method의 소스코드는 다음과 같다.
public ActionForward execute(ActionMapping mapping, ActionForm form,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {

    ActionForward forward = null;

    try {
        preProcess(mapping, form, request, response);
        getLogger().debug("\n\n" + this.getClass().getName()
                + ".process() Started!");
        forward = process(mapping, form, request, response);
        getLogger().debug("\n\n" + this.getClass().getName()
                + ".process() Ended!");
        forward = postProcess(mapping, form, request, response, forward);
    } catch (InvalidTokenException tokenException) {
        
        getLogger().debug("\n InvalidTokenException  catch!!");
        forward = processInvalidTokenException(mapping, form, request,
                response, tokenException);
    } catch (RuntimeException uncheckedException) {
        
        getLogger().debug("\n RuntimeException  catch!!");
        forward = processUnCheckedException(mapping, form, request,
                response, uncheckedException);
    } catch (Exception checkedException) {
        
        getLogger().debug("\n Action Support Exception catch!!");
        forward = processCheckedException(mapping, form, request, response,
                checkedException);
    } finally {
        
        getLogger().debug("\n Finally !!");
        forward = processFinally(mapping, form, request, response, forward);
    }
    return forward;
}
위의 DefaultActionSupport의 method들은 다음과 같은 역할을 수행한다.
  • getLogger
  • logger를 설정하기 위한 abstract method로서 DefaultActionSupport를 상속받은 클래스에서는 이 method를 구현하여 logger를 설정해줘야 한다.
  • preProcess
  • process() method 호출 전에 호출되는 method로서 Synchronized Token설정의 확인 및 validateToken, resetToken을 처리한다. Action을 수행하기 위한 preCondition이 필요할 경우 이 method를 override하여 구현한다.
  • Process
  • Struts Action Class의 execute() method와 같이 DefaultActionSupport를 상속받은 하위 Action 클래스에서 반드시 구현해야 하는 method로 비즈니스 로직을 호출하는 코드를 담는다.
  • postProcess
  • process() method 호출 후 호출되는 method로서 Synchronized Token설정의 확인 및 saveToken을 처리한다. Action의 process() method 수행 후 처리해야할 post Condition이 존재할 경우 이 method를 override 하여 구현한다.
  • processInvalidTokenException
  • Synchronized Token 사용시 Token이 유효한 값이 아닐 경우에 대한 처리 로직을 담는다. “요청이 올바르지 않습니다.”라는 메시지를 담은 ActionMessage를 생성하고 InvalidTokenException을 throw 한다.
  • processUnCheckedException
  • RunTimeException 발생시 발생된 Exception을 throw한다. UnChecked Exception 발생시 필요한 처리로직을 이 method를 override하여 구현한다.
  • processCheckedException
  • 발생된 Exception을 Throw한다. Checked Exception 발생시 필요한 처리로직을 이 method를 override하여 구현한다.
  • processFinally
  • execute mthod의 finally 구문에서 호출되는 method이다. Finally 구문에서 필요한 처리로직이 있다면 이 method를 override하여 구현한다.
DefaultActionSupport에서 제공하는 기능이외에 Action 공통 추가 기능이 더 필요할 경우, DefaultActionSupport를 상속받은 상위 클래스를 정의하고 그 상위클래스에서 위의 각 method를 override하여 필요한 기능을 추가한다.

Samples

다음은 DefaultActionSupport를 확장하여 Action 클래스를 작성한 예이다.
public class UpdateUserAction extends DefaultActionSupport {
	
	public Log getLogger() throws Exception {
		return DefaultActionUtils.getLogger(this.getClass().getName());
	}
	
	public ActionForward process(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		ApplicationContext ctx = getWebApplicationContext();
		UserService userService = (UserService) ctx.getBean("userService");

		UserVO userVO = new UserVO();
		UserForm userForm = (UserForm) form;
		BeanUtils.copyProperties(userVO, userForm);
		userService.updateUser(userVO);

		if (EmpUtil.null2str(request.getParameter("flag")).equals("admin")) {
			return mapping.findForward("success_list");
		}
		else {
			return mapping.findForward("success_update");
		}
	}
}
DefaultActionSupport를 상속한 Action 클래스는 DefaultActionSupport 에서 abstract 메소드로 선언한 getLogger 메소드와 process 메소드를 반드시 구현해야 한다. logger를 얻어오기 위한 getLogger 에서는 위의 예와 같이 DefaultActionUtils 클래스의 getLogger 를 이용하여 log4j 기반의 로거를 쉽게 설정할 수 있다. 예에서는 full package 클래스명으로 category 명을 설정했는데 log4j 에서 주로 사용하는 방식이다. 많이 매칭되는 category 의 로거 설정을 따르게 되며 매칭되는 category가 없는 경우 default로 root 로거로 설정된다. getLogger().debug("로그 메시지") 또는 Exception을 함께 로깅하고 싶을 때 getLogger().debug("로그 메시지", e) 와 같이 사용할 수 있으며, 보통 같은 Action에는 같은 로깅 정책을 적용하는 것이 일반적이므로 Constructor 에서 한번만 logger = this.getLogger(); 와 같이 지정할 수도 있다. process 메소드에서는 Action 클래스의 메인 로직을 작성하면 된다.
Log Level에 따른 로그 출력
  • logger.debug("디버그 메시지");
  • logger.info("인포 메시지");
  • logger.warn("경고 메시지");
  • logger.error("에러 메시지");
  • logger.fatal("치명적인 에러 메시지");

DefaultDispatchActionSupport

    Struts의 DispatchAction의 기능을 구현하고 있는 클래스이며 DefaultActionSupport를 상속받아 DefaultActionSupport의 기능을 그대로 사용할 수 있다. 패키지는 anyframe.web.struts.common.action 이다.

Samples

다음은 DefaultDispatchActionSupport를 확장하여 Action 클래스를 작성한 예이다.
public class UserAction extends DefaultDispatchActionSupport {
	
	private Log logger;

	public UserAction() {
		try {
			logger = this.getLogger();
		} catch(Exception e) {
			
		}
	}
	
	public Log getLogger() throws Exception {
		return DefaultActionUtils.getLogger(this.getClass().getName());
	}

	public ActionForward add(ActionMapping mapping, ActionForm form,
	...
		return mapping.findForward("success");
	}

	public ActionForward addUserView(ActionMapping mapping, ActionForm form,
	...
		return mapping.findForward("success");
	}
	
	public ActionForward checkDuplication(ActionMapping mapping, ActionForm form,
	...
		return mapping.findForward("success");
	}
	public ActionForward getUser(ActionMapping mapping, ActionForm form,
	...
		return mapping.findForward("get");
	}
	public ActionForward getUserList(ActionMapping mapping, ActionForm form,
	...
		return mapping.findForward("list");
	}
	public ActionForward updateUser(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		ApplicationContext ctx = getWebApplicationContext();
		UserService userService = (UserService) ctx.getBean("userService");

		UserVO userVO = new UserVO();
		UserForm userForm = (UserForm) form;
		BeanUtils.copyProperties(userVO, userForm);
		userService.updateUser(userVO);

		if (EmpUtil.null2str(request.getParameter("flag")).equals("admin")) {
			return mapping.findForward("success_list");
		}
		else {
			return mapping.findForward("success_update");
		}
	}
}
DefaultDispatchActionSupport를 상속한 Action 클래스는 DefaultActionSupport 를 상속한 클래스 작성과 다르게 하나의 Action 안에 관련된 기능(ex. add, update, remove, view, ...) 을 모아 둔 형태이다. process 메소드 대신 각각의 메소드 명으로 메인 로직을 작성한다. client에서 Action 클래스를 호출할 때 struts-config.xml 의 ActionMapping의 parameter 속성으로 지정된 리터럴로 전달된 메소드 명을 자동으로 실행하게 된다. ActionMapping은 에러 처리, Synchronized Toke 처리 등을 위해 분리하여 작성할 수 있으며 각 메소드에 실행 후 적절한 forward 정보를 설정하는 것에 유의한다.

Resources