얼마전에 성철이 형이 물어봐서 답해줬던 내용이다.

많은 개발자들이 애플리케이션 서버로 톰캣을 사용하는 경우에 스태틱 파일(html, css, js, 이미지)은 톰캣 앞에 아파치 웹 서버(Httpd)를 두어서 처리하게 하는 것이 좋다고 생각한다. 외부의 요청은 일단 Apache Httpd가 받고, 톰캣 내에서 처리할 자바 애플리케이션만 톰캣으로 다시 전달해서 처리하고 그 외의 리소스는 Apache Httpd가 직접 처리하게 만들어야 성능이 좋다고 생각한다. 자바로 만든 서버인 톰캣은 스태틱 파일 처리에서 Apache Httpd만 못하다는 것이 그 이유다.

하지만 톰캣과 Httpd의 개발자에 따르면 이는 개발자들이 잘못 알고 있는 미신이다. 아직도 톰캣 3를 사용하고 있는 것이 아니라면 말이다.

자세한 내용은 Myth or truth: One should always use Apache httpd in front of Apache Tomcat to improve performance?에 잘 나와있다. 지금은 스프링 소스의 직원이 된 아파치 톰캣과 Httpd 의 핵심 개발자들이 직접 작성한 내용이다.

톰캣은 5.5부터 Httpd의 native 모듈을 사용해서 스태틱 파일을 처리하는 기능을 제공한다. 이 경우 Httpd와 톰캣이 같은 모듈을 사용하는 셈이니 성능에서 차이가 날 이유가 없다. 실제 테스트 한 결과를 봐도 톰캣에서 아파치 Native 모듈을 사용하는 것이 순수하게 아파치 Httpd만 사용하는 것과 비교해서 성능이 전혀 떨어지지 않는다.

따라서 단지 스태틱 파일 처리의 성능만을 위해서라면 굳이 톰캣 앞에 Apache Httpd를 두는 것은 불필요하다. 오히려 메모리만 많이 먹고, 관리부담은 커지고, 불필요한 부하만 걸릴 뿐이다.

물론 Httpd의 다른 기능이나 모듈을 사용해야 할 필요가 있다면 그때는 Httpd를 앞에 두고 사용해야겠지만. 예를 들어 하나의 서버에서 PHP 애플리케이션과 자바 애플리케이션을 함께 사용하거나, Httpd 서버를 간단한 로드밸런싱을 위해서 사용해야 하는 경우라면 Httpd를 앞에 두고 톰캣을 연결해서 사용하도록 하면 될 것이다.

  • facebook
  • friendfeed
  • google_buzz
  • reddit
  • stumble
  • tumblr
  • twitter
  • rss
  • bookmark

Related posts:

  1. 스프링 컨테이너에는 설정파일이 없다
  2. 파이썬 완벽 가이드 전자책
  3. Maven archetype 설정파일 자동생성기 – ArchetypeXmlWriter
  4. Spring 3.0 (59) 프로퍼티 파일 이용하기 – placeholder vs SpEL
  5. 유쾌한 이슈처리 재촉 메일
  6. Spring-OSGi 시작하기 – OSGi
  7. 당신은 고난받기 위해 태어난 사람
  8. Apache Tomcat Tips & Tricks from the Pros – 웨비나 소식
  9. Spring 3.0 (58) Static Class를 XML없이 빈으로 등록하기
  10. [토스3] 스프링 3.0.4 <mvc:default-servlet-handler/>를 이용해서 UrlRewriteFilter없이 깔끔한 URL을 만들기
  11. 태터툴즈 이틀 사용기


출처 - http://toby.epril.com/?p=1125




Posted by linuxism
,

이전에 스프링 MVC Controller Class 에 대해서 아주아주 간략한 소개 글을 올렸는데 오늘은 MultiActioncontroller 사용하는 방법을 간단히 소개해 볼께요. 사실 저도 한번도 안 써보다가 이번에 한번 활용해 보았네요. ^^;

MultiActionController 는 다중 액션(연관 또는 비슷한 로직을 수행하는 기능들을 하나의 컨트롤러에 구현할때 사용) 에 사용한다고 했는데요...

예로 로그인 관련 로직을 수행하는 Controller를 작성해본다고 해봅시다.
로그인 관련이라 하면 일단 로그인 페이지의 뷰와 로그인 했을 때의 뷰와 로그아웃 했을 때의 뷰를 보여주는 기능들이 있겠죠...

그럼 아래와 같이 MultiActionController 를 상속 받은 LoginController 를 만들어야겠군요...

public class LoginController extends MultiActionController {
   // 로그인 페이지의 뷰
   public ModelAndView loginPage(HttpServletRequest request, 
      HttpServletResponse response) {
      return new ModelAndView("login");
   }

