美文网首页springbootJava In Mind
使用Spring RestTemplate发送HTTP请求

使用Spring RestTemplate发送HTTP请求

作者: SevenLin1993 | 来源:发表于2019-11-19 00:11 被阅读0次

    技术公众号:Java In Mind(Java_In_Mind),欢迎关注!

    Spring RestTemplate

    RestTemplate是Spring用来进行HTTP访问的HTTP客户端,它遵循RESTful规范,并且简化了与HTTP服务端的通信,RestTemplate的底层默认使用JDK自带的HttpURLConnection实现,不过它也提供了自定义入口,可以通过HttpAccessor.setRequestFactory设置HTTP能力的提供方,可以是Apache HttpComponents或者是Netty或者是OkHttp等其他HTTP客户端的实现。

    image.png

    主要API

    RestTemplate的API主要以HTTP的请求方式来命名:

    DELETE
    • delete,删除URL指向的资源
    GET
    • getForObject,获取资源,并且把Response的内容封装成对应的对象实例
    • getForEntity,获取资源,并且把Response封装成ResponseEntity
    HEAD
    • headForHeaders,获取URI指向的资源的所有Header信息
    OPTIONS
    • optionsForAllow,获取支持的HTTP请求方式
    POST
    • postForLocation,创建资源,并且返回该资源的地址
    • postForObject,创建资源,并且把Response的内容封装成对象实例
    PUT
    • put,修改UTI指向的资源
    any
    • exchange,执行Http请求,通过RequestEntity,RequestEntity支持Builder模式
    • execute,执行Http请求,支持使用RequestCallback进行在请求前回调,并且支持通过ResponseExtractor解析Response

    了解完简单使用一下

    内置包装器

    • ByteArrayHttpMessageConverter
    • StringHttpMessageConverter
    • ResourceHttpMessageConverter
    • SourceHttpMessageConverter
    • AllEncompassingFormHttpMessageConverter
    • AtomFeedHttpMessageConverter
    • RssChannelHttpMessageConverter
    • MappingJackson2XmlHttpMessageConverter
    • Jaxb2RootElementHttpMessageConverter
    • MappingJackson2HttpMessageConverter
    • GsonHttpMessageConverter
    • JsonbHttpMessageConverter

    模拟服务

    @RestController
    @RequestMapping("/demo")
    @SpringBootApplication
    @Slf4j
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        private List<Foo> foos = new CopyOnWriteArrayList<>();
    
        @GetMapping("/list")
        public ResponseEntity list(@RequestParam(value = "name", required = false) String name) {
            log.info("accept a list request...");
            boolean emptyQuery = StringUtils.isEmpty(name);
            return ResponseEntity
                .ok(foos.stream().filter(i -> emptyQuery || i.getName().equals(name)).collect(Collectors.toList()));
        }
    
        @PostMapping
        public ResponseEntity create(@RequestBody Foo foo) {
            log.info("accept create request,foo:{}", foo);
            // uuid
            foo.setId(UUID.randomUUID().toString());
            // add
            foos.add(foo);
            return ResponseEntity.ok(foo);
        }
    
        @GetMapping("/error")
        public ResponseEntity error() {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("error");
        }
    
        @Data
        @AllArgsConstructor
        public static class Foo {
            private String id;
            private String name;
            private int age;
        }
    }
    

    发起POST请求

    //create RestTemplate
    String baseUrl = "http://localhost:8080";
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setUriTemplateHandler(factory);
    
    //request body
    Map<String, String> foo = new HashMap<>();
    foo.put("name", "HTTP");
    foo.put("age", "18");
    ResponseEntity<String> responseEntity = restTemplate.postForEntity("/demo", foo, String.class);
    
    //parse response
    if(responseEntity.getStatusCode().is2xxSuccessful()){
        log.info("success:{}",responseEntity.getBody());
    }else{
        log.error("error,statusCode:{},return:{}",responseEntity.getStatusCode().value(),responseEntity.getBody());
    }
    

    发起GET请求

    // create RestTemplate
    String baseUrl = "http://localhost:8080";
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setUriTemplateHandler(factory);
    
    // build uri and request
    String uri = UriComponentsBuilder.fromPath("/demo/list").queryParam("name", "HTTP").toUriString();
    ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
    
    // parse response
    if (responseEntity.getStatusCode().is2xxSuccessful()) {
        log.info("success:{}", responseEntity.getBody());
    } else {
        log.error("error,statusCode:{},return:{}", responseEntity.getStatusCode().value(),
            responseEntity.getBody());
    }
    

    使用exchange

    // create RestTemplate
    RestTemplate restTemplate = new RestTemplate();
    RequestEntity<Void> requestEntity = RequestEntity.get(new URI("http://localhost:8080/demo/list"))
            .build();
    ResponseEntity<String> responseEntity =
            restTemplate.exchange(requestEntity, String.class);
    // parse response
    if (responseEntity.getStatusCode().is2xxSuccessful()) {
        log.info("success:{}", responseEntity.getBody());
    } else {
        log.error("error,statusCode:{},return:{}", responseEntity.getStatusCode().value(),
                responseEntity.getBody());
    }
    

    使用execute

    // create RestTemplate
    RestTemplate restTemplate = new RestTemplate();
    String result = restTemplate.execute("http://localhost:8080/demo/list", HttpMethod.GET, new RequestCallback() {
        @Override
        public void doWithRequest(ClientHttpRequest request) throws IOException {
            // 修改Header
            request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        }
    }, new ResponseExtractor<String>() {
        @Override
        public String extractData(ClientHttpResponse response) throws IOException {
            // 解析結果
            return IOUtils.toString(response.getBody(), StandardCharsets.UTF_8);
        }
    });
    log.info("result:{}", result);
    

    错误处理

    RestTemplate支持自定义错误处理,可以继承默认DefaultResponseErrorHandler,也可以实现接口ResponseErrorHandler,然后通过restTemplate.setErrorHandler()配置

    // 构建RestTemplate
    RestTemplate restTemplate = new RestTemplate();
    try {
        ResponseEntity<String> responseEntity =
            restTemplate.getForEntity("http://localhost:8080/demo/error", String.class);
        // parse response
        if (responseEntity.getStatusCode().is2xxSuccessful()) {
            log.info("success:{}", responseEntity.getBody());
        } else {
            log.error("error,statusCode:{},return:{}", responseEntity.getStatusCode().value(),
                responseEntity.getBody());
        }
    } catch (HttpStatusCodeException e) {
        log.error("error,statusCode={},body={}", e.getStatusCode(), e.getResponseBodyAsString(), e);
    }
    

    常用设置

    • 超时设置

      // timeout config
      SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
      httpRequestFactory.setConnectTimeout(1000*5);
      httpRequestFactory.setReadTimeout(1000*10);
      // create RestTemplate
      RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
      
    • 切换HTTP实现为HttpComponents

      //使用HttpComponents
      HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
      httpRequestFactory.setConnectTimeout(1000*5);
      httpRequestFactory.setReadTimeout(1000*10);
      //构建RestTemplate
      RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
      
    • 设置baseUrl

      String baseUrl = "http://localhost:8080";
      DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
      factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);
      RestTemplate restTemplate = new RestTemplate();
      restTemplate.setUriTemplateHandler(factory);
      

    总结

    RestTemplate是Spring提供的方便HTTP请求的类,API封装也更加上层,使用起来也比较方便,并且支持对Response的多种格式的解析,支持错误处理等功能,并且提供比较灵活的底层支持,方便使用者自己选择需要的HTTP客户端的实现。

    相关文章

      网友评论

        本文标题:使用Spring RestTemplate发送HTTP请求

        本文链接:https://www.haomeiwen.com/subject/bfviictx.html