欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中調(diào)用第三方接口的詳細(xì)代碼示例

 更新時(shí)間:2024年12月07日 14:33:53   作者:-代號(hào)9527  
這篇文章主要介紹了Java中調(diào)用第三方接口的詳細(xì)代碼示例,文章總結(jié)了多種Java進(jìn)行HTTP請(qǐng)求的方法,每種方法都有其特點(diǎn)和適用場(chǎng)景,從原生到封裝,再到聲明式客戶(hù)端,滿(mǎn)足了不同復(fù)雜度的HTTP請(qǐng)求需求,需要的朋友可以參考下

0、測(cè)試接口

寫(xiě)兩個(gè)測(cè)試接口,一個(gè)GET,一個(gè)POST

@RestController
@RequestMapping("/svc1")
public class Controller {

    @GetMapping("/t1")
    public String doGet(@RequestParam(required = false) String name) {
        return "test" + name;
    }

    @PostMapping("/t2")
    public ResultVo doPost(@RequestBody RequestBodyDto dto, @RequestParam String key) {
        return new ResultVo(200, "操作成功", dto.getName() + dto.getChoose() + key);
    }
}

1、JDK的HttpURLConnection

原生版,主要依靠JDK的 java.net包,GET請(qǐng)求:

import java.net.HttpURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