   // 로그인 했을 때의 뷰
   public ModelAndView doLogin(HttpServletRequest request, 
      HttpServletResponse response) {
      /* 중략 */
      return new ModelAndView(new RedirectView(url, true));
   }

   // 로그아웃 했을 때의 뷰
   public ModelAndView doLogout(HttpServletRequest request, 
      HttpServletResponse response) {
      /* 중략 */
      return new ModelAndView(new RedirectView(url, true));
   }
}

그럼 다음으로 손 볼 곳은 ???-servlet.xml 이겠군요...

<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
   <property name="mappings">
      <value>
         /doLogin.do=loginController
         /doLogout.do=loginController
         /loginPage.do=loginController
      </value>
   </property>
   
   <bean id="loginController" class="com.depository.controller.LoginController" />
</bean>

보시면 아시겠지만 /doLogin.do 의 요청이 오면 LoginController 의 doLogin 메쏘드를 타고, /doLogout.do 의 요청이 오면 doLogout 메쏘드를 타게 되니 이름만 맞춰주는거만 하면 오타 안나게 하시면 됩니다.

굳이 MethodNameResolver 설정 안하셔도 된다는거죠... 일단 제가 테스트 해보면서 제대로 동작하는걸 확인했으니... 아님 말구요~ ㅡ,.ㅡ;a


출처 - http://depository.tistory.com/168

'Framework & Platform > Spring' 카테고리의 다른 글

Spring - @RequestMapping  (0) 2012.05.09
Spring MVC Deprecated API  (0) 2012.05.08
spring controller 종류  (0) 2012.05.08
spring에서 thread  (0) 2012.05.02
spring mvc - 입력 값 검증 및 BindException  (0) 2012.04.25
Posted by linuxism
,


스프링 MVC 어플리케이션의 작동을 구현할때에는 스프링 컨트롤러 클래스중 하나를 확장해서 사용하게 된다.

controller 는 DispatcherServlet 으로 부터 요청을 받아들여 사용자를 대신하여 비즈니스 기능을 수행하게 된다.

스프링 MVC 의 컨트롤러는 스트러츠나 웹워크의 액션과 같은 단순한 액션 계층구조와는 달리 매우 풍부한 컨트롤러 계층 구조를 제공하고 있다는 점이다.

 1.gif

 

컨트롤러 계층구조의 가장 상위에는Controller 인터페이스가 있다. 이 인터페이스를 구현하는 모든 클래스는 스프링 MVC 프레임웍에서 요청을 처리하는 데 사용될 수 있다. 만약 컨트롤러를 만든다면 반드시 이 인터페이스를 구현해야 한다.

Controller 인터페이스를 직접 구현하여 클래스를 작성할 수 도 있지만 그보다는 계층구조의 아래부분에 위치하는 클래스들 중 하나를 확장해서 사용하는것이 낫다. Controller 인터페이스는 컨트롤러와 스프링MVC 간의 기본적인 규약을 정의하는 반면에, 다른 컨트롤러 클래스들은 그에 대하여 부가적인 기능들도 제공하기 때문이다.

 

컨트롤러의 종류및 특징에 대해 알아보자...

 

1. Controller ( 인터페이스 ) : 단순한 유형으로써 간단한 컨트롤러 만들고자 할때 사용된다.

 

2. AbstractController : 단순한 유형으로써 Controller 인터페이스 보다 약간 더 부가적인 기능을 포함한다.

 다음과 같은 프로퍼티를 포함하고 있다.

 supportedMethods, requiresSession, synchronizeSession, cacheSeconds, useExpiresHeader, useCacheHeader

 

 

 EmployeeController.java

 

public class EmployeeListController extends AbstractController {

 @Override
 protected ModelAndView handleRequestInternal(HttpServletRequest request,
   HttpServletResponse response) throws Exception {
  ModelAndView mav = new ModelAndView();
  mav.setViewName("jsp/list/employeeList");
  mav.addObject("message", "HelloWorld!!!");
  return mav;
 }
}

 

 

 

위와 같이 handleRequestInternal() 는 AbstractController 실행에 있어서 주된 메소드로서 이 메소드를 제정의 함으로써 컨트롤러의 기능을 구현할 수 있다.

 

그리고 설정파일(springmvc-servlet.xml) 에서 추가적인 기능을 포함시킬수 있다. 다음은 한 예를 보자.

 

<bean id="employeeListController" class="com.example.control.EmployeeListController">
  <property name="supportedMethods">
   <value>GET,POST</value>
  </property>
 </bean>

 supportMethods 는  get방식인지, post 방식인지를 설정하는 property 이다. value 는 get 방식, post 방식, get,post  둘다 설정가능하다.

아주 간단한 경우, Controller를 구현할 때에는 Controller 인터페이스를 직접 구현하기보다는, AbstractController 추상 클래스를 상속 받아 구현하는 경우가 더 많다.

 

