點選關註公眾號,Java幹貨 及時送達 👇
為什麽會有跨域問題
因為瀏覽器的同源政策,就會產生跨域。比如說發送的異步請求是不同的兩個源,就比如是不同的的兩個埠或者不同的兩個協定或者不同的網域名稱。由於瀏覽器為了安全考慮,就會產生一個同源政策,不是同一個地方出來的是不允許進行互動的。
常見的跨域解決方式
在控制層加入允許跨域的註解
@CrossOrigin
使用
httpclient
,不依賴瀏覽器使用閘道器
Gateway
註解:@CrossOrigin
在控制層加入允許跨域的註解,即可完成一個計畫中前後埠跨域的問題
閘道器整合
Spring Cloud Gateway
作為Spring Cloud生態系中的閘道器,目標是替代
Netflix Zuul
,其 不僅提供統一的路由方式,並且還基於Filer鏈的方式提供了閘道器基本的功能,例如:安全、監 控/埋點、限流等。
(1)路由
路由是閘道器最基礎的部份,路由資訊有一個ID、一個目的URL、一組斷言和一組 Filter組成。如果斷言路由為真,則說明請求的URL和配置匹配
(2)斷言
Java8中的斷言函式。
Spring Cloud Gateway
中的斷言函式輸入型別是Spring5.0框 架中的
ServerWebExchange
。
Spring Cloud Gateway
中的斷言函式允許開發者去定義匹配來自 於
http request
中的任何資訊,比如請求頭和參數等。
(3)過濾器
一個標準的
Spring webFilter
。
Spring cloud gateway
中的filter分為兩種型別的 Filter,分別是
Gateway Filter
和
Global Filter
。過濾器Filter將會對請求和響應進行修改處理
Spring cloud Gateway
發出請求。然後再由
Gateway Handler Mapping
中找到與請 求相匹配的路由,將其發送到
Gateway web handler
。Handler再透過指定的過濾器鏈將請求發 送到實際的服務執行業務邏輯,然後返回。
計畫中使用
新建模組
service_gateway
<dependencies>
<!-- 公共模組依賴 -->
<dependency>
<groupId>com.lzq</groupId>
<artifactId>service_utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 服務註冊 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
配置檔
#伺服端口
server.port=9090
# 服務名
spring.application.name=service-gateway
# nacos服務地址 預設8848
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8888
#使用服務發現路由
spring.cloud.gateway.discovery.locator.enabled=true
#設定路由id
spring.cloud.gateway.routes[0].id=service-hosp
#設定路由的uri lb負載均衡
spring.cloud.gateway.routes[0].uri=lb://service-hosp
#設定路由斷言,代理servicerId為auth-service的/auth/路徑
spring.cloud.gateway.routes[0].predicates= Path=/*/hosp/**
#設定路由id
spring.cloud.gateway.routes[1].id=service-cmn
#設定路由的uri
spring.cloud.gateway.routes[1].uri=lb://service-cmn
#設定路由斷言,代理servicerId為auth-service的/auth/路徑
spring.cloud.gateway.routes[1].predicates= Path=/*/cmn/**
#設定路由id
spring.cloud.gateway.routes[2].id=service-hosp
#設定路由的uri
spring.cloud.gateway.routes[2].uri=lb://service-hosp
#設定路由斷言,代理servicerId為auth-service的/auth/路徑
spring.cloud.gateway.routes[2].predicates= Path=/*/userlogin/**
建立啟動類
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication. class, args);
}
}
修改前端
.evn
檔,改成存取閘道器埠號
做集群部署時,他會根據名稱實作負載均衡
跨域理解:發送請求後,閘道器過濾器會進行請求攔截,將跨域放行,轉發到伺服器中
跨域配置類
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
若之前采用註解跨域,需要將
@CrossOrigin
去掉
Httpclient
常見的使用場景:多系統之間介面的互動、爬蟲
http原生請求,獲取百度首頁程式碼
public class HttpTest {
@Test
public void test1() throws Exception {
String url = "https://www.badu.com";
URL url1 = new URL(url);
//url連線
URLConnection urlConnection = url1.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
//獲取httpURLConnection輸入流
InputStream is = httpURLConnection.getInputStream();
//轉換為字串
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader);
String line;
//將字串一行一行讀取出來
while ((line = br.readLine())!= null){
System.out.println(line);
}
}
}
//設定請求型別
httpURLConnection.setRequestMethod("GET");
//請求包含 請求行、空格、請求頭、請求體
//設定請求頭編碼
httpURLConnection.setRequestProperty("Accept-Charset","utf-8");
使用
HttpClient
發送請求、接收響應
建立
HttpClient
物件。建立請求方法的例項,並指定請求URL。如果需要發送GET請求,建立
HttpGet
物件;如果需要發送POST請求,建立HttpPost
物件。如果需要發送請求參數,可呼叫
HttpGet
、HttpPost
共同的setParams(HetpParams params)
方法來添加請求參數;對於HttpPost
物件而言,也可呼叫setEntity(HttpEntity entity)
方法來設定請求參數。呼叫
HttpClient
物件的execute(HttpUriRequest request)
發送請求,該方法返回一個HttpResponse
。呼叫
HttpResponse
的getAllHeaders()
、getHeaders(String name)
等方法可獲取伺服器的響應頭;呼叫HttpResponse
的getEntity()
方法可獲取HttpEntity
物件,該物件包裝了伺服器的響應內容。程式可透過該物件獲取伺服器的響應內容。釋放連線。無論執行方法是否成功,都必須釋放連線
整合測試,添加依賴
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
@Test
public void test2(){
//可關閉的httpclient客戶端,相當於開啟一個瀏覽器
CloseableHttpClient client = HttpClients.createDefault();
String url = "https://www.baidu.com";
//構造httpGet請求物件
HttpGet httpGet = new HttpGet(url);
//響應
CloseableHttpResponse response = null;
try {
response = client.execute(httpGet);
// 獲取內容
String result = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}finally {
//關閉流
if (client != null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
計畫中使用,系統呼叫平台介面保存資訊,根據傳入josn數據保存資訊
系統中
@RequestMapping(value="/hospital/save",method=RequestMethod.POST)
public String saveHospital(String data, HttpServletRequest request) {
try {
apiService.saveHospital(data);
} catch (YyghException e) {
return this.failurePage(e.getMessage(),request);
} catch (Exception e) {
return this.failurePage("數據異常",request);
}
return this.successPage(null,request);
}
saveHospital
方法
@Override
public boolean saveHospital(String data) {
JSONObject jsonObject = JSONObject.parseObject(data);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("hoscode","10000");
paramMap.put("hosname",jsonObject.getString("hosname"))
//圖片
paramMap.put("logoData", jsonObject.getString("logoData"));
// http://localhost:8201/api/hosp/saveHospital
//httpclient
JSONObject respone =
HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveHospital");
System.out.println(respone.toJSONString());
if(null != respone && 200 == respone.getIntValue("code")) {
returntrue;
} else {
throw new YyghException(respone.getString("message"), 201);
}
}
HttpRequestHelper
工具類
/**
* 封裝同步請求
* @param paramMap
* @param url
* @return
*/
public static JSONObject sendRequest(Map<String, Object> paramMap, String url){
String result = "";
try {
//封裝post參數
StringBuilder postdata = new StringBuilder();
for (Map.Entry<String, Object> param : paramMap.entrySet()) {
postdata.append(param.getKey()).append("=")
.append(param.getValue()).append("&");
}
log.info(String.format("--> 發送請求:post data %1s", postdata));
byte[] reqData = postdata.toString().getBytes("utf-8");
byte[] respdata = HttpUtil.doPost(url,reqData);
result = new String(respdata);
log.info(String.format("--> 應答結果:result data %1s", result));
} catch (Exception ex) {
ex.printStackTrace();
}
return JSONObject.parseObject(result);
}
HttpUtil
工具類
public static byte[] send(String strUrl, String reqmethod, byte[] reqData) {
try {
URL url = new URL(strUrl);
HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
httpcon.setDoOutput(true);
httpcon.setDoInput(true);
httpcon.setUseCaches(false);
httpcon.setInstanceFollowRedirects(true);
httpcon.setConnectTimeout(CONN_TIMEOUT);
httpcon.setReadTimeout(READ_TIMEOUT);
httpcon.setRequestMethod(reqmethod);
httpcon.connect();
if (reqmethod.equalsIgnoreCase(POST)) {
OutputStream os = httpcon.getOutputStream();
os.write(reqData);
os.flush();
os.close();
}
BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"utf-8"));
String inputLine;
StringBuilder bankXmlBuffer = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
bankXmlBuffer.append(inputLine);
}
in.close();
httpcon.disconnect();
return bankXmlBuffer.toString().getBytes();
} catch (Exception ex) {
log.error(ex.toString(), ex);
return null;
}
}
對應平台介面
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
@Autowired
private HospitalService hospitalService;
@ApiOperation(value = "上傳醫院")
@PostMapping("saveHospital")
public R saveHospital(HttpServletRequest request) {
//透過request取到前端介面傳過來的值
Map<String, String[]> parameterMap = request.getParameterMap();
//將陣列值轉換成一個值
Map<String, Object> paramMap = HttpRequestHelper.switchMap(parameterMap);
//將map集合轉成josn字串
String mapStr = JSONObject.toJSONString(paramMap);
//josn字串轉成物件
Hospital hospital = JSONObject.parseObject(mapStr, Hospital. class);
//加入MongoDB中
hospitalService.saveHosp(hospital);
return R.ok();
}
}
即可完成不同系統中的相互呼叫。
來源:blog.csdn.net/weixin_52210557/article/details/122803085
END
看完本文有收獲?請轉發分享給更多人
關註「Java編程鴨」,提升Java技能
關註Java編程鴨微信公眾號,後台回復:碼農大禮包可以獲取最新整理的技術資料一份。涵蓋Java 框架學習、架構師學習等!
文章有幫助的話,在看,轉發吧。
謝謝支持喲 (*^__^*)