WebMvcConfigurerAdapter

FRAMEWORK/SPRING 2017. 10. 19. 16:25

spring mvc의 xml과 java config를 비교해서 한번 살펴보겠다.

EnableWebMvc

@Configuration
@EnableWebMvc
public class WebConfig {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:annotation-driven/>

</beans>

xml의 은 @EnableWebMvc과 같은 설정이다. 위의 설정은 해주는게 많다. messageConverter, formatting, validating 기타 등등 아주 여러가지를 해주는 어노테이션 및 xml 설정이다. 나머지는 인터넷에서 쉽게 찾을 수 있으니 참고만 하길 바란다.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

}

우리는 WebMvcConfigurerAdapter을 상속받아서 커스터마이징을 할 수 있다.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

  @Override
  public void addFormatters(FormatterRegistry registry) {
  }
}

Conversion and Formatting

<mvc:annotation-driven conversion-service="conversionService"/>

<bean id="conversionService"
      class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="org.example.MyConverter"/>
        </set>
    </property>
    <property name="formatters">
        <set>
            <bean class="org.example.MyFormatter"/>
            <bean class="org.example.MyAnnotationFormatterFactory"/>
        </set>
    </property>
    <property name="formatterRegistrars">
        <set>
            <bean class="org.example.MyFormatterRegistrar"/>
        </set>
    </property>
</bean>

위의 xml과 javaconfig는 똑같은 설정이다. 간단하게 addFormatters 메서드를 재정의하면 된다.

Validation

@Override
public Validator getValidator() {
  return null;
}
<mvc:annotation-driven validator="globalValidator"/>

마찬가지로 getValidator를 재정의하면 위의 xml과 같은 설정이 된다.

Interceptors

@Override
public void addInterceptors(InterceptorRegistry registry) {
  registry.addInterceptor(new LocaleInterceptor());
  registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
  registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}
<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/admin/**"/>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/secure/*"/>
        <bean class="org.example.SecurityInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

위의 설정은 인터셉터이다. addInterceptors를 재정의해서 등록하면 된다.

Content Negotiation

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
  configurer.mediaType("json", MediaType.APPLICATION_JSON);
}
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="mediaTypes">
        <value>
            json=application/json
            xml=application/xml
        </value>
    </property>
</bean>

위의 xml설정은 java config의 configureContentNegotiation 재정의해서 등록하면 된다.

View Controllers

@Override
public void addViewControllers(ViewControllerRegistry registry) {
  registry.addViewController("/").setViewName("home");
}
<mvc:view-controller path="/" view-name="home"/>

static한 html을 바로 사용하기 좋은 설정이다. addViewControllers만 재정의해서 등록하면 된다.

Serving of Resources

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
  registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/");
}
<mvc:resources mapping="/resources/**" location="/public-resources/"/>

리소스들은 등록한다 addResourceHandlers만 재정의하면 된다.

<mvc:resources mapping="/resources/**" location="/public-resources/" cache-period="31556926"/>

캐쉬 설정도 가능하다.

Falling Back On the “Default” Servlet To Serve Resources

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  configurer.enable();
}
<mvc:default-servlet-handler/>

위는 같은 설정이다.

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  configurer.enable("myCustomDefaultServlet");
}
<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>

Path Matching

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
  configurer
    .setUseSuffixPatternMatch(true)
    .setUseTrailingSlashMatch(false)
    .setUseRegisteredSuffixPatternMatch(true)
    .setPathMatcher(antPathMatcher())
    .setUrlPathHelper(urlPathHelper());
}

@Bean
public UrlPathHelper urlPathHelper() {
  //...
}

@Bean
public PathMatcher antPathMatcher() {
  //...
}
<mvc:annotation-driven>
    <mvc:path-matching
        suffix-pattern="true"
        trailing-slash="false"
        registered-suffixes-only="true"
        path-helper="pathHelper"
        path-matcher="pathMatcher"/>
</mvc:annotation-driven>

<bean id="pathHelper" class="org.example.app.MyPathHelper"/>
<bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>

configurePathMatch만 재정의 하면 된다.

Message Converters

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
    .indentOutput(true)
    .dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
    .modulesToInstall(new ParameterNamesModule());
  converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
  converters.add(new MappingJackson2XmlHttpMessageConverter(builder.xml().build()));
}
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="objectMapper"/>
        </bean>
        <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
            <property name="objectMapper" ref="xmlMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
      p:indentOutput="true"
      p:simpleDateFormat="yyyy-MM-dd"
      p:modulesToInstall="com.fasterxml.jackson.module.paramnames.ParameterNamesModule"/>

<bean id="xmlMapper" parent="objectMapper" p:createXmlMapper="true"/>

위의 설정도 같은 설정이다.

솔직히 거의다 아는 내용이지만 아예 모르거나 긴가민가 하는 부분도 몇개 있다. 다음에는 저 설정이 어떤 역할을 하는지 알아보자!

출처 : http://docs.spring.io/spring/docs/4.3.0.RC2/spring-framework-reference/htmlsingle/#mvc-config-

: