SpringBoot调用外部接口的几种方式
  • 使用FeignClient调用
  • 1、在使用方引入依赖
  • 2、服务接口调用方
  • 2.1、在启动类上加上@EnableFeigncliens注解
  • 2.2、编写Feign接口调用服务controller层
  • 2.3、服务接口调用service层
  • 3、服务接口提供者
  • 4、说明
  • 使用RestTemplate调用
  • 1、引入依赖
  • 2、RestTemplateConfig配置类
  • 3、接口调用
  • 使用WebClient调用
  • 1、引入依赖
  • 2、接口调用示例
  • 使用Apache HttpClient调用
  • 使用HttpURLConnection调用
  • 使用OkHttp调用
  • 1、引入依赖
  • 2、示例代码
  • 使用AsyncHttpClient调用
  • 1、引入依赖
  • 2、示例代码


使用FeignClient调用

FeignClient调用大多用于微服务开发中,各服务之间的接口调用。它以Java接口注解的方式调用HTTP请求,使服务间的调用变得简单
  • 1.

1、在使用方引入依赖

<!-- Feign注解 这里openFeign的版本要和自己使用的SpringBoot匹配-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <!-- <version>4.0.1</version> -->
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

2、服务接口调用方

2.1、在启动类上加上@EnableFeigncliens注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class StudyfeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(StudyfeignApplication.class, args);
        System.out.println("项目启动成功");
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
2.2、编写Feign接口调用服务controller层
import com.hysoft.studyfeign.service.SysUserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("feign")
public class SysUserController {

    @Autowired
    private SysUserClient sysUserClient;

    @PostMapping("getUserId")
    public void getUserId(String userId){
        this.sysUserClient.getUserById(userId);
    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
2.3、服务接口调用service层
feign的客户端需要使用@FeignClient注解进行表示,这样扫描时才知道这是一个feign客户端。@FeignClient最常用的就两个属性,一个name,用于给客户端定义一个唯一的名称,另一个就是url,用于定义该客户端调用的远程地址。url中的内容,可以写在配置文件application.yml中,便于管理
  • 1.
@Service
@FeignClient(name = "feign-service",url = "${master-getuserbyId}")
public interface SysUserClient {

    @PostMapping("/master/test")
    String getUserById(String id);

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

application.yml中的配置如下

server:
  port: 8081
master-getuserbyId: http://localhost:8080
  • 1.
  • 2.
  • 3.

3、服务接口提供者

对于接口提供者来说没有特别要求,和正常的接口开发一样
  • 1.

4、说明

需要说明的是,在接口调用方,可以继续拓展service层,书写service实现层,进一步进行拓展
  • 1.
import org.springframework.stereotype.Service;

@Service
public class SysUserClientImpl implements SysUserClient{
    @Override
    public String getUserById(String id) {
        return "";
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

使用RestTemplate调用

RestTemplate中几个常用的方法:getForObject()、getForEntity()、postForObject()、postForEntity()。其中,getForObject() 和 getForEntity() 方法可以用来发送 GET 请求
  • 1.

1、引入依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  • 1.
  • 2.
  • 3.
  • 4.

2、RestTemplateConfig配置类

SimpleClientHttpRequestFactory类对应的HTTP库是JDK自带的HttpUrlConnection,当然我们可以根据自身的需求使用其他的HTTP库,例如HttpComponentsAsyncClientHttpRequestFactory
  • 1.
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);//单位为ms
        factory.setConnectTimeout(5000);//单位为ms
        return factory;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

3、接口调用

@RestController
public class TestRestTemplate {
    @Resource
    private RestTemplate restTemplate;

    @GetMapping(value = "/saveUser")
    public void saveUser(String userId) {
        String url = "http://127.0.0.1:8080/master/test";
        Map map = new HashMap<>();
        map.put("userId", "hy001");
        String results = restTemplate.postForObject(url, map, String.class);
    }
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

使用WebClient调用

Spring3.0引入了RestTemplate,但是在后来的官方源码中介绍,RestTemplate有可能在未来的版本中被弃用,所谓替代RestTemplate,在Spring5中引入了WebClient作为异步的非阻塞、响应式的HTTP客户端。
  • 1.

1、引入依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.

2、接口调用示例

public class TestWebClient {
    @Test
    public void doGet() {
        String userId = "郭郭";
        String url = "http://127.0.0.1:8080/master/test/getSysUserById?userId={userId}";
        Mono<String> mono = WebClient
                //创建WebClient实例
                .create()
                //方法调用,WebClient中提供了多种方法
                .get()
                //请求url
                .uri(url, userId)
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //返回最终结果:block是阻塞的/subscribe()非阻塞式获取响应结果
        System.out.println("响应结果:" + mono.block());
    }
    @Test
    public void doPost() {
        Map map = new HashMap<>();
        map.put("name", "郭郭");
        String requestBody = JSON.toJSONString(map);
        String url = "http://127.0.0.1:8080/master/test/saveUser";
        Mono<String> mono = WebClient
                //创建WebClient实例
                .create()
                //方法调用,WebClient中提供了多种方法
                .post()
                //请求url
                .uri(url)
                //指定请求的Content-Type为JSON
                .contentType(MediaType.APPLICATION_JSON)
                //使用bodyValue方法传递请求体
                .bodyValue(requestBody)
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //返回最终结果:block是阻塞的/subscribe()非阻塞式获取响应结果
        System.out.println("响应结果:" + mono.block());
    }
}
  • 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.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
在上述doPost请求中,我们的请求接口入参是一个Map,但是需要转换为JSON格式传递,这是因为WebClient默认是使用JSON序列化的。
  • 1.

使用Apache HttpClient调用

public class TestHttpClient {
    @Test
    public void doGet() throws IOException {
        //步骤一:创建httpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //步骤二:创建HTTP请求
        HttpGet httpGet = new HttpGet("http://127.0.0.1:8094/masterdata/sysUser/getSysUserById?userId=郭郭");
        //步骤三:发送请求并获取响应数据
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //步骤四:处理响应数据
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity);
        //步骤五:关闭httpClient和response
        response.close();
        httpClient.close();
    }
    @Test
    public void doPost() throws IOException {
        //步骤一:创建httpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //步骤二:创建HTTP请求
        HttpPost httpPost = new HttpPost("http://127.0.0.1:8094/masterdata/sysUser/saveUser");
        //步骤三:设置请求体数据,使用JSON格式
        Map map = new HashMap<>();
        map.put("name", "郭郭");
        String requestBody = JSON.toJSONString(map);
        StringEntity stringEntity = new StringEntity(requestBody, "UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        
        //步骤四:发送请求并获取响应数据
        CloseableHttpResponse response = httpClient.execute(httpPost);
        //步骤五:处理响应数据
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity);
        //步骤五:关闭httpClient和response
        response.close();
        httpClient.close();
    }
}
  • 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.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.

使用HttpURLConnection调用

public class TestHttpURLConnection {

    @Test
    public void doGet() throws IOException {
        String userId = "郭郭";  // 参数值
        userId = URLEncoder.encode(userId, "UTF-8"); // 对参数值进行URL编码
        //步骤一:创建URL对象
        URL url = new URL("http://127.0.0.1:8094/masterdata/sysUser/getSysUserById?userId=" + userId);
        //步骤二:打开连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //步骤三:设置请求方式
        conn.setRequestMethod("GET");
        //步骤四:读取响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        System.out.println(sb.toString());
    } 
    @Test
    public void doPost() throws IOException {
        //创建URL对象
        URL url = new URL("http://127.0.0.1:8094/masterdata/sysUser/saveUser");
        //打开连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求方式
        conn.setRequestMethod("POST");
        // 设置请求头
        conn.setRequestProperty("Content-Type", "application/json");
        //启用输出流
        conn.setDoOutput(true);
        //设置请求体数据
        Map map = new HashMap<>();
        map.put("name", "郭郭");
        String requestBody = JSON.toJSONString(map);
        //发送请求体数据
        try (DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream())) {
            outputStream.write(requestBody.getBytes(StandardCharsets.UTF_8));
        }

        //读取响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        System.out.println(sb.toString());
    } 
  }
  • 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.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.

使用OkHttp调用

1、引入依赖

<!--okhttp依赖-->
  <dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.0.0</version>
  </dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

2、示例代码

public class TestOkHttp {

    @Test
    public void doGet() throws IOException {
        OkHttpClient client = new OkHttpClient();
        String url = "http://127.0.0.1:8080/master/test/getSysUserById?userId=郭郭";
        Request request = new Request.Builder().url(url).build();
        try (Response response = client.newCall(request).execute()) {
            ResponseBody body = response.body();
            System.out.println(body.string());
        }
    }

    @Test
    public void doPost() throws IOException{
        OkHttpClient client = new OkHttpClient();
        String url = "http://127.0.0.1:8080/master/test/saveUser";
        MediaType mediaType = MediaType.get("application/json; charset=utf-8");
        //requestBody请求入参
        Map map = new HashMap<>();
        map.put("name", "admin");
        RequestBody requestBody = RequestBody.create(mediaType, JSON.toJSONString(map));
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        try (Response response = client.newCall(request).execute()) {
            ResponseBody body = response.body();
            System.out.println(body.string());
        }
    }
}
  • 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.
  • 29.
  • 30.
  • 31.
  • 32.

使用AsyncHttpClient调用

1、引入依赖

<dependency>
      <groupId>org.asynchttpclient</groupId>
      <artifactId>async-http-client</artifactId>
      <version>2.12.3</version>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

2、示例代码

public class TestAsyncHttpClient {
    @Test
    public void doGet() throws IOException {
        try (AsyncHttpClient client = new DefaultAsyncHttpClient();) {
            BoundRequestBuilder requestBuilder = client.prepareGet("http://127.0.0.1:8080/master/test/getSysUserById?userId=hy001");
            CompletableFuture<String> future = requestBuilder.execute()
                    .toCompletableFuture()
                    .thenApply(Response::getResponseBody);
            //使用join等待响应完成
            String responseBody = future.join();
            System.out.println(responseBody);
        }
    }
    @Test
    public void doPost() throws IOException {
        try (AsyncHttpClient client = new DefaultAsyncHttpClient();) {
            BoundRequestBuilder requestBuilder = client.preparePost("http://127.0.0.1:8094/8080/master/test/saveUser");
            //requestBody请求入参
            Map map = new HashMap<>();
            map.put("name", "admin");
            String requestBody = JSON.toJSONString(map);
            requestBuilder.addHeader("Content-Type", "application/json");
            requestBuilder.setBody(requestBody);
            CompletableFuture<String> future = requestBuilder.execute()
                    .toCompletableFuture()
                    .thenApply(Response::getResponseBody);
            //使用join等待响应完成
            String responseBody = future.join();
            System.out.println(responseBody);
        }
    }
  }
  • 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.
  • 29.
  • 30.
  • 31.
  • 32.