(스프링) 7장 고급 스프링 MVC

1. DispatcherServlet 설정 사용자 정의하기

AbstractAnnotationConfigDispatcherServletInitializer에는 눈에 보이는 것 외에 뭔가 더 있어 보인다. SpitterWebApplnitializer에 작성한 세가지 메소드는 반드시 오버라이드되어야 하는 추상 메소들이 있다. 하지만 추가 설정을 하기 위해 오버라이드할 수 있는 메소드들도 있다.
이러한 메소들중 하나가 customizeRegistration()이다. AbstractAnnotationConfigDispatcherServletInitializer가 서블릿 컨테이너와 DIspatcherServlet을 등록한 다음, ServletRegistration안에 전달하면서 customizeRegistration()메소드를 호출한다. customizeRegistration()를 오버라이딩함으로써 DispatcherServlet에 추가적인 설정을 적용한다.


만약 멀티파트를 지원하는 서블릿3.0을 사용할 것이라면 DispatcherServlet에 멀티파트 요청을 등록한다. MultipartConfigElement를 설정하도록 customizeRegistration() 메소드를 아래와 같이 오버라이딩 한다.

@Override
protected void customizeRegistration(Dynamic registration)
{
  registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));
}

-->customizeRegistration()에서 넘겨지는 ServletRegistration.Dynamic으로 setLoadOnStartup()을 호출하여 load-on-startup우선순위를 설정하고, setInitParameter()를 호출하여 초기 인자들을 설정하고, 서블릿 3.0 멀티파트 지원을 설정하기 위해 setMultipartConfig()를 호출하는 것들을 포함한 몇가지 기능을 수행한다.


2. 서블릿과 필터 추가하기

AbstractAnnotationConfigDispatcherServletInitializer의 정의에 따르면, 기본적으로 DispatcherServlet과 ContextLoaderListener가 생성된다. 하지만 서블릿,필터,리스너를 추가적으로 등록하고 싶다면 어떻게 할까?

자바 기반의 초기화 방식에서 동작시킬 때의 장저은(web.xml을 사용하는 방식과 달리)사용자가 원하는 대로 초기화 클래스를 정의한다는 것이다. 따라서 웹 컨테이너에 추가적인 컴포넌트를 등록한다면, 새로운 초기화 클래스를 생성하기만 하면된다. 가장 쉬운 방법은 스프링의 WebApplicationInitializer인터페이스를 구현하는 것이다.


위 코드는 서블릿-등록 초기화 클래스다. 이 클래스는 서블릿을 등록하고 각 서블릿을 단일 패스에 매핑시킨다. DispatcherServlet을 수동으로 등록하는 것도 같은 방식을 쓸 수 있다.
비슷하게, WebApplicationInitializer를 새로 생성하는 것으로 리스너와 필터를 등록한다.
다음 코드는 필터 등록 방법으로 보여주는 예이다.



서블릿 3.0 컨테이너로 배포할 때 WebApplicationInitializer는 자바로 서블릿, 필터, 리스너를 등록하기 위한 일반적인 방법이다. 하지만 필터를 등록하여 단순히 DispatcherServlet에만 매핑한다면, 간단하게 AbstractAnnotationConfigDispatcherServletInitializer를 사용하면 된다.

다수의 필터를 DispatcherServlet에 매핑하기 위해 필용한 것은 AbstractAnnotationConfigDispatcherServletInitializer의 getServletFilters()메소드 오바라이드이다. 필터를 등록하기 위해 AbstractAnnotationConfigDispatcherServletInitializer에서 오버라이드된 getServletFilters() 메소드를 보자.

@Override
protected Filter[] getServletFilters(){
 return new Filter[] {new MyFilter()};
}

--->필터의 매핑에 대한 선언을 해줄 필요는 없다. getServletFilters()에서 반환되는 필터는 자동적으로 DispatcherServlet에 매핑된다.


3. web.xml에서 DispatcherServlet 선언하기

일반적으로 스프링 MVC 애플리케이션이라면 DispatcherServlet과 CotextLoaderListener가 필요하다. 그리고 AbstractAnnotationConfigDispatcherServletInitializer는 자동적으로 두 클래스를 등록한다. 하지만 web.xml으로 등록한다면 전부 직접해주어야 한다.


예) web.xml로 스프링 MVC설정하기

<web-app version="2.5"~~~>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value> //루트 컨텍스트위치 설정
  </context-param>

<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener //ContextLoaderListener등록
  </listener-class>
</listener>

<servlet>
  <servlet-name>appServlet</servlet-name>
  <servlet-class>
    org.springframework.web.servlet.DispatcherServlet //DispatcherServlet등록
  </servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>appServlet</servlet-name>   //DispatcherServlet을 /에 매핑
  <url-pattern>/</url-patter>
