SpringBoot解决跨域问题
准备 js 脚本!DOCTYPE html html langzh-CN head meta charsetUTF-8 title跨域测试/title /head body script fetch(http://127.0.0.1:8080/test, { method: GET }) .then(response { return response.json(); }) .then(data { console.log(返回的数据, data); }) .catch(error { console.error(请求出错, error); }); /script /body /html准备后端代码RestController public class Controller { GetMapping(/test) public int test() { return 200; } }启动后端服务现在直接打开 html 文件控制台会报错。Access to fetch at http://127.0.0.1:8080/test from origin null has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource.报错信息提示请求的资源没有一个叫做 Access-Control-Allow-Origin 的头部其实只要在返回的响应信息的响应头中添加一个键值对就可以了。RestController public class Controller { GetMapping(/test) public int test(HttpServletResponse httpServletResponse) { httpServletResponse.addHeader(Access-Control-Allow-Origin, *); return 200; } }Access-Control-Allow-Origin: *所有网页都可以向服务器发送请求服务器都允许跨域。Access-Control-Allow-Origin: https://baidu.com只有 url 为 https://baidu.com 的网页发起的请求才允许跨域。但是给每一个方法都手动编写这行代码太麻烦了SpringBoot 有没有提供什么快捷方式呢方案一实现 WebMvcConfigurer 接口也就是添加跨域的配置Configuration public class WebMvcConfiguration implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) // 所有接口跨域 .allowCredentials(true) // 允许浏览器在跨域请求中发送认证信息 .allowedOriginPatterns(*) // Access-Control-Allow-Origin: * .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) // 允许的方法 .allowedHeaders(*) // 允许的请求头 .exposedHeaders(*); // 哪些响应头可以暴露给前端 } }方案二在类或者方法上添加 CrossOrigin 注解整个类的所有接口、单个接口可以跨域RestController public class Controller { GetMapping(/test) CrossOrigin public int test() { return 200; } }停之停之看到这个注解我突然想到不就是在响应头里面塞键值对吗我们完全可以通过面向切面编程自己实现这个效果。引入依赖dependency groupIdorg.aspectj/groupId artifactIdaspectjweaver/artifactId version1.9.20/version /dependency创建注解Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) // CO CrossOrigin public interface CO { }编写切面类Component Aspect public class CrossOriginAspect { After(annotation(org.example.demo.CO)) public void work() { ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes null) { return; } HttpServletResponse response attributes.getResponse(); if (response null) { return; } // add K-V response.setHeader(Access-Control-Allow-Origin, *); response.setHeader(Access-Control-Allow-Methods, GET,POST,PUT,DELETE,OPTIONS); response.setHeader(Access-Control-Allow-Headers, *); System.out.println(跨域切面触发); } }现在在接口上添加 CO 注解同样可以实现跨域效果日志也正常输出RestController public class Controller { GetMapping(/test) CO public int test() { return 200; } }下面是跨域的两个知识点服务器可以正常处理跨域的请求并不是跨域的请求就不处理。只是响应返回到浏览器之后js 拿不到返回的数据可以在后端服务中添加日志或者打断点来实践。只有浏览器才有跨域的限制这个是因为浏览器的同源策略具体看这里 浏览器的同源策略 - 安全 | MDN。像我们在后端服务中用 okhttp 调用第三方接口是没有跨域的限制的。