Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[예외] Servlet 예외처리 - 오류 페이지 작동 원리 본문

인프런/[인프런] 스프링 MVC 2

[예외] Servlet 예외처리 - 오류 페이지 작동 원리

Seung__ 2021. 9. 27. 22:19
  • 서블릿은 Exception (예외)가 발생해서 서블릿 밖으로 전달되거나
  • 또는 response.sendError() 가 호출 되었을 때 설정된 오류 페이지를 찾는다.

 

 

1. 오류 페이지 작동 원리


  • 예외 발생 흐름
WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
  • sendError 흐름
WAS(sendError 호출 기록 확인) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러 (response.sendError())
    @GetMapping("/error-ex")
    public void errorEx(){
        throw new RuntimeException("예외 터짐!");
    }
  • WAS는 해당 예외를 처리하는 오류 페이지 정보를 확인한다.
    • new ErrorPage(RuntimeException.class, "/error-page/500")
  • 예를 들어서 RuntimeException 예외가 WAS까지 전달되면, WAS는 오류 페이지 정보를 확인한다.
  • 확인해보니 RuntimeException 의 오류 페이지로 /error-page/500 이 지정되어 있다.
  •  WAS는 오류 페이지를 출력하기 위해 /error-page/500 를 다시 요청한다.
  • 오류 페이지 요청 흐름
WAS `/error-page/500` 다시 요청 -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러(/error-page/ 500) -> View
  • 예외 발생과 오류 페이지 요청 흐름
1. WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
   ↓
2. WAS `/error-page/500` 다시 요청 -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러(/errorpage/ 500) -> View
  • 핵심
    • 중요한 점은 웹 브라우저(클라이언트)는 서버 내부에서 이런 일이 일어나는지 전혀 모른다!
    • 오직 서버 내부에서 오류 페이지를 찾기 위해 추가적인 호출을 한다.
  • 정리
    • 예외가 발생해서 WAS까지 전파된다.
    • WAS는 오류 페이지 경로를 찾아서 내부에서 오류 페이지를 호출한다.
    • 이때 오류 페이지 경로로 필터, 서블릿, 인터셉터, 컨트롤러가 모두 다시 호출된다.

 

 

 

2. 오류 정보 추가


  • WAS는 오류 페이지를 단순히 다시 요청만 하는 것이 아니라, 
  • 오류 정보를 request 의 attribute 에 추가해서 넘겨줌!!!
  • 필요하면 오류 페이지에서 전달된 오류 정보를 사용할 수 있음.
  • request.attribute에 서버가 담아준 정보를 사용해 보자.
    • requestDispatcher에 상수로 정보 이름이 등록되어 있음.
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@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";
    }

    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());
    }
}
  • log
ERROR_EXCEPTION_TYPE: class java.lang.RuntimeException
ERROR_REQUEST_URI: /error-ex
ERROR_SERVLET_NAME: dispatcherServlet
ERROR_STATUS_CODE: 500
dispatcherTYpe=ERROR

 

 

3. GitHub : 210927 Servlet ErrorPage


 

bsh6463/Exception

Contribute to bsh6463/Exception development by creating an account on GitHub.

github.com

 

Comments