SpringMVC 통합 글로벌 예외 처리

SpringMVC 글로벌 예외 처리 및 처리 순서의 통합
SpringMVC가 발생합니까 처리 통합 글로벌 예외를 사용하는 경우 최근 문제, 그들은 아약스 요청 및 일반 웹 요청을 json으로 오류 메시지를 반환하거나 별도로 잘못된 페이지로 이동합니다.

실제로 방법을 재 작성 HandlerExceptionResolver 인터페이스 resolveException을 구현 SpringHandlerExceptionResolver이라는 HandlerExceptionResolver을 사용자 정의하는 표준 방법을 수행 할 때, 다음과 같이 구현 :

수입 com.alibaba.fastjson.JSON; 
수입 com.alibaba.fastjson.JSONObject; 
수입 com.alibaba.fastjson.support.config.FastJsonConfig; 
수입 com.alibaba.fastjson.support.spring.FastJsonJsonView; 
수입 com.butioy.common.bean.JsonResult; 
수입 com.butioy.common.exception.BaseSystemException; 
수입 java.util.HashMap에; 
수입 java.util.Map; 
수입 나오는 javax.servlet.http.HttpServletRequest; 
수입의 javax.servlet.http.HttpServletResponse; 
수입 org.slf4j.Logger; 
수입 org.slf4j.LoggerFactory; 
수입 org.springframework.beans.ConversionNotSupportedException; 
수입 org.springframework.core.Ordered;
수입 org.springframework.beans.TypeMismatchException;
수입 org.springframework.beans.factory.annotation.Autowired; 
수입 org.springframework.http.converter.HttpMessageNotReadableException; 
수입 org.springframework.http.converter.HttpMessageNotWritableException; 
수입 org.springframework.validation.BindException; 
수입 org.springframework.web.HttpMediaTypeNotAcceptableException; 
수입 org.springframework.web.HttpMediaTypeNotSupportedException; 
수입 org.springframework.web.HttpRequestMethodNotSupportedException; 
수입 org.springframework.web.bind.MethodArgumentNotValidException; 
수입 org.springframework.web.bind.MissingPathVariableException; 
수입 org.springframework.web.bind.MissingServletRequestParameterException;
수입 org.springframework.web.bind.ServletRequestBindingException; 
org.springframework.web.context.request 가져옵니다. 비동기 .AsyncRequestTimeoutException; 
수입 org.springframework.web.multipart.support.MissingServletRequestPartException; 
수입 org.springframework.web.servlet.HandlerExceptionResolver; 
수입 org.springframework.web.servlet.ModelAndView; 
수입 org.springframework.web.servlet.NoHandlerFoundException; 
수입 org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException; 

/ * * 
 * <p> 
 * 스프링 MVC统一异常处理
 * </ p> 
 * 
 * @author butioy 
 * / 
