[RESTful Web Service]-4
Dowon Lee님의 Spring Boot를 이용한 RESTful Web Services 개발 강의를 학습한 내용입니다.
RESTful Service 기능 확장
Validation API
의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.5.6</version>
</dependency>
@Size(min = 2, message = "Name은 2글자 이상")
private String name;
@Past
private Date joinDate;
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
@RestControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
//...
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(),
"Validation Failed", ex.getBindingResult().toString());
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}
}
- 2글자 미만의 name을 POST할 때 400Bad Request
다국어 처리
@SpringBootApplication
public class RestfulWebServiceApplication {
//...
@Bean
public LocaleResolver localeResolver(){
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.KOREA);
return localeResolver;
}
}
HelloWorldController
public class HelloWorldController {
@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);
}
}
- @Autowired : 의존성 주입
application.yml
spring:
messages:
basename: messages
messages.properties(default, en, fr)
greeting.message = 안녕하세요
greeting.message = Hello
greeting.message = Bonjour
Response 데이터 형식 변환(XML)
의존성 추가
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.10.2</version>
</dependency>
Response 데이터 제어(Filtering)
@JsonIgnore //외부에 노출시키지 않음
private String password;
@JsonIgnore
private String ssn;
- @JsonIgnore : 외부에 노출시키지 않음
@JsonIgnore 없이
@JsonIgnoreProperties(value = {"password", "ssn"})
public class User {
//...
}
- 동일한 결과
프로그래밍으로 제어하는 Filtering
개별 사용자 조회
@JsonFilter("UserInfo")
public class User {
//...
}
- @JsonFilter(필터이름)
@RestController
@RequestMapping("/admin")
public class AdminUserController {
//...
@GetMapping("/users/{id}")
public MappingJacksonValue retrieveUser(@PathVariable int id) {
User user = service.findOne(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
.filterOutAllExcept("id", "name", "joinDate", "ssn");
FilterProvider filters = new SimpleFilterProvider().addFilter("UserInfo", filter);
MappingJacksonValue mapping = new MappingJacksonValue(user);
mapping.setFilters(filters);
return mapping;
}
}
- @RequestMapping(" ") : prefix
- SimpleBeanPropertyFilter.filterOutAllExcept(""); : 포함하는 것
전체 사용자 조회
@GetMapping("/users")
public MappingJacksonValue retrieveAllUsers() {
List<User> users = service.findAll();
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
.filterOutAllExcept("id", "name", "joinDate", "ssn");
FilterProvider filters = new SimpleFilterProvider().addFilter("UserInfo", filter);
MappingJacksonValue mapping = new MappingJacksonValue(users);
mapping.setFilters(filters);
return mapping;
}
URI를 이용한 REST API 버전 관리
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonFilter("UserInfoV2")
public class UserV2 extends User{
private String grade;
}
public class AdminUserController {
//...
@GetMapping("/v2/users/{id}")
public MappingJacksonValue retrieveUserV2(@PathVariable int id) {
User user = service.findOne(id);
if (user == null) {
throw new UserNotFoundException(String.format("ID[%s] not found", id));
}
UserV2 userV2 = new UserV2();
BeanUtils.copyProperties(user, userV2);
userV2.setGrade("VIP");
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter
.filterOutAllExcept("id", "name", "joinDate", "grade"); //포함하는 것
FilterProvider filters = new SimpleFilterProvider().addFilter("UserInfoV2", filter);
MappingJacksonValue mapping = new MappingJacksonValue(userV2);
mapping.setFilters(filters);
return mapping;
}
}
Request Parameter를 이용한 버전 관리
@GetMapping(value = "/users/{id}/", params = "version=1")
public MappingJacksonValue retrieveUserV1(@PathVariable int id) {
//...
}
@GetMapping(value = "/users/{id}/", params = "version=2")
public MappingJacksonValue retrieveUserV2(@PathVariable int id) {
//...
}
- ex) localhost:8088/admin/users/1/?version=2
Header를 이용한 버전 관리
@GetMapping(value = "/users/{id}", headers = "X-API-VERSION=1")
public MappingJacksonValue retrieveUserV1(@PathVariable int id){
//...
}
@GetMapping(value = "/users/{id}", headers = "X-API-VERSION=2")
public MappingJacksonValue retrieveUserV2(@PathVariable int id){
//...
}
MIME Type을 이용한 버전 관리
@GetMapping(value = "/users/{id}", produces = "application/vnd.company.appv1+json")
public MappingJacksonValue retrieveUserV1(@PathVariable int id){
//...
}
@GetMapping(value = "/users/{id}", produces = "application/vnd.company.appv2+json")
public MappingJacksonValue retrieveUserV2(@PathVariable int id){
//...
}
- URI, RequestParameter : 일반 브라우저에서 실행 가능
- Header, MIME Type : 일반 브라우저 실행 불가능
Author And Source
이 문제에 관하여([RESTful Web Service]-4), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@earlybird7/RESTful-Web-Service-4저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)