[英]@ExceptionHandler response not working in Tomcat
I'm working to handle exceptions with Spring MVC. 我正在努力处理Spring MVC的异常。 I'm using @ControllerAdvice and @ExceptionHandler. 我正在使用@ControllerAdvice和@ExceptionHandler。 In order to return a JSON I tried both cases: @ResponseBody and ResponseEntity. 为了返回JSON,我尝试了两种情况:@ResponseBody和ResponseEntity。
Here is my Controller: 这是我的控制器:
@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;}
}
I'm using the tomcat 7 plugin for maven to run and debug the app, so when I debug I can see that the @ExceptionHandler is firing and executing the return statement. 我正在使用tomcat 7插件来运行和调试该应用程序,因此在调试时,我可以看到@ExceptionHandler正在触发并执行return语句。 But instead of receiving a JSON what I'm getting is an HTTP 500 error: 但是我没有收到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)
If I return a view or a ModelView is working, but whenever I try to return a ResponseBody or ResponseEntity, I'm still getting the same error. 如果我返回视图或ModelView在工作,但是每当我尝试返回ResponseBody或ResponseEntity时,我仍然会遇到相同的错误。
Finally, if instead of using tomcat, I use SpringBoot to run the app, I'm not getting the error and I'm response as I supposed to receive: 最后,如果我不是使用tomcat,而是使用SpringBoot运行该应用程序,那么我不会收到错误,并且应该收到以下信息:
{"error":"E888"}
Why is not working with Tomcat? 为什么不使用Tomcat?
Thanks. 谢谢。
The reason is the way Spring handle the exception. 原因是Spring处理异常的方式。 In plain Spring application without Boot @ExceptionHandler
is used by exceptionResolver and it works for browser user or in other words it is thinked for render page when an exception arrives. 在没有Boot @ExceptionHandler
普通Spring应用程序中,exceptionResolver使用它,它适用于浏览器用户,换句话说,当异常到达时,它被认为是呈现页面。 The flow of the your request don't pass through the contenNegotiationResolver and for this reason you continue to get the exception. 您的请求流不会通过contenNegotiationResolver,因此您将继续获取异常。 In Spring boot the fow of the life-cycle of the request was thinked for manage exception for browser user and not-browser-user like application, and for this reason it works, I can suggest of refers to the official documentation for more details. 在Spring Boot中,认为请求生命周期的流是针对浏览器用户和非浏览器用户之类的应用程序的管理异常,因此,它可以正常工作,我建议您参考官方文档以获取更多详细信息。
Update for to answer at a comment. 更新以在评论中回答。
In Spring boot you manage the exception in very different way respect plain spring mvc application for many details i suggest to se the documentation at link spring boot doc . 在Spring Boot中,您可以通过普通Spring MVC应用程序以非常不同的方式管理异常,以获取许多详细信息,我建议您在link spring boot doc中获取文档 。 If you want use a plain spring web application I can suggest to use an aspect. 如果您想使用普通的Spring Web应用程序,我建议您使用一个方面。 You could use the plain @ExceptionHandler
usage and return a ModelView implementation in answer for the plain page request in @Controller
Class without @ResponseBody
and create an aspect with a that manage the exception for method annotated with @ResponseBody and that returned ResponseEntity. 您可以使用普通的@ExceptionHandler
用法,并在没有@ResponseBody
的情况下为@Controller
类中的普通页面请求返回@ExceptionHandler
实现,并创建一个方面来管理@ResponseBody注释的方法和返回的ResponseEntity的异常。 Thew aspect could be a think like below, note that in this sample I developed the poincut expression for intercept the methods that return an ResponseEntity under com.springapp.mvc package: 这可能是下面的想法,请注意,在此示例中,我开发了poincut表达式来拦截在com.springapp.mvc包下返回ResponseEntity的方法:
Aspect: 方面:
@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;
}
}
don't forgot of insert in your configuration 不要忘记在配置中插入
xml style: xml样式:
<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>
Java style: Java风格:
@Configuration
@EnableAspectJAutoProxy
...
class AspectConfiguration{
...
}
controller: 控制器:
@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");
}
}
I hope that it can help you 希望对您有所帮助
@ExceptionHandler
method doesn't have a @ResponseBody
return type it can only return a ModelView
or a String
which is translated to a view @ExceptionHandler
方法不具有@ResponseBody
返回类型它只能返回一个ModelView
或一个String
被转换为一个视图
The return type can be a String, which is interpreted as a view name or a ModelAndView object. 返回类型可以是String,它被解释为视图名称或ModelAndView对象。
see here for more information: Spring @ExceptionHandler does not work with @ResponseBody 查看更多信息: Spring @ExceptionHandler不适用于@ResponseBody
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.