1 什么是跨域
- 当一个域名请求另一个域名的资源时,即是跨域
- 协议,主机,端口任何一个不同即为跨域
2 解决跨域
核心就是设置响应头,允许跨域
2.1 通过过滤器解决
- 通过过滤器统一添加响应头
public class CrossOriginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
try{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse)res;
//设置response的响应消息头实现跨域问题的解决
/* 允许跨域的主机地址 */
response.setHeader("Access-Control-Allow-Origin", "*");
/* 允许跨域的请求方法GET, POST, HEAD 等 */
response.setHeader("Access-Control-Allow-Methods", "*");
/* 重新预检验跨域的缓存时间 (s) */
response.setHeader("Access-Control-Max-Age", "3600");
/* 允许跨域的请求头 */
response.setHeader("Access-Control-Allow-Headers", "*");
/* 是否携带cookie */
response.setHeader("Access-Control-Allow-Credentials", "true");
//放行
chain.doFilter(request,response);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void destroy() {
}
}
- 配置过滤器
可参考环境搭建配置字符编码过滤器
FilterRegistration.Dynamic crossOriginFilter = servletContext.addFilter("crossOriginFilter", new CrossOriginFilter());
crossOriginFilter.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.FORWARD,DispatcherType.REQUEST,DispatcherType.INCLUDE),
false,
"/*"
);
public class Config extends AbstractDispatcherServletInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// 调用父类的onStartup
super.onStartup(servletContext);
// 创建乱码过滤器对象
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
// 设置字符集
encodingFilter.setEncoding("UTF-8");
// 添加到servlet容器中
FilterRegistration.Dynamic registration = servletContext.addFilter("encodingFilter", encodingFilter);
// 添加映射
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.FORWARD,DispatcherType.REQUEST,DispatcherType.INCLUDE),
false,
"/*"
);
// 注册解决跨域的过滤器
FilterRegistration.Dynamic crossOriginFilter = servletContext.addFilter("crossOriginFilter", new CrossOriginFilter());
crossOriginFilter.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.FORWARD,DispatcherType.REQUEST,DispatcherType.INCLUDE),
false,
"/*"
);
}
/**
创建Servlet容器,创建springmvc容器
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
// 由于是基于注解开发,创建注解开发对应的容器
AnnotationConfigWebApplicationContext acw = new AnnotationConfigWebApplicationContext();
// 注册配置类
acw.register(SpringMvcConfiguration.class);
return acw;
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
创建根容器,根容器是不可以访问子容器Servlet容器的bean,也就控制了service层是不能访问controller层的bean
创建springioc容器
*/
@Override
protected WebApplicationContext createRootApplicationContext() {
// 由于是基于注解开发,创建注解开发对应的容器
AnnotationConfigWebApplicationContext acw = new AnnotationConfigWebApplicationContext();
// 注册配置类: 这就要注册spring的配置类
acw.register(ApplicationContextConfiguration.class);
return acw;
}
}
2.2 通过CrossOrigin注解
在需要跨域的请求上使用注解CrossOrigin
此注解用于指定是否支持跨域访问
@RequestMapping("/useCrossOrigin")
@CrossOrigin
public String useCrossOrigin(@RequestBody(required = false) User user){
System.out.println("user is "+user);
return "success";
}
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ORIGINS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = { "*" };
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = false;
/** @deprecated as of Spring 5.0, in favor of {@link CorsConfiguration#applyPermitDefaultValues} */
@Deprecated
long DEFAULT_MAX_AGE = 1800;
/**
* Alias for {@link #origins}.
*/
@AliasFor("origins")
String[] value() default {};
/**
"*"代表所有域的请求都支持
如果没有定义,所有请求的域都支持
*/
@AliasFor("value")
String[] origins() default {};
/**
允许请求头中的header,默认都支持
*/
String[] allowedHeaders() default {};
/**
响应头中允许访问的header,默认为空
*/
String[] exposedHeaders() default {};
/**
用于指定支持的HTTP请求方式列表
*/
RequestMethod[] methods() default {};
/**
是否允许cookie随请求发送,使用时必须指定具体的域
*/
String allowCredentials() default "";
/**
预请求的结果的有效期 * 默认值是:1800秒 (30分钟).
*/
long maxAge() default -1;
}