Software Development Engineer @ Amazon
reniowood at gmail.com resume
다음 내용은 Spring Web MVC 5.1.0.RELEASE 버전의 공식 문서인 Web On Servlet Stack의 Spring Web MVC 부분 중 일부분을 발췌해 번역해 놓은 것입니다. 링크된 공식 문서의 내용과 다른 부분이나 생략된 부분이 있을 수 있습니다.
@EnableWebMvc
어노테이션을 사용한다.
@Configuration
@EnableWebMvc
public class WebConfig {
}
WebMvcConfigurer
인터페이스를 구현 할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
}
Number
와 Date
타입을 위한 formatter가 준비되어 있다. (@NumberFormat
과 @DateTimeFormat
어노테이션도 지원한다). Joda-Time이 classpath에 있으면 Joda-Time formatting library도 지원한다.
다음과 같이 임의의 formatter와 converter도 추가 가능하다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
JSR-303 Bean Validation provider가 classpath에 있으면 LocalValidatorFactoryBean
이 전역 validator로 등록되어 @Valid
와 Validated
를 처리한다.
임의의 전역 Validator
인스턴스를 사용하고 싶으면 다음과 같이 메소드를 override한다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public Validator getValidator(); {
// ...
}
}
임의의 Validator
구현을 추가할 수도 있다.
@Controller
public class MyController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new FooValidator());
}
}
다음과 같이 요청에 적용할 interceptor를 추가할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}
}
Spring MVC가 어떻게 요청의 media type을 결정할지 설정할 수 있다.
기본값은 URL 경로 확장자(json
, xml
, rss
등)를 먼저 확인하도록 하고, 그 다음에 Accept
헤더를 확인하도록 되어있다.
Accept
헤더만 확인하도록 하거나, URL을 기반으로 content type을 결정하고 싶으면 다음 링크를 참조한다. Suffix Match와 Suffix Match and RFD
다음과 같이 임의로 content type을 처리할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.mediaType("json", MediaType.APPLICATION_JSON);
configurer.mediaType("xml", MediaType.APPLICATION_XML);
}
}
configureMessageConverters()
(Spring MVC가 제공하는 기본 converter를 대체한다.) 나 extendMessageConverters()
(기본 converter를 수정하거나 새로운 converter를 추가한다)를 override해서 HttpMessageConverter
를 설정할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {
@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.createXmlMapper(true).build()));
}
}
위의 예제에선 Jackson2ObjectMapperBuilder
을 이용해 MappingJackson2HttpMessageConverter
과 MappingJackson2XmlHttpMessageConverter
모두 설정한다.
다음 모듈이 classpath에 있으면 자동으로 등록한다.
다음 Jackson 모듈도 지원한다.
javax.money
타입을 지원한다 (비공식 모듈)다음 예제처럼 뷰를 만들어내는 로직이 필요없는 경우에 요청을 바로 처리할 수 있는 ParameterizableViewController
를 정의할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
다음 예제는 JSP와 Jackson을 JSON 렌더링을 위한 기본 View
로 설정해 content negotation을 설정한다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.enableContentNegotiation(new MappingJackson2JsonView());
registry.jsp();
}
}
다음 예제는 /resources
로 시작하는 요청에 대해 /public
혹은 classpath의 /static
에 대한 상대 경로에 존재하는 정적 리소스를 응답하도록 설정한다. 리소스는 브라우저 캐시가 1년 뒤에 만료되도록 설정한다. Last-Modified
헤더를 평가해 304
상태 코드가 반환된다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public", "classpath:/static/")
.setCachePeriod(31556926);
}
}
Spring MVC는 DispatcherServlet
을 /
경로에 연결하고, 정적 리소스는 기본 Servlet의 컨테이너가 처리할 수 있도록 해준다. 이를 위해 DefaultServletHttpRequestHandler
를 /**
URL에 가장 낮은 우선순위로 연결하도록 한다. 기본적으로는 다른 모든 URL HandlerMapping
이 기본 Servlet으로 가는 요청보다 먼저 처리되도록 되어있지만, 임의로 설정한 HandlerMapping
인스턴스를 사용하기 위해서는 order
값을 DefaultServletHttpRequestHandler
의 값인 Integer.MAX_VALUE
보다 낮게 설정해아 한다.
다음과 같이 설정하면 DefaultServletHttpRequestHandler
를 이용할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
기본 Servlet을 위한 RequestDispatcher
`를 경로가 아닌 이름으로 찾으므로, Tomcat, Jetty 등과 같은 기본 이름이 아닌 다른 이름을 가진 임의의 기본 Servlet을 사용하기 위해서는 다음과 같이 명시적으로 기본 Servlet의 이름을 지정해주어야 한다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable("myCustomDefaultServlet");
}
}
다음과 같이 임의로 URL 경로 매칭에 대한 설정을 변경할 수 있다.
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseSuffixPatternMatch(true)
.setUseTrailingSlashMatch(false)
.setUseRegisteredSuffixPatternMatch(true)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper())
.addPathPrefix("/api",
HandlerTypePredicate.forAnnotation(RestController.class));
}
@Bean
public UrlPathHelper urlPathHelper() {
//...
}
@Bean
public PathMatcher antPathMatcher() {
//...
}
}
@EnableWebMvc
는 다음과 같은 역할을 하는 DelegatingWebMvcConfiguration
를 불러온다.
WebMvcConfigurer
를 찾아 configuration을 변경할 수 있도록 위임한다.고급 설정이 필요하면 @EnableWebMvc
를 제거하고 DelegatingWebMvcConfiguration
를 직접 상속하면 된다.
@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {
// ...
}