使用SpringBoot跨系統(tǒng)調(diào)用接口的方案
一、簡介
項目開發(fā)中存在系統(tǒng)之間互調(diào)問題,又不想用dubbo,這里提供幾種springboot方案:
1、使用Feign進(jìn)行消費(fèi)(推薦)
2、使用原始httpClient請求
3、使用RestTemplate方法
二、方案
方案一:使用Feign進(jìn)行消費(fèi)(推薦)
1、在maven中添加依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.2</version> </dependency>
2、啟動類上加上@EnableFeignClients
@EnableHystrix
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.aaa.aurora"})
@SpringBootApplication
@EnableTransactionManagement
@ComponentScan(basePackages = "com.aaa.aurora")
@ImportResource(locations= {"classpath:spring.xml","spring-security.xml"})
@MapperScan("com.aaa.aurora.mapper")
public class AuroraWebApplication {
public static void main(String[] args) {
SpringApplication.run(AuroraWebApplication.class, args);
}
}
3、編寫service接口
@FeignClient(url = "${pangu.url}",name = "panguUrl")
public interface PanGuService {
@RequestMapping(value = "/pangu/restful/check",method = RequestMethod.POST)
JSONObject check(@RequestParam(name="queryEngine") String queryEngine, @RequestParam(name="querySql") String querySql, @RequestParam(name="jobNo") String jobNo);
}
其中:pangu.url是配置在application.properties中的ip及端口
pangu.url = 192.168.1.3:8080 /pangu/restful/check是要調(diào)的接口名
4、代碼中調(diào)用
@Autowired
private PanGuService panGuService;
JSONObject jsonObject = null;
try {
jsonObject = panGuService.auroraPriviledge(PRESTO_DRIVER, query.get("sql"), user.getWorkNo());
} catch (Exception e) {
throw new Exception("請求系統(tǒng)異常");
}
if (PANGU_FAIL.equals(jsonObject.get("code"))) {
LOG.info(jsonObject.get("msg").toString());
throw new BusinessException(jsonObject.get("msg").toString());
}
方案二:使用原始httpClient請求
使用HttpClient發(fā)送請求、接收響應(yīng)很簡單,一般需要如下幾步即可。
1. 創(chuàng)建HttpClient對象。
2. 創(chuàng)建請求方法的實例,并指定請求URL。如果需要發(fā)送GET請求,創(chuàng)建HttpGet對象;如果需要發(fā)送POST請求,創(chuàng)建HttpPost對象。
3. 如果需要發(fā)送請求參數(shù),可調(diào)用HttpGet、HttpPost共同的setParams(HttpParams params)方法來添加請求參數(shù);對于HttpPost對象而言,也可調(diào)用setEntity(HttpEntity entity)方法來設(shè)置請求參數(shù)。
4. 調(diào)用HttpClient對象的execute(HttpUriRequest request)發(fā)送請求,該方法返回一個HttpResponse。
5. 調(diào)用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務(wù)器的響應(yīng)頭;調(diào)用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務(wù)器的響應(yīng)內(nèi)容。程序可通過該對象獲取服務(wù)器的響應(yīng)內(nèi)容。
6. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接。
public JSONObject doPost(String queryEngine, String querySql, String jobNo) {
JSONObject jsonObject = null;
//1.創(chuàng)建httpClient對象
CloseableHttpClient client = HttpClients.createDefault();
//2.創(chuàng)建請求方法的實例,并指定請求URL
String url = "http://192.168.1.11:8080";
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/json;charset=utf8");
//3.參數(shù)
AuroraPriviledge auroraPriviledge = new AuroraPriviledge();
auroraPriviledge.setQueryEngine(queryEngine);
auroraPriviledge.setQuerySql(querySql);
auroraPriviledge.setJobNo(jobNo);
String jsonString = JSON.toJSONString(auroraPriviledge);
StringEntity entity = new StringEntity(jsonString, "UTF-8");
post.setEntity(entity);
//4.調(diào)用execute,返回response
CloseableHttpResponse response = null;
try {
response = client.execute(post);
HttpEntity responseEntity = response.getEntity();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (client != null) {
client.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return jsonObject;
}
方案三:使用RestTemplate方法
1.get請求:getForObject(...)和getForEntity(...)兩個方法,區(qū)別在于前者直接返回預(yù)期的對象,即返回體中的body對象,后者返回的是ResponseEntity封裝類,里面包含了HTTP請求的頭信息。
2.post請求:與get請求類似,只是多一個request參數(shù),request對象會作為httpEntity進(jìn)行處理。
package com.yyy.aurora;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
/**
* Description
*
* @author Bob
* @date 2020/4/15
**/
public class TestRest {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
//get請求
//方法一:getForEntity(String url, Class<T> responseType, Object... uriVariables),沒有參數(shù)
String url = "https://restapi.amap.com/v3/ip?key=075b6eddd825148a674dfa8a8558ac62";
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
System.out.println(forEntity);
// <200,{"status":"1","info":"OK","infocode":"10000","province":"上海市","city":"上海市","adcode":"310000","rectangle":"120.8397067,30.77980118;122.1137989,31.66889673"},{Server=[Tengine], Date=[Sat, 18 Apr 2020 02:47:38 GMT], Content-Type=[application/json;charset=UTF-8], Content-Length=[167], Connection=[close], X-Powered-By=[ring/1.0.0], gsid=[011130051098158717805837600019751129378], sc=[0.071], Access-Control-Allow-Origin=[*], Access-Control-Allow-Methods=[*], Access-Control-Allow-Headers=[DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key,x-biz,x-info,platinfo,encr,enginever,gzipped,poiid]}>
String s = restTemplate.getForObject(url, String.class);
System.out.println(s);
// {"province":"上海市","city":"上海市","adcode":"310000","infocode":"10000","rectangle":"120.8397067,30.77980118;122.1137989,31.66889673","status":"1","info":"OK"}
//方法一:getForEntity(String url, Class<T> responseType, Object... uriVariables),url中用占位符,傳入?yún)?shù)
//該方法提供了三個參數(shù),其中var1為請求的地址(即url),var2為請求響應(yīng)body的包裝類型,var3為url中的參數(shù)綁定
url = "https://restapi.amap.com/v3/ip?key={?}";
forEntity = restTemplate.getForEntity(url, String.class, "075b6eddd825148a674dfa8a8558ac62");
//方法二:getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables),map傳參
url = "https://restapi.amap.com/v3/ip?key={key}";
Map<String, Object> map = new HashMap<>();
map.put("key", "075b6eddd825148a674dfa8a8558ac62");
forEntity = restTemplate.getForEntity(url, String.class, map);
//方法三:getForEntity(URI url, Class<T> responseType),uri傳參
URI uri = URI.create("https://restapi.amap.com/v3/ip?key=075b6eddd825148a674dfa8a8558ac62");
forEntity = restTemplate.getForEntity(uri, String.class);
//post請求,與get請求類型,只是多一個必填request對象
//postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
forEntity = restTemplate.postForEntity(url, null, String.class, "075b6eddd825148a674dfa8a8558ac62");
s = restTemplate.postForObject(url, null, String.class, "075b6eddd825148a674dfa8a8558ac62");
}
}
補(bǔ)充:SpringBoot關(guān)于系統(tǒng)之間的遠(yuǎn)程互相調(diào)用
1、SpringBoot關(guān)于系統(tǒng)之間的遠(yuǎn)程互相調(diào)用
可以采用RestTemplate方式發(fā)起Rest Http調(diào)用,提供有g(shù)et、post等方式。
1、1遠(yuǎn)程工具類
此處使用Post方式,參考下面封裝的HttpClient類 1.1
/**
* Created by @kai on 2018/12/24/024.
* Time: 13:54
* Desc: 遠(yuǎn)程連接工具類
*/
@Service
public class HttpClient {
/**
* 根據(jù)遠(yuǎn)程地址發(fā)起訪問-參數(shù)類型為form表單
* @param url 遠(yuǎn)程地址
* @param method 遠(yuǎn)程方法
* @param params 方法參數(shù)
* @return
*/
public Object client(String url,HttpMethod method,MultiValueMap<String,String> params){
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/x-www-form-urlencoded");
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,httpEntity,String.class);
String body = responseEntity.getBody();
JSONObject jsonObject = JSONObject.parseObject(body);
return jsonObject.get("data");
}
/**
* 根據(jù)遠(yuǎn)程地址發(fā)起訪問-參數(shù)類型為JSON
* @param url 遠(yuǎn)程地址
* @param method 遠(yuǎn)程方法
* @param params 方法參數(shù)
* @return
*/
public Object clientJson(String url,HttpMethod method,Map<String,Object> params){
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
cn.hutool.json.JSONObject jsonObject = JSONUtil.parseFromMap(params);
HttpEntity<cn.hutool.json.JSONObject> httpEntity = new HttpEntity<>(jsonObject, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,httpEntity,String.class);
String body = responseEntity.getBody();
JSONObject jsonObjectResult = JSONObject.parseObject(body);
return jsonObjectResult.get("data");
}
}
[ 1.1]
1、2遠(yuǎn)程參數(shù)說明
工具類中提供了遠(yuǎn)程過程中傳遞參數(shù)的兩種格式:
其中 headers.add("Content-Type", "application/x-www-form-urlencoded") 為form表單格式,支持鍵值對數(shù)據(jù)傳輸;
當(dāng)參數(shù)類型為form表單時,數(shù)據(jù)需要封裝成MultiValueMap<String,String>格式,前臺使用controller接受時,可以直接使用 MultiValueMap 變量接收,參照代碼如下 1.2
/**
* 保存分組策略對象
* @param
* @return
*/
@RequestMapping(value = "/saveDocGroupPolicy",method = RequestMethod.POST)
public ApiResult saveGroupPolicy(@RequestParam MultiValueMap<String,String> paramMap,@Valid GroupStrategyIO groupStrategyIO){
Integer userId = ShiroUtil.getExamUserId();
List<String> userList = new ArrayList<>();
userList.add(userId+"");
paramMap.put("userId",userList);
Object jsonObject = httpClient.client(ExamConfigConstants.url+"/exam/configPolicy/saveDocGroupPolicy", HttpMethod.POST, paramMap);
return ApiResult.success(jsonObject);
}
[ 1.2] 接受參數(shù)為form對象
headers.setContentType(MediaType.APPLICATION_JSON_UTF8)
為json數(shù)據(jù)格式
當(dāng)參數(shù)為json格式時,遠(yuǎn)程服務(wù)器接受參數(shù)需加上注解@RequestBody,對于復(fù)雜參數(shù)可以使用對象接受,將對象轉(zhuǎn)為Map,對數(shù)據(jù)進(jìn)行加工,再將map轉(zhuǎn)化為JSONObject,參照代碼如下:1.3
/**
* 保存試卷策略
* @param paperStrategyIO 試卷策略對象
* @return
*/
@RequestMapping(value = "/savePaperConfig")
public ApiResult savePaperConfig(@RequestBody PaperStrategyIO paperStrategyIO){
Map<String, Object> paramMap = BeanUtil.beanToMap(paperStrategyIO);
Integer userId = ShiroUtil.getExamUserId();
paramMap.put("userId",userId);
Object jsonObject = httpClient.clientJson(ExamConfigConstants.url+"/exam/paper/savePaperConfigWithMap", HttpMethod.POST, paramMap);
return ApiResult.success(jsonObject);
}
[ 1.3] 接收參數(shù)為復(fù)雜json串
2、后記
關(guān)于RestTemplate還有很多可調(diào)用的API,可以查看官方網(wǎng)站了解
http://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
java如何判斷一個數(shù)是否是素數(shù)(質(zhì)數(shù))
這篇文章主要介紹了java如何判斷一個數(shù)是否是素數(shù)(質(zhì)數(shù)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
Java中的線程池ThreadPoolExecutor深入解析
這篇文章主要介紹了Java中的線程池ThreadPoolExecutor深入解析,線程池,thread pool,是一種線程使用模式,線程池維護(hù)著多個線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù),需要的朋友可以參考下2023-11-11
Eclipse中實現(xiàn)JS代碼提示功能(圖文教程)
本文通過圖文并茂的形式給大家介紹了Eclipse中實現(xiàn)JS代碼提示功能,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-11-11
SpringCloudConfig之client端報錯Could?not?resolve?placeholder問
這篇文章主要介紹了SpringCloudConfig之client端報錯Could?not?resolve?placeholder?‘from‘?in?value?“${from}“問題及解決方案,具有很好的參考價值,希望對大家有所幫助2022-12-12
Java嵌入式開發(fā)的優(yōu)勢及有點(diǎn)總結(jié)
在本篇內(nèi)容里小編給大家整理了關(guān)于Java嵌入式開發(fā)的優(yōu)勢及相關(guān)知識點(diǎn)內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2022-11-11

