技术公众号: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客户端的实现。
主要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客户端的实现。