[Spring] 토비의 스프링 Vol.2 4장 스프링 @MVC (3)

Shiba·2023년 11월 23일
0

🍀 스프링 정리

목록 보기
18/21
post-thumbnail

📗 스프링 @MVC (3)

📖 스프링 3.1의 @MVC

📝 새로운 RequestMapping 전략

스프링 3.1에서 사용가능한 애노테이션을 사용하는 MVC 기술중 가장 큰 변화는 @RequestMapping을 담당하는 핸들러 매핑 전략, 핸들러 어댑터 전략, 예외 처리 전략이 새로운 방식으로 모두 대체된 것

DispatcherServlet 전략스프링 3.0스프링 3.1
HandlerMappingDefaultAnnotation
HandlerMapping
RequestMapping
HandlerMapping
HandlerAddapterAnnotationMethod
HandlerAdapter
RequestMapping
HandlerAdapter
HandlerExceptionResolverAnnotationMethodHandler
ExceptionResolver
ExceptionHandler
ExceptionResolver

스프링 3.1의 새로운 전략 클래스의 이름은 각 전략이 지원하는 애노테이션 이름으로 시작한다.
그런데, 컨트롤러 코드에서 볼 때는 애노테이션의 종류가 달라지지도 않았고 방법이 변한 것도 없다. 스프링 3.0에서 작성된 @MVC 코드는 스프링 3.1에서 그대로 사용할 수 있다.

스프링 3.1 @MVC 변화의 가장 큰 특징은 DispatherServlet 전략이 아주 유연한 확장성을 가질 수 있도록 아키텍처가 개선됐다는 점이다.

◼ @RequestMapping 메소드와 핸들러 매핑 전략의 불일치

@RequestMapping을 담당하는 DefaultAnnotationHandlerMapping 같은 전략 클래스가 DispatcherServlet 전략의 설계의도와 맞지 않는 부분이 있기 때문

DispatcherServlet의 핸들러 매핑 전략은 요청을 처리할 빈의 오브젝트(핸들러)를 찾아주면 그 핸들러가 요청을 처리하는 방식
@RequestMapping은 오브젝트 내의 특정 메소드에 매핑하기 위해 설계됨.

빈의 오브젝트만 찾아주면 되던 핸들러 매핑 전략이 메소드 레벨에서 컨트롤러를 작성하기 때문에 메소드에도 매핑을 해주어야할 필요가 생김.
- 자바의 메소드는 오브젝트로 취급되지 않음 -> 빈이 될 수 없음 -> 매핑 불가

그래서 스프링 3.0의 DefaultAnnotationHandlerMapping 전략에선 매핑 결과가 요청을 담당할 메소드가 들어있는 컨트롤러의 오브젝트가 되어야 했다.

핸들러 매핑 전략에선 선정된 핸들러만 가지고는 어떤 메소드가 사용될지 알 수 없기 때문에 핸들러 인터셉터의 사용도 제한됨.

@Audit 애노테이션이 붙어있는 @RequestMapping 메소드가 실행될 때마다 관련 정보를 파일에 저장하도록 하는 감사 기능을 가진 핸들러 인터셉터를 만들어야 한다고 하자.

@Controller
public class JobController {
	@RequestMapping("/specialjob")
    @Audit
    public String specialjob(...) {
    	...
    }
    ...
}

핸들러 인터셉터의 prehandle() 메소드에서 @RequestMapping 메소드에 달린 애노테이션 정보를 가져와 활용하는 인터셉터를 만드는 것은 불가능하다.
-핸들러 매핑 결과가 최종 실행될 메소드가 아니라 메소드가 속한 오브젝트이기 때문

스프링 3.1에서는 @RequestMapping을 처리하는 전략 클래스를 새롭게 설계해서 문제를 해결했다.

public class AuditInterceptor extends HandlerInterceptorAdapter {
	@Override
    public boolean preHandle(HttpServletRequest request,
    		HttpServletResponse response, Object handler) throws Exception {
    	HandlerMethod hm = (HandlerMethod)handler; // HandlerMethod 타입으로 캐스팅
        if(hm.getMethodAnnotation(Audit.class) != null) {
        	saveAuditinfo(request, response, handler);
        }
        
        return super.prehandle(request, response, handler);
    }
    
