簡體   English   中英

Spring MVC,將@ExceptionHandler遷移到HandlerExceptionResolver以獲取RESTful服務

[英]Spring MVC, Migrate @ExceptionHandler to HandlerExceptionResolver for a RESTful service

背景

我有一個錯誤消息類:

@XmlRootElement
public class ErrorMessage {
    private String message;

    public ErrorMessage() {
    }

    public ErrorMessage(String message) {
        this.message = message;
    }

    public String getError() {
        return message;
    }

    public void setError(String message) {
        this.message = message;
    }
}


此類已被指定為Spring MVC REST控制器中@ExceptionHandler的返回值:

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
ErrorMessage handleException(RuntimeException e) {
    return new ErrorMessage("something went wrong");
}

每當客戶端在使用application/json作為Acceptapplication/json出請求后觸發RuntimeException ,它就會收到一個響應,其中包含正確的狀態代碼和匹配的JSON正文:

{"error":"something went wrong"}

或者,如果Accept標頭是application/xml則接收XML主體:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<errorMessage><error>something went wrong</error></errorMessage>


問題

現在,我想通過實現一個HandlerExceptionResolver來使這個解決方案變成一般,所以我不必將@ExceptionHandler復制/粘貼到每個控制器(或者創建一個其他控制器可以擴展的公共“父控制器”)。

但是, AbstractHandlerExceptionResolver.doResolveException()方法返回ModelAndView而不是我的專有ErrorMessage ,所以我嘗試了以下內容:

public class RuntimeExceptionHandlerExceptionResolver extends AbstractHandlerExceptionResolver {

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        if (ex instanceof RuntimeException) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            ModelAndView mav = new ModelAndView();
            mav.addObject("error", "something went wrong");
            return mav;
        }
        return null;
    }
}

調試時,我可以看到調用了mav.addObject()方法。 客戶端的響應具有預期的狀態代碼,但內容類型是text/html帶有html的text/html ,而不是原始請求中的Accept標頭指定的JSON或XLM內容。

(旁注,上面示例中的實際異常,響應代碼和文本消息並不重要,它們只是用作簡單示例。)

Spring版本:3.1.1.RELEASE

要使@ExceptionHandler使用內容協商, AnnotationMethodHandlerExceptionResolver有一個setMessageConverters()方法,必須與消息轉換器一起提供,例如:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
    <property name="messageConverters">
        <list>
            <ref bean="xmlConverter"/>
            <ref bean="jsonConverter"/>
        </list>
    </property>
</bean>

但由於您使用的是自定義方法,因此您可能必須自己實現此功能。 最簡單的方法可能是來自AnnotationMethodHandlerExceptionResolver源的 Ctrl-C Ctrl-V ,特別是handleResponseBody()方法。

我花了一些時間調查此事,我寫了一篇博文 ,其中我提出了解決問題的方法。

更新:如果您使用的是Spring 3.2,則可以利用@ControllerAdvice批注。 更多細節可以在我的第二篇博文中找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM