跨域是前后端分离,前端页面发起异步ajax请求,而浏览器因为同源策略导致请求失败,请求正确到了服务端,而且服务端也正常处理,只不过浏览器不认可,所以跨域问题的门槛是浏览器,也就是web前端,但是服务端可以解决这个跨域问题。
springboot解决跨域,最容易想到的就是配置一个继承自WebMvcConfigurerAdapter的类。
先构建跨域请求:
准备:
1.准备一个nginx服务器,配置页面,启动,访问80端口,这是一个域,
2.准备springboot代码,配置简单controller,提供对外访问端口8080,这是另一个域,正好构成跨域环境。
ajax-cors.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>ajax</title>
<style>
#root input{padding:10px;border:1px solid #ddd;color:#fff;border-radius: 3px;background: lightgreen;font-size: 16px;}
#root .box{padding:5px;}
#root textarea{width:790px;height:100px;resize: none;}
</style>
</head>
<body>
<div id="root">
<div class="box">
<input type="button" value="ajax-cors" onclick="handleclick()"/>
</div>
<div class="box">
<input type="button" value="ajax-cors-springboot" onclick="handleclick2()"/>
</div>
<div class="box">
<textarea id="output"></textarea>
</div>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script>
var base_url = "http://localhost:3000";
function handleclick(){
$.ajax({
url:base_url+"/koa/test",
type:"get",
success:function(data){
$("#output").val(JSON.stringify(data))
},
error:function(xhr,textStatus,errorThrown){
$("#output").val(textStatus)
}
})
}
function handleclick2(){
$.ajax({
url:"http://localhost:8080/ajaxcors/test",
type:"get",
success:function(data){
$("#output").val(JSON.stringify(data))
},
error:function(xhr,textStatus,errorThrown){
$("#output").val(textStatus)
}
})
}
</script>
</body>
</html>
springboot项目依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
</dependencies>
请求控制类:
package com.xxx.springboot.web;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
@RestController
@RequestMapping("/ajaxcors")
public class AjaxCorsController {
@GetMapping("/test")
public Map<String, Object> test(){
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", 200);
JSONObject json = new JSONObject();
json.put("id", 102);
json.put("name", "buejee");
json.put("age", 18);
map.put("data", json);
return map;
}
}
分别启动springboot和nginx
先来通过浏览器检查springboot提供的http://localhost:8080/ajaxcors/test接口:
接口访问正常。
浏览器访问nginx控制下的页面:http://localhost/ajax-cors.html
因为跨域,请求失败。
解决办法就是增加一个配置:
package com.xxx.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SuppressWarnings("deprecation")
@Configuration
public class SpringMvcConfigurer extends WebMvcConfigurerAdapter{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedMethods("*")
.allowedOrigins("*")
.allowedHeaders("*");
}
}
再次启动springboot服务,访问正常:
/
springboot解决跨域问题,还有两种办法,就是通过设置Filter和使用注解@CrossOrigin的方法:
设置Filter:
这个Filter bean可以在启动类里面添加,bean对象需要一个Filter实现类:
@Bean
public FilterRegistrationBean registerFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.addUrlPatterns("/*");
bean.setFilter(new MyCorsFilter());
return bean;
}
自定义MyCorsFilter类:
package com.xxx.springboot.config;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class MyCorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "http://localhost:8090");
chain.doFilter(request, response);
}
}
另外最简单的办法就是在控制类上增加注解@CrossOrigin
服务端解决跨域,思路都类似,就是设置响应头,允许对应的域,对应的方法,对应的请求头,对应的请求路径,一般可以通过通配符"*"设置允许一切域、请求头、方法。
异步ajax跨域问题,不是服务端导致的,但是可以通过在服务端做设置解决跨域问题。