@Slf4j
@Controller
public class ErrorPageController {
// RequestDispatcher 클래스에 final static으로 정의돼 있음
public final static String FORWARD_REQUEST_URI = "jakarta.servlet.forward.request_uri";
public final static String FORWARD_CONTEXT_PATH = "jakarta.servlet.forward.context_path";
public final static String FORWARD_MAPPING = "jakarta.servlet.forward.mapping";
public final static String FORWARD_PATH_INFO = "jakarta.servlet.forward.path_info";
public final static String FORWARD_SERVLET_PATH = "jakarta.servlet.forward.servlet_path";
public final static String FORWARD_QUERY_STRING = "jakarta.servlet.forward.query_string";
public final static String INCLUDE_REQUEST_URI = "jakarta.servlet.include.request_uri";
public final static String INCLUDE_CONTEXT_PATH = "jakarta.servlet.include.context_path";
public final static String INCLUDE_PATH_INFO = "jakarta.servlet.include.path_info";
public final static String INCLUDE_MAPPING = "jakarta.servlet.include.mapping";
public final static String INCLUDE_SERVLET_PATH = "jakarta.servlet.include.servlet_path";
public final static String INCLUDE_QUERY_STRING = "jakarta.servlet.include.query_string";
public final static String ERROR_EXCEPTION = "jakarta.servlet.error.exception";
public final static String ERROR_EXCEPTION_TYPE = "jakarta.servlet.error.exception_type";
public final static String ERROR_MESSAGE = "jakarta.servlet.error.message";
public final static String ERROR_REQUEST_URI = "jakarta.servlet.error.request_uri";
public final static String ERROR_SERVLET_NAME = "jakarta.servlet.error.servlet_name";
public final static String ERROR_STATUS_CODE = "jakarta.servlet.error.status_code";
@RequestMapping("/error-page/500")
public String errorPage500(HttpServletRequest request, HttpServletResponse response){
log.info("errorPage 500");
printErrorInfo(request);
return "error-page/500";
}
// API 오류 JSON 반환
@RequestMapping(value="/error-page/500",produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String,Object>> errorPage500Api(HttpServletRequest request,HttpServletResponse response){
log.info("API Eroor Page : 500");
HashMap<String, Object> result = new HashMap<>();
Exception ex = (Exception)request.getAttribute(ERROR_EXCEPTION);
result.put("message",ex.getMessage());
result.put("status",request.getAttribute(ERROR_STATUS_CODE));
Integer statusCode = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
return new ResponseEntity<>(result, HttpStatus.valueOf(statusCode));
}
private void printErrorInfo(HttpServletRequest request){
log.info("FORWARD_REQUEST_URI : {}",request.getAttribute(FORWARD_REQUEST_URI ));
log.info("FORWARD_CONTEXT_PATH : {}",request.getAttribute(FORWARD_CONTEXT_PATH));
log.info("FORWARD_MAPPING :{}",request.getAttribute(FORWARD_MAPPING));
log.info("FORWARD_PATH_INFO : {}",request.getAttribute(FORWARD_PATH_INFO));
log.info("FORWARD_SERVLET_PATH : {}",request.getAttribute(FORWARD_SERVLET_PATH));
log.info("FORWARD_QUERY_STRING : {}",request.getAttribute(FORWARD_QUERY_STRING));
log.info("INCLUDE_REQUEST_URI : {}",request.getAttribute(INCLUDE_REQUEST_URI ));
log.info("INCLUDE_CONTEXT_PATH : {}",request.getAttribute(INCLUDE_CONTEXT_PATH));
log.info("INCLUDE_PATH_INFO : {}",request.getAttribute(INCLUDE_PATH_INFO ));
log.info("INCLUDE_MAPPING : {}",request.getAttribute(INCLUDE_MAPPING ));
log.info("INCLUDE_SERVLET_PATH : {}",request.getAttribute(INCLUDE_SERVLET_PATH));
log.info("INCLUDE_QUERY_STRING : {}",request.getAttribute(INCLUDE_QUERY_STRING));
log.info("ERROR_EXCEPTION: {}",request.getAttribute(ERROR_EXCEPTION ));
log.info("ERROR_EXCEPTION_TYPE : {}",request.getAttribute(ERROR_EXCEPTION_TYPE));
log.info("ERROR_MESSAGE : {}",request.getAttribute(ERROR_MESSAGE ));
log.info("ERROR_REQUEST_URI : {}",request.getAttribute(ERROR_REQUEST_URI));
log.info("Dispatcher Type : {}",request.getDispatcherType());
}
}
API는 요청/응답 모두 JSON 형식이여야 한다.
요청 Http 헤더에 Accept 헤더라는 것이 있다.
만약 이 Accept 헤더에 "application/json"을 설정하지 않고 모든 반환 타입을 허용하도록 설정(Accept : */*)하게 되면
위 코드에서 우선 순위의 관계로 errorPage500 메서드가 호출되며 아래의 그림과 같이 API 오류 응답을 HTML로 받게
돼버려, API를 사용하는 개발자 입장에서 난처하게 된다.(HTML을 일일이 파싱해야 한다)
이를 방지하고자 produecs=MediaType.JSON_VALUE로 설정을 하고 요청 Accept도 application/json으로 설정을 하면
아래와 같이 API 오류 응답을 JSON으로 받을 수가 있다.