资讯专栏INFORMATION COLUMN

慕课网_《Ajax跨域完全讲解》学习总结

fredshare / 2871人阅读

摘要:时间年月日星期三说明本文部分内容均来自慕课网。当预检请求通过的时候,才发送真正的请求。

时间:2018年04月18日星期三
说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com
教学源码:https://github.com/zccodere/s...
学习源码:https://github.com/zccodere/s...

第一章:课程介绍 1-1 课程介绍

课程介绍

什么是AJAX跨域问题

产生AJAX跨域问题的原因

解决AJAX跨域问题的思路和方法

什么是AJAX跨域问题

简单来说,就是前端调用后端服务接口时

如果服务接口不是同一个域,就会产生跨域问题

AJAX跨域场景

前后端分离、服务化的开发模式

前后端开发独立,前端需要大量调用后端接口的场景

只要后端接口不是同一个域,就会产生跨域问题

跨域问题很普遍,解决跨域问题也很重要

AJAX跨域原因

浏览器限制:浏览器安全校验限制

跨域(协议、域名、端口任何一个不一样都会认为是跨域)

XHR(XMLHttpRequest)请求

AJAX跨域问题解决思路

浏览器:浏览器取下跨域校验,实际价值不大

XHR:不使用XHR,使用JSONP,有很多弊端,无法满足现在的开发要求

跨域:被调用方修改支持跨域调用(指定参数);调用方修改隐藏跨域(基于代理)

编写测试代码

被调用方后端代码编写:Spring Boot

调用方前端代码编写:Jquery

引入前端Jasmine测试框架

第二章:环境搭建 2-1 后端项目

代码编写

1.创建名为ajax-server的maven工程pom如下



    4.0.0

    com.myimooc
    ajax-server
    0.0.1-SNAPSHOT
    jar

    ajax-server
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.1.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



2.编写AjaxServerStart类

package com.myimooc.ajax.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 
* 标题: 启动类
* 描述: AJAX跨域讲解后端项目
* * @author zc * @date 2018/04/18 */ @SpringBootApplication public class AjaxServerStart { public static void main(String[] args) { SpringApplication.run(AjaxServerStart.class, args); } }

3.编写ResultBean类

package com.myimooc.ajax.server.vo;

import java.io.Serializable;

/**
 * 
* 标题: REST请求响应POJO类
* 描述: 封装请求响应结果
* * @author zc * @date 2018/04/18 */ public class ResultBean implements Serializable{ private static final long serialVersionUID = 7867107433319736719L; private String data; public ResultBean(String data) { this.data = data; } public String getData() { return data; } public void setData(String data) { this.data = data; } }

4.编写TestController类

package com.myimooc.ajax.server.controller;

import com.myimooc.ajax.server.vo.ResultBean;
import com.myimooc.ajax.server.vo.User;
import org.springframework.web.bind.annotation.*;

/**
 * 
* 标题: 测试控制器
* 描述: 提供REST服务
* 使用 @CrossOrigin 注解支持跨域,可以放到类或方法上面 * @author zc * @date 2018/04/18 */ @RestController @RequestMapping("/test") //@CrossOrigin public class TestController { @GetMapping("/get1") public ResultBean get1() { System.out.println("TestController.get1"); return new ResultBean("get1ok"); } @PostMapping("/postJson") public ResultBean postJson(@RequestBody User user) { System.out.println("TestController.postJson"); return new ResultBean("postJson" + user.getName()); } @GetMapping("/getCookie") public ResultBean getCookie(@CookieValue(value = "cookie1") String cookie1) { System.out.println("TestController.getCookie"); return new ResultBean("getCookie" + cookie1); } @GetMapping("/getHeader") public ResultBean getHeader( @RequestHeader("x-header1") String header1, @RequestHeader("x-header2") String header2) { System.out.println("TestController.getHeader"); return new ResultBean("getHeader" + header1+header2); } }
2-2 前端项目

代码编写

1.创建名为ajax-client的maven工程pom如下



    4.0.0

    com.myimooc
    ajax-client
    0.0.1-SNAPSHOT
    jar

    ajax-client
    Demo project for Spring Boot

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.1.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.webjars
            jquery
            3.3.0
        
        
            org.webjars
            jasmine
            2.5.0
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



2.编写index.html




    
    Index

    

    
    
    
    




发生get1请求





3.编写application.properties

server.port=8081

4.编写AjaxClientStart类

package com.myimooc.ajax.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AjaxClientStart {

    public static void main(String[] args) {
        SpringApplication.run(AjaxClientStart.class, args);
    }
}

5.启动AjaxServerStart和AjaxClientStart,并访问http://localhost:8081,点击发生get1请求,产生跨域问题如下

第三章:解决跨域 3-1 禁止检查

Chrome浏览器的跨域设置

Windows方法

参考文档:https://www.cnblogs.com/laden...

使用说明:在属性页面中的目标输入框里加上:--disable-web-security --user-data-dir=C:MyChromeDevUserData

