
@RestControllerAdvice
: 파라미터를 주지 않으면 global하게 동작
@RestControllerAdvice
public class RestApiExceptionHandler {
@ExceptionHandler(value = {Exception.class})
public ResponseEntity exception(Exception e){
log.error("RestApiExceptionHandler", e);
return ResponseEntity.status(400).build();
}
@Slf4j
@RestControllerAdvice(basePackages = "com.example.exception.controller")
//클래스 지정도 가능 basePackageClasses={RestApiController.class, RestApiBController.class}
public class RestApiExceptionHandler {
@ExceptionHandler(value = {IndexOutOfBoundsException.class})
public ResponseEntity exception(IndexOutOfBoundsException e){
log.error("RestApiExceptionHandler", e);
return ResponseEntity.status(200).build();
}
@Slf4j
@RestController
@RequestMapping("/api/b")
public class RestApiBController {
@GetMapping("/hello")
public void hello(){
throw new NumberFormatException("Number Format Exception");
}
@ExceptionHandler(value = {NumberFormatException.class})
public ResponseEntity numberFormatErrorHandler(NumberFormatException e){
log.error("RestApiBController",e);
return ResponseEntity.ok().build();
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder //builder()를 통해 객체 생성
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class Api<T> {
private String resultCode;
private String resultMessage;
private T data;
}
@Slf4j
@RestControllerAdvice
public class RestApiExceptionHandler {
@ExceptionHandler(value = {NoSuchElementException.class})
public ResponseEntity noSuchElement(NoSuchElementException e){
log.error("",e);
var response = Api.builder()
.resultMessage(HttpStatus.NOT_FOUND.name())
.resultCode(String.valueOf(HttpStatus.NOT_FOUND.value()))
.build();
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(response);
}
}
다음과 같이 Api 클래스에 제네릭을 사용하여 반환 데이터의 타입은 자유롭게 지정해주고, resultCode와 resultMessage를 지정해주면 항상 동일한 형태의 response를 내려줄 수 있다.
@RestController
@RequestMapping("/api/user")
public class UserApiController {
private static List<UserResponse> userList = List.of(
UserResponse.builder()
.id("1")
.age(15)
.name("Kim")
.build()
,
UserResponse.builder()
.id("2")
.age(20)
.name("Lee")
.build()
);
@GetMapping("/id/{userId}")
public Api<UserResponse> getUser(
@PathVariable String userId
){
var user = userList.stream().filter(
it->it.getId().equals(userId)
).findFirst().get();
Api<UserResponse> response = Api.<UserResponse>builder()
.resultCode(String.valueOf(HttpStatus.OK.value()))
.resultMessage(HttpStatus.OK.name())
.data(user)
.build();
return response;
}
}
Pathvariable을 통해 입력받은 userId에 해당하는 유저 데이터를 반환한다.
UserResponse 모델에 @Build를 사용하여서 setter가 아닌 build()로 인스턴스 생성 가능 noSuchElement() 에러 핸들러가 동작한다.