    private void saveAuditInfo(HttpServletRequest request,
    		HttpServletResponse response, Object handler) {
    	//요청정보를 감사 용도의 외부 파일에 저장하는 용도        
    }
}

handler를 HandlerMethod라는 새로운 타입으로 정의

◼ HandlerMethod

@RequestMapping이 붙은 메소드의 정보를 추상화한 오브젝트 타입

- 컨트롤러 오브젝트 대신 추상화된 메소드 정보를 담은 오브젝트를 핸들러 매핑의 결과로 돌려주고, 핸들러 어댑터는 HandlerMethod 오브젝트의 정보를 이용해 메소드를 실행
- 핸들러 어댑터가 핸들러 오브젝트의 정보를 이용해 간접적으로 @RequestMapping을 실행하도록 접근 방법을 바꾼 것

HandlerMethod는 다섯 가지의 핵심 정보를 지니고 있음

  • 빈 오브젝트
  • 메소드 메타정보
  • 메소드 파라미터 메타정보
  • 메소드 애노테이션 메타정보
  • 메소드 리턴 값 메타정보

◼ @RequestMapping 전략 선택

지금까지 설명한 HandlerMethod를 이용한 핸들러 매핑 전략은 스프링 3.1의 DispatherSevlet의 기본 전략이 아니다.
- 스프링은 구버전과의 호환성을 중요시하여 스프링 3.0의 전략과 차이가 없다.
- 3.1버전에 맞게 코드를 수정하더라도 코드가 크게 변경되지 않음

HandlerMethod를 지원하는 새로운 전략 사용법

  • RequestMappingHandlerMapping 같은 새로운 전략 빈을 <bean>으로 등록하거나 새로운 전략 빈을 등록해주는 <mvc:annotation-driven>을 이용하면 된다.
    - <mvc:annotation-driven>에는 스프링 3.1에 새롭게 도입된 전략 빈을 등록하는 기능이 포함되어 있음.

  • @Configuration 클래스를 사용한다면 @EnableWebMvcWebMvcConfigurationSupport를 이용해도 HandlerMethod를 지원하는 새로운 전략 빈이 등록됨.

📝 @RequestMapping 핸들러 매핑: RequestMappingHandlerMapping

RequestMappinHandlerMapping 이란?
- @RequestMapping 매핑정보를 다루는 전략 클래스
- 클라이언트의 요청을 @RequestMapping이 붙은 메소드로 매핑해주는 것
- 매핑 결과는 @RequestMapping 메소드의 정보를 추상화한 HandlerMethod 타입 오브젝트

◼ 요청 조건

DispatcherServlet서블릿 컨테이너에서 동작하는 서블릿이므로 핸들러 매핑이 다루는 요청은 서블릿이 전달받는 HTTP 서블릿 요청이다. 여기서 HTTP 요청이란 브라우저와 같은 클라이언트가 HTTP 프로토콜을 통해 보내오는 정보이다.
요청정보가 핸들러 메소드 매핑에 어떻게 사용되는지 알고 싶다면 핸들러 메소드의 매핑 기준을 먼저 알아야 한다. 핸들러 메소드의 매핑 기준은 대부분 @RequestMapping 애노테이션의 엘리먼트와 값으로 표현된다. 메소드뿐만 아니라 클래스나 인터페이스 레벨에 존재하는 @RequestMapping 정보도 매핑 기준으로 사용된다.

이렇게 매핑의 기준이 되는 정보를 스프링에서는 요청 조건이라고 한다.

@RequestMapping에 넣을 수 있는 엘리먼트를 기준으로 요청 조건을 정리해보면 다음 표와 같다

엘리먼트요청 조건지원 버전
value, 디폴트URL 패턴3.0, 3.1
methodHTTP 요청 메소드3.0, 3.1
params파라미터3.0, 3.1
headersHTTP 헤더3.0, 3.1
consumesContent-type 헤더3.1
producesAccept 헤더3.1