공용  클래스SpringHandlerExceptionResolver는 HandlerExceptionResolver {구현 

    전용  정적 로거 로거 = LoggerFactory.getLogger (. SpringHandlerExceptionResolver 클래스 ); 

    개인 FastJsonConfig fastJsonConfig; 

    @Autowired 
    공개 SpringHandlerExceptionResolver (FastJsonConfig fastJsonConfig) {
          .fastJsonConfig = fastJsonConfig; 
    } 

    @Override 
    공공 의 ModelAndView resolveException (HttpServletRequest의 요청에 응답 HttpServletResponse를, 대상물 핸들러 예외 예) { 
        의 ModelAndView MV = specialExceptionResolve (예, 요청);
        경우 ( == MV) { 
            문자열 메시지 = " 系统异常,请联系管理员" ;
            // BaseSystemException 내 사용자 정의 예외 기본 클래스는 RuntimeException을 상속입니다 
            IF BaseSystemException instanceof를 (EX를) { 
                메시지 = ex.getMessage (); 
            } 
            뮤직 비디오 = errorResult (메시지, " / 오류 " , 요청); 
        } 
        반환 뮤직 비디오; 
    } 

    / * * 
     이 방법은 복사 * {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver # doResolveException}
     * 추가 지정 처리, 400, 404, 405, 406, 415, 500 (변수 문제를 일으킬), 처리 (503) 
     * 
     * @param 이상 정보 EX 
     * @param 요청이 현재 요청의 여부를 판단하기위한 현재의 요청 개체 ( 아약스 요청) 
     * @return 뷰 모델 객체 
     * / 
    개인 의 ModelAndView specialExceptionResolve (예외 EX, HttpServletRequest의 요청) {
        시도 {
             경우 (NoSuchRequestHandlingMethodException instanceof를 전 
                 || NoHandlerFoundException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_FOUND_EXCEPTION 요청); 
            } 
            다른  경우 (HttpRequestMethodNotSupportedException instanceof를 예) {
                 반환결과 (HttpExceptionEnum.NOT_SUPPORTED_METHOD_EXCEPTION 요청); 
            } 
            다른  경우 (HttpMediaTypeNotSupportedException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_SUPPORTED_MEDIA_TYPE_EXCEPTION 요청); 
            } 
            다른  경우 (HttpMediaTypeNotAcceptableException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_ACCEPTABLE_MEDIA_TYPE_EXCEPTION 요청); 
            } 
            다른  경우 (MissingPathVariableException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_SUPPORTED_METHOD_EXCEPTION 요청); 
            } 
            다른 경우 (MissingServletRequestParameterException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.MISSING_REQUEST_PARAMETER_EXCEPTION 요청); 
            } 
            다른  경우 (ServletRequestBindingException instanceof를 예) {
                 반환결과 (HttpExceptionEnum.REQUEST_BINDING_EXCEPTION 요청); 
            } 
            다른  경우 (ConversionNotSupportedException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_SUPPORTED_CONVERSION_EXCEPTION 요청); 
            } 
            다른  경우 (TypeMismatchException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.TYPE_MISMATCH_EXCEPTION 요청); 
            } 
            다른  경우 (HttpMessageNotReadableException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.MESSAGE_NOT_READABLE_EXCEPTION 요청); 
            } 
            다른  경우 (HttpMessageNotWritableException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.MESSAGE_NOT_WRITABLE_EXCEPTION 요청); 
            } 
            다른  경우 (MethodArgumentNotValidException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.NOT_VALID_METHOD_ARGUMENT_EXCEPTION 요청); 
            } 
            다른  경우(MissingServletRequestPartException instanceof는 예) {
                 반환 결과 (HttpExceptionEnum.MISSING_REQUEST_PART_EXCEPTION 요청); 
            } 
            다른  경우 (않고 BindException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.BIND_EXCEPTION 요청); 
            } 
            다른  경우 (AsyncRequestTimeoutException instanceof를 예) {
                 반환 결과 (HttpExceptionEnum.ASYNC_REQUEST_TIMEOUT_EXCEPTION 요청); 
            } 
        } 캐치 (예외 handlerException) { 
            logger.warn ( " 의 취급 [ " + ex.getClass () getName () +. " ] 예외의 결과 " , handlerException); 
        } 
        반환  널 (null)을 ; 
    } 

    / * * 
     *判断是否AJAX请求
     * 
     * @param 요청请求对象 
     * 참 @return : AJAX 거짓 요구 : 비 Ajax 요청 
     * / 
    전용 부울 isajax (HttpServletRequest의 요청) {
         반환  " 는 XMLHttpRequest " .equalsIgnoreCase (request.getHeader ( " X - 요청-와 " )); 
    } 

    / * * 
     * 반환하는 오류 메시지가 
     * 
     * @param 오류 메시지 
     파라미터 : URL 오류 페이지 URL 
     * @param 요청 요청 개체 
     *의 @return 모델 뷰 객체 
     * / 
    개인 의 ModelAndView errorResult (메시지 문자열, 문자열 URL, HttpServletRequest의 요청) { 
        logger.warn ( " 요청 처리가 실패 요청 URL = [{ }, 실패 이유는 {} " , Request.getRequestURI () 메시지);
        IF (isajax (요청)) {
             반환 JsonResult ( 500 , 메시지); 
        } 다른 사람을 {
             반환 normalResult (메시지, URL을); 
        } 
    } 

    / * * 
     * 반환 예외 정보 
     * 
     * @param HttpException 이상 정보 
     * @param 요청 요청 개체
     * @return 모델 뷰 객체 
     * / 
    개인 의 ModelAndView 결과 (HttpExceptionEnum HttpException, HttpServletRequest의 요청) { 
        logger.warn ( " {} 요청 처리는 요청 URL = {}, 실패 이유 실패 " , Request.getRequestURI () HttpException .getMessage ());
         IF (isajax (요청)) {
             반환 JsonResult (httpException.getCode ()을 httpException.getMessage ()); 
        } 밖의 {
             반환 normalResult을 (httpException.getMessage () " / 에러 " ); 
        } 
    } 

    / * * 
     * 오류 페이지를 반환 
     *
     파라미터 : 메시지 오류 
     파라미터 : URL 오류 페이지 URL 
     * @return 모델 뷰 객체 
     * / 
    개인 의 ModelAndView normalResult (메시지 문자열, 문자열 URL) { 
        지도 <문자열, 문자열> 모델 = 새로운 새로운 HashMap의 <문자열, 문자열> (); 
        model.put ( " ERRORMESSAGE " , 메시지);
         돌아가  새로운 새 의 ModelAndView (URL, 모델); 
    } 

    / * * 
     * 오류 데이터를 반환 
     * 
     * @param 오류 메시지 
     * @return 모델 뷰 객체가 
     * / 
    개인 의 ModelAndView JsonResult ( INT의 코드를, 문자열 메시지) { 
        의 ModelAndView 뮤직 비디오 = 새 새 ;의 ModelAndView ()를 
        FastJsonJsonView 보기 = 새로운 새로운 FastJsonJsonView (); 
        view.setFastJsonConfig (fastJsonConfig) 
        view.setAttributesMap (합니다 (된 JSONObject) JSON.toJSON (JsonResult.fail (코드, 메시지))); 
        mv.setView (보기) 
        반환 뮤직 비디오를; 
    } 
}