</servlet-mapping>

</web-app>



ContextLoadListener와 DispatcherServlet은 각각 스프링 애플리케이션 컨텍스트를 불러온다.
contextConfigLocation컨텍스트 인자는 ContextLoaderListener에서 불러올 루트 애플리케이션 컨텍스트가 정의된 XML파일의 위치를 명시한다.

DispatcherServlet은 서블릿 이름을 기반으로 한 XML파일에서 애플리케이션 컨텍스트를 불러온다. 위 코드에서는 appServlet이다. 따라서 DispatcherServlet은 /WEB-INF/appServlet-context.xml파일에서 애플리케이션 컨텍스트를 불러오도록 되어 있다.



**XML설정 방식보다 자바기반 설정을 사용하기 위해서는 DispatcherServlet과 ContextLoaderListener에 AnnotationConfigWebApplicationContext를 사용할 것을 명시해야 한다.

아래코드는 자바기반 스프링 설정을 위한 스프링 MVC설정 web.xml파일의 예제이다.

<web-app version="2.5"~~~>
  <context-param>
    <param-name>contextClass</param-name>  <---자바 설정사용
    <param-value>     org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </context-param>


<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>com.habuma.spitter.config.RootConfig</param-value> <--루트 설정 클래스 명시
</context-param>

<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

<servlet>
  <servlet-name>appServlet</servlet-name>
  <servlet-class>
    org.springframework.web.servlet.DispatcherServlet
  </servlet-class>
  <init-param>
   <param-name>contextClass</param-name> <---자바 설정 사용
   <param-value>     org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </init-param>

  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    com.habuma.spitter.config.WebConfigConfig
   </param-value>
  </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>appServlet</servlet-name>   //DispatcherServlet을 /에 매핑
  <url-pattern>/</url-patter>
</servlet-mapping>

</web-app>


4. 멀티파트 폼 데이터 처리하기

사용자가 웹 애플리케이션을 통해 콘텐츠를 업로드 하는 것은 일반적인 방식이다.

  <<멀티파트 리졸버 설정하기>>


  •   CommonsMultipartResolver-멀티파트 요청을 Jakarta Commons FileUpload를 사용하여 결정
  • StandardServletMultipartResolver-서블릿 3.0을 사용한 멀티파트 요청에 대한 지원(Spring 3.1부터~)

 
<서블릿 3.0으로 멀티파트 요청 결정하기>

사용자가 업로드하는 파일의 최대 크기에 제한을 두려면 어떻게 해야 할까? 업로드되는 파일이 임시로 저장되는 위치를 명시하고 싶다면 어떻게 해야할까?
스프링 설정에서 StandardServletMultipartResolver를 설정하는 대신 서블릿 설정에서 멀티파트 설정을명시해 주어야한다. 최소한 업로드 동안 파일을 저장할 임시 패스를 명시해 주어야 한다.

WebApplicationInitializer를 구현한 서블릿 초기화 클래스에서 DispatcherServlet을 설정하면, 서블릿 등록시에 setMultpartConfg()를 호출하고 MutlpartConfigElement의 인스턴스를 전달할 때 멀티파트의 세부사항을 설정한다. 아래에 임시 파일 위치를 /tmp/spittr/uploads로 설정하기 위한 DIsptacherServlet의 최소한의 멀티파트 설정이 있다.

DispatcherSevlet ds=new DispatcherServlet();
Dynamic registraion=context.addServlet("appServlet",ds);
registration.addMapping("/");
registration.setMultipartConfg(
 new MultipartConfigElement("/tmp/spittr/Uploads"));


AbstractAnnotationConfigDispatcherServletInitializer나 AbstractDispatcherServletInitializer를 상속받은 서블릿 초기화 클래스로 설정된 DispatcherServlet을 사용한다면 DispatcherServlet의 인스턴스를 생성하거나 서블릿 컨텍스트로 직접 등록해 줄 필요가 없다. 결과적으로 같이 동작할 Dynamic서블릿 등록의 참조가 없다는 말이다. 하지만 멀티파트 세부사항 설정을 위해 customizeRegistration()메소드를 오버라이딩하는 것이 가능하다.

@Override
protected void customizeRegistration(Dynamic registration)
{
  registration.setMultipartConfig( new MultipartConfigElement("/tmp/spittr/uploads",2097152,419434,0));
}

--> 업로드되는 파일의 크기를 2MB로 제한하고, 전체 요청의 크기를 4MB로 제한하며, 모든 파일을 디스크에 쓰도록 하고싶다면 위와 같이 MultipartConfigElement를 설정하여 사용한다.



<이미지 파일을 클라우드에 저장하기>

*Amazon S3에 파일 저장하기


댓글

이 블로그의 인기 게시물

(18장) WebSocekt과 STOMP를 사용하여 메시징하기

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