使用Spring RestTemplate发送HTTP请求

技术公众号: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 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 foo = new HashMap<>();
foo.put("name", "HTTP");
foo.put("age", "18");
ResponseEntity 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 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 requestEntity = RequestEntity.get(new URI("http://localhost:8080/demo/list"))
        .build();
ResponseEntity 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() {
    @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 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请求)