#说明
本文给出几种java后端配置跨域的方法,在tomcat7和8上测试通过。如果你只是为了前后端联调的话,那最好不要采用配置后端的方法,而是使用前端框架提供的解决方案,比如你使用的是vue框架的话,可以采用参考这篇博文:https://www.jianshu.com/p/95b2caf7e0da
#方法一
如果只需要Http的Get与Post方法跨域的话,则使用下面的方法可以很轻松的解决:
在web.xml中添加如下过滤器,这个过滤器是tomcat自带的,所以不需要添加任何额外的依赖:
<filter>
<filter-name>CorsFilterfilter-name>
<filter-class>org.apache.catalina.filters.CorsFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CorsFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
#方法二
方法一经过我的测试仅仅能够让post和put请求跨域,其他请求如put,delete请求仍然无法跨域,有的博客上说能够通过在上面的过滤器配置中添加如下的初始化参数来解决:
<filter>
<filter-name>CorsFilterfilter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilterfilter-class>
<init-param>
<param-name>cors.allowOriginparam-name>
<param-value>*param-value>
init-param>
<init-param>
<param-name>cors.supportedMethodsparam-name>
<param-value>GET, POST, HEAD, PUT, DELETEparam-value>
init-param>
<init-param>
<param-name>cors.supportedHeadersparam-name>
<param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modifiedparam-value>
init-param>
filter>
从参数名看,上面的参数似乎非常有可能解决问题,但是我尝试了之后,delete和put等请求依旧无法跨域,但是我服务器给客户端的api想要尽量满足RESTful的风格,那么put和delete的方法请求服务器肯定是必不可少的,于是我只能尝试着自己写过滤器了,我调研了一下服务器禁止跨域的原理,通过抓包发现浏览器在进行跨域访问之前会先用options方法请求tomcat服务器,然后tomcat服务器会用http响应头返回一些参数,比如"Access-Control-Allow-Methods"参数表示允许跨域的Http方法,"Access-Control-Allow-Origin"参数表示允许跨域的源,"Access-Control-Allow-Headers"表示跨域允许的请求头的参数.
参数名 | 含义 |
---|---|
Access-Control-Allow-Methods | 允许跨域的Http方法 |
Access-Control-Allow-Origin | 允许跨域的源地址 |
Access-Control-Allow-Headers | 跨域允许的请求头的参数 |
根据服务器返回的参数,如果浏览器发现该跨域请求非法,则会禁止该跨域请求。有了这些知识之后,其实只要自己在java端写一个全局过滤器就可以了,给所有请求的响应都加上那几个参数,表示允许对服务器进行任何跨域访问,这样浏览器就不会加以阻止了,过滤器的代码如下:
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CORSFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//*表示允许所有域名跨域
httpResponse.addHeader("Access-Control-Allow-Origin", "*");
httpResponse.addHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept");
//允许跨域的Http方法
httpResponse.addHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
可以看出这一段代码只是在响应头上面加了三个参数而已,之后在web.xml上面配置:
<filter>
<filter-name>CorsFilterfilter-name>
<filter-class>org.du.personalsitemock.mockutil.CORSFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CorsFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
经过测试,这个方法可以保证DELETE和PUT等方法也可以跨域,到此跨域问题就解决了。而且你会发现还可以通过Access-*那三个参数的值进行更加灵活的配置,比如只允许部分源地址可以跨域等等。