出现跨域的原因:浏览器会限制脚本中发起的跨站请求
场景:假设有AB两台服务器,A服务器前台访问B服务器后台,就会出现跨域的问题。
报错如下:
解决方法:解决ajax跨域可以通过jsonp、过滤器、nginx转发3种,由于jsonp只支持get,所以jsonp不考虑。
1.过滤器使用方法:
1.1 web.xml
<!-- cors解决跨域访问问题 -->
<filter>
<filter-name>cors</filter-name>
<filter-class>com.cloudtech.web.filter.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/external/*</url-pattern>
</filter-mapping>
注意:1.项目是spring mvc项目,如果是spring boot项目在过滤器类上增加对应的注解就行。
2. 在web.xml中配置过滤器,需要放在其他过滤器之前,以免造成影响
1.2 过滤器类
package com.cloudtech.web.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author wude
* @version 1.0.0
* @description
* @date 2018-08-17 14:38
*/
public class SimpleCORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
httpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
httpServletResponse.addHeader("Access-Control-Allow-Headers", "Content-Type");
httpServletResponse.addHeader("Access-Control-Max-Age", "1800");//30 min
filterChain.doFilter(servletRequest, httpServletResponse);
}
@Override
public void destroy() {
}
}
Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。
Access-Control-Allow-Credentials: 是否允许请求带有验证信息,XMLHttpRequest请求的withCredentials标志设置为true时,认证通过,浏览器才将数据给脚本程序。
Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息
Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数
Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开
Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感
注意: 我之前只配置了Access-Control-Allow-Origin参数,试了很久还是不行,一直提示我配置Access-Control-Allow-Headers参数。
1.3 前端代码
function test(){
var stationList = new Array;
stationList.push({"code":2,"mode":2,"stationId":"G3561"});
$.ajax({
url : "http://XXXX:9980/climate/external/reverseControll",
data : JSON.stringify(stationList),
type : 'POST',
contentType: "application/json",
dataType : 'json',
success : function(data) {
if(data.code == 0){
return layer.msg(data.error);
}else{ //成功
layer.closeAll();
layer.msg(data.error, {icon: 1});
var index = $(".layui-tab-title .layui-this").index();
setTimeout(function(){
$("#form").submit();
},1000);
}
}
});
}
1.4 后台controller配置
/**
* 远程下发指令
*
* @param seconds
* @return
*/
@RequestMapping(value = "reverseControll", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public BaseDataResult reverseControll(@RequestBody List<SecondSwitch> seconds) {
return new BaseDataResult(0,"成功!")
}
1.5 测试
打印"成功!",表示跨域配置成功。