20.

【Spring】@RestControllerアノテーションとは

編集
この記事の要点
  • @RestControllerREST API のコントローラを表す Spring MVC アノテーション
  • @Controller + @ResponseBody をまとめたもの
  • クラス内のすべてのメソッドの戻り値が自動で JSON / XML 化される(View 解決をしない)
  • 通常の View を返す場合は @Controller、API なら @RestController

 

@RestController の基本

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public UserDto get(@PathVariable Long id) {
        return userService.findById(id);
        // ← 自動で JSON 化されてレスポンスボディに書き出される
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public UserDto create(@RequestBody UserCreateRequest req) {
        return userService.create(req);
    }

    @PutMapping("/{id}")
    public UserDto update(@PathVariable Long id, @RequestBody UserUpdateRequest req) {
        return userService.update(id, req);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}

@RestController vs @Controller

項目@RestController@Controller
用途REST APIHTML View 返却
戻り値JSON / XML として直接出力View 名として解釈、テンプレート探す
@ResponseBodyクラス全体に暗黙適用個別メソッドに付ける必要
典型例外部 API / SPA バックエンドサーバサイドレンダリング

レスポンスの型

① POJO / DTO(標準)

@GetMapping("/{id}")
public UserDto get(@PathVariable Long id) {
    return userService.findById(id);
}
// → {"id": 1, "name": "Alice", "email": "..."}

② List / Map

@GetMapping
public List list() {
    return userService.findAll();
}

@GetMapping("/summary")
public Map summary() {
    return Map.of(
        "total", 100,
        "active", 80
    );
}

③ ResponseEntity(ステータス・ヘッダ制御)

@GetMapping("/{id}")
public ResponseEntity get(@PathVariable Long id) {
    return userService.findByIdOptional(id)
        .map(ResponseEntity::ok)
        .orElseGet(() -> ResponseEntity.notFound().build());
}

@PostMapping
public ResponseEntity create(@RequestBody UserCreateRequest req) {
    UserDto created = userService.create(req);
    URI location = URI.create("/api/users/" + created.getId());
    return ResponseEntity.created(location).body(created);
}

④ ストリーミング

@GetMapping(value = "/export", produces = "text/csv")
public ResponseEntity export() {
    StreamingResponseBody body = out -> {
        userService.streamAll().forEach(user -> {
            try {
                out.write((user.toCsvLine() + "\n").getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) { throw new RuntimeException(e); }
        });
    };
    return ResponseEntity.ok()
        .header("Content-Disposition", "attachment; filename=\"users.csv\"")
        .body(body);
}

例外ハンドリング

@RestController
public class UserController {

    @GetMapping("/{id}")
    public UserDto get(@PathVariable Long id) {
        return userService.findById(id)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found"));
    }

    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(UserNotFoundException ex) {
        return new ErrorResponse("USER_NOT_FOUND", ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map handleValidation(MethodArgumentNotValidException ex) {
        Map errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage())
        );
        return errors;
    }
}

// グローバルエラーハンドラ
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleAll(Exception ex) {
        log.error("Unexpected", ex);
        return new ErrorResponse("INTERNAL_ERROR", "システムエラー");
    }
}

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. @After
  2. @Autowired
  3. @Bean
  4. @Before
  5. @Column
  6. @Component
  7. @Configuration
  8. @Controller
  9. @Data
  10. @Entity
  11. @GeneratedValue
  12. @Id
  13. @Modifying
  14. @PathVariable
  15. @PropertySource
  16. @Repository
  17. @RequestBody
  18. @RequestMapping
  19. @ResponseBody
  20. @RestController
  21. @Service
  22. @SpringBootApplication
  23. @Table
  24. @Transactional
  25. @Value