Spring @ExceptionHandler不能与@ResponseBody一起使用

Sve*_*ges 26 rest spring-mvc

我尝试为休息控制器配置一个spring异常处理程序,该处理程序能够根据传入的accept头将映射呈现给xml和json.它现在抛出500个servlet异常.

这工作,它拿起home.jsp:

@ExceptionHandler(IllegalArgumentException.class)
public String handleException(final Exception e, final HttpServletRequest request, Writer writer)
{
    return "home";
}
Run Code Online (Sandbox Code Playgroud)

这不起作用:

@ExceptionHandler(IllegalArgumentException.class)
public @ResponseBody Map<String, Object> handleException(final Exception e, final HttpServletRequest request, Writer writer)
{
    final Map<String, Object> map = new HashMap<String, Object>();
    map.put("errorCode", 1234);
    map.put("errorMessage", "Some error message");
    return map;
}
Run Code Online (Sandbox Code Playgroud)

在同一控制器中,通过相应的转换器将响应映射到xml或json:

@RequestMapping(method = RequestMethod.GET, value = "/book/{id}", headers = "Accept=application/json,application/xml")
public @ResponseBody
Book getBook(@PathVariable final String id)
{
    logger.warn("id=" + id);
    return new Book("12345", new Date(), "Sven Haiges");
}
Run Code Online (Sandbox Code Playgroud)

任何人?

thr*_*ups 22

你的方法

@ExceptionHandler(IllegalArgumentException.class)
public @ResponseBody Map<String, Object> handleException(final Exception e, final HttpServletRequest request, Writer writer)
Run Code Online (Sandbox Code Playgroud)

不起作用,因为它有错误的返回类型.@ExceptionHandler方法只有两个有效的返回类型:

  • ModelAndView中.

有关更多信息,请参阅http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html.这是链接中的特定文本:

返回类型可以是String,它被解释为视图名称或ModelAndView对象.

回应评论

Thanx,我似乎对此过度了解.这很糟糕......任何想法如何以xml/json格式自动提供异常? - Sven Haiges 7小时前

这就是我所做的(我实际上是在Scala中完成的,所以我不确定语法是否完全正确,但你应该得到要点).

@ExceptionHandler(Throwable.class)
@ResponseBody
public void handleException(final Exception e, final HttpServletRequest request,
        Writer writer)
{
    writer.write(String.format(
            "{\"error\":{\"java.class\":\"%s\", \"message\":\"%s\"}}",
            e.getClass(), e.getMessage()));
}
Run Code Online (Sandbox Code Playgroud)

  • 您好,只是为了评论@ExceptionHandler方法的返回类型非常广泛.根据文档,它可以是ModelAndView,Model对象,java.util.Map,org.springframework.web.servlet.View,String或void (2认同)

小智 13

Thanx,我似乎对此过度了解.这很糟糕......任何想法如何以xml/json格式自动提供异常?

Spring 3.0中的新功能可以利用MappingJacksonJsonView来实现:

private MappingJacksonJsonView  jsonView = new MappingJacksonJsonView();

@ExceptionHandler(Exception.class)
public ModelAndView handleAnyException( Exception ex )
{
    return new ModelAndView( jsonView, "error", new ErrorMessage( ex ) );
}
Run Code Online (Sandbox Code Playgroud)

  • @borjab不是因为它是一种无效的方法,只是因为它们正在推动迁移到[MappingJackson2JsonView](http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/网/ servlet的/视图/ JSON/MappingJackson2JsonView.html) (3认同)

Era*_*dan 10

这似乎是一个确认的错误(SPR-6902 @ResponseBody不能与@ExceptionHandler一起使用)

https://jira.springsource.org/browse/SPR-6902

固定在3.1 M1虽然......


ast*_*ere 6

如果您使用消息转换器将错误对象编组为响应内容,则以下可能是一种解决方法

@ExceptionHandler(IllegalArgumentException.class)
public String handleException(final Exception e, final HttpServletRequest request)
{
    final Map<String, Object> map = new HashMap<String, Object>();
    map.put("errorCode", 1234);
    map.put("errorMessage", "Some error message");
    request.setAttribute("error", map);
    return "forward:/book/errors"; //forward to url for generic errors
}

//set the response status and return the error object to be marshalled
@SuppressWarnings("unchecked")
@RequestMapping(value = {"/book/errors"}, method = {RequestMethod.POST, RequestMethod.GET})
public @ResponseBody Map<String, Object> showError(HttpServletRequest request, HttpServletResponse response){

    Map<String, Object> map = new HashMap<String, Object>();
    if(request.getAttribute("error") != null)
        map = (Map<String, Object>) request.getAttribute("error");

    response.setStatus(Integer.parseInt(map.get("errorCode").toString()));

    return map;
}
Run Code Online (Sandbox Code Playgroud)


rya*_*694 6

我使用的是Spring 3.2.4.我解决这个问题的方法是确保我从异常处理程序返回的对象有getter.

没有getter,Jackson无法将对象序列化为JSON.

在我的代码中,对于以下ExceptionHandler:

@ExceptionHandler(RuntimeException.class)
@ResponseBody
public List<ErrorInfo> exceptionHandler(Exception exception){
    return ((ConversionException) exception).getErrorInfos();
}
Run Code Online (Sandbox Code Playgroud)

我需要确保我的ErrorInfo对象有getter:

package com.pelletier.valuelist.exception;

public class ErrorInfo {
private int code;
private String field;
private RuntimeException exception;

public ErrorInfo(){}

public ErrorInfo(int code, String field, RuntimeException exception){
    this.code = code;
    this.field = field;
    this.exception = exception;
}

public int getCode() {
    return code;
}

public String getField() {
    return field;
}

public String getException() {
    return exception.getMessage();
}
}
Run Code Online (Sandbox Code Playgroud)