RequestMappingHandlerMapping은 @RequestMapping의 6가지 조건에 확장 포인트를 통해 등록되는 커스텀 조건을 더해서 총 7가지 요청 조건을 사용.
@RequestMapping이나 커스텀 조건은 타입, 메소드에 각각 지정가능하므로 총 14가지 요청조건을 고려

@RequestMapping을 이용해 요청 조건을 만들 때는 각 조건이 어떻게 조합되는지 잘 알고 있어야 한다. 특히 타입 레벨과 메소드 레벨 양쪽에 조건이 있거나 한 번에 하나 이상의 값이 사용됐을 때 각 조건이 어떻게 조합되어서 핸들러 메소드의 최종 요청 조건이 만들어지는지 이해해야 한다.

◼ 요청 조건의 결합 방식

커스텀 조건을 제외한 나머지 @RequestMapping의 6가지 요청 조건의 결합 방식만 살펴보자.

URL 패턴 : PatternRequestCondition

가장 기본이 되는 URL 경로를 패턴 형태로 나타낸 것
- {}를 이용해 하나 이상의 URL 패턴을 정의한 경우 OR로 연결.
- 최소한 하나 이상의 패턴이 일치하면 조건 만족
- 반면에 클래스와 메소드 모두에 지정되어 있으면 타입 레벨과 메소드 레벨의 경로를 조합
EX) 클래스 ({"/a", "/b"}), 메소드 ({"/c", "/d"}) => ( "/ac", "/ad", "/bc", "/bd" )
- 한 쪽에만 패턴이 있다면 그 패턴만 적용

RequestMappingHandlerMapping 전략 빈에는 URL 패턴 요청 조건에서 사용하는 두 가지 프로퍼티가 존재

  • useSuffixPatternMatch : URL 패턴 조건에 ".*"를 포함시킬지를 결정
    - 디폴트 값은 true
    - /hello로 시작하는 모든 URL 패턴이 조건을 만족한다

  • useTrailingSlashMatch :URL 패턴 조건에 "/"가 붙는 경우를 포함시킬지 결정
    - ❗ "/hello" 와 "/hello/"는 엄연히 다른 URL이다.
    - 디폴트 값은 true이다. 둘을 구분하고 싶다면 false로 바꾸면 된다.

HTTP 요청 방법 : RequestMethodsRequestCondition

GET, POST, PUT, DELETE 같은 HTTP 요청 방법에 대한 요청 조건methods 엘리먼트로 지정한다.
- 조합 방법은 타입과 메소드에 지정된 모든 요청 방법을 OR로 결합하는 것이다.

파라미터 : ParamsRequestCondition

타입과 메소드에 있는 모든 파라미터 조건 값이 AND로 연결
- 모두 만족해야 조건을 만족할 수 있음

헤더 : HeadersRequestCondition

스프링 3.1에서는 Content-Type과 Accept를 헤더 요청 조건에 넣더라도 무시된다. 이 두 가지는 좀 더 의미 있는 요청 조건으로 분리됐다.
- Content-Type과 Accept 헤더는 각각 Content-Type 요청 조건과 Accept 요청 조건으로 취급됨. - 구버전 호환성을 위함

Content-Type 헤더 : ConsumesRequestCondition

HTTP 요청의 헤더에 나오는 Content-Type은 요청의 내용이 어떤 형식인지를 알려줌

  • Content-Type 요청 조건을 사용하는 경우
    - 파일 업로드를 위해 <form>의 enctype을 지정한 경우와 아닌 경우를 구분할 때
    - JSON 요청과 일반 요청을 구분해야 하는 경우
@RequestMapping(headers="Content-Type=application/json") // Content-Type 헤더
@RequestMapping(consumes="application/json") // Content-Type 요청 조건

- 헤더조건은 타입과 메소드에 지정한 모든 조건이 AND로 연결됨.
반면에 Content-Type 조건은 OR로 연결된다.

