5. ResponseEntity로 객체 리턴 및 응답 코드 지정

Veloger·2022년 11월 17일
1

spring CH16 JSON

목록 보기
4/4
  • 지금까지 상태코드를 지정하기 위해 HttpServletResponse 의 setStatus()와 sendError()를 사용했음.

  • 문제점은 에러 시, JSON이 아닌 HTML 결과를 응답함.

  • 정상, 비정상 모두 JSON 응답을 위해 ResponseEntity 사용.


5.1 ResponseEntity로 응답 데이터 처리

-> ErrorResponse.java

public class ErrorResponse {
    private String message;

    public ErrorResponse(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

ErrorResponse 객체를 이용하도록 member() 수정

-> RestMemberController.java

	@GetMapping("/api/members/{id}")
    public ResponseEntity<Object> member(@PathVariable Long id,  // 리턴 타입으로 일반 객체 사용
                                 HttpServletResponse response) throws IOException{
        Member member = memberDao.selectById(id);
        if(member == null){
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                    .body(new ErrorResponse("no member"));
        }
        return ResponseEntity.status(HttpStatus.OK)
                .body(member);
    }
  • body : body로 지정한 객체를 사용해서 변환
  • status : 지정한 값을 응답 상태 코드로 사용

실행 결과


ResponseEntity 사용법

  • status와 body를 이용

    	ResponseEntity.status(상태코드).body(객체)
  • 상태코드는 HttpStatus에 정의된 값 이용
    ( Document 보러 가기 )

  • 상태코드 OK와 body를 한번에 사용

    	ResponseEntity.ok(member)
  • body가 없을 때, build() 사용

    	ResponseEntity.status(HttpStatus.NOT_FOUND).build()
  • body가 없고, status 대신 사용하는 메서드

  • noContent() : 204
  • badRequest() : 400
  • notFound() : 404


5.2 @ExceptionHandler 적용 메서드에서 ResponseEntity롤 응답

  • ResponseEntity를 정상 응답에도 사용을 하면, ResponseEntity를 사용하는 코드가 반복된다.

  • 컨트롤러에서 익센션 발생시 작동하는 @ExceptionHandlerResponseEntity를 사용하는 코드를 만들어서 리턴하도록 코드를 수정.

	@GetMapping("/api/members/{id}")
    public Member member(@PathVariable Long id,  // 리턴 타입으로 일반 객체 사용
                                 HttpServletResponse response) throws IOException{
        Member member = memberDao.selectById(id);
        if(member == null){
            return new MemberNotFoundException();
        }
        return member;
    }
    
    
	@ExceptionHandler(MemberNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNoData() {
    	return ResponseEntity.status(HttpStatus.NOT_FOUND)
    		.body(new ErrorResponse("no member"));
}

에러 처리 코드를 별도의 클래스로 분리

@RestControllerAdvice("controller")
public class ApiExceptionAdvice {
	
    @ExceptionHandler(MemberNotResponseException.class)
    public ResponseEntity<ErrorResponse> handleNoData () {
    	return ResponseEntity.status(HttpStatus.NOT_FOUND)
        .body(new ErrorResponse("no member"));
    }
}


5.3 @Valid 에러 결과를 JSON으로 응답

  • @Valid 붙은 커맨드 객체의 검증도 HTML 응답이므로, 이를 JSON 형식으로 바꿔보자.
  • Errors 타입 파라미터를 추가해서 직접 에러 응답을 생성.

-> 기존코드

	@PostMapping("/api/members")
    public ResponseEntity<Object> newMember(
            @RequestBody @Valid RegisterRequest regReq) {
        try{
            Long newMemberId = registerService.regist(regReq);
            URI uri = URI.create("/api/members/" + newMemberId);
            return ResponseEntity.created(uri).build();
        } catch(DuplicateMemberException dupEx){
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
        }

    }

-> 수정 코드

    @PostMapping("/api/members")
    public ResponseEntity<Object> newMember(
            @RequestBody @Valid RegisterRequest regReq
            , Errors errors){
        if(errors.hasErrors()){
            String errorCodes = errors.getAllErrors()
                    .stream()
                    .map(error -> error.getCodes()[0]) // error는 ObjectError
                    .collect(Collectors.joining("."));
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(new ErrorResponse("errorCodes = "+errorCodes));
        }
        ...생략

    }

  • @RequestBody가 붙은 @Valid 붙은 객체를 검증 실패했을 때, Errors 파라미터가 없으면 MethodArgumentNotValidException 발생.
  • 이때 @ExceptionHandler 를 이용해서 익셉션 처리.
	@RestControllerAdvice("controller")
    public class ApiExceptionAdvice {

        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<ErrorResponse> handleBindException (
                MethodArgumentNotValidException ex) {
            String errorCodes = ex.getBindResult().getAllErrors()
                    .stream()
                    .map(error -> error.getCodes()[0])
                    .collect(Collectors.joining(","));
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(new ErrorResponse("errorCodes = "+errorCodes));
        }
    }

0개의 댓글

관련 채용 정보