zoukankan      html  css  js  c++  java
  • 跨域请求的解决方案

    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

  • 相关阅读:
    git本地分支管理
    SpringMVC的第一个入门案例
    原来热加载如此简单,手动写一个 Java 热加载吧
    Spring Boot2 系列教程(十七)SpringBoot 整合 Swagger2
    SpringBoot 开发案例之参数传递的正确姿势
    MENU Java 中的 final、finally、finalize 有什么不同?
    Java Web 学习(1) —— Servlet
    Spring 基础知识学习
    SpringBoot中如何灵活的实现接口数据的加解密功能?
    Java中常用的四种线程池
  • 原文地址:https://www.cnblogs.com/wq-9/p/11751232.html
Copyright © 2011-2022 走看看