跨域請求的解決方案

1 本節任務

 
理解 ajax 的跨域訪問
 

2Ajax 跨域介紹

 
跨域,指的是瀏覽器不能執行其餘網站的腳本。它是由瀏覽器的同源策略形成的,是瀏覽器
對 JavaScript 施加的安全限制。
 
什麼是同源策略: 所謂的同源,指的是域名、協議、端口均相等。
不一樣源的系統使用 ajax 發送求,會存在跨域的問題:例如
http://www.abc.com/ 訪問 http://www.xyz.com 域名不一致,存在跨域
http://www.abc.com/ 訪問 https://www.abc.com 協議不一致,存在跨域
http://www.abc.com:80/ 訪問 http://www.abc.com:81 端口不一致,存在跨域 
 
 

3Ajax 跨域問題

 

3.1 創建 ajax-origin 項目

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjsxt.ajax.origin</groupId> <artifactId>ajax-origin</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties>
<!-- spring 依賴 --> <spring.version>4.3.18.RELEASE</spring.version> <jstl.version>1.2</jstl.version> <servlet-api.version>2.5</servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <jackson.version>2.9.0</jackson.version>
</properties> <dependencies>
<!-- jsp 相關依賴 -->
<!-- servlet 依賴 -->
<!-- jstl 依賴 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version>
</dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope>
</dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope>
</dependency>
</dependencies> <build> <finalName>ajax</finalName> <plugins>
<!-- 配置 Tomcat 插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/ajax</path> <port>9090</port>
</configuration>
</plugin>
</plugins>
</build>
</project>
View Code

 

3.2 發送 Ajax 請求

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script type="text/javascript">
function sendAjax(){
$.post("http://localhost:7070/order/loadOrderList02","uid=1234",function(data){
alert(data);
});
}
</script>
</head> <body><a href="javascript:sendAjax()">sendAjax</a>
</body>
</html>
View Code

 

3.3 觀察跨域問題 

 

 

4Ajax 跨域解決方案

 

4.1 服務器段解決

 
服務端設置 response header 中 Access-Control-Allow-Origin 字段
 

4.2 前端 JSONP 解決

 
利用 script 標籤,不受同源策略的限制,用戶從服務請求數據,服務器返回一個帶有方法和數據
的 js 代碼。
 
 

1 本節任務

 
服務器段,使用 CORSFilter 過濾器解決跨域問題
 

2CORSFilter 解決跨域訪問原理

 
經過 CORSFilter 過濾器在服務器端修改 Http 的響應頭
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: http://example.com:8080/
 

3 修改 order-sys 項目

 

3.1 添加 CORSFilter 依賴

<dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>2.5</version> <scope>runtime</scope>
</dependency>
View Code

 

3.2web.xml 配置 CORSFilter

<filter> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <init-param>
<param-name>cors.allowOrigin</param-name> 
<param-value>*</param-value>
</init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>Accept, Origin, X-Requested-With, Content-Type, 
Last-Modified</param-value>
</init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <param-value>Set-Cookie</param-value>
</init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value>
</init-param>
</filter> <filter-mapping> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern>
</filter-mapping>
View Code
3.3 啓動 order-sys 項目
4 啓動 ajax-origin 測試
 
 

 

 

<!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version>
</dependency>
View Code

3.3 修改 OrderController 類

 
Controller 添加一個接收遠程 ajax 請求的方法,該方法後一個接收回調函數的參數.
/****
* 接收 jsonp 請求,響應 js 的字符串到客戶端
* @param uid
* @param callback
* @return
*/
@RequestMapping("/loadOrderList03")
@ResponseBody
public String loadOrderList03(String uid,String callback){
System.out.println("uid="+uid);
Order o1=new Order();
o1.setId("111");
o1.setTotal(123.0);
o1.setDate("2018-10-10");
Order o2=new Order();
o2.setId("222");
o2.setTotal(1232.0);
o2.setDate("2018-10-13");
Order o3=new Order();
o3.setId("333");
o3.setTotal(333.0);
o3.setDate("2018-10-31");
List<Order> list = new ArrayList<>();
list.add(o1);
list.add(o2);
list.add(o3);
//result 是須要響應到客戶端的 js 代碼
String result=callback+"("+JSON.toJSONString(list)+")";
return result; }
View Code

3.4 啓動 order-sys 項目

 

4 修改 ajax-origin 項目

 

4.1 導入 juqery 函數庫

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>

 

4.2 發送請求

 
利用<script src="url?callback=doSomething"></script>發送請求
<script
src="http://localhost:7070/order/loadOrderList03?uid=9999&callback=doCallback"></script>

 

 

4.3 定義 callback 回調函數

function doCallback(data){
//將 json 對象轉化爲字符串
var str=JSON.stringify(data);
alert(str);
}

 

4.4 啓動 ajax-origin 測試
 

5jquery 對 jsonp 支持

function sendAjax(){
/* $.post("http://localhost:7070/order/loadOrderList02","uid=1234",function(data){
alert(data);
});
*/
$.getJSON("http://localhost:7070/order/loadOrderList03?callback=?","uid=1234",
function(data){
//將 json 對象轉化爲字符串
var str=JSON.stringify(data);
alert(str);
});
}
View Code

 

 

 

 

 

 

3RMI 模擬服務器集羣部署

 

3.1 創建 rmi-cluster-provider 項目

 

3.2 創建 UserService 接口

package com.bjsxt.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
/***
* 建立須要發佈的服務對應的業務接口
* @author Administrator
* Remote 接口用於標識其方法能夠從非本地虛擬機上調用的接口。
*/
public interface UserService extends Remote{
public String helloRmi(String name) throws RemoteException;
}

3.3 創建 UserServiceImpl 實現類

package com.bjsxt.service.impl;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import com.bjsxt.service.UserService;
/***
* 建立發佈的服務對應的實現類
* @author Administrator
*
*/
public class UserServiceImpl
extends UnicastRemoteObject implements UserService {
public UserServiceImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
@Override
public String helloRmi(String name) throws RemoteException {
// TODO Auto-generated method stub
return "hello "+name; } }
View Code

 

3.4 發佈集羣服務

 
啓動程序三次,每次啓動修改端口號,實現服務的集羣部署
package com.bjsxt.app;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import com.bjsxt.service.UserService;
import com.bjsxt.service.impl.UserServiceImpl;
public class ProviderApp {
public static void main(String[] args) {
try{
/****
* 完成遠程服務的發佈
*/
//將遠程服務發佈在本地的 8888 端口
LocateRegistry.createRegistry(8888);
//發佈的遠程服務的訪問 url
String name="rmi://localhost:8888/rmi";
//建立一個提供具體服務的遠程對象
UserService userService = new UserServiceImpl();
//給提供遠程服務的對象綁定一個 url
Naming.bind(name, userService);
System.out.println("=============發佈 rmi 遠程服務============");
}catch(Exception ex){
ex.printStackTrace();
} } }
View Code

 

4RMI 消費集羣服務

 

4.1 創建 rmi-cluster-consumer 項目

 
 
4.2 拷貝 UserService 接口
 
4.3 實現集羣服務消費
 
package com.bjsxt.app;
import java.rmi.Naming;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import com.bjsxt.service.UserService;
public class ConsumerApp {
public static void main(String[] args) {
List<String> urls = new ArrayList<String>();
urls.add("rmi://localhost:7777/rmi");
urls.add("rmi://localhost:8888/rmi");
urls.add("rmi://localhost:9999/rmi");
String url =null;
while(true){
try{
//經過隨機的負載均衡算法,產生隨機的訪問地址
int index=ThreadLocalRandom.current().nextInt(urls.size());
//發佈的遠程服務的訪問 url
url = urls.get(index);
//經過發佈的遠程服務的 url,得到遠程服務的代理對象
UserService userService = (UserService) Naming.lookup(url);
System.out.println("得到的遠程服務的代理對象:"
+userService.getClass().getName());
//經過遠程服務的代理對象調用遠程服務方法
String result = userService.helloRmi("===="+url+"======= rmi");
System.out.println("result="+result);
Thread.sleep(3000);
}catch (Exception e) {
// TODO: handle exception
urls.remove(url); //剔除不可用的服務的地址
e.printStackTrace();
} } } }
View Code

相關文章
相關標籤/搜索