3. AbstractCommandController : AbstractController 에 기반한 컨트롤러를 사용할 경우에는 넘어온 파라미터를 HttpServletRequest. 로  부터 필요한 값을 얻을 것이다..그러나 그렇게 하면 비즈니스 객체에 바인딩시키는 로직을 추가로 작성해야하며 또한 컨트롤러 자체의 유효성 검증 로직도 포함시켜야 한다..바인딩 로직과 유효성 검증은 진정한 컨트롤러의 역할이 아니다. 컨트롤러가 만약에 파라미터에 기초하여 작업을 수행하는 경우라면 AbstractCommandController 를 사용해야한다. 이컨트롤러는 명령객체에 자동으로 바인딩 시켜 주며, 파라미터 유효성 확인을 위한 검증기를 플러그인 할 수 있는 훅(hook) 을 제공한다.

 

다음의 예제소스를 보자

 

 

ExAbstractCommandController.java

import net.jtlab.example.dao.ExAbstractCommand;

import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;

public class ExAbstractCommandController extends AbstractCommandController {

 public ExAbstractCommandController(){
  //명령클래스 설정
  setCommandClass(ExAbstractCommand.class);
 } 
 @Override
 protected ModelAndView handle(HttpServletRequest request,
   HttpServletResponse response, Object command, BindException errors)
   throws Exception {
  
  ExAbstractCommand abstractCommand = (ExAbstractCommand)command;
  System.out.println(abstractCommand.getId());
  System.out.println(abstractCommand.getPassword());
  System.out.println(abstractCommand.getName());
  
  return null;
 }
}

 

 

예제를 보면 ExAbstractCommandController 클래스는 handle() 메소드는 AbstractCommandController 를 위한 주된 실행 메소드라는 것을 알수 있으며 또한 AbstractController 와 다르게 Object 객체와 BindException 객체가 추가된 것을 알 수 있다.

생성자에서 추가된 ExAbstractCommand 클래스는 요청된 파라미터를 저장하는 객체로서 단순 setter, getter 메소드를 포함하고 있다.

스프링은 handle() 메소드가 호출되기 이전에 , 요청에 전달된 모든 파라미터를 명령객체의 특성에 맞추어 주기 때문에

명령컨트롤러는 요청 파라미터를 명령객체에 바인딩시켜줌으로써 쉽게 다룰수 있다.

 

파라미터로 넘어온 값을 단순 출력하는 예제 이므로 한번 실습하기를 권한다.

 

4. SimpleFormController : 사용자가 정보를 등록하고자 할때 그정보가 별다른 문제가 없다면 성공적으로 등록되고 잘못된 데이터를 입력했다면 값을 수정하고 다시 제출해야 할것이다. 이런 경우 등록 절차를 구현하기 위해 폼을 구현하는 AbstractController 와 폼을 처리하기 위한 AbstractCommandController 를 사용해야 할 것이다. 이 두개의 서로 다른 컨트롤러를 관리해야 하는 번거로움을 해결할 수 있는 컨트롤러가 바로 SimpleFormController 이다. 폼 컨트롤러는 명령컨트롤러의 개념을 이어 받았으며 만일 HTTP get 요청을 받았을 경우에는 폼을 보여주고 HTTP post 요청을 받았을 경우에는 폼을 처리하는 기능이 추가된 컨트롤러 이다.

다음의 예제를 살펴보자.

 

 

ExSimpleFormController.java

import org.springframework.web.servlet.mvc.SimpleFormController;

public class ExSimpleFormController extends SimpleFormController {

 public ExSimpleFormController() {
  setCommandClass(ExSimpleFormCommand.class);
 }

 @Override
 protected void doSubmitAction(Object command) throws Exception {
  ExSimpleFormCommand exSimpleFormCommand = (ExSimpleFormCommand)command;
  System.out.println(exSimpleFormCommand.getName());
  System.out.println(exSimpleFormCommand.getTel());
  System.out.println(exSimpleFormCommand.getAddress());  
 }
}

 

 

명확하지 않은 것은 이 컨트롤러가 어떻게 폼을 보여줄지를 알 수 있는지에 대한 것이다. 또한 성공시킨 후 사용자를 어디로 이동시킬지 또한 명확하지 않다. 또 doSubmitAction() 메소드는 ModelAndView 객체를 리턴하지도 않는다..

SimpleFormController 는 뷰와 관련된 자세한 사항은 컨트롤러의 자바로부터 가급적이면 분리시키도록 설계됐다.. ModelAndView 객체를 하드코딩하는 대신, 다음과 같이 컨텍스트 설정파일에서 컨트롤러를  설정할 수 있는 것이다.

 

 

