https://kdyspring.tistory.com/44
이전 글에 이어서 System Exception 또는 Custom Exception 에러 발생 시 공통 Response 값에 에러 데이터들(에러 코드, 에러 메시지)을 객체에 담아서 공통으로 에러 데이터를 리턴해주는 기능을 개발한 과정에 대해 정리해 보았습니다.
1. System Exception과 Custom Exception를 정의한 Enum 클래스를 생성.
package com.example.login.common.error;
import lombok.Getter;
import lombok.ToString;
import org.springframework.http.HttpStatus;
@Getter
@ToString
public enum ExceptionEnum {
// System Exception
RUNTIME_EXCEPTION(HttpStatus.BAD_REQUEST, "E0001"),
ACCESS_DENIED_EXCEPTION(HttpStatus.UNAUTHORIZED, "E0002"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "E0003"),
// Custom Exception
SECURITY(HttpStatus.UNAUTHORIZED, "CE0001", "로그인이 필요합니다");
private final HttpStatus status;
private final String code;
private String message;
ExceptionEnum(HttpStatus status, String code) {
this.status = status;
this.code = code;
}
ExceptionEnum(HttpStatus status, String code, String message) {
this.status = status;
this.code = code;
this.message = message;
}
}
2. 사용자 정의 예외 클래스 생성
1. 컴파일 시 발생하는 예외 처리를 구현할 경우에는 Exception을 상속받아 구현
2. 실행 시 발생하는 예외 처리를 구현할 경우에는 RuntimeException을 상속받아 구현
ApiException.java
package com.example.login.common.error;
import lombok.Getter;
@Getter
public class ApiException extends RuntimeException {
private ExceptionEnum error;
public ApiException(ExceptionEnum e) {
super(e.getMessage());
this.error = e;
}
}
3. 전역 예외 처리 Class 생성
- 발생한 예외를 통합하여 관리 할 수 있는 @RestControllerAdvice 어노테이션과 System Exception 및 Custom Exception핸들링을 해주는 @ExceptionHandler를 사용 하여 전역으로 발생한 예외를 처리해줄 수 있는 Class를 생성.
ApiExceptionAdvice.java
package com.example.login.common.error;
import com.example.login.common.api.ApiResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.nio.file.AccessDeniedException;
@RestControllerAdvice
public class ApiExceptionAdvice {
@ExceptionHandler({ApiException.class})
public ResponseEntity<ApiResult> exceptionHandler(HttpServletRequest request, final ApiException e) {
ApiExceptionEntity apiExceptionEntity = ApiExceptionEntity.builder()
.errorCode(e.getError().getCode())
.errorMessage(e.getError().getMessage())
.build();
//e.printStackTrace();
return ResponseEntity
.status(e.getError().getStatus())
.body(ApiResult.builder()
.status("error")
.message("")
.exception(apiExceptionEntity)
.build());
}
@ExceptionHandler({RuntimeException.class})
public ResponseEntity<ApiResult> exceptionHandler(HttpServletRequest request, final RuntimeException e) {
ApiExceptionEntity apiExceptionEntity = ApiExceptionEntity.builder()
.errorCode(ExceptionEnum.RUNTIME_EXCEPTION.getCode())
.errorMessage(e.getMessage())
.build();
e.printStackTrace();
return ResponseEntity
.status(ExceptionEnum.RUNTIME_EXCEPTION.getStatus())
.body(ApiResult.builder()
.status("error")
.message("")
.exception(apiExceptionEntity)
.build());
}
@ExceptionHandler({AccessDeniedException.class})
public ResponseEntity<ApiResult> exceptionHandler(HttpServletRequest request, final AccessDeniedException e) {
ApiExceptionEntity apiExceptionEntity = ApiExceptionEntity.builder()
.errorCode(ExceptionEnum.ACCESS_DENIED_EXCEPTION.getCode())
.errorMessage(e.getMessage())
.build();
e.printStackTrace();
return ResponseEntity
.status(ExceptionEnum.ACCESS_DENIED_EXCEPTION.getStatus())
.body(ApiResult.builder()
.status("error")
.message("")
.exception(apiExceptionEntity)
.build());
}
@ExceptionHandler({Exception.class})
public ResponseEntity<ApiResult> exceptionHandler(HttpServletRequest request, final Exception e) {
ApiExceptionEntity apiExceptionEntity = ApiExceptionEntity.builder()
.errorCode(ExceptionEnum.INTERNAL_SERVER_ERROR.getCode())
.errorMessage(e.getMessage())
.build();
e.printStackTrace();
return ResponseEntity
.status(ExceptionEnum.INTERNAL_SERVER_ERROR.getStatus())
.body(ApiResult.builder()
.status("error")
.message("")
.exception(apiExceptionEntity)
.build());
}
}
4. 구현 및 테스트 결과
4-1. LoginCheckIntercepter.java
package com.example.login.common.intercepter;
import com.example.login.vo.UserVO;
import org.apache.catalina.User;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.WebUtils;
import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
@Component
public class LoginCheckIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
UserVO userVo = (UserVO) request.getSession().getAttribute("login");
if (userVo != null) {
return true;
}
request.setAttribute("exception", "AuthenticationException");
request.getRequestDispatcher("/api/error").forward(request, response);
return false;
}
}
4-2. ErrorController.java
package com.example.login.common.error;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import javax.security.sasl.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/api")
@ApiIgnore
public class ErrorController {
@RequestMapping("/error")
public void error(HttpServletRequest request) throws AuthenticationException{
String exception = (String) request.getAttribute("exception");
if ("AuthenticationException".equals(exception)) {
throw new ApiException(ExceptionEnum.SECURITY);
}
}
}
4-3. 테스트 결과
'Spring Framework' 카테고리의 다른 글
[Spring Boot] REST-API 공통 Response 값 포맷 개발 과정 (0) | 2023.03.15 |
---|---|
Spring Boot 프로젝트에서 Mybatis로 Mysql 데이터베이스(DB) 연동하는법 (2) | 2021.10.05 |
(Spring,JSP) JSP에서 날짜 값을 fmt태그를 사용해 포맷하는법 (0) | 2021.09.24 |
(Spring)Postman를 사용해서 Spring으로 구축한 REST API 서버가 정상작동하는지 테스트 하는 방법 (0) | 2021.09.20 |
Spring Boot에서 JSP 연동(사용)하는 방법 (0) | 2021.09.19 |