[Spring] Validation API and LocaleResolver ๐งฑ
Validation API(์ ํจ์ฑ ์ฒดํฌ) ๐ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ฐ์ดํฐ์ ๋ํ ์ ํจ์ฑ ์ฒดํฌ
@Valid
// User Class
import lombok.AllArgsConstructor;
import lombok.Data;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import java.util.Date;
@Data
@AllArgsConstructor
public class User {
private Integer id;
@Size(min=2) // ์ต์ ๊ธธ์ด 2๊ฐ ์ด์
private String name;
@Past // ๋ฏธ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ์ ์ฝ ์กฐ๊ฑด
private Date joinDate;
}
// UserController Class
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user){
User savedUser = service.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}") //๋ฐํ ๊ฐ์ ๊ฐ๋ณ ๋ณ์ id
.buildAndExpand(savedUser.getId()) //์ ์ฅ๋ user ๊ฐ์ id ๊ฐ์ ์ง์
.toUri(); //URI๋ก ๋ฐํ
return ResponseEntity.created(location).build();
//์๋ฒ๋ก๋ถํฐ ์ ์ ํ ์ํ ์ฝ๋๋ฅผ ๋ณด๋ด์ฃผ๋ ๊ฒ์ด ์ข์ api์
}
๐ ์ํ ์ฝ๋๋ 400 Bad Request ๋ค๋ง, body์ ์์ธ ๋ด์ฉ ์ ๋ฌ์ X
์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด ExceptionResponse์ ์์ธ๋ฅผ ์์ฑํ๋ค.
๋ค์๊ณผ ๊ฐ์ด handleMethodArgumentNotValid ๋ฉ์๋๋ฅผ ์ฌ์ ์ ํ๋ค.
// CustomizedResponseEntityExceptionHandler Class
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(),
ex.getMessage(), ex.getBindingResult().toString());
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}
๐ ์ํ ์ฝ๋๋ 400 Bad Request ๋์ผ, body์ ์์ธ ๋ด์ฉ ์ ๋ฌ O
Refactoring ๐
// CustomizedResponseEntityExceptionHandler Class ๐ ์์
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(),
"Validation Failed", ex.getBindingResult().toString());
// User Class ๐ ์์
@Size(min=2, message = "Name์ 2๊ธ์ ์ด์ ์
๋ ฅํด ์ฃผ์ธ์.") // ์ต์ ๊ธธ์ด 2๊ฐ ์ด์
private String name;
๐ Body์ ์์ธ message, details ๋ด์ฉ์ด ์์ ํ ๋๋ก ์ ๋ฌ๋๋ค.
๋ค๊ตญ์ด ์ฒ๋ฆฌ๋ฅผ ์ํ Internationalization ๊ตฌํ
๋ค๊ตญ์ด ์ฒ๋ฆฌ : ํ๋์ ์ถ๋ ฅ๊ฐ์ ์ฌ๋ฌ ๊ฐ์ง ์ธ์ด๋ก ํ์ ํด์ฃผ๋ ๊ธฐ๋ฅ
-
(์ ๊ณตํ๊ณ ์ ํ๋ ์ธ์ด๋ณ๋ก ์ง์ญ ์ฝ๋, ์ธ์ด ์ค์ ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ํ์)
-
ํน์ Controller์ ํํด์๊ฐ ์๋๋ผ Project ์ ๋ฐ์ ์ผ๋ก ์ ์ฉ
- ๋ค๊ตญ์ด ์ฒ๋ฆฌ์ ํ์ํ bean์ Spring Boot Application์ ๋ฑ๋ก
@SpringBootApplication
public class RestfulWebServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RestfulWebServiceApplication.class, args);
}
@Bean
public LocaleResolver localeResolver() { // ์น ์์ฒญ๊ณผ ๊ด๋ จํด์ Locale์ ์ถ์ถํ๊ณ ์ด Locale ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ์๋ง์ ์ธ์ด์ ๋ฉ์์ง๋ฅผ ์ ํ
SessionLocaleResolver localeResolver = new SessionLocaleResolver(); // Session์ Locale ์ ๋ณด๋ฅผ ๋ฃ๊ณ ์ด๋ฅผ ํตํด ๋ค๊ตญ์ด๋ฅผ ์ฒ๋ฆฌํด ์ฃผ๋ ์ญํ
localeResolver.setDefaultLocale(Locale.KOREA);
return localeResolver;
}
}
- @bean์ ๋ฑ๋กํ๊ฒ ๋๋ฉด SpringBoot๊ฐ ์ด๊ธฐํ๋ ๋, ํด๋น ๋น์ ํด๋นํ๋ ์ ๋ณด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ด ๋ฑ๋ก
-
application.yml์ ์ฌ์ฉํ ๋ค๊ตญ์ด ํ์ผ ๋ฑ๋ก
-
Resource์ ๋ค๊ตญ์ด ํ์ผ(properties) ์์ฑ
// Controller
@Autowired
private MessageSource messageSource;
@GetMapping(path = "/hello-world-internationalized")
public String helloWorldInternationalized(
@RequestHeader(name = "Accept-Language", required=false) Locale locale) {
return messageSource.getMessage("greeting.message", null, locale);
}
locale ๊ฐ์ ์ง์ ํ์ง ์์์ ๋๋ ๐ default_locale๊ฐ์ธ ํ๊ตญ์ด ๋ฆฌํด
ex) Headers์ KEY(Accept-Language) VALUE(fr) ๐ ํ๋์ค์ด ๋ฆฌํด
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ([Spring] Validation API and LocaleResolver ๐งฑ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@daydream/Spring-Validation-API-and-LocaleResolver์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค