现在对于调用外部http接口的包已经有很多了,比如 Java 原生的 HttpURLConnection,Apache的 HttpClient,Spring的 RestTemplate 以及 WebClient ,Square 的 OkHttp 以及Netflix 的 Feign,从简单到高级功能可以说是应有尽有
不过对于内部都是RPC进行交互的服务,只有一些简单的场景需要调用 HTTP 接口,考虑项目如果为为spring的项目,可以考虑直接使用 RestTemplate
这里以之前写的费用分摊系统 为例,展示一下使用 GET 和 POST 请求的方式
GET方法 首先看下GET请求的查询项目列表接口,先看一下接口
现在开始写编写代码,首先根据返回结构定义好返回类型信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Data public class Resp <T> { private Integer status; private String errCode; private String msg; private T data; } @Data public class PageData <T> { private Integer total; private List<T> items; } @Data public class ProjectData { private Long projectId; private String projectName; private String projectDesc; } @EqualsAndHashCode(callSuper = true) @Data public static class ProjectPageResp extends Resp <PageData<ProjectData>> {}
现在可以使用 RestTemplate 发起请求,其相关的API定义如下
主要有 getForObject 和 getForEntity 两类,之间的区别就是 getForObject 只能获取返回的body部分,而 getForEntity 可以同时获取到对应的状态码、响应header信息
1 2 3 4 5 6 7 8 public <T> T getForObject (String url, Class<T> responseType, Object... uriVariables) ;public <T> T getForObject (String url, Class<T> responseType, Map<String, ?> uriVariables) ;public <T> T getForObject (URI url, Class<T> responseType) ;public <T> ResponseEntity<T> getForEntity (String url, Class<T> responseType, Object... uriVariables) ;public <T> ResponseEntity<T> getForEntity (String url, Class<T> responseType, Map<String, ?> uriVariables) ;public <T> ResponseEntity<T> getForEntity (URI url, Class<T> responseType) ;
因为分页接口有两个变量,所以可以简单使用第一个 API
1 2 3 4 String url = "http://localhost:8081/expense/project/list?page={page}&size={size}" ;ProjectPageResp forObject = restTemplate.getForObject(url, ProjectPageResp.class, 1 , 10 );
POST方法 这个以创建项目的接口来看一下使用方式
同样先定义好请求及响应类
1 2 3 4 5 6 7 8 9 @Data public class CreateProject { private List<String> members; private String projectName; private String projectDesc; }
在发起 POST 请求前,看一下其提供的 API
1 2 3 4 5 6 7 8 9 10 11 12 public URI postForLocation (String url, @Nullable Object request, Object... uriVariables) ;public URI postForLocation (String url, @Nullable Object request, Map<String, ?> uriVariables) ;public URI postForLocation (URI url, @Nullable Object request) ;public <T> T postForObject (String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) ;public <T> T postForObject (String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) ;public <T> T postForObject (URI url, @Nullable Object request, Class<T> responseType) ;public <T> ResponseEntity<T> postForEntity (String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) ;public <T> ResponseEntity<T> postForEntity (String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) ;public <T> ResponseEntity<T> postForEntity (URI url, @Nullable Object request, Class<T> responseType) ;
可以看到基本和 GET 的 API 类似,主要就是多了 postForLocation 相关的方法,这个主要用来获取 301、302状态码返回的重定向地址信息
我们这里可以使用 postForObject 即可
1 2 3 4 5 6 7 8 9 final CreateProject createProject = new CreateProject ();createProject.setMembers(Lists.newArrayList("成员1" , "成员2" )); createProject.setProjectName("测试项目" ); createProject.setProjectDesc("哈哈" ); String url = "http://localhost:8081/expense/project/create" ;final Resp resp = restTemplate.postForObject(url, createProject, Resp.class);
Exchange方法 简单的方式我们直接使用之前的 GET 和 POST 方法即刻,但是有一些特殊的场景,比如有一些接口鉴权需要设置header或cookie等,则无法支持,这时候可以使用 Exchange方法
这里我们针对之前的两个方法,转换成使用 Exchange方法,同时设置cookie等信息
Exchange的方法定义如下
1 2 3 4 5 6 7 8 public <T> ResponseEntity<T> exchange (String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) ;public <T> ResponseEntity<T> exchange (String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) ;public <T> ResponseEntity<T> exchange (URI url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, Class<T> responseType) ;public <T> ResponseEntity<T> exchange (String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Object... uriVariables) ;public <T> ResponseEntity<T> exchange (String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) ;public <T> ResponseEntity<T> exchange (URI url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType) ;public <T> ResponseEntity<T> exchange (RequestEntity<?> requestEntity, Class<T> responseType) ;public <T> ResponseEntity<T> exchange (RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType) ;
下面看下使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 HttpHeaders headers = new HttpHeaders ();headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Cookie" , "cookie信息" ); headers.set("Token" , "token信息" ); String url = "http://localhost:8081/expense/project/list?page={page}&size={size}" ;ResponseEntity<ProjectPageResp> exchange = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity <>(headers), ProjectPageResp.class, 1 , 10 ); System.out.println(exchange); final CreateProject createProject = new CreateProject ();createProject.setMembers(Lists.newArrayList("成员1" , "成员2" )); createProject.setProjectName("测试项目" ); createProject.setProjectDesc("哈哈" ); final HttpEntity<CreateProject> httpPostEntity = new HttpEntity <>(createProject, headers);String url = "http://localhost:8081/expense/project/create" ;final ResponseEntity<Resp> exchange1 = restTemplate.exchange(url, HttpMethod.POST, httpPostEntity, Resp.class);
RestTemplate 内部实际默认使用的是 JDK 的HttpURLConnection,同时也支持配置使用 Apache 的 HttpClient 以及 OkHttp3,可以按需配置使用
如使用OkHttp3, 需要添加依赖(maven)
1 2 3 4 5 <dependency > <groupId > com.squareup.okhttp3</groupId > <artifactId > okhttp</artifactId > <version > 4.12.0</version > </dependency >
这时可以进行RestTemplate的配置
1 2 3 4 5 6 7 8 OkHttpClient client = new OkHttpClient .Builder() .addInterceptor(new LoggingInterceptor ()) .build(); ClientHttpRequestFactory clientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory (client);final RestTemplate restTemplate = new RestTemplate (clientHttpRequestFactory);
使用 HttpClient 也是类似的方式~