Spring 이라기보다 Java에서 원래 제공하던 놈(javax) 중에
@Valid 라는 것이 있다.
Spring에서는 해당 @Valid를 Validator라는 인터페이스로 지원을 하고 있다.
이는, 해당 Object 내의 field들을 검사해서 NULL인지 혹은 타입체크(email, phone 등) 여부를 체크할 수 있는 좋은 어노테이션인데,
현재 기준으로 그냥 쓰면 안되는 것 중에 하나가
Collection을 Validate 하는 부분이 안된다.
Google에 검색을 해보아도 Collection은 @Valid가 적용이 안된다는 걸 알 수 있는데,
그럼 해당 dto는 List로 받아오기 때문에 @Valid로 설정했던 값들
@NotNull, @Nullable 들이 적용이 안되게 된다.
List를 하나의 Object라 생각하기 때문이다.
반면에 아래와 같은 일반 단일 Object는 Validation이 가능하다
요점은, 해당 List로 받아오는 List 에 대해서 검사를 어떻게 할 것인가에 대한 점인데
이미 누군가가 올려둔 방법이 있다
다만 코드를 보면 아래와 같다.
출처(퍼옴)
https://gompangs.tistory.com/entry/Spring-Valid-Collection-Validation-%EA%B4%80%EB%A0%A8
스프링/스프링부트 애노테이션(Annotation) 정리
스프링 부트와 스프링에서 사용하는 애노테이션에 대한 내용을 간략하게 정리하고 자세하게 알아볼 때는 키워드를 가지고 공부할 수 있도록 유도하는 포스트.
해당 애노테이션을 사용할 때 필요한 라이브러리나 설정 방법은 따로 기술하지 않고 애노테이션 정보만 빠르게 볼 수 있도록 정리하였다.
@ComponentScan
ApplicationContext.xml에 이런식으로 xml에 bean을 직접등록하는 방법도 있고 위와 같이 애노테이션을 붙여서 하는 방법도 있음
base-package를 넣으면 해당 패키지 아래에 있는 컴포넌트들을 찾고 그 과정을 spring-context-버전(4.3.11.RELEASE).jar에서 처리한다.
@Component로 다 쓰지 왜 굳이 @Repository, @Service, @Controller등을 사용하냐면 예를들어 @Repository는 DAO의 메소드에서 발생할 수 있는 unchecked exception들을 스프링의 DataAccessException으로 처리할 수 있기 때문이다. 또한 가독성에서도 해당 애노테이션을 갖는 클래스가 무엇을 하는지 단 번에 알 수 있다.
그리고 그렇게 작성하면 자동으로 등록되는 빈의 이름은 클래스의 첫문자가 소문자로 바뀐 이름이 자동적용된다.
(HomeController -> homeController)
@EnableAutoConfiguration
classpath의 내용에 기반해서 자동 생성해준다. 만약 tomcat-embed-core.jar가 존재하면 톰캣 서버가 setting된다.
@Configuration
@Required
@Qualifier("id123")
(같은 타입이 존재하는 경우 ex) 동물, 원숭이, 닭, 개, 돼지)
@Resource
@PostConstruct, @PreConstruct
@PreDestroy
@PropertySource
클래스에 @PropertySource("classpath:/settings.properties")라고 적고 클래스 내부에 @Resource를 Environment타입의 멤버변수앞에 적으면 매핑된다.
@ConfigurationProperties
속성 클래스를 따로 만들어두고 그 위에 (prefix="mail")을 써서 프로퍼티의 접두사를 사용할 수 있음
mail.host = mailserver@mail.com
mail.port = 9000
mail.defaultRecipients[0] = admin@mail.com
mail.defaultRecipients[1] = customer@mail.com
@Lazy
@Component나 @Bean 애노티에션과 같이 쓰는데 클래스가 로드될 때 스프링에서 바로 bean등록을 마치는 것이 아니라 실제로 사용될 때 로딩이 이뤄지게 하는 방법이다.
@Value
@Value("${value.from.file}")
private String valueFromFile; 이라고 구성되어 있으면 value.from.file의 값을 가져와서 해당 변수에 주입해준다.
spEL을 이용해서 조금 더 고급스럽게 쓸 수 있다.
@Value(#{systemProperties['priority'] ?: 'some default'})
@SpringBootApplication
@RequestMapping
컨트롤러나 컨트롤러의 메서드에 적용한다.
@RequestMapping("/list"), @RequestMapping("/home, /about");
@RequestMapping("/admin", method=RequestMethod.GET)
@CookieValue
해당 쿠기가 존재하지 않으면 500 에러를 발생시킨다.
속성으로 required가 있는데 default는 true다. false를 적용하면 해당 쿠키 값이 없을 때 null로 받고 에러를 발생시키지 않는다.
public String view(@CookieValue(value="auth")String auth){...}; // 쿠키의 key가 auth에 해당하는 값을 가져옴
@CrossOrigin
@RequestMapping이 있는 곳에 사용하면 해당 요청은 타 도메인에서 온 ajax요청을 처리해준다.
@CrossOrigin(origins = "http://jeong-pro.tistory.com", maxAge = 3600)
-> 기본 도메인이 http://jeong-pro.tistory.com 인 곳에서 온 ajax요청만 받아주겠다.
@ModelAttribute
바인딩 기준은 처럼 어떤 태그의 name값이 해당 클래스의 멤버 변수명과 일치해야하고 set메서드명도 일치해야한다.
class Person{
String id;
public void setId(String id){ this.id = id;}
}
@GetMapping
@PostMapping, @PutMapping, @PatchMapping, @DeleteMapping은 유추 가능함.
@SessionAttributes
@SessionAttributes("name")이라고 하면 Model에 key값이 "name"으로 있는 값은 자동으로 세션에도 저장되게 한다.
@Valid
@InitBinder
@RequestAttribute
@RequestBody
@RequestHeader
@RequestHeader(value="Accept-Language")String acceptLanguage 로 사용 //ko-KR,ko;q=0.8,en-US;q=0.6
@RequestParam
@RequestPart
@RequestPart("file")MultipartFile file로 받아올 수 있음.
@ResponseBody
만약 객체를 return하는 경우 JACKSON 라이브러리에 의해 문자열로 변환되어 전송된다.
context에 설정된 resolver를 무시한다고 보면된다. (viewResolver)
@PathVariable
@ExceptionHandler(ExceptionClassName.class)
@ControllerAdvice
@RestControllerAdvice
@ResponseStatus
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "my page URL changed..") => 예외처리 함수 앞에 사용한다.
@EnableEurekaServer
@EnableDiscoveryClient
@Transactional
@Transaction(readOnly=true, rollbackFor=Exception.class) : readOnly는 읽기전용임을 알리고 rollbackFor는 해당 Exception이 생기면 롤백하라는 뜻
@Transaction(noRollbackFor=Exception.class)는 해당 Exception이 나타나도 롤백하지 말라는 뜻
@Transaction(timeout = 10)은 10초안에 해당 로직을 수행하지 못하면 롤백하라는 뜻.
@Cacheable
주의할 점은 입력이 같으면 항상 출력이 같은 메서드(=순수 함수)에 적용해야한다.
그런데 또 항상 같은 값만 뱉어주는 메서드에 적용하려면 조금 아쉬울 수 있다. 따라서 메서드 호출에 사용되는 자원이 많고 자주 변경되지 않을 때 사용하고 나중에 수정되면 캐시를 없애는 방법을 선택할 수 있다.
@Cacheable(value="cacheKey"), @Cacheable(key="cacheKey")
@CachePut
해당 애노테이션이 있으면 메서드호출을 항상한다. 그러므로 @Cacheable과 상충되어 같이 사용하면 안된다.
@CacheEvict
캐시된 데이터는 언제가는 지워져야한다. 그러지 않으면 결과값이 변경이 일어났는데도 기존의 데이터(캐시된 데이터)를 불러와서 오류가 발생할 수 있다.
물론 캐시 설정에서 캐시 만료시간을 줄 수도 있다.
@CacheEvict(value="cacheKey"), @CacheEvict(value="cacheKey", allEntries=true)
allEntries는 전체 캐시를 지울지 여부를 선택하는 것이다.
@CacheConfig
@Scheduled
@Scheduled(cron = "0 0 07 * * ?") "초 분 시 일 월 요일 년(선택)에 해당 메서드 호출
모든 애너테이션 정리(퍼옴)
https://jeong-pro.tistory.com/151
애너테이션 정리
https://blog.naver.com/dugksl23/222438631851
애너테이션 정리2
https://blog.naver.com/dugksl23/222438631851