- Content-Type 조건타입과 메소드 둘다 존재하는 경우 메소드의 조건만 사용
메소드 조건이 없을 때만 타입의 조건을 사용

Accept 헤더 : ProducesRequestCondition

Accept 헤더도 headers 대신 produces 엘리먼트를 이용해 조건을 지정할 수 있다.
- Accept는 클라이언트가 받아들일 수 있는 미디어 타입을 지정하는데에 사용
- consumes와 동일한 결합 방식을 가짐

📝 @RequestMapping 핸들러 어댑터

HandlerMethod 타입의 핸들러를 담당하는 핸들러 어댑터는 RequestMappingHandlerAdapter이다.

스프링 3.1에서 몇가지 파라미터와 리턴 타입, 애노테이션이 추가되었다.

@Vaildated/@Vaild

모든 애트리뷰트 파라미터에 적용되는 @Vaild모델 클래스의 필드에 붙은 @NotEmpty나 @Length 같은 JSR-303 빈 검증기 애노테이션을 이용모델의 값을 검증
JSR-303은 다른 방식으로 검증이 필요한 경우, 제약 조건 애노테이션에 조건이 적용될 검증 그룹을 지정하게 해줌.
- 모델 오브젝트를 검증할 때 특정 그룹의 제약 조건을 적용하고 싶으면 @Validate를 이용

@Valid와 @RequestBody

스프링 3.1의 @Vaild는 메시지 컨버터를 이용하는 @RequestBody 파라미터에도 사용 가능
- 모델 오브젝트와 같은 방법으로 간단히 검증 가능
- 검증에 오류가 있다면 MethodArgumentNotValidException 예외가 발생

UriComponentsBuilder

URI/URL 정보를 추상화한 UriComponents를 손쉽게 생성할 수 있게 도와주는 빌더 클래스
- 문자열 하나에 여러 요소가 조합된 URI를 안전하고 편리하게 다룰 수 있다.
- URI를 조합하는 것도 가능하다.

RedirectAttributes와 리다이렉트 뷰

리다이렉트는 현재 요청에 대한 응답을 뷰로 생성해서 보내는 대신 브라우저에게 새로운 URL로 요청을 다시 보내라고 지시하는 응답 방식
- 핸들러 메소드에서 리다이렉트를 사용하려면 RedirectView 뷰나 redirect: 접두어가 붙은 뷰 이름을 리턴하면 된다.

리다이렉트 뷰는 보통 모델 정보를 생성할 필요가 없지만, 리다이렉트 URL에 파라미터 정보를 추가하는 경우에는 Model을 이용하는것이 편리하다.
하지만, 모델을 이용해 URL에 들어갈 애트리뷰트를 설정하는 방식에는 불필요하게 @ModelAttribute 메소드가 만든 레퍼런스 정보까지 들어가버린다는 단점이 있다.
따라서 모델정보를 받아온 뒤 제거하는 작업을 진행해야한다.

스프링 3.1에서는 RedirectAttribute를 통해 위와 같은 번거로움을 해소했다.
Model 대신 RedirectAttribute에 담긴 정보를 활용하여 URL을 생성한다.
RedirectAttribute는 Model의 하위 타입이므로 Model과 동일한 방법으로 사용하면 된다.

RedirectAttribute와 플래시 애트리뷰트

RedirectAttribute에는 플래시 애트리뷰트를 추가하는 기능도 존재
- 플래시 애트리뷰트는 POST 요청에서 만들어져 저장되고 다음 GET 요청에서 사용
- 스프링 @MVC는 RedirectAttribute 파라미터에서 직접 플래시 애트리뷰트를 추가해주기만 하면 된다.

public String saveForm(@ModelAttribute("user") User user, RedirectAttrbutes 
		ra) { ...
	ra.addFlashAttribute("message", "저장됐습니다");
    ra.addAttribute("status", status);
    return "redirect:/result";
}

컨트롤러에서 플래시 애트리뷰트를 가져와 뷰로 넘기는 번거로운 작업이 필요없이 뷰에서 직접 모델에 담긴 플래시 애트리뷰트를 사용하면 된다.

