기본적으로 2가지 방식이 있다
dto - User.java
package com.example.exception.dto;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class User {
@NotEmpty
@Size(min=1,max=10)
private String name;
@Min(1)
@NotNull
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
controller - ApiController.java
package com.example.exception.controller;
import com.example.exception.dto.User;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/user")
public class ApiController {
@GetMapping("")
public User get(@RequestParam String name, @RequestParam(required = false) Integer age){
//(required = false)란 그 변수가 없어도 동작을 하되, 그 변수는 Null이 된다
//(required = false)는 ?name=1234같이 값이 안들어가있으면 error 터뜨림
User user = new User();
user.setName(name);
user.setAge(age);
int a= 10+age; //age에 값을 넣어주지 않으면 Null point가 발생하도록 함
return user;
}
@PostMapping("")
public User post(@Valid @RequestBody User user){
System.out.println(user);
return user;
}
}
name과 age에 아무 값을 안넣고 GET 요청을 넣었더니 에러 발생~!
java:18 ->
user.setAge(age);
User.java에서
public void setAge(int age) {
this.age = age;
}
int로 age를 받아야 하는데,
ApiController.java에서
@GetMapping("")
public User get(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age){
//(required = false)란 그 변수가 없어도 동작을 하되, 그 변수는 Null이 된다
//(required = false)는 ?name=1234같이 값이 안들어가있으면 error 터뜨림
User user = new User();
user.setName(name);
user.setAge(age);
int a= 10+age; //age에 값을 넣어주지 않으면 Null point가 발생하도록 함
return user;
}
Integer로 받아버리니 에러가 터져버린다.
또 다른 예제로
Post를 보냈는데,
서버 쪽에서는 친절하게 에러를 알려주지만
클라이언트쪽에서는 단순하게 에러를 터뜨리고 끝낸다
첫 번째 방법!
ExceptionHandler
advice - GlobalControllerAdvice
package com.example.exception.advice;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice //Rest API Controller에 할 예정이니까
public class GlobalControllerAdvice {
//내가 잡고자 하는 메소드 만들어보자
@ExceptionHandler(value = Exception.class) //전체적인 예외 다 잡을거임
public ResponseEntity exception(Exception e){ //Rest API니까 ResponseEntity받자
//value = Exception.class 여기서 설정한 값을 Exception e에 매개변수로 받을 수 있다
System.out.println("----------------------");
System.out.println(e.getLocalizedMessage());
System.out.println("----------------------");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("");
}
}
내가 지정한 ExceptionHandler를 통해 메시지가 찍히게 됨
아까와는 다르게 Body에 아무런 메시지도 없다!
ExceptionHandler 함수에
System.out.println(e.getClass().getName());
추가해주면
어떤 예외가 터졌는지 볼 수 있게 된다
그대로 복사해서 따로 잡아보자
특정 메소드의 예외 잡기!
@ExceptionHandler(value= MethodArgumentNotValidException.class)
public ResponseEntity MethodArgumentNotValidException(MethodArgumentNotValidException e){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
결과 :
또는,
@RestControllerAdvice(basePackages = "com.example.exception.controller")
basePackages를 붙여서
특정 패키지 하위에 있는 모든 예외들을 다 잡을 것이다
라고 명시 가능
두 번째 방법!
특정 컨트롤러에서만 예외 잡기
package com.example.exception.controller;
import com.example.exception.dto.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/user")
public class ApiController {
@GetMapping("")
public User get(@RequestParam(required = false) String name, @RequestParam(required = false) Integer age){
//(required = false)란 그 변수가 없어도 동작을 하되, 그 변수는 Null이 된다
//(required = false)는 ?name=1234같이 값이 안들어가있으면 error 터뜨림
User user = new User();
user.setName(name);
user.setAge(age);
int a= 10+age; //age에 값을 넣어주지 않으면 Null point가 발생하도록 함
return user;
}
@PostMapping("")
public User post(@Valid @RequestBody User user){
System.out.println(user);
return user;
}
@ExceptionHandler(value= MethodArgumentNotValidException.class)
public ResponseEntity MethodArgumentNotValidException(MethodArgumentNotValidException e){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
}
맨 아래에 ExceptionHandler를 그대로 복사해서 해당 controller에 붙여넣어주면,
해당 controller에서 나오는 예외만 잡겠다는 의미가 됨
예외처리 코드
위 POST 예외는
무슨 코드를 타고 예외로 잡힐까?
@ExceptionHandler(value= MethodArgumentNotValidException.class)
public ResponseEntity MethodArgumentNotValidException(MethodArgumentNotValidException e){
System.out.println("api controller");
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
@RestControllerAdvice()
위와 같이 GlobalControllerAdvice에 예외처리 메소드가 있다고 하더라도,
@ExceptionHandler
해당 controller에 있는 예외처리 메소드가 우선순위이다!
'Spring' 카테고리의 다른 글
Spring - DTO를 사용하는 이유 (0) | 2022.06.16 |
---|---|
Validation 모범 사례 (0) | 2022.06.13 |
Custom Validation (0) | 2022.06.05 |
Validation (0) | 2022.06.01 |
Object Mapper 활용 - json 값 바꾸기 (0) | 2022.05.30 |