Anyframe Web 확장하기

Anyframe Web를 기반으로 웹 어플리케이션을 개발할 때 프로젝트 고유의 기능을 추가로 고려해야할 경우가 있을 것이다. 전체 어플리케이션에 공통적으로 필요한 기능인 경우 프레임워크를 확장하여 이러한 요구사항을 쉽게 해결할 수 있다.
Anyframe Web는 Struts를 확장한 Web Application Framework 이기에 Struts와 같은 확장 Point를 제공한다.

Anyframe Web의 대표적인 확장 포인트
  • org.apache.struts.action.PlugIn 인터페이스를 구현한 프로젝트 자체의 컴포넌트 등록 가능
  • Struts 설정 클래스 확장 - ex.) ActionMapping ◁ DefaultActionMapping ◁ EmpActionMapping
  • 컨트롤러 계층의 확장 - ex.) RequestProcessor ◁ DefaultRequestProcessor ◁ EmpRequestProcessor
  • View 컴포넌트 확장 - ex.) Struts Message Tag ◁ Anyframe Message Tag
예를 들어 모든 request 에 대해 로깅 처리를 하고 싶다던지 특별한 보안 관련 체크 로직 처리가 필요할 수 있다. 이런 요구사항의 경우 Servlet Filter(Servlet2.3 이상) 기능을 적용하여 처리할 수도 있지만 Struts 기반의 어플리케이션에서는 RequestProcessor의 processPreprocess()메소드를 확장하여 쉽게 구현할 수 있다. Struts API의 사용 (ex. Struts 설정 요소 참조)및 어플리케이션 모듈 별로 선별하여 적용 가능한 장점이 있다.
웹 어플리케이션에서 request를 처리하는 일련의 과정은 순서가 있으며 확장 기능의 Constraints 로 순서가 매우 critical한 경우 프레임워크에서 제공하는 확장 포인트 이외에 적절한 확장 기능을 고려해야할 수도 있다.
Struts의 RequestProcessor에는 많은 메소드가 있으며 이 중 별도로 구현을 제공하지 않으며 확장하여 사용 가능한 대표적인 두가지가 processRoles(), processPreprocess()이다. Anyframe Web 에서는 이를 확장하여 processRoles() 에서 role 기반의 권한관리 기능이 적용되어 있으며 processPreprocess() 에서는 web.xml의 Servlet init parameter로 설정된 character-encoding 값에 따라 encoding을 적용할 수 있도록 제공하고 있다.
RequestProcessor 를 확장한 경우 struts-config.xml에 controller 설정은 다음과 같다.
<contoller
     contentType="text/html;charset=euc-kr"
     debug="3"   local="true"   nocache="true"
     processorClass="anyframe.web.struts.common.action.DefaultRequestProcessor" />
이 외에도 Anyframe Web에서 템플릿 Action 클래스로 제공하는 DefaultActionSupport, ExceptionHandler 클래스인 DefaultBaseExceptionHandler, 일부 공통 validation 체크 메소드를 제공하는 DefaultForm 등을 상속하여 프로젝트 고유의 기능을 추가한 클래스를 만들고 이를 베이스로 삼을 수 있다. (struts-config.xml에 관련 클래스 설정이 들어가는 부분을 주의깊게 맞춰줘야 함!)

Samples

DefaultActionSupport의 확장 예
다음은 DefaultActionSupport을 상속하여 공통 기능을 추가한 예이다.
public abstract class EmpActionSupport extends DefaultActionSupport {
	private Log logger;

	public EmpActionSupport() throws Exception {
			logger = this.getLogger();
	}
	
	public Log getLogger() throws Exception {
		return DefaultActionUtils.getLogger(this.getClass().getName());
	}
	
	public abstract ActionForward process(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	public void preProcess(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		super.preProcess(mapping, form, request, response);
		logger.info(this.getClass().getName() + "preProcess extended some logic here ..");
	}


	public ActionForward postProcess(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response,
			ActionForward forward) throws Exception {

		logger.info(this.getClass().getName() + "postProcess extended some logic here ..");
		return super.postProcess(mapping, form, request, response, forward);
	}
}
logger를 Constructor에서 한번만 설정토록 하고 Action 실행(process 메소드) 직전과 직후에 some logic(로깅 처리)를 추가한 예이다.
위에서 확장한 EmpActionSupport을 베이스로 업무 Action 작성 시
public class GetUserListAction extends EmpActionSupport {
	public ActionForward process(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
	    logger.debug("this.getClass().getName() process() started.");
	    ...
	}
}
해당 Action이 실행될 때 parent인 EmpActionSupport에서 공통으로 적용한 preProcess, postProcess 의 추가 로직이 함께 실행될 것이다. logger 설정은 EmpActionSupport 에서 이미 적용되어 있으므로 바로 logger.debug .. 와 같이 사용할 수 있게 된다.

Resources