<div class="flash_message">
	${message}
</div>

◼ 확장 포인트

스프링 3.1에서는 메소드 호출과 모델 바인딩, 파라미터 변환 등을 담당하는 어댑터가 바뀌었기 때문에 확장 포인트도 달라진다.

파라미터 : HandlerMethodArgumentResolver

핸들러 메소드에서 사용할 수 있는 새로운 종류의 파라미터 타입을 추가하려면 다음의 HandlerMethodArgumentResolver 인터페이스를 구현한 클래스를 만들어 RequestMappingHandlerAdapter의 customArgumentResolvers 프로퍼티에 추가해주면 된다.

public interface HandlerMethodArgumentResolver {
	boolean supportsParameter(MethodParameter parameter);
    Object resolveArgument (MethodParameter parameter,
    					ModelAndViewContainer mavContainer,
                        NativeWebRequest webRequest,
                        WebDataBinderFactory binderFactory) throws Exception;
}

리턴 값 : HandlerMethodReturnValueHandler

리턴값을 처리하는 기능도 확장할 수 있다. HandlerMethodReturnValue Handler 인터페이스를 구현하고 이를 RequestMappingHandlerAdapter의 customReturnValueHandlers 프로퍼티에 넣어주면 된다.

public interface HandlerMethodReturnValueHandler {
	boolean supportsReturnType(MethodParameter returnType);
    void handleReturnValue(Object returnValue,
    					MethodParameter returnType,
                        ModelAndViewContainer mavContainer,
                        NativeWebRequest webRequest) throws Exception;
}

이 두 가지 확장 포인트는 RequestMappingHandler가 기본적으로 제공하는 파라미터와 리턴 값 처리 클래스에서도 사용된다.

📝 @EnableWebMvc와 WebMvcConfigurationSupport를 이용한 @MVC 설정

스프링 3.1의 최신 @MVC 전략을 사용하려면 XML 설정에 <mvc:Annotation-driven>을 넣거나 인프린 빈 설정용 애노테이션을 이용해 @MVC 빈이 등록되게 해야 한다. @MVC 전략과 관련된 설정을 넣는 경우 mvc 네임스페이스의 전용 태그는 불편하다. 본격적으로 @MVC의 기능을 활용하려면 이제부터 설명할 자바 코드를 이용한 @MVC 빈 등록 및 설정 방식을 사용하는 것이 좋다.

◼ @EnableWebMvc와 WebMvcConfigurer

@Configuration 클래스에 @EnableWebMvc를 붙여주면 <mvc:annotation-config/>를 넣었을 때와 동일하게 스프링 3.1의 최신 전략 빈이 등록된다.

- 스프링은 @Enable 전용 애노테이션으로 등록되는 인프라 빈에 대한 추가 설정을 위해 설정용 빈을 활용하는 방법을 제공.
- 인프라 빈의 설정을 담당하는 기능을 가진 클래스를 만들어 빈으로 등록하면 @Enable 전용 애노테이션을 처리하는 단계에서 설정용 빈을 활용해 인프라 빈의 설정을 마무리함.

이렇게 @Enable 전용 애노테이션의 설정을 위해 사용되는 빈을 설정자 또는 컨피규어러(Configurer)라고 한다.

@Enable이 구현해야하는 인터페이스는 WebMvcConfigurer이다.

public interface WebMvcConfigurer {
	void addFormatters(FormatterRegistry registry);
    
    void configureMessageConverters(List<HttpMessageConverter<?>> converters);
    
    Validator getValidator();
    
    void addArgumentResolvers(List<HandlerMethodArgumentResolver>
    	returnValueResolvers);
        
    void addReturnValueHandler(List<HandlerMethodReturnValueHandler>
    	returnValueHandlers);
        
    void configureHandlerExceptionResolvers(List<HandlerExceptionResolver>
    	exceptionResolvers);
        
    void addInterceptors(InterceptorRegistry registry);
    
