ajax 跨域 springboot
CORS 定义
Cross-Origin Resource Sharing(CORS)跨来源资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。
CORS 对比 JSONP
都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题
- JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
- 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
- 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>