[RESTful Web Service]-4

32394 ワード

DowonLeeがSpringBootを使ってRESTful Webサービスを開発するコースを学びました

RESTfulサービス機能の拡張


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);
    }
}
POST名が
  • 文字未満の場合、400 Bad 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

    レスポンスデータフォーマットの変換(XML)


    依存項目の追加

            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-xml</artifactId>
                <version>2.10.2</version>
            </dependency>

    レスポンスデータ制御(Filtering)

        @JsonIgnore //외부에 노출시키지 않음
        private String password;
        @JsonIgnore
        private String ssn;
  • @JsonIgnore:露出しない
  • @JosonIgnoreなし

    @JsonIgnoreProperties(value = {"password", "ssn"})
    public class User {
    //...
    }
  • と同じ結果
  • プログラミング制御のフィルタリング


    個々のユーザーの表示

    @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タイプを使用したバージョン管理

        @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タイプ:一般ブラウザ
  • を実行できません