springmvc-servlet.xml

 <bean name="/simpleFormController.do" class="net.jtlab.example.action.ExSimpleFormController">
  <property name="formView">
   <value>simpleFormView</value>
  </property>
  <property name="successView">
   <value>successView</value>
  </property>
 </bean>

 

 

 

SimpleFormController 는 어떤 서비스객체 뿐만 아니라 위와같이 formView 특성과 successView 특성을 추가로 설정해야한다.

formView 특성은 컨트롤러가 HTTP GET요청을 받았을때나 또는 에러가 발생했을때 보여줘야할 뷰의 논리적인 이름이다.

successView 특성은 성공적으로 폼이 제출됐을때 보여줘야 할 뷰의 논리적인 이름이다. 

그렇지만 doSubmitAction() 의 사용은 제약사항이 있다. ModelAndView 객체를 리턴할 필요성이 없어짐으로써 동시에 모델데이터를 뷰에 넘기는 것도 불가능하게 되었다. 만약에 데이터를 전송하여 뷰에 보여지도록 해야 하는 경우라면 doSubmitAction() 대신에 onSubmit() 메소드를 재정의 해야 할 것이다.

 

 

ExSimpleFormController.java

import org.springframework.web.servlet.mvc.SimpleFormController;

public class ExSimpleFormController extends SimpleFormController {

  @Override
 protected ModelAndView onSubmit(Object command, BindException errors)
   throws Exception {
  ExSimpleFormCommand exSimpleFormCommand = (ExSimpleFormCommand)command;  
  return new ModelAndView(getSuccessView(), "formCommand", exSimpleFormCommand);
 }

}

 

 

다른 컨트롤러의 핸들러메소드와 마찬가지로 ModelAndView 객체를 리턴하지만 여전히 컨텍스트 설정파일에서 성공한 뷰를 설정할 수 있기 때문에 뷰의 논리적인 이름을 설정할때는 반드시 getSuccessView() 메소드를 호출해야한다.

 

5. MultiActionController : 위의 모든 컨트롤러는 하나의 작업만을 수행하는 것들이었다. 컨트롤러의 하나의 액션은 아무래도 제한적일 수 있으며 비슷하거나 관련된 기능을 수행하는 컨트롤러들 사이에 많은 양의 반복적인 코드를 만들 여지가 있어야 한다. MutiActionController는 다중액션을 수행할 수 있는 특별한 종류의 컨트롤러로서 각 액션은 다양한 메소드와 연결될 수 있다.

다음의 예제를 살펴보자.

 

 

ExMultiActionController.java

import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

public class ExMultiActionController extends MultiActionController {
 
 public ModelAndView add(HttpServletRequest request, HttpServletResponse response){
  System.out.println("Add Data!!!");
  return new ModelAndView("AddView");
 }
 public ModelAndView delete(HttpServletRequest request, HttpServletResponse response){
  System.out.println("Delete Data!!!");
  return new ModelAndView("DeleteView");
 }
 public ModelAndView retrieve(HttpServletRequest request, HttpServletResponse response){
  System.out.println("Retrieve Data!!!");
  return new ModelAndView("RetrieveView");
 }
 public ModelAndView update(HttpServletRequest request, HttpServletResponse response){
  System.out.println("Update Data!!!");
  return new ModelAndView("UpdateView");
 }
}

 

 

 

위의 소스 예제를 보면 메소드 4개를 선언했으며 각각의 ModelAndView 객체에 뷰의 논리적인 이름을 명시하여 리턴하였다..

이제 어떤 요청이 있을 경우 해당 메소드를 실행할지 결정하는 일이 남아 있다..

MultiActionController 는 메소드 이름 리졸버에 기초하여 메소드의 이름을 결정한다.

Spring 에서는 NameResolver를 제공하고 있다.

 - ParameterMethodNameResolver : 요청 파라미터를 기초로 하여 실행 메소드 이름을 결정한다.

 - PropertiesMethodNameResolver : 키 - 값 쌍의 목록을 기초로 하여 실행 메소드 이름을 결정한다.

 

우선 ParameterMethodNameResolver 사용하여 설정하면 설정파일은 다음과 같다.

 

 

springmvc-servlet.xml

 <bean id="exMultiActionController" class="net.jtlab.example.action.exMultiActionController">
  <property name="methodNameResolver">
   <ref local="exPropertiesMethodNameResolver"/>
  </property>
 </bean> 

 <bean id="exPropertiesMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
  <property name="mappings">
   <props>
    <prop key="/addMultiActionData.do">add</prop>
    <prop key="/deleteMultiActionData.do">delete</prop>
    <prop key="/updateMultiActionData.do">update</prop>
    <prop key="/retrieveMultiActionData.do">retrieve</prop>
   </props>
  </property>
 </bean>

 

 

출처 - 



Posted by linuxism
,