    void addViewControllers(ViewControllerRegistry registry);
    
    void addResourceHandlers(ResourceHandlerRegistry registry);
    
    void configureDefaultServletHandling(DefaultServletHandlerConfigurer 
    	configurer);
}

인터페이스이기 때문에 모두 구현해야한다. 만약 사용하지 않는 메소드가 많아 불편하다면 필요한 메소드만 오버라이딩해서 사용할 수 있게 만들어진 WebMvcConfigurerAdapter 클래스를 상속할 수도 있다.

이제 각 메소드를 이용한 설정 기능은 어떤 것이고 어떻게 이용하는지 살펴보자

addFormatters()

폼 값과 모델 오브젝트의 프로퍼티 사이의 변환 작업을 지원해주는 MVC용 컨버터
스프링 3.1에서는 addFormatters() 메소드가 제공하는 FormatterRegistry를 이용해 간단히 포매터를 등록할 수 있다.

포매터가 다른 빈에 의존하지 않는다면 포매터 오브젝트를 직접 생성해서 추가한다.

public void addFormatters(FomatterRegistry registry) {
	registry.addFormatter(new MyFormatter());
}

만약 포매터가 다른 빈을 이용해야 한다면 포매터를 먼저 빈으로 등록하는 것이 깔끔하다. 폼에서 넘어온 ID 값을 엔티티 오브젝트로 변환하는 포매터라면 서비스 빈이나 DAO 빈을 주입 받아 사용해야 한다. 이 경우, @Bean 메소드를 사용해 빈으로 정의한 뒤 addFormatters에서 포매터 빈을 가져와 레지스트리에 저장하는 방법을 사용

@Autowired Userservice userService;

@Bean
public UserFormatter userFormatter() {
	return new UserFormatter(userService);
}

public void addFormatters(FormatterRegistry registry) {
	registry.addFormatter(userFormatter());
}

포매터 빈이 XML이나 다른 @Configuration 클래스에 정의되어 있다면 다음과 같이 @Autowired를 이용해 포매터 빈을 주입받아 넣어주면 된다.

@Autowired UsreFormatter userFormatter;

public void addFormatters(FormatterRegistry registry) {
	registry.addFormatter(userFormatter);
}

addFormatterForFieldType() 메소드를 이용하면 포매터가 특정 타입의 필드에만 적용되게 만들 수 있다. 또한 addFormatterForFieldAnnotation()을 이용해 특정 애노테이션이 붙은 필드에만 적용되는 포매터로 등록하는 것도 가능하다.

FormatterRegistry를 이용해 컨버터를 등록할 수도 있다. 모델 바인딩에 사용할 용도라면 포매터가 컨버터보다 낫겠지만, 그래도 컨버터를 사용하고 싶다면 FormatterRegistry의 addConverter() 메소드를 이용하면 된다.

configureMessageConverters()

스프링이 기본적으로 제공해주는 메시지 컨버터 구성을 사용하지 않고 직접 메시지 컨버터를 구성하고 싶다면 configureMessageConverters()의 List<HttpMessasgeConverter<?>> 타입 파라미터를 이용해 사용할 메시지 컨버터를 추가하면 된다.

메시지 컨버터도 다른 빈에 의존하는 빈 형태로 만들어야 하는 게 아니라면 직접 오브젝트를 생성해서 등록하면 된다.

public void configureMessageConverters(
	List<HttpMessageConverter<?>> converters) {
    
    converters.add(new MappingJacksonHttpMessageConverter());
    converters.add(new MyMessageConverter());
}

메시지 컨버터를 추가하는 방식인데 메소드 이름이 figure로 시작하는 이유는 하나라도 메시지 컨버터를 추가하면 디폴트 메시지 컨버터가 모두 무시되기 때문이다.
디폴트 메시지 컨버터를 유지한 채로 메시지 컨버터를 추가하고 싶다면 WebMvcConfigurationSupport 확장을 이용해야 한다.

getValidator

디폴트로 등록되는 JSP-303 검증기용 LocalValidatorFactoryBean을 대신할 범용 검증기를 등록할 경우에 사용

