@ComponentScan 에노테이션은 정말 단비같은 에노테이션이라는 것을 사용할 때마다 느끼고 또 느낀다.
일단, 이번기회에 Controller 공통 Advice 를 가능하게 해주는 @ControllerAdvice 에노테이션을 배우는 와중, ComponentScan의 대상으로 등록되지 않는 듯해서, 어떻게하면 ComponentScan으로 등록할수 있을까..하고 기억을 되살리는 겸 서칭과 책 정독을 시작한 것을 기억을 되살려보자.
@ControllerAdvice 에노테이션은 컨트롤러의 공통기능을 정의하는 에노테이션이며 클래스에 붙인다. , @ExceptionHandler 에노테이션을 가져 익셉션을 공통처리할 수 있게끔한다. @ExceptionHandler 에노테이션의 값은 처리할 Exception의 클래스를 지정한다.
다시 @ComponentScan 에노테이션으로 넘어와서.
-
포함은 includeFilters , 제외는 exculdeFilters 로 시작하며 @Filter 에노테이션의 배열[] 로 값을 갖는다.
-
@Filter 에노테이션 속성 값으로 type 속성을 주고, FilterType의 상수값을 적용하면 해당 필터타입으로 필터링을 한다는 것을 뜻한다.
-
ANNOTATION, ASSIGNABLE_TYPE, ASPECTJ, REGEX 정도로 타입을 구분한다.
-
어노테이션, 어사이너블 타입은 class 속성을 가지며 class배열[]을 값으로 갖고 클래스들을 지정하여 필터링한다.
-
에스펙트J, 정규표현식은 pattern 속성을 가지며 String배열[]을 값으로 가지고, 정규표현식이나 ASPECTJ 문법으로 범위를 정하고 필터링한다.
ASPECTJ문법 사용의 전제조건은 ASPECTJWEAVER 의존이 존재해야한다는 것을 기억하며, AOP 설정에도 @Pointcut 이나 @Around 의 값으로 execution 명시자에 사용된다는 것을 기억한다. @ASPECT 어노테이션 적용클래스는 @ComponentScan의 대상이 된다..고? 기억한다.
ASSIGNABLE_TYPE은 Validator 구현객체의 support 메서드에 사용된다는 것을 기억하고 있다. Validator 사용시 support()메서드는 반드시 구현해야한다. 즉 해당타입과 그 하위타입을 일컫는 말이다.
Global Range Validator 사용시 Validator 등록 없이 검증을 하려면 Bean-Validation-api 와 Bean-Validation-Provider 의 의존이 필요하다...고 기억한다. Provider 의존으로는 Hibernate-Validator 인가..이게 Bean-Validation Provider로 사용했을 것이다.
검증 커멘드 객체의 필드 값에 @Email @NotEmpty @NotBlank @NotNull @Size 등의 에노테이션을 추가해서 검증 했을거고...
Controller Range Validator에는 Validator 구현객체를 @InitBinder 에노테이션이 적용된 메서드에 적용시켰을거다.
매개변수가 WebDataBinder....의 메서드로 setValidator , addValidator 를 사용해서 Validator를 추가 하고 ,
@Valid 에노테이션을 요청매핑 에노테이션이 적용된 파라미터의 커맨드 객체 앞에 두고 검증을 하여 Errors 객체에 에러 코드를 <form:errors> 로 출력했을 거다...제대로 기억하는게 맞나 싶은데 이게...맞나. 애석하다, 잊어가는게..
Interceptor 구현객체를 @EableWebMvc 적용 클래스이자 WebMvcConfigurer 구현객체의 addInterceptors 메서드 에서 addInteceptor 메서드에 Interceptor 구현객체를 설정 한후 addPathPatterns 메서드에 값으로 Ant 패턴을 준다는 것을 기억한다. 메서드 명이 맞나 모르겠다.
Ant 패턴은 * ** ? 로 경로를 표현한다.
기억되살리기는 여기까지하고, 본론 코드를 적어 놓는다.
여기가 핵심. @ComponentScan 에노테이션에 @Filter 배열로 컴포넌트 스캔 영역을 include (includeFilters) 해놓았다.
필터링 타입은 ANNOTATION 이며, classes 속성에는 org.springframework.web.bind.anntation.ControllerAdvice.class 가 등록됬다.
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.soomin.controller", "com.soomin.interceptor" }, includeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {
org.springframework.web.bind.annotation.ControllerAdvice.class }) })
public class WebMvcConifg implements WebMvcConfigurer {
위에 적어놓은 기억되살리기가 맞는 지 확인과정과 기억 남기기용 @EnableWebMvc 적용 클래스이자 WebMvcConfigurer 구현객체의 메서드와 설정 기제.
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.soomin.controller", "com.soomin.interceptor" }, includeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {
org.springframework.web.bind.annotation.ControllerAdvice.class }) })
public class WebMvcConifg implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// DateTimeFormatter 설정이 첫번째
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 a HH시 mm분 ss초");
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(formatter)).build();
// .simpleDateFormat("yyyy년 MM월 dd일 a HH시 mm분 ss초")
/*
* .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).build();
*/
converters.add(0, new MappingJackson2HttpMessageConverter(objectMapper));
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 인터셉터의 addPathPatterns 메서드의 경로는 Ant패턴으로 정의한다.
registry.addInterceptor(new AuthCheckInterceptor())
.addPathPatterns("/edit/**")/* .excludePathPatterns("edit/help/**") */;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/main").setViewName("main");
}
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages.label");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
'springframework' 카테고리의 다른 글
@Log4j 에노테이션 적용이 안될때... (0) | 2020.08.02 |
---|---|
paging 기법. (0) | 2020.07.29 |
Multi-Thread 환경에서의 Spring Bean , ApplicationContext (0) | 2020.07.16 |
Servlet과 Thread-safe (0) | 2020.07.16 |
.do 확장자의 사용..? (0) | 2020.07.16 |