@Slf4j
public class TestDemo {

    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            // 創(chuàng)建URL對(duì)象
            URL url = new URL("http://localhost:8080/svc1/t1");
            // 打開(kāi)連接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            // 讀取響應(yīng)
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            // 處理響應(yīng)
            String inputLine;
            StringBuilder response = new StringBuilder();
            while ((inputLine = reader.readLine()) != null) {
                response.append(inputLine);
            }
            System.out.println(response);

        } catch (Exception e) {
            log.error("調(diào)用失敗");
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

URL類(lèi)是JDK java.net包下的一個(gè)類(lèi),表示一個(gè)統(tǒng)一資源標(biāo)識(shí)符(Uniform Resource Identifier)引用

POST請(qǐng)求:

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import com.alibaba.fastjson.JSON;

@Slf4j
public class TestDemo {

    public static void main(String[] args) {

        try {
            // 創(chuàng)建URL對(duì)象
            URL url = new URL("http://localhost:8080/svc1/t2?key=abc");
            // 打開(kāi)連接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            // 設(shè)置請(qǐng)求頭與數(shù)據(jù)格式
            connection.setRequestProperty("Content-Type", "application/json; utf-8");
            connection.setRequestProperty("Accept", "application/json");
            // 允許向服務(wù)器寫(xiě)入數(shù)據(jù)
            connection.setDoOutput(true);
            RequestBodyDto dto = new RequestBodyDto("Tom", "A");
            String json = JSON.toJSONString(dto);
            // 寫(xiě)入JSON到請(qǐng)求體
            try (OutputStream os = connection.getOutputStream()) {
                BufferedOutputStream bos = new BufferedOutputStream(os);
                bos.write(json.getBytes(StandardCharsets.UTF_8));
                bos.flush();
            }

            // 讀取響應(yīng)
            try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
                StringBuilder response = new StringBuilder();
                String responseLine;
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
                System.out.println("Response: " + response.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

2、Apache的HttpClient

后續(xù)這些方式,本質(zhì)上就是對(duì)java.net包的一個(gè)封裝了。先引入Apache做http請(qǐng)求的依賴(lài)坐標(biāo):

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.16</version>
</dependency>
public class TestDemo {

    public static void main(String[] args) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 創(chuàng)建POST請(qǐng)求對(duì)象
            HttpPost httpPost = new HttpPost("http://localhost:8080/svc1/t2?key=abc");
            // 設(shè)置請(qǐng)求頭
            httpPost.setHeader("Content-Type", "application/json; utf-8");
            httpPost.setHeader("Accept", "application/json");
            // 設(shè)置請(qǐng)求體
            RequestBodyDto dto = new RequestBodyDto("Tom", "A");
            String json = JSON.toJSONString(dto);
            StringEntity entity = new StringEntity(json);
            httpPost.setEntity(entity);
            // 執(zhí)行請(qǐng)求并獲取響應(yīng)
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            // 處理響應(yīng)
            if (null != responseEntity) {
                String responseStr = EntityUtils.toString(responseEntity);
                System.out.println(responseStr);
                // 也可按需把json串反序列化成Java對(duì)象,略
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

3、SpringBoot的RestTemplate

使用SpringBoot封裝的RestTemplate,依賴(lài)寫(xiě)web的:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

把RestTemplate的Bean放到IoC容器中:

@Configuration
public class RestTemplateConfig {

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

3.1 GET

發(fā)送Get請(qǐng)求,常用方法:

  • getForObject
  • getForEntity
/**
* url為請(qǐng)求的地址
* responseType為請(qǐng)求響應(yīng)body的類(lèi)型
* urlVariables為url中的參數(shù)綁定
* 
*/
getForEntity(Stringurl,Class responseType,Object…urlVariables)

/**
* URI對(duì)象來(lái)替代之前getForEntity的url和urlVariables參數(shù)來(lái)指定訪(fǎng)問(wèn)地址和參數(shù)綁定
* URI是JDK java.net包下的一個(gè)類(lèi)
* 
*/
getForEntity(URI url,Class responseType)

示例:

@SpringBootTest
class LearningApplicationTests {

    @Resource
    private RestTemplate restTemplate;

    @Test
    void contextLoads() {
        String url = "http://localhost:8080/svc1/t1?name={name}";
        // 參數(shù)
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("name", "Tom");
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, paramMap);
        // 狀態(tài)碼
        HttpStatus statusCode = responseEntity.getStatusCode();
        // 響應(yīng)
        String body = responseEntity.getBody();
        System.out.println(statusCode + body);

    }
}

接口路徑不用字符串,改為URI對(duì)象:

@Test
 void testTemplate() {
     String url = "http://localhost:8080/svc1/t1";
     String name = "Tom";
     // 使用 UriComponentsBuilder 構(gòu)建 URL
     URI uri = UriComponentsBuilder.fromHttpUrl(url)
             .queryParam("name", name)
             .build()
             .toUri();
     ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
     // 狀態(tài)碼
     HttpStatus statusCode = responseEntity.getStatusCode();
     // 響應(yīng)
     String body = responseEntity.getBody();
     System.out.println(statusCode + body);

 }

最后,getForObject:

getForObject(String url,Class responseType,Object...urlVariables)
getForObject(String url,Class responseType,Map urlVariables)
getForObject(URI url,Class responseType)

和getForEntity的區(qū)別是,getForObject只有一個(gè)響應(yīng)的內(nèi)容,響應(yīng)碼、響應(yīng)頭等沒(méi)有

3.2 POST

常用方法:

  • postForEntity
  • postForObject
  • postForLocation

以postForEntity為例,其參數(shù)可選:(重載)

postForEntity(String url,Object request,Class responseType,Object...  uriVariables) 
postForEntity(String url,Object request,Class responseType,Map  uriVariables) 
postForEntity(URI url,Object request,Class responseType)

示例:

 @Test
void testTemplate2() {
    String url = "http://localhost:8080/svc1/t2?key=Tom";
    RestTemplate restTemplate = new RestTemplate();
    // 請(qǐng)求頭
    HttpHeaders headers = new HttpHeaders();
    headers.add(HttpHeaders.AUTHORIZATION, "Bear xx");
    // headers.set("Content-Type", "application/x-www-form-urlencoded");
    headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
    // 創(chuàng)建請(qǐng)求體對(duì)象并放入數(shù)據(jù)
    HttpEntity<RequestBodyDto> requestData = new HttpEntity<>(new RequestBodyDto("Tom", "A"), headers);
    // 和postForEntity一個(gè)意思
    ResponseEntity<String> responseEntity = restTemplate.exchange(
            url,
            HttpMethod.POST,
            requestData,
            String.class
    );
    // 獲取響應(yīng)狀態(tài)碼和響應(yīng)體
    HttpStatus statusCode = responseEntity.getStatusCode();
    String responseBody = responseEntity.getBody();
    System.out.println(statusCode + " " + responseBody);
}

4、SpringCloud的Feign

上面的RestTemplate,在調(diào)三方接口時(shí)挺好用的,但微服務(wù)架構(gòu)下,各個(gè)微服務(wù)之間調(diào)用時(shí),url就不好寫(xiě),由此,用Feign:一個(gè)聲明式的http客戶(hù)端

核心思路是聲明出:

  • 你調(diào)誰(shuí)
  • 用什么方式
  • 請(qǐng)求參數(shù)是啥
  • 返回類(lèi)型是啥

引入依賴(lài):

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

啟動(dòng)類(lèi)上加上@EnableFeignClients

//在order的啟動(dòng)類(lèi)中開(kāi)啟Feign
@EnableFeignClients
@MapperScan("com.llg.order.mapper")
@SpringBootApplication
public class OrderApplication{
	
	public static void main(String[] args){
		SpringApplication.run(OrderApplication.class,args);
	}
}
  • 以order服務(wù)調(diào)用user服務(wù)為例,編寫(xiě)調(diào)用方:
// 遠(yuǎn)程調(diào)用userservice服務(wù)
@FeignClient("userservice")
public interface UserClient {
	@GetMapping("/user/{id}")
	User findById(@PathVariable("id") Long id);
	// 后續(xù)接口自行添加
}


?。indById這個(gè)方法名隨便起
?。≌{(diào)用的接口路徑、調(diào)用的服務(wù)名、請(qǐng)求參數(shù)、返回類(lèi)型聲明正確就行
主要是基于SpringMVC的注解來(lái)聲明遠(yuǎn)程調(diào)用的信息,比如:

?服務(wù)名稱(chēng):userservice

?請(qǐng)求方式:GET

?請(qǐng)求路徑:/user/{id}

?請(qǐng)求參數(shù):Long id

?返回值類(lèi)型:User
  • 注入上面定義的FeignClient類(lèi),也就是UserClient,直接調(diào)用聲明的那個(gè)方法
@Autowired
private UserClient userClient;

public Order queryOrderById(Long orderId){
	//查詢(xún)訂單
	Order order = orderMapper.findById(orderId);
	//利用feign發(fā)起http請(qǐng)求,查用戶(hù)
	User user = userClient.findById(order.getUserId());
	//封裝,對(duì)象的某個(gè)屬性也是個(gè)對(duì)象,即引用類(lèi)型
	order.setUser(user);
	return order;
} 
  • 被調(diào)用方有多個(gè)實(shí)例時(shí),負(fù)載均衡也不用考慮,F(xiàn)eign用了Ribbon做負(fù)載均衡
  • 關(guān)于Feign請(qǐng)求頭的添加,可重寫(xiě)RequestInterceptor的apply方法:
@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        //添加token
        requestTemplate.header("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ");
    }
}
  • 要做降級(jí)邏輯的話(huà):如下,調(diào)用消息中心服務(wù)
// @FeignClient的fallbackFactory指定下降級(jí)邏輯的類(lèi)
@Component
@FeignClient(contextId = "remoteMessageService", value = ServiceNameConstants.MESSAGE_SERVICE, fallbackFactory = RemoteMessageFallbackFactory.class)
public interface RemoteMessageService {

    /**
     * 發(fā)送定時(shí)消息任務(wù):每分鐘掃描發(fā)送消息
     *
     * @return 結(jié)果
     */
    @GetMapping("/inner/message/sendTimingMessage")
    public R<Void> sendTimingMessage();

    /**
     * 發(fā)送系統(tǒng)消息
     *
     * @return 結(jié)果
     */
    @PostMapping("/inner/message/sendSystemMessage")
    public R<Void> sendSystemMessage(@RequestBody MessageSendSystemDto messageSendSystemDto);
}
// 降級(jí)邏輯
@Component
public class RemoteMessageFallbackFactory implements FallbackFactory<RemoteMessageService>{
    private static final Logger log = LoggerFactory.getLogger(RemoteMessageFallbackFactory.class);

    @Override
    public RemoteMessageService create(Throwable throwable) {
        throwable.printStackTrace();
        log.error("消息服務(wù)調(diào)用失敗:{}", throwable.getMessage());
        return new RemoteMessageService() {
            @Override
            public R<Void> sendTimingMessage() {
                return R.fail("調(diào)用發(fā)送定時(shí)消息接口失敗:" + throwable.getMessage());
            }

            @Override
            public R<Void> sendSystemMessage(MessageSendSystemDto messageSendSystemDto) {
                return R.fail("調(diào)用發(fā)送消息接口失敗:" + throwable.getMessage());
            }

        };
    }
}

5、Hutool的HttpUtil

還是對(duì) java.net的封裝,引入依賴(lài):

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version> <!-- 請(qǐng)檢查最新版本 -->
</dependency>

處理GET和POST:

/**
 * @param url           baseUrl
 * @param requestMethod 請(qǐng)求方式
 * @param headerMap     請(qǐng)求頭參數(shù)key-value
 * @param paramMap      路徑參數(shù)key-value,形如?name=Tom&country=Chain
 * @param bodyJsonStr   post的body傳參,json字符串
 * @return 響應(yīng)體
 */
public static String sendRequest(String url, Method requestMethod, Map<String, String> headerMap, Map<String, Object> paramMap, String bodyJsonStr) {
    // 路徑參數(shù)不為空時(shí),拼接URL
    if (paramMap != null) {
        UrlBuilder urlBuilder = UrlBuilder.of(url);
        paramMap.forEach((k, v) -> urlBuilder.addQuery(k, v));
        url = urlBuilder.toString();
    }
    //發(fā)送請(qǐng)求
    HttpResponse httpResponse = HttpUtil.createRequest(requestMethod, url)
            .addHeaders(headerMap)
            .body(bodyJsonStr)
            .execute();

    return httpResponse.body();

}

測(cè)試下:

@Test
void testHuTool() {
    String url = "http://localhost:8080/svc1/t1";
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("name", "Tom");
    Map<String, String> headerMap = new HashMap<>();
    headerMap.put("Authorization", "Bear xx");
    String response = sendRequest(url, Method.GET, headerMap, paramMap, null);
    System.out.println(response);
}

@Test
void testHuTool2() {
    String url = "http://localhost:8080/svc1/t2";
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("key", "Tom");
    Map<String, String> headerMap = new HashMap<>();
    headerMap.put("Authorization", "Bear xx");
    RequestBodyDto dto = new RequestBodyDto("Tom", "A");
    String bodyJsonStr = JSON.toJSONString(dto);
    String response = sendRequest(url, Method.POST, headerMap, paramMap, bodyJsonStr);
    System.out.println(response);
}

6、失敗后重試

考慮到遠(yuǎn)程調(diào)用可能失敗,失敗后重試三次,以上面的hutool為例來(lái)實(shí)現(xiàn),其余的都一樣,主要還是一個(gè)是否成功標(biāo)記位 + 一個(gè)計(jì)數(shù),successFlag不用voilate,并發(fā)安全也不用考慮,線(xiàn)程內(nèi)部調(diào)用的,用到的數(shù)存棧里了都。

/**
  * @param url           baseUrl
  * @param requestMethod 請(qǐng)求方式
  * @param headerMap     請(qǐng)求頭參數(shù)key-value
  * @param paramMap      路徑參數(shù)key-value,形如?name=Tom&country=Chain
  * @param bodyJsonStr   post的body傳參,json字符串
  * @return 響應(yīng)體
  */
 public static String sendRequest(String url, Method requestMethod, Map<String, String> headerMap, Map<String, Object> paramMap, String bodyJsonStr) {
     // 是否成功標(biāo)記位
     boolean successFlag = false;
     // 重試次數(shù)累計(jì)
     int retryCount = 1;
     HttpResponse httpResponse = null;
     while (!successFlag && retryCount <= 3) {
         try {
             // 路徑參數(shù)不為空時(shí),拼接URL
             if (paramMap != null) {
                 UrlBuilder urlBuilder = UrlBuilder.of(url);
                 paramMap.forEach((k, v) -> urlBuilder.addQuery(k, v));
                 url = urlBuilder.toString();
             }
             // 發(fā)送請(qǐng)求
             httpResponse = HttpUtil.createRequest(requestMethod, url)
                     .addHeaders(headerMap)
                     .body(bodyJsonStr)
                     .execute();
             if (httpResponse.getStatus() != 200) {
                 retryCount++;
             } else {
                 successFlag = true;
             }
         } catch (Exception e) {
             e.printStackTrace();
             retryCount++;
         }
     }

     return httpResponse == null ? null : httpResponse.body();

 }

總結(jié) 

到此這篇關(guān)于Java中調(diào)用第三方接口的文章就介紹到這了,更多相關(guān)Java調(diào)用第三方接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問(wèn)題

    Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問(wèn)題

    這篇文章主要介紹了Mybatis之foreach標(biāo)簽內(nèi)傳入list為空的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • java  ThreadPoolExecutor使用方法簡(jiǎn)單介紹

    java ThreadPoolExecutor使用方法簡(jiǎn)單介紹

    這篇文章主要介紹了java ThreadPoolExecutor使用方法簡(jiǎn)單介紹的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Java中的break和continue關(guān)鍵字的使用方法總結(jié)

    Java中的break和continue關(guān)鍵字的使用方法總結(jié)

    下面小編就為大家?guī)?lái)一篇Java中的break和continue關(guān)鍵字的使用方法總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • 什么是springMVC?視圖和視圖解析器實(shí)例代碼

    什么是springMVC?視圖和視圖解析器實(shí)例代碼

    在 springMVC 中的目標(biāo)方法最終返回都是一個(gè)視圖,返回的視圖都會(huì)由一個(gè)視圖解析器來(lái)處理,這篇文章主要介紹了什么是springMVC?視圖和視圖解析器,需要的朋友可以參考下
    2023-09-09
  • Redis原子計(jì)數(shù)器incr,防止并發(fā)請(qǐng)求操作

    Redis原子計(jì)數(shù)器incr,防止并發(fā)請(qǐng)求操作

    這篇文章主要介紹了Redis原子計(jì)數(shù)器incr,防止并發(fā)請(qǐng)求操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • Java中ArrayList類(lèi)的源碼解析

    Java中ArrayList類(lèi)的源碼解析

    本文主要介紹了Java中ArrayList類(lèi)的源碼解析,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • Java上傳視頻實(shí)例代碼

    Java上傳視頻實(shí)例代碼

    本文通過(guò)實(shí)例代碼給大家講解了java上傳視頻功能,代碼分為頁(yè)面前臺(tái)和后臺(tái),工具類(lèi),具體實(shí)例代碼大家通過(guò)本文學(xué)習(xí)吧
    2018-01-01
  • Spring Boot應(yīng)用監(jiān)控的實(shí)戰(zhàn)教程

    Spring Boot應(yīng)用監(jiān)控的實(shí)戰(zhàn)教程

    Spring Boot 提供運(yùn)行時(shí)的應(yīng)用監(jiān)控和管理功能,下面這篇文章主要給大家介紹了關(guān)于Spring Boot應(yīng)用監(jiān)控的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • Java RandomAccessFile的用法詳解

    Java RandomAccessFile的用法詳解

    下面小編就為大家?guī)?lái)一篇Java RandomAccessFile的用法詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • 詳解Java TCC分布式事務(wù)實(shí)現(xiàn)原理

    詳解Java TCC分布式事務(wù)實(shí)現(xiàn)原理

    這篇文章主要介紹了詳解Java TCC分布式事務(wù)實(shí)現(xiàn)原理,對(duì)分布式事務(wù)感興趣的同學(xué),一定要看一下
    2021-04-04

最新評(píng)論