springContext.xml 프로필의 모양 구성한 후 글

<bean 클래스 = "com.butioy.common.handler.SpringHandlerExceptionResolver"/ >
다음, 모든, 오류 메시지가없는 정상입니다,하지만 난 요청시 추측으로 사용자 지정 오류 페이지를 반환하지 않았습니다 바람둥이을 시작하지만, 바람둥이 기본 오류 페이지

 

그래서 코드의 실행을 추적하는 디버거. 드디어 예외 핸들러 콩 선언 내부에 저장되어 봄의 위해 HandlerExceptionResolvers 수집 processHandlerException 방법의 DispatcherServlet 클래스가 발견.

 

그런 다음 찾아이 세 가지 예외 핸들러 콩은 우리가 선언되지 않은 것입니다 수 있습니다 나는이 세 가지 콩이 DispatcherServlet.java에서 같은 패키지 SpringMVC의 기본 초기화, 스프링 webmvc 항아리 패키지를 것을 깨달았다 정보를 확인 다음과 같이 DispatcherServlet.properties 구성 파일, 구성 파일을 읽습니다

 

이 세 가지 기본 콩 있지만, 우선 순위가 높은 이유는 그것을 사용자 정의보다 있지만? 그래서 이러한 클래스가 보면 열을 가리 킵니다. 이러한 간접 구현 봄 정렬 된 인터페이스에서 발견된다. 이 인터페이스는 하나의 방법은 getOrder (), 본 방법이 빈의 실행 우선 순위를 나타내는 int 값을 반환한다. 클래스 위의 통합 예외 처리 구현 주석 또한 여기에 오류 메시지가이 클래스를 처리하고있다 궁금는 DefaultHandlerExceptionResolver # doResolveException 방법의 복사, 언급된다. 위의 디버거 추적, 우리가 알고있는 때 빈의 실행 DefaultHandlerExceptionResolver 인스턴스의 순서는 SpringHandlerExceptionResolver 우리의 사용자 정의를 통해 콩 우선 순위, 그래서 그 404,415은 SpringMVC 콩 가공 처리 기본 예외로 오류 메시지와 일치 할 것이다. 어떤 우리의 원래 의도와 일치하지 않습니다. 그래서 나는 조금 변형 SpringHandlerExceptionResolver뿐만 아니라 정렬 된 인터페이스를 달성하기 위해 :

 

