Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring Rest模板自定义异常处理_Spring_Spring Mvc - Fatal编程技术网

Spring Rest模板自定义异常处理

Spring Rest模板自定义异常处理,spring,spring-mvc,Spring,Spring Mvc,我正在使用来自外部API的一些REST端点,为此我正在使用REST模板接口。当我从这些调用中收到某些HTTP状态代码时,我希望能够抛出自定义应用程序异常。为了实现它,我正在实现ResponseErrorHandler接口,如下所示: public class MyCustomResponseErrorHandler implements ResponseErrorHandler { private ResponseErrorHandler myErrorHandler = new De

我正在使用来自外部API的一些REST端点,为此我正在使用REST模板接口。当我从这些调用中收到某些HTTP状态代码时,我希望能够抛出自定义应用程序异常。为了实现它,我正在实现ResponseErrorHandler接口,如下所示:

public class MyCustomResponseErrorHandler implements ResponseErrorHandler {

    private ResponseErrorHandler myErrorHandler = new DefaultResponseErrorHandler();

    public boolean hasError(ClientHttpResponse response) throws IOException {
        return myErrorHandler.hasError(response);
    }

    public void handleError(ClientHttpResponse response) throws IOException {
        String body = IOUtils.toString(response.getBody());
        MyCustomException exception = new MyCustomException(response.getStatusCode(), body, body);
        throw exception;
    }

}

public class MyCustomException extends IOException {

    private HttpStatus statusCode;

    private String body;

    public MyCustomException(String msg) {
        super(msg);
        // TODO Auto-generated constructor stub
    }

    public MyCustomException(HttpStatus statusCode, String body, String msg) {
        super(msg);
        this.statusCode = statusCode;
        this.body = body;
    }

    public HttpStatus getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(HttpStatus statusCode) {
        this.statusCode = statusCode;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

}
最后,这是客户端代码(不相关的代码省略):

public LoginResponse-doLogin(字符串电子邮件、字符串密码){
HttpEntity requestEntity=新的HttpEntity(电子邮件、密码);
试一试{
ResponseEntity ResponseEntity=restTemplate.exchange(myBaseURL+“/user/account/”+email、HttpMethod.GET、requestEntity、LoginResponse.class);
返回responseEntity.getBody();
}捕获(例外e){
//自定义错误处理程序正在运行,这里我们应该接收一个MyCustomException
if(MyCustomException的实例){
MyCustomException异常=(MyCustomException)e;
info(“调用api/user/account api端点时出错:”+e.getMessage());
}否则{
info(“尝试解析登录响应JSON对象时出错”);
}
}
返回null;
}
我的应用程序上下文:

<?xml version="1.0" encoding="UTF-8"?>
<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:mvc="http://www.springframework.org/schema/mvc" xmlns:spring="http://camel.apache.org/schema/spring"
    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-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

    <!-- Rest template (used in bridge communication) -->
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <property name="errorHandler" ref="myCustomResponseErrorHandler"></property>
    </bean>

    <!-- Bridge service -->
    <bean id="myBridgeService" class="a.b.c.d.service.impl.MyBridgeServiceImpl"/>

    <!-- Bridge error handler -->
    <bean id="myCustomResponseErrorHandler" class="a.b.c.d.service.handlers.MyCustomResponseErrorHandler"/>

</beans>

我怀疑我没有正确理解此自定义错误处理的行为。每个rest模板方法都可能抛出一个RestClientException,它遵循异常层次结构,是RuntimeException的子类,而不是IOException,它是在自定义响应错误处理程序中抛出的,即:我无法在rest模板方法调用中捕获自定义异常

关于我如何捕捉这些异常的任何线索?是高度相关的,但从我的角度来看,经历了相同的问题,尽管它是作为解决方案提出的


[1] :

您已将自定义的
异常
IOException

public class MyCustomException extends IOException {
ResponseErrorHandler#handleError()
方法从
RestTemplate#HandlerResponseError(..)
调用,该方法由
RestTemplate#doExecute(..)
调用。此根调用被包装在一个
try catch
块中,该块捕获
IOException
,并将其重新包装在
ResourceAccessException
中,后者是一个
RestClientException

一种可能是捕获
RestClientException
并获取其
原因


另一种可能是将自定义的
异常
作为
运行时异常
的子类型

如果使用springmvc,则可以使用annotation
@ControllerAdvice
创建控制器。在控制器中写入:

@ExceptionHandler(HttpClientErrorException.class)
public String handleXXException(HttpClientErrorException e) {
    log.error("log HttpClientErrorException: ", e);
    return "HttpClientErrorException_message";
}

@ExceptionHandler(HttpServerErrorException.class)
public String handleXXException(HttpServerErrorException e) {
    log.error("log HttpServerErrorException: ", e);
    return "HttpServerErrorException_message";
}
...
// catch unknown error
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
    log.error("log unknown error", e);
    return "unknown_error_message";
}
DefaultResponseErrorHandler
抛出这两种异常:

@Override
public void handleError(ClientHttpResponse response) throws IOException {
    HttpStatus statusCode = getHttpStatusCode(response);
    switch (statusCode.series()) {
        case CLIENT_ERROR:
            throw new HttpClientErrorException(statusCode, response.getStatusText(),
                    response.getHeaders(), getResponseBody(response), getCharset(response));
        case SERVER_ERROR:
            throw new HttpServerErrorException(statusCode, response.getStatusText(),
                    response.getHeaders(), getResponseBody(response), getCharset(response));
        default:
            throw new RestClientException("Unknown status code [" + statusCode + "]");
    }
}

您可以使用:
e.getResponseBodyAsString()
e.getStatusCode()blabla以在异常发生时获取响应消息。

这里的最佳方法是什么?如果我的异常必须继承自异常,那么每次使用时我都必须在RestClientException中获取异常RestTemplate@Zarathustra我认为你不能有另一种类型的检查异常
handleError
仅声明为抛出
IOException
。除非您讨论的是其他组件,否则只有这两个选项,
IOException
或未检查的异常。您可以访问下面的线程。它有完整的工作代码和说明:
@Override
public void handleError(ClientHttpResponse response) throws IOException {
    HttpStatus statusCode = getHttpStatusCode(response);
    switch (statusCode.series()) {
        case CLIENT_ERROR:
            throw new HttpClientErrorException(statusCode, response.getStatusText(),
                    response.getHeaders(), getResponseBody(response), getCharset(response));
        case SERVER_ERROR:
            throw new HttpServerErrorException(statusCode, response.getStatusText(),
                    response.getHeaders(), getResponseBody(response), getCharset(response));
        default:
            throw new RestClientException("Unknown status code [" + statusCode + "]");
    }
}