일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 스프링 부트
- spring
- OAuth 2.0
- apache thrift
- elasticache
- ServletContextInitializer
- spring-mybatis
- WebApplicationInitializer
- Fiilter
- spring boot 1.3
- spring boot devtools
- spring security
- 스프링시큐리티
- spring cloud
- mybatis
- 데브툴즈
- Spring MVC
- @MVC
- Multi DataSource
- spring camp
- 인텔리J
- devtools
- 스프링
- KSUG
- OAuth2.0
- spring boot mybatis
- spring test mvc
- spring cloud config
- Spring Security OAuth
- Spring Boot
- Today
- Total
홍이의 개발 노트
Spring MVC 3.1 에서 달라진 <mvc:annotation-driven/> 전략 본문
기존 Spring MVC 3.0.x의 <mvc:annotation-driven/> 태그의 전략은
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
클래스를 사용하여 맵핑 및 여러 클래스를 추가하여 구성이 되었다.
하지만 이번 3.1 버전이 나오며 이야기가 달라졌다.
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
이 두개의 클래스가 주축이 되면서 기능 및 구성이 달라지고
기존과는 거의 호환이 되게 만들졌다.
기존의 전략은 박성철님 블로그 ( http://gyumee.egloos.com/3056225 ) 여기에서 보는 것과 같이 구성되어 있었다.
하지만 3.1은 조금 달라졌다.
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="order" value="0" />
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<!-- <mvc:message-converters> 태그의 messageConverter와 통합 -->
<util:list id="messageConverters">
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="writeAcceptCharset" value="false" />
</bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter" />
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" />
<!-- jaxb2라이브러리 존재시 -->
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
<!-- -->
<!-- jackson 라이브러리 존재시 -->
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<!-- -->
<!-- rome 라이브러리 존재시 -->
<bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter" />
<bean class="org.springframework.http.converter.feed.RssChannelHttpMessageConverter" />
<!-- -->
</util:list>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
<property name="conversionService" ref="conversion-service" />
</bean>
</property>
<property name="messageConverters" ref="messageConverters"/>
<!-- <mvc:argument-resolvers> 태그 존재시 -->
<!--
<property name="customArgumentResolvers">
</property>
-->
<!-- <mvc:return-value-handlers> 태그 존재시 -->
<!--
<property name="customReturnValueHandlers">
</property>
-->
</bean>
<bean class="org.springframework.web.servlet.handler.MappedInterceptor">
<constructor-arg index="0">
<null />
</constructor-arg>
<constructor-arg index="1">
<bean class="org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor">
<constructor-arg index="0" ref="conversion-service" />
</bean>
</constructor-arg>
</bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="messageConverters" ref="messageConverters"/>
<property name="order" value="0"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver">
<property name="order" value="1"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver">
<property name="order" value="2"/>
</bean>
이렇게 변경이 되었다
먼저 변경된 부분만 이야기하면
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
이 두 부분이 바뀐것이 가장 큰 변화이고
그다음은 customArgumentResolvers 이 속성의 인터페이스가 변경 되었다.
기존에는 WebArgumentResolver인터페이스를 상속 받았으나 3.1부터는 HandlerMethodArgumentResolver 인터페이스를 상속 받아 구현을 해야한다.
하지만 <mvc:annotation-driven/> 여기서 등록시에는 기존 WebArgumentResolver 이부분을 구현한 클래스가 사용은 가능하다. 내부적으로 ServletWebArgumentResolverAdapter 클래스를 사용하여 호환 가능하게 변경을 해준다.
하지만 생각지 못한 버그가 발생할 수 있으니 변경된 인터페이스를 적용하는 것을 추천한다.
그리고 customModelAndViewResolvers 이 속성 또한 변경되었다.
기존에는 ModelAndViewResolver인터페이스를 상속 받았으나 3.1부터는 HandlerMethodReturnValueHandler 인터페이스를 상속받아 구현해야한다.
이름은 customReturnValueHandlers 속성의 이름으로 변경되었으며 WebArgumentResolver와 같이 인터페이스도 변경되었다.
추가로 로딩되는 Bean으로는
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="messageConverters" ref="messageConverters"/>
<property name="order" value="0"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver">
<property name="order" value="1"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver">
<property name="order" value="2"/>
</bean>
이렇게 3개의 Bean이 로딩이 된다
첫번째 로딩되는 Bean인 ExceptionHandlerExceptionResolver 클래스는 RequestMappingHandlerAdapter 에서 참조 하는 messageConverters를 똑같이 참조하고 있다.
용도를 정확히는 확인해보지는 않았지만 대략 @RequestBody의 @Valid 어노테이션을 사용할 수 있는 것과 관계 있는 것으로 보인다.
이부분은 추후로 보완할 예정이다.