addArgumentResolvers()

RequestMappingHandlerAdapter의 파라미터 처리용 확장 포인트인 HandlerMethodArgumentResolver를 추가할 수 있는 메소드.
- 디폴트 파라미터 타입이나 애노테이션 외에 새로운 파라미터 종류를 지원할 경우에 사용

addReturnValueHandlers()

RequestMappingHandlerAdapter의 리턴 값 처리용 확장 포인트
HandlerMethodReturnValueHandler를 추가할 때 사용.
- 새로운 리턴 값 처리 방식을 추가하는 경우 사용

configureHandlerExceptionResolvers()

디폴트로 등록되는 핸들러 예외 전략을 새롭게 구성하려고 할 때 사용
- 메시지 컨버터와 마찬가지로 이 메소드에서 핸들러 예외 리졸버를 추가하면 디폴트 예외 리졸버는 무시된다.
- 디폴트 예외 전략은 그대로 두고 예외 리졸버를 새로 추가하려면 WebMvcConfigurationSupport를 이용해야 한다.

addInterceptors()

인터셉터를 등록해주는 <mvc:interceptors>의 자바 코드 버전.
파라미터로 제공되는 InterceptorRegistry를 이용인터셉터 오브젝트 또는 빈을 추가한다.
- InterceptorRegistry는 addInterceptor()와 addWebRequestInterceptor() 메소드를 통해 각각 HandlerInterceptor와 WebRequestInterceptor 타입의 인터셉터를 등록하게 해준다.

addViewControllers()

URL 패턴을 그대로 뷰 이름으로 돌려주는 간단한 컨트롤러를 등록하는 메소드
- /hello URL 요청을 받아서 아무 작업 없이 그대로 /hello 뷰로 연결하면 되는 경우에 사용
- 모델정보 없이 간단히 JSP 뷰를 테스트하거나 고정된 내용을 가진 페이지를 출력하는 경우 등에 사용하기에 적합

addResourceHandlers()

스프링 3.0.4에서 추가된 <mvc:resources>의 기능을 담당하는 메소드

다음과 같이 XML에서 리소스 매핑을 선언했다면

<mvc:resources mapping="/ui/**" location="classpath:/META-INF/webresources/" />

addResourceHandlers() 메소드에선 다음과 같이 등록해주면 된다.

public void addResourceHandlers(ResourceHandlerRegistry registry) {
	registry.addResourceHandler("/ui/**");
    		.addResourceLocations("classpath:/META-INF/webresources/");
}

configureDefaultServletHandling()

<mvc:default-servlet-handler/>를 등록한 것과 같은 설정 결과를 낸다.

public void configureDefaultServletHandling(DefaultServletHandlerConfigurer
		configurer) {
        configurer.enable();
}

◼ @MVC 설정자 빈 등록 방법

@EnableWebMvc를 위한 설정정보WebMvcConfigurer 타입의 설정자 빈을 만들어 등록하면 된다.

가장 손쉽게 생각할 수 있는 방법은 @EnableWebMvc가 붙은 @Configuration 클래스에 @Bean 메소드를 넣어서 설정자 빈을 등록하는 것이다.

@Configuration
@EnableMvc
public class AppConfig {
	@Bean
    public WebConfigurer webMvcConfigurer() {
    	return new MyWebMvcConfigurer();
    }
}
public class MyWebMvcConfigurer implements WebMvcConfigurer {
	...
}

@Configuration이 붙은 클래스도 빈으로 등록되므로 WebConfig가 WebMvcConfigurer를 구현하게 만들면 WebMvcConfigurer 타입 빈이 등록되는 것이다.
WebConfig가 직접 WebMvcConfigurer를 구현하게 만들면 필요없는 메소드까지 만들어야 해서 불편하니 WebMvcConfigurerAdapter를 상속하자.

@Configuration
@EnableMvc
public class WebConfig extends WebMvcConfigurerAdapter {
	...
}
profile
모르는 것 정리하기

0개의 댓글