自从做了前后端分离项目以后,就遇到了跨域问题.一直也没有深入自己去测试,反正能解决就行了,今天自己写了一系列测试,得到了java解决跨域问题的多种方法;
1.首先是基本没用过的jsonp方式:(缺点:麻烦,只支持GET请求)
$("#btn3").click(function () {
$.ajax({
url: "http://localhost:9090/test3",
type: "get",
dataType: "jsonp", //这里指定请求后台服务器返回类型jsonp
// jsonpCallback: "gao", //指定请求地址后面callback的值
// jsonp:"callback", //指定jsonp请求地址的参数名,默认callback
success: function (data) {
alert(data);
}
});
});
如果上面不指定jsonpCallback的请求值时,会默认生成随机的请求值;如下:
http://localhost:9090/test3?callback=jsonp1536806347498
后台处理的话,就要在参数返回时,使用jsonp请求值包裹返回值,如 jsonp1536806347498(...);
@GetMapping("/test3")
public void tt3e(HttpServletRequest request, HttpServletResponse response) throws IOException {
String callback = request.getParameter("callback");
String result = new ObjectMapper().writeValueAsString(Arrays.asList(1, 1, 1, 1));
String now = callback + "(" + result + ")";
response.getWriter().write(now);
}
2.后台返回参数header添加跨域参数;(全是优点)
这种前台不用做任何操作,只要后台进行一些添加参数即可;方式有以下几种;
第一种,添加过滤器,拦截器方式:
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setCharacterEncoding("utf-8");
response.setHeader("Access-Control-Allow-Origin", "*"); // 解决跨域访问报错
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600"); // 设置过期时间
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
public class MyConfig implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
return true;
}
}
这种方式不管你已何种方式请求,跨域或者不跨域,在返回参数header参数中,都可以看到以下参数:
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Thu, 13 Sep 2018 02:50:53 GMT
Pragma: no-cache
Transfer-Encoding: chunked
因为用下面的方式跨域时,本地用postman测试时候,因为没有这些参数,一直以为没有生效,所以一直采用这种方式,没有敢用其他方式.......其实下面方式也是生效的,只有跨域请求的时候会在返回参数中带有这些跨域参数;
第二种,springboot直接重写跨域配置,这种方式比较简单,推荐:
public class MyCros implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
}
第三种:在类或者方法上添加@CrossOrigin注解;看到网上有在ssm项目中遇到不生效的问题,看到解决办法有的因为@RequestMapping注解中没有指定method请求方式造成的,只要添加get或post等参数就可以了.我在springboot中没有出现这种问题;