跨域请求的解决方案

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

原文地址:https://www.cnblogs.com/wq-9/p/11751232.html