Mac OS方法

参考文档:http://blog.csdn.net/justinji...

使用说明:用命令行打开 Google Chrome:open -a "Google Chrome" --args --disable-web-security

3-2 使用JSONP

代码编写

1.编写JsonpAdvice类

package com.myimooc.ajax.server.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

/**
 * 
* 标题: JSONP 全局处理
* 描述: 统一处理JSONP
* * @author zc * @date 2018/04/18 */ @ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{ public JsonpAdvice() { // 与前端约定好回调方法名称,默认是callback super("callback2"); } }

2.修改index.html

        // 测试方法
        it("jsonp请求", function (done) {
            // 服务器返回的结果
            var result;
            $.ajax({
                url: base + "/get1",
                dataType: "jsonp",
                jsonp:"callback2",
                success: function (res) {
                    result = res;
                }
            });

            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function () {
                expect(result).toEqual({
                    "data":"get1ok"
                });

                // 校验完成,通知jasmine框架
                done();
            },100);
        });

JSONP的弊端

服务器需要改动代码支持

只支持GET

发送的不是XHR请求

3-3 支持跨域

常见的JavaEE架构

跨域解决方向

被调用方解决

基于支持跨域的解决思路

基于Http协议关于跨域的相关规定,在响应头里增加指定的字段告诉浏览器,允许调用

跨域请求是直接从浏览器发送到被调用方

修改被调用方的Http服务器

调用方解决

基于隐藏跨域的解决思路

跨域请求不会浏览器直接发送到被调用方

而是从中间的Http服务器(Apache、Nginx)转发过去

修改调用方的Http服务器

被调用方支持跨域

【重点】Web应用服务器(Tomcat、Netty、WebLogic或应用程序)实现

Http服务器(Nginx)配置实现

Http服务器(Apache)配置实现

使用Filter解决

编写代码

1.编写CrosFilter类

package com.myimooc.ajax.server.config;

import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 
* 标题: 服务端解决跨域
* 描述: 使用Filter
* * @author zc * @date 2018/04/18 */ public class CrosFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse res = (HttpServletResponse)response; HttpServletRequest req = (HttpServletRequest)request; // 支持所有域 String origin = req.getHeader("Origin"); if (!StringUtils.isEmpty(origin)){ // 支持任何域名的跨域调用 且 支持带cookie(是被调用方域名的cookie,而不是调用方的cookie) res.addHeader("Access-Control-Allow-Origin",origin); } // 指定允许的域,带cookie时,origin必须是全匹配,不能使用 * // res.addHeader("Access-Control-Allow-Origin","http://localhost:8081"); // 允许所有域,但不能满足带 cookie 的跨域请求 // res.addHeader("Access-Control-Allow-Origin","*"); // 支持所有自定义头 String headers = req.getHeader("Access-Control-Allow-Headers"); if (!StringUtils.isEmpty(headers)){ // 允许所有header res.addHeader("Access-Control-Allow-Headers",headers); } // 允许所有header // res.addHeader("Access-Control-Allow-Headers","*"); // 指定允许的方法 // res.addHeader("Access-Control-Allow-Methods","GET"); // 允许所有方法 res.addHeader("Access-Control-Allow-Methods","*"); // 允许浏览器在一个小时内,缓存跨域访问信息(即上面三个信息) res.addHeader("Access-Control-Max-Age","3600"); // 启用 cookie res.addHeader("Access-Control-Allow-Credentials","true"); chain.doFilter(request,response); } @Override public void destroy() { } }

2.编写FilterConfig类

package com.myimooc.ajax.server.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 
* 标题: 配置类
* 描述: 注册CrosFilter
* * @author zc * @date 2018/04/18 */ @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean(){ FilterRegistrationBean filter = new FilterRegistrationBean(); filter.addUrlPatterns("/*"); filter.setFilter(new CrosFilter()); return filter; } }

3.启动AjaxServerStart和AjaxClientStart,并访问http://localhost:8081,跨域解决

简单请求与非简单请求

简单请求:浏览器先发送真正的请求后检查

请求方法:GET、HEAD、POST的一种

请求header:无自定义header;Content-Type为:text/plain、multipart/form-data、application/x-www-form-urlencoded的一种

非简单请求:浏览器先发预检命令,检查通过后,才发送真正的请求

常见的有:PUT、DELETE

其它条件:发送Json格式的请求、带自定义header的请求

预检命令:浏览器检测到跨域请求, 会自动发出一个OPTIONS请求, 就是所谓的预检(preflight)请求。当预检请求通过的时候,才发送真正的请求。

Nginx配置

修改主机hosts文件增加映射本地域名:127.0.0.1 b.com(表示被调用方的域名)

在conf目录下创建vhost目录