여기 그것은 기본을 가장 높은 우선 순위를 부여, 그래서 당신은 사용자 정의 클래스의 우선 순위를 실행 할 수 있습니다. 과연, 그 결과는 내가 기대 좋아합니다.

다음은 오류 페이지를 반환 :


여기 (나는 방식 JSONP 요청을 여기에 사용되는 한) JSON 데이터를 반환 것입니다 :


이 시점에서, 전체 SpringMVC 글로벌 예외 핸들러가 완료되었습니다. 나는 데이터로 JSON 아약스 요청을 요청하기 위해 여기, 그래서 우리는했다. 실제의 경우 일 수있다.

주 : 스프링 mvc.xml에 배치되도록 기억하지 않고이 방법을 사용하면 <MVC : 기본적 서블릿 처리기 /> SpringHandlerExceptionResolver 404 오류에 영향하도록 배치되어야한다. 하는 doDispatch 방법 DispatcherServlet이 클래스에서, 우리는 코드의 라인을 찾을 수

// 현재 요청에 대한 핸들러를 결정합니다. 
mappedHandler = 및 getHandler (processedRequest);
경우 (mappedHandler ==  || mappedHandler.getHandler () == ) { 
  noHandlerFound (processedRequest 응답); 
  반환 ; 
}

url로한다 취득에 대응하는 핸들러가 존재하지 않는 경우 및 getHandler 여기서 ()는 핸들러를 검색
<기본적 서블릿 처리기 MVC /> 에서 선언
org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler이.
이 방법은 (404)의 예외를 throw하지 않습니다 noHandlerFound을 수행하지 않습니다.
주목해야 할 또 다른 점은 web.xml을 구성 파일에 DispatcherServlet을 할당에 추가 할 수 있다는 것입니다

<초기화-PARAM은> 
    <! - 경로 매핑이 발견되지 않는 경우, 예외가 아니라 404 오류 페이지의 web.xml 구성에보다 발생합니다 -> 
    <PARAM 이름> throwExceptionIfNoHandlerFound </ PARAM 이름> 
    <PARAM - 값> 에 해당하는 </ PARAM 값> 
</ 초기화-PARAM>

당신은 (404)의 경우에,이 구성을 추가하지 않는 경우, 예외를 던져,하지만 반환하지 않습니다 때문에의 404 응답 상태 
다음은 DispatcherServlet.java의 일부의 소스는 다음과 같습니다

보호  무효 noHandlerFound (HttpServletRequest의 요청, HttpServletResponse를 응답) 가 발생 예외 {
   경우 (pageNotFoundLogger.isWarnEnabled ()) { 
      pageNotFoundLogger.warn ( "[+ 대해 getRequestURI (요청) + URI와 HTTP 요청을 찾을 수 없습니다 매핑" 
              '이름의 DispatcherServlet에를 "] "+ getServletName () +" ' " ); 
  } 
  경우 ( .throwExceptionIfNoHandlerFound) {
       던져  새로운 NoHandlerFoundException (request.getMethod () 대해 getRequestURI (요청)
                 새로운 ServletServerHttpRequest (요청)를 .getHeaders ()); 
  } 
  다른 {
      response.sendError (HttpServletResponse.SC_NOT_FOUND); 
  } 
}

여기 throwExceptionIfNoHandlerFound이 false 인 경우 예외가 발생되지 않고, 볼 수 있지만 브라우저에게 404 응답 상태를 제공 할 수 있습니다. DispatcherServlet.java에서이 속성의 기본값은 false입니다.

원본 링크 : HTTPS : //blog.csdn.net/butioy_org/article/details/78718405

추천

출처www.cnblogs.com/muxi0407/p/11607708.html