2016-06-02 2 views
0

Spring MVC로 예외를 처리하기 위해 노력하고 있습니다. @ControllerAdvice 및 @ExceptionHandler를 사용하고 있습니다. JSON을 반환하기 위해 @ResponseBody 및 ResponseEntity 두 가지 경우를 시도했습니다. 여기 Tomcat에서 @ExceptionHandler 응답이 작동하지 않습니다.

내 컨트롤러입니다 : 내가 디버깅 할 때

@ControllerAdvice 
public class GlobalExceptionController { 

@ExceptionHandler(CustomGenericException.class) 
@ResponseBody 
public ErrorResource handleCustomException(CustomGenericException ex) { 

     ErrorResource errorResource=new ErrorResource("Example 1"); 
    errorResource.error=ex.getErrCode(); 

    return errorResource; 

} 

@ExceptionHandler(Exception.class) 
public ResponseEntity<ErrorResource> handleAllException(Exception ex) { 

    ErrorResource errorResource=new ErrorResource("Example 2"); 
    errorResource.error=ex.getMessage(); 

    return new ResponseEntity<ErrorResource>(errorResource,HttpStatus.NOT_FOUND); 

} 

} 
class ErrorResource { 
public String error; 

public ErrorResource(String a){error=a;} 
} 

내가 받는다는 실행하는 데 바람둥이 7 플러그인을 사용하여 응용 프로그램을 디버깅하고있어, 그래서 @ExceptionHandler이 발사 및 반환을 실행하는 것을 볼 수있다 성명서. 그러나 대신 JSON을받은 것을 내가 갖는 것은 HTTP 500 오류입니다 :

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.mkyong.web.exception.CustomGenericException 
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:979) 
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 

나는 모델 뷰가 작동 뷰 또는 반환,하지만 난위한 responseBody 또는 ResponseEntity을 반환하려고 할 때마다, 나는 아직도 해요 경우 동일한 오류가 발생합니다.

마지막으로, 대신에 Tomcat을 사용하는, 내가 응용 프로그램을 실행하는 데 SpringBoot를 사용하는 경우, 내가 오류를받지 못했습니다 내가 응답 해요 내가받을 생각으로 왜 작동하지 않습니다

{"error":"E888"} 

수코양이?

감사합니다.

+0

동작은 완전히 서블릿 내에 있기 때문에 Tomcat에 전혀 문제가되지 않습니다. – Raedwald

답변

0

이유는 Spring이 예외를 처리하는 방식입니다. 부트가없는 일반 Spring 어플리케이션에서는 @ExceptionHandler이 exceptionResolver에 의해 사용되며 브라우저 사용자에게 해당됩니다. 즉, 예외가 도착하면 렌더 페이지에 대해 생각됩니다. 요청의 흐름이 contenNegotiationResolver를 통과하지 못하므로 예외가 계속 발생합니다. 스프링 부트에서는 요청의 라이프 사이클 중 fow가 브라우저 사용자와 브라우저 사용자가 아닌 응용 프로그램과 같은 예외를 관리하는 것으로 생각되어 왔고 이러한 이유로 작동합니다. 자세한 내용은 공식 문서를 참조하십시오.

의견에 대한 답변.

봄 부팅시 많은 세부 사항에 대한 일반 스프링 mvc 응용 프로그램을 매우 다른 방식으로 예외 관리합니다. 링크 spring boot doc의 설명서를 참조하십시오. 일반 스프링 웹 응용 프로그램을 사용하려면 한 가지 측면을 사용할 것을 제안 할 수 있습니다. 일반 @ExceptionHandler 사용법을 사용하고 이없는 @Controller 클래스의 일반 페이지 요청에 대한 응답으로 ModelView 구현을 반환하고 @ResponseBody로 주석을 추가하고 ResponseEntity를 반환하는 메서드에 대한 예외를 관리하는 애스 팩트를 만들 수 있습니다. Thew aspect는 아래와 같이 생각할 수 있습니다.이 샘플에서 com.springapp 아래에 ResponseEntity를 반환하는 메소드를 가로 채기위한 poincut 표현식을 개발했습니다.MVC 패키지 :

측면 :

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 

    <aop:aspectj-autoproxy/> 

    <context:component-scan base-package="com.springapp.mvc"/> 

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/WEB-INF/pages/"/> 
     <property name="suffix" value=".jsp"/> 
    </bean> 

... 
</beans>  

자바 스타일 :

@Configuration 
@EnableAspectJAutoProxy 
... 
class AspectConfiguration{ 
... 
} 

컨트롤러

가 구성

XML 스타일 인서트 잊었하지 않는

@Aspect 
@Component 
public class GlobalExceptionRestAOPController { 


    private ObjectMapper objectMapper = new ObjectMapper(); 

    @Around("execution(org.springframework.http.ResponseEntity com.springapp.mvc..*(..))") 
    public Object manageException(ProceedingJoinPoint pjp) throws Throwable{ 
     Object result; 
     try{ 
      result = pjp.proceed(); 
     } catch (Exception e){ 
      // log it. 
         result = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON).body(objectMapper.writeValueAsString(new ExceptionReport(e.toString()))); 

     } 

     return result; 
    } 
} 

class ExceptionReport{ 
    private final String error; 

    public ExceptionReport(String error) { 
     this.error = error; 
    } 

    public String getError() { 
     return error; 
    } 
} 
:

@Controller 
public class HelloController { 


    @RequestMapping(value = "/jsonHelloEx", method = RequestMethod.GET, produces = "application/json") 
    public ResponseEntity printWelcomeWithException() { 
     String nullableString = null; 
     nullableString.equals(""); 
     return ResponseEntity.ok("Hello"); 
    } 
} 

나는 그것이 @ResponseBody 반환에만 반환 할 수 있습니다 입력하면

+0

그래서 예외를 처리하고 싶다면 앱에서 스프링 부트를 구현하고 거기에서 실행해야합니다. 유일한 옵션입니까? – rcentellesc

+0

나는 나의 answare를 당신의 문제의 해결책을 찾을 수 있도록 도울 수있는 예제로 업데이트한다. –

+0

당신의 도움에 감사드립니다. 실제로, 나는 약간의 문서를 읽고 있었고 나는 스프링 부트로 나의 애플리케이션을 마이그레이션했다. 모든 것에 감사드립니다. 나는 너에게 대답을했다. – rcentellesc

0

@ExceptionHandler 방법은없는 도움이 될 수 있다는 희망 ModelView 또는 뷰

The return type can be a String, which is interpreted as a view name or a ModelAndView object.

로 번역 된 String 자세한 내용은 여기를 참조하십시오. Spring @ExceptionHandler does not work with @ResponseBody

+1

이것은 스프링의 후방 버전에서 변경되었습니다. [link] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html)를 참조하십시오. – rcentellesc

관련 문제