修改nginx.conf在最后面增加一行代码:include vhost/*.conf;

在vhost目录下创建b.com.conf

启动niginx,访问b.com/test/get1

编写b.com.conf

server{
    listen 80;
    server_name b.com;

    location /{
        proxy_pass http://localhost:8080/;

        add_header Access-Control-Allow-Methods *;
        add_header Access-Control-Max-Age 3600;
        add_header Access-Control-Allow-Credentials true;

        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Headers $http_access_control_allow_headers;

        if ($request_method = OPTIONS){
            return 200;
        }
    }
}

Apache配置

修改conf/httpd.conf找到LoadModule vhost_alias_module module/mod_vhost_alias.so取消注释

修改conf/httpd.conf找到LoadModule proxy_module module/mod_ proxy.so取消注释

修改conf/httpd.conf找到LoadModule proxy_http_module module/mod_ proxy_http.so取消注释

修改conf/httpd.conf找到LoadModule headers_module module/mod_ headers.so取消注释

修改conf/httpd.conf找到LoadModule rewrite_module module/mod_ rewrite.so取消注释

修改conf/httpd.conf找到Include conf/extra/httpd-vhosts.conf取消注释

修改conf/extra/httpd-vhosts.conf在最后面增加下面的内容即可


    ServerName b.com
    ErrorLog "logs/b.com-error.log"
    CustomLog "logs/b.com-access.log" common
    ProxyPass / http://localhost:8080/

    # 把请求头的origin值返回到Access-Control-Allow-Origin字段
    Header always set Access-Control-Allow-Origin "expr=%{req:origin}"

    # 把请求头的Access-Control-Allow-Headers值返回到Access-Control-Allow-Headers字段
    Header always Access-Control-Allow-Headers "expr=%{Access-Control-Allow-Headers}"

    Header always set Access-Control-Allow-Methods "*";
    Header always set Access-Control-Max-Age "3600";
    Header always set Access-Control-Allow-Credentials ""true";

    # 处理预检命令OPTIONS,直接返回204
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD}OPTIONS
    RewriteRule ^(.*)$"/" [R=204,L]

Spring框架支持

在类或方法上使用注解@CrossOrigin即可支持跨域

3-4 隐藏跨域

使用Nginx反向代理实现

修改主机hosts文件增加映射本地域名:127.0.0.1 a.com

在vhost目录下创建a.com.conf

启动niginx,访问a.com/ajaxserver/get1

编写a.com.conf

server{
    listen 80;
    server_name a.com;

    location /{
         proxy_pass http://localhost:8081/;
    }

    location /ajaxserver{
         proxy_pass http://localhost:8080/test/;
    }

}

使用Apache反向代理实现

修改conf/extra/httpd-vhosts.conf在最后面增加下面的内容即可


    ServerName a.com
    ErrorLog "logs/a.com-error.log"
    CustomLog "logs/a.com-access.log" common
    ProxyPass / http://localhost:8081/
    ProxyPass /ajaxserverapache http://localhost:8080/test

第四章:课程总结 4-1 课程总结

课程总结

产生原因:主要是浏览器对Ajax请求的限制

解决思路:JSONP、支持跨域、隐藏跨域

核心原理:了解Http协议关于跨域方面的规定

解决方法:使用Filter、Nginx正反向代理、Apache正反向代理、Spring框架支持

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69141.html

相关文章

  • AJAX跨域简单讲解【Python版】

    摘要:结果如图所示,第二个由于跨域仍然报错,第三个则正常输出在中修改也可以通过向浏览器返回特定响应头,告诉浏览器它是允许被跨域调用的,使用的添加和两个字段,更新如下将的方法请求的接口改为,依次点击,第二个已经可以正常输出内容 总结自慕课网:ajax跨域完全讲解,并且原视频中后台为JAVA,这里改成了Python。 什么是AJAX跨域 只要协议、域名、端口有任何一个不同,都被当作是不同的域,...

    xiaochao 评论0 收藏0
  • 课网_《如何使用高德云图在线制作属于你的地图》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。用户可以在服务器端调用云存储云检索从而构建自己的存储和检索服务,甚至可以制作自己的数据管理台。 时间:2017年08月13日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:云图产品介绍 1-1 云图产品介绍...

    k00baa 评论0 收藏0
  • 课网_《如何使用高德云图在线制作属于你的地图》学习总结

    摘要:时间年月日星期日说明本文部分内容均来自慕课网。用户可以在服务器端调用云存储云检索从而构建自己的存储和检索服务,甚至可以制作自己的数据管理台。 时间:2017年08月13日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:云图产品介绍 1-1 云图产品介绍...

    afishhhhh 评论0 收藏0
  • 课网_《RxJava与RxAndroid基础入门》学习总结

    时间:2017年10月16日星期一说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:课程简介 1-1 课程介绍 本门课程的主要内容 RxJava是什么 RxAndroid是什么 RxJava常用操作符(重点、难点) 怎样在项目中使用RxJava和RxAndroid 如何学...

    刘明 评论0 收藏0

发表评论

0条评论

fredshare

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<