Bootstrap

restTemplate请求 捕获异常处理

背景:某接口需要Oath2认证,需要获取对应token信息,由于该接口请求使用 x-www-form-urlencoded 经过尝试,使用hutool的方法均不能满足上述需求,转而使用restTemplate来做http请求。但是又碰到了 在请求返回异常时直接抛出,而不是正常打印相关信息,因此需要做异常处理,代码逻辑如下。

 String pelecnTokenEndpoint="xxx";
        String ClientId = "xxx";
        String ClientSecret = "xxx";
        String scope = "xxx";
        String token = null;
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-type","application/x-www-form-urlencoded");
        MultiValueMap<String,Object> formMap = new LinkedMultiValueMap<>();
        formMap.add("grant_type","client_credentials");
        formMap.add("client_id",pelecnClientId);
        formMap.add("client_secret",pelecnClientSecret);
        formMap.add("scope",scope);
        String content = JSONUtil.toJsonStr(formMap);
        RestTemplate restTemplate = new RestTemplate();
        //todo:关键配置
        restTemplate.setErrorHandler(new RestTemplateErrorHandler());
        HttpEntity<MultiValueMap> doneEntity = new HttpEntity<>(formMap,headers);
        //String body = restTemplate.postForObject(pelecnTokenEndpoint, doneEntity, String.class);
        ResponseEntity<PanasonicResponseTO> stringResponseEntity = restTemplate.postForEntity(pelecnTokenEndpoint, doneEntity, PanasonicResponseTO.class);
        log.info("[接口]响应:[{}]",JSONObject.toJSONString(stringResponseEntity));
        cn.hutool.json.JSONObject tokenResponse = JSONUtil.parseObj(stringResponseEntity);
        if(!StringUtil.isEmpty(stringResponseEntity.getBody().getAccess_token())){
            token = stringResponseEntity.getBody().getAccess_token();
            log.info("access_token:{}",token);
        }else {
            log.info("token请求返回状态信息:{},statusCodeValue:{},消息体:{}",stringResponseEntity.getStatusCode(),stringResponseEntity.getStatusCodeValue(),stringResponseEntity.getBody().getError());
        }

这里的关键点是restTemplate.setErrorHandler(new RestTemplateErrorHandler())

下面,看一下如果没有做处理前的情况:

这里直接抛出了异常,而不是将异常信息返回,需要看一下为什么会产生这个东西?

在做restTemplate.postForEntity() 这里有execute

这里会走到 doExecute

在走进doExecute时,会走进handleResponse

然后,处理响应,看handleError方法

这个handlerError实现了defaultResponseErrorHandler

最终,在返回时根据handleError处理

所以这里是直接捕获异常出来,而不是打印相关信息。

处理方法

如果想要自己捕获异常信息,自己处理异常可以通过实现ResponseErrorHandler类来实现,

public interface ResponseErrorHandler {

    // 标示 Response 是否存在任何错误。实现类通常会检查 Response 的 HttpStatus。
    boolean hasError(ClientHttpResponse var1) throws IOException;

    // 处理 Response 中的错误, 当 HasError 返回 true 时才调用此方法。
    void handleError(ClientHttpResponse var1) throws IOException;

    // handleError 的替代方案,提供访问请求URL和HTTP方法的额外信息。
    default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
        this.handleError(response);
    }
}

如果想要按照自己想要的打印信息来返回,即类似HttpClient从Response中获取HttpStatus和body中的报错信息,而不是抛出异常,可以使用自己的Handler处理,可以使用以下实现

@Component
public class RestTemplateErrorHandler implements ResponseErrorHandler {
    @Override
    public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
        return true;
    }

    @Override
    public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {

    }
}

这里hasError直接正常范湖,就可以不做异常抛出了。

;