ajax 跨域 springboot

 

CORS 定义

Cross-Origin Resource Sharing(CORS)跨来源资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。

 

CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS

 

方法一:Controller增加spring注解:

@CrossOrigin

这里虽然指SpringBoot但是SpringMVC也是一样的,要求在Spring4.2及以上的版本

 

方法二:使用filter拦截器:

Application增加FilterRegistrationBean的@Bean:

package com.xc.boot;
import com.xc.boot.filter.CrosFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class BootApplication {

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

   @Bean
   public FilterRegistrationBean registerFilter(){
      FilterRegistrationBean bean = new FilterRegistrationBean();
      bean.addUrlPatterns("/*");
      bean.setFilter(new CrosFilter());
      return bean;
   }
}

 

创建CrosFilter拦截器类:

package com.xc.boot.filter;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
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)) {
            System.out.println("origin:" + origin);
            res.addHeader("Access-Control-Allow-Origin", origin);//允许其他域名访问
        }

        String headers = req.getHeader("Access-Control-Request-Headers");
        if (!StringUtils.isEmpty(headers)) {
            res.addHeader("Access-Control-Allow-Headers", headers);//允许的请求头字段
        }

        res.addHeader("Access-Control-Allow-Methods", "*");//允许的请求类型
        res.addHeader("Access-Control-Max-Age", "1800");//预检结果缓存时间
        res.addHeader("Access-Control-Allow-Credentials", "true");//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

 

创建测试controler类:

package com.xc.boot.controller;
import com.xc.boot.common.ResultBean;
import com.xc.boot.entity.User;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
@RestController
@RequestMapping("ajax")
public class AjaxController {
    @RequestMapping("get1")
    public ResultBean index() {
        System.out.println("get1:" + new Date());
        return new ResultBean("get1 ok");
    }

    @PostMapping("/postJson")
    public ResultBean postJson(@RequestBody User user) {
        System.out.println("postJson:" + new Date());
        return new ResultBean("postJson " + user.getName());
    }

    @GetMapping("/getCookie")
    public ResultBean getCookie(@CookieValue(value = "cookie1") String cookie1) {
        System.out.println("getCookie:" + new Date());
        return new ResultBean("getCookie " + cookie1);
    }

    @GetMapping("/getHeader")
    public ResultBean getHeader(@RequestHeader(value = "x-header1") String header1, @RequestHeader(value = "x-header2") String header2) {
        System.out.println("getHeader:" + new Date());
        return new ResultBean("getHeader " + header1 + " " + header2);
    }
}

 

创建测试ajax:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AJAX跨越完全讲解</title>
<script src="jquery-1.11.3.js"></script>
<link rel="stylesheet" type="text/css" href="jasmine-2.8.0/jasmine.css">
<script src="jasmine-2.8.0/jasmine.js"></script>
<script src="jasmine-2.8.0/jasmine-html.js"></script>
<script src="jasmine-2.8.0/boot.js"></script>
</head>
<body>
   <script>
      function get1() {
         $.getJSON("http://localhost:8082/boot/ajax/get1").then(function(result) {
            console.log(result);
         });
      }

      // 每一个测试用例的超时时间
      jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
      // 请求的接口的前缀
      var base = "http://localhost:8082/boot/ajax";
      //测试模块
      describe("晓风轻-ajax跨越完全讲解", function() {
         // 测试方法
         it("get1请求", function(done) {
            // 服务器返回的结果
            var result;
            $.getJSON(base + "/get1").then(function(jsonObj) {
               result = jsonObj;
            });
            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function() {
               expect(result).toEqual({
                  "data" : "get1 ok"
               });
               // 校验完成,通知jasmine框架
               done();
            }, 100);
         });
         
         // 测试方法
         /*it("jsonp请求", function(done) {
            // 服务器返回的结果
            var result;
            $.ajax({
               url: base +"/get1",
               dataType: "jsonp",
               jsonp: "callback2",
               cache:true,
               success: function(json){
                  result = json;
               }
            });
            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function() {
               expect(result).toEqual({
                  "data" : "get1 ok"
               });
               // 校验完成,通知jasmine框架
               done();
            }, 100);
         });*/

         
         it("postJson请求", function(done) {
            // 服务器返回的结果
            var result;
            $.ajax({
               type : "post",
               url: base + "/postJson",
               contentType : "application/json;charset=utf-8",
               data: JSON.stringify({name: "xc"}),
               success: function(json){
                  result = json;
               }
            });
            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function() {
               expect(result).toEqual({
                  "data" : "postJson xc"
               });
               // 校验完成,通知jasmine框架
               done();
            }, 100);
         });
         
         it("getCookie请求", function(done) {
            // 服务器返回的结果
            var result;
            $.ajax({
               type : "get",
               url: base + "/getCookie",
               xhrFields:{
                  withCredentials:true
               },
               success: function(json){
                  result = json;
               }
            });
            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function() {
               expect(result).toEqual({
                  "data" : "getCookie xc"
               });
               // 校验完成,通知jasmine框架
               done();
            }, 100);
         });

         it("getHeader请求", function(done) {
            // 服务器返回的结果
            var result;
            $.ajax({
               type : "get",
               url: base + "/getHeader",
               headers:{
                  "x-header1" : "AAA"
               },
               beforeSend: function(xhr){
                  xhr.setRequestHeader("x-header2","BBB")
               },
               success: function(json){
                  result = json;
               }
            });
            // 由于是异步请求,需要使用setTimeout来校验
            setTimeout(function() {
               expect(result).toEqual({
                  "data" : "getHeader AAA BBB"
               });
               // 校验完成,通知jasmine框架
               done();
            }, 100);
         });
      
      });
   </script>
</body>
</html>