文章目录
1. 前置知识 2. 原理和解决方案总结 2.1. 跨域不通过原理流程图 2.2. 实现原理:添加以下http响应头 2.3. 四种跨域实现方式及优先级(从高到低)
3. 具体实现代码 3.1. 跨域全局配置方式-Filter(全适用) 3.2. 跨域全局配置方式-SpringMvc 3.3. 跨域单个配置方式-WebServlet 3.4. 跨域单个配置方式-SpringMvc
4.非java实现方式
9. 参考文章
1. 前置知识
【尚硅谷】【视频】【B站】禹神:一小时彻底搞懂跨域&解决方案 【尚硅谷】【笔记】【CSDN】禹神:彻底搞懂前端跨域&解决方案
2. 原理和解决方案总结
2.1. 跨域不通过原理流程图
2.2. 实现原理:添加以下http响应头
序号 响应头 含义 1 Access-Control-Allow-Origin 允许的源 2 Access-Control-Allow-Methods 允许的方法 3 Access-Control-Allow-Headers 允许的自定义头 4 Access-Control-Max-Age 预检请求的结果缓存时间(可选)
2.3. 四种跨域实现方式及优先级(从高到低)
跨域全局配置方式-Filter(全适用): 重写 Filter.doFilter(),设置 res.setHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数跨域全局配置方式-SpringMvc : 重写 WebMvcConfigurer.addCorsMappings(),设置 registry.addMapping(“/**”).allowedOrigins(“*”)等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)跨域单个配置方式-WebServlet: 设置 res.addHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数跨域单个配置方式-SpringMvc : 添加 @CrossOrigin注解,设置origins等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
3. 具体实现代码
3.1. 跨域全局配置方式-Filter(全适用)
重写Filter.doFilter()
,设置 res.setHeader("Access-Control-Allow-Origin", "*")
等响应头参数
@Configuration
public class CorsFilter implements Filter {
@Override
public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException , ServletException {
HttpServletResponse res = ( HttpServletResponse ) response;
res. setHeader ( "Access-Control-Allow-Origin" , req. getHeader ( "Origin" ) ) ;
if ( req. getMethod ( ) . equalsIgnoreCase ( "OPTIONS" ) && ! ObjUtil . hasNull ( req. getHeader ( "Origin" ) , req. getHeader ( "Access-Control-Request-Method" ) ) ) {
res. setHeader ( "Access-Control-Allow-Methods" , req. getHeader ( "Access-Control-Request-Method" ) ) ;
res. setHeader ( "Access-Control-Allow-Headers" , req. getHeader ( "Access-Control-Request-Headers" ) ) ;
res. setHeader ( "Access-Control-Max-Age" , "5" ) ;
return ;
}
}
}
3.2. 跨域全局配置方式-SpringMvc
重写 WebMvcConfigurer.addCorsMappings(),设置 registry.addMapping(“/**”).allowedOrigins(“*”)等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings ( CorsRegistry registry) {
registry. addMapping ( "/**" )
. allowedOrigins ( "*" )
. allowedOriginPatterns ( "*" )
. allowedMethods ( "*" )
. allowedHeaders ( "*" )
. maxAge ( 1800 ) ;
}
}
3.3. 跨域单个配置方式-WebServlet
设置 res.addHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数
@Slf4j
@WebServlet ( name = "ajax" , value = { "/ajax/WebServlet" , "/ajax/WebServlet/" } )
public class AjaxWebServlet extends HttpServlet {
@Override
protected void service ( HttpServletRequest req, HttpServletResponse res) throws IOException {
log. warn ( "method==【{}】, name==【{}】, header.origin==【{}】, Access-Control-Request-Method==【{}】, Access-Control-Request-Headers==【{}】" , req. getMethod ( ) , req. getParameter ( "name" ) , req. getHeader ( "Origin" ) , req. getHeader ( "Access-Control-Request-Method" ) , req. getHeader ( "Access-Control-Request-Headers" ) ) ;
res. setHeader ( "Access-Control-Allow-Origin" , "*" ) ;
res. setHeader ( "Access-Control-Allow-Methods" , "*" ) ;
res. setHeader ( "Access-Control-Allow-Headers" , "*" ) ;
res. setHeader ( "Access-Control-Max-Age" , "1800" ) ;
res. getWriter ( ) . write ( DateUtil . now ( ) + "@" + req. getMethod ( ) ) ;
}
}
3.4. 跨域单个配置方式-SpringMvc
添加 @CrossOrigin注解,设置origins等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
@Slf4j
@RestController
@RequestMapping ( "/ajax" )
public class AjaxController {
@CrossOrigin (
origins = { "*" } ,
originPatterns = { "*" } ,
methods = { } ,
allowedHeaders = { "*" } ,
maxAge = 1800
)
@RequestMapping ( value = "/CrossOrigin" , method = { RequestMethod . GET , RequestMethod . PUT } )
@SneakyThrows
void ajax ( HttpServletRequest req, HttpServletResponse res) {
log. warn ( "method==【{}】, name==【{}】, header.origin==【{}】, Access-Control-Request-Method==【{}】, Access-Control-Request-Headers==【{}】" , req. getMethod ( ) , req. getParameter ( "name" ) , req. getHeader ( "Origin" ) , req. getHeader ( "Access-Control-Request-Method" ) , req. getHeader ( "Access-Control-Request-Headers" ) ) ;
res. getWriter ( ) . write ( DateUtil . now ( ) + "@" + req. getMethod ( ) ) ;
}
}
4.非java实现方式
4.1. nginx代理
配置nginx反向代理。在配置文件nginx.conf
的http
中添加一个server
将AJAX
请求通过nginx
转发。本例中,将AJAX
请求发给58080
端口,然后转发给8080
端口
server {
listen 58080 ;
server_name localhost;
location / {
proxy_pass http: / / localhost: 8080 ;
# 增加响应头
add_header Access - Control - Allow - Origin "*" ; # 【跨域配置】[ 必需] 允许请求源 :默认值 无,配置"*" 允许所有。
if ( $request_method = 'OPTIONS ') { # 如果是复杂请求的预检请求(参考SpringMvc ,最好同时判断请求头Origin 、Access - Control - Request - Method 都不为null ,略),设置以下响应头,且没必要透传,直接返回
add_header Access - Control - Allow - Origin "*" ; # 【跨域配置】[ 必需] 允许请求源 :默认值 无,配置"*" 允许所有。
add_header Access - Control - Allow - Methods "*" ; # 【跨域配置】[ 有复杂请求方法时必需] 允许请求方法:默认值 无,配置 "*" ,允许所有
add_header Access - Control - Allow - Headers "*" ; # 【跨域配置】[ 有复杂请求头时必需] 允许请求头 : 默认值 无,配置 "*" ,允许所有
add_header Access - Control - Max - Age "5" ; # 【跨域配置】[ 非必需] 预检缓存时长: 默认值 依赖客户端。EDGE 浏览器默认值为3 秒。【注意浏览器不要禁用缓存,否则不生效】
return 204 ;
}
}
}
9. 参考文章
@CrossOrigin详细参数说明 SpringBoot处理跨域请求的四种方法