【Spring】RestTemplate定制拦截器+ 异常处理(Exception Handle)

The RestTemplate provides a higher level API over HTTP client libraries

官方:https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#rest-resttemplate

  • RestTemplate: The original Spring REST client with a synchronous, template method API.  As of 5.0 the RestTemplate is in maintenance mode

  • WebClient: a non-blocking, reactive alternative that supports both synchronous and asynchronous as well as streaming scenarios. 后续推荐

参考:https://www.baeldung.com/rest-template    https://www.cnblogs.com/coder-qi/p/use-spring-RestTemplate.html    https://juejin.cn/post/6844903842065154061


需掌握的知识点:RestTemplate如何初始化,如何切换不同的底层实现:HttpURLConnection、HttpClient


一、如何初始化

    1)初始化RestTemplate bean  

  • 定义单独的@Configuration类,@Bean完成RestTemplate初始化(可根据情况指定不同的底层实现)         
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setReadTimeout(2000);
return new RestTemplate(simpleClientHttpRequestFactory);
}

     2)切换RestTemplate不同的底层实现

         在上述bean定义类构造方法使用java.net.HttpURLConnection初始化;可以通过构造方法初始化切换其他实现 ClientHttpRequestFactory 接口具体实现类.

    样例:RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

二、定制

1)定制拦截器 ClientHttpRequestInterceptor

  Spring提供了ClientHttpRequestInterceptor接口,可以对请求进行拦截,并在其被发送至服务端之前修改请求或是增强相应的信息

  • 定制拦截器

  

  • 把自定义的ClientHttpRequestInterceptor添加到RestTemplate,可添加多个

   

三、如何开发

URIs:Many of the RestTemplate methods accept a URI template and URI template variables, either as a String variable argument, or as Map<String,String>.

// 使用string变量
String result = restTemplate.getForObject("https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); // 使用Map<String, String> Map<String, String> vars = Collections.singletonMap("hotel", "42"); String result = restTemplate.getForObject("https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);

 URI templates将自动编码, 样例:restTemplate.getForObject("https://example.com/hotel list", String.class);   // Results in request to "https://example.com/hotel%20list"

 Headers: 使用exchanges()指定请求头

String uriTemplate = "https://example.com/hotels/{hotel}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);

RequestEntity<Void> requestEntity = RequestEntity.get(uri).header("MyRequestHeader", "MyValue").build();
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
// 响应header
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
//响应body String body
= response.getBody();

Body:Objects passed into and returned from RestTemplate methods are converted to and from raw content with the help of an HttpMessageConverter.

 

四、执行失败场景

RestTemplate执行失败抛出RestClientException异常

 

五、设置状态码&异常处理

参考:https://www.bezkoder.com/spring-boot-controlleradvice-exceptionhandler/

1、如果controller定义返回具体类型,如String、User,则状态码200

2、如果抛出restClientException,则状态码500  

 

方法1:ResponseEntity extends HttpEntity:自定义状态码

       controller方法定义:返回ResponseEntity<User> xxx,

       实现: return new  ResponseEntity.ok(user).   或      return new ResponseEntity<>(user, HttpStatus.OK);       

样例中body为String类型

@GetMapping("/test")
public ResponseEntity<String> test() {
    String url = "http://www.baidu.com";
    try {
        restTemplate.getForEntity(url, String.class);
    } catch (RestClientException e)
    {
        return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
    return ResponseEntity.ok("SUCCESS");
} 

方法2:方法上@ControllerAdvice + @ExceptionHandler + @ResponseStatus(value=HttpStatus.NOT_FOUND)

In the example above, we use @ControllerAdvice for REST web services and return ResponseEntity object additionally.

Spring also provides @ResponseBody annotation which tells a controller that the object returned is automatically serialized into JSON and passed it to the HttpResponse object. This way does not require ResponseEntity but you need to use @ResponseStatus to set the HTTP status code for that exception.

@ControllerAdvice
@ResponseBody
public class ControllerExceptionHandler {

  @ExceptionHandler(ResourceNotFoundException.class)
  @ResponseStatus(value = HttpStatus.NOT_FOUND)
  public ErrorMessage resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
    ErrorMessage message = new ErrorMessage(...);
    return message;
  }
}

  

posted @ 2021-12-21 15:22  飞翔在天  阅读(795)  评论(0编辑  收藏  举报