Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 그리디
- 김영한
- 인프런
- Android
- Proxy
- 스프링 핵심 원리
- AOP
- jpa
- Thymeleaf
- Spring Boot
- transaction
- http
- 백준
- pointcut
- 알고리즘
- Exception
- Greedy
- db
- java
- 스프링
- springdatajpa
- Servlet
- kotlin
- SpringBoot
- JDBC
- spring
- QueryDSL
- 자바
- JPQL
- 스프링 핵심 기능
Archives
- Today
- Total
개발자되기 프로젝트
[API예외] API 예외처리 본문
- HTML 페이지의 경우 지금까지 설명했던 것 처럼 4xx, 5xx와 같은 오류 페이지만 있으면
- 대부분의 문제를 해결할 수 있음.
- API는 각 오류 상황에 맞는 오류 응답 스펙을 정하고, JSON으로 데이터를 내려줘야함.
1. WevServerCustomizer
- WAS에 예외가 전달되거나,
- response.sendError() 가 호출되면 위에 등록한 예외 페이지 경로가 호출됨.
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
@Component
public class WebServerCustomizer implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404");
ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error-page/500");
ErrorPage errorPageEx = new ErrorPage(RuntimeException.class, "/error-page/500");
factory.addErrorPages(errorPage404, errorPage500, errorPageEx);
}
}
2. ApiExceptionController
- Api예외 처리를 하는 controller를 만들어 보자
- @PathVariable로 넘어오는 id가 ex인 경우 RuntimeException을 던진다.
- RuntimeException이 발생하는 경우 "/error-page-500"을 호출한다.
- 정상 호출인 경우 MemberDto를 반환.(json형식)
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class ApiExceptionController {
@GetMapping("/api/members/{id}")
public MemberDto getMember(@PathVariable("id") String id){
if(id.equals("ex")){
throw new RuntimeException("잘못된 사용자");
}
return new MemberDto(id, "hello"+id);
}
@Data
@AllArgsConstructor
static class MemberDto{
private String memberId;
private String name;
}
}
- 정상요청
- 예외요청
- 현재 구조는 HTML이 나온다.
- API통신을 하기 때문에 예외가 발생해도 JSON으로 DATA를 전달해야함.
3. API응답
- Exception이 발생하면 "/error-page/500" 경로로 controller호출함.
- produce : accept타입과 일치하면 같은 요청 경로여도 우선순위를 가짐.
- 이 경우 "/error-page/500" 사용하는 method는 2개 이지만 accept가 json인 경우
- errorPage500Api()가 호출됨.
- ResponseEntity<Object>(object, HttpStatus)를 사용하면
- object를 JSON형식으로 변환하여 MessageBody에 넣어줌.
@Slf4j
@Controller
public class ErrorPageController {
//RequestDispatcher 상수로 정의되어 있음
public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
public static final String ERROR_MESSAGE = "javax.servlet.error.message";
public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
@RequestMapping("/error-page/404")
public String errorPage404(HttpServletRequest request, HttpServletResponse response){
log.info("errorPage 404");
printErrorInfo(request);
return "error-page/404";
}
@RequestMapping("/error-page/500")
public String errorPage500(HttpServletRequest request, HttpServletResponse response){
log.info("errorPage 500");
printErrorInfo(request);
return "error-page/500";
}
@RequestMapping(value = "/error-page/500", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, Object>> errorPage500Api(
HttpServletRequest request, HttpServletResponse response){
log.info("API ErrorPage 500");
Map<String, Object> result = new HashMap<>();
Exception ex = (Exception) request.getAttribute(ERROR_EXCEPTION);
result.put("status", request.getAttribute(ERROR_STATUS_CODE));
result.put("message", ex.getMessage());
Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
return new ResponseEntity<>(result, HttpStatus.valueOf(statusCode));
}
private void printErrorInfo(HttpServletRequest request){
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("ERROR_SERVLET_NAME: {}", request.getAttribute(ERROR_SERVLET_NAME));
log.info("ERROR_STATUS_CODE: {}", request.getAttribute(ERROR_STATUS_CODE));
log.info("dispatcherTYpe={}", request.getDispatcherType());
}
}
- 응답 데이터를 위해서 Map 을 만들고 status , message 키에 값을 할당햇음.
- Jackson 라이브러리는 Map 을 JSON 구조로 변환 가능.
4. GitHub : 210928 Servlet,API, Exception
'인프런 > [인프런] 스프링 MVC 2' 카테고리의 다른 글
[API예외] HandlerExceptionResolver (0) | 2021.09.28 |
---|---|
[API예외] SpringBoot 기본 오류 처리 (0) | 2021.09.28 |
[예외] SpringBoot - BasicErrorController (0) | 2021.09.27 |
[예외] SpringBoot - 오류페이지 (0) | 2021.09.27 |
[예외] Servlet 예외처리 - interceptor (0) | 2021.09.27 |
Comments