专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

java 面试题:如何实现跨域?

ins518 2025-05-26 16:23:14 技术文章 8 ℃ 0 评论

在 Java 中实现跨域(Cross-Origin Resource Sharing,CORS)主要有以下几种方式,具体选择取决于应用场景和架构设计:

一、前端代理(开发环境)

在开发环境中,可通过前端脚手架(如 Vue CLI、Create React App)配置代理服务器,将请求转发到后端 API。
优点:无需修改后端代码,仅开发环境使用。
缺点:生产环境需另寻方案。

示例(Vue CLI)

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://backend-api.com', // 后端API地址
        changeOrigin: true,
        pathRewrite: { '^/api': '' }
      }
    }
  }
}

二、后端配置(生产环境主流方案)

1. Spring Boot(推荐)

通过添加@CrossOrigin注解或全局配置实现。

方法一:Controller 级别(局部)

@RestController
@RequestMapping("/api")
public class UserController {
    // 允许指定域名跨域
    @CrossOrigin(origins = "http://example.com")
    @GetMapping("/users")
    public List<User> getUsers() {
        return userService.getAllUsers();
    }
}

方法二:全局配置(推荐)

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 所有接口
                .allowedOrigins("*") // 允许所有域名
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法
                .allowedHeaders("*") // 允许的请求头
                .allowCredentials(true) // 允许携带Cookie
                .maxAge(3600); // 预检请求缓存时间
    }
}

2. Filter 配置(非 Spring 项目)

自定义 Filter 拦截所有请求并添加 CORS 响应头。

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req, res);
    }
}

在web.xml中注册 Filter:

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>com.example.CorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

三、Nginx 反向代理(生产环境)

通过 Nginx 将前端和后端请求代理到同一域名下,避免跨域问题。
配置示例

server {
    listen 80;
    server_name example.com;

    # 前端静态资源
    location / {
        root /path/to/frontend;
        index index.html;
    }

    # 后端API代理
    location /api/ {
        proxy_pass http://backend-api-server:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

四、JSONP(兼容性方案)

利用<script>标签不受同源策略限制的特性,仅支持 GET 请求。
后端实现

@GetMapping("/data")
public void getData(HttpServletRequest req, HttpServletResponse res) throws IOException {
    String callback = req.getParameter("callback"); // JSONP回调函数名
    String data = "{\"name\":\"John\",\"age\":30}"; // 返回数据
    
    res.setContentType("application/javascript");
    res.getWriter().write(callback + "(" + data + ")"); // 包装为函数调用
}

前端调用

<script>
function handleData(data) {
    console.log(data);
}
</script>
<script src="http://api.example.com/data?callback=handleData"></script>

五、CORS Filter 配置(细粒度控制)

对于复杂场景,可通过配置更细粒度的 CORS 策略。

@Bean
public CorsFilter corsFilter() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(Arrays.asList("http://example.com")); // 允许的域名
    config.setAllowedMethods(Arrays.asList("GET", "POST")); // 允许的方法
    config.setAllowCredentials(true); // 允许携带Cookie
    config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/api/**", config); // 仅对/api路径生效
    
    return new CorsFilter(source);
}

六、注意事项

  1. 生产环境禁止allowedOrigins("*"):若需允许所有域名,应改用allowedOriginPatterns("*")并配合allowCredentials(true)。
  2. Cookie 与认证:若需携带 Cookie,需同时设置:后端:Access-Control-Allow-Credentials: true 且 allowedOrigins 不能为*。前端:fetch或axios中设置withCredentials: true。
  3. 预检请求(Preflight):复杂请求(如 PUT、DELETE、带自定义头)会先发送 OPTIONS 请求,需确保服务器正确响应。

总结

  • 开发环境:优先使用前端代理。
  • Spring 项目:推荐@CrossOrigin注解或全局配置。
  • 非 Spring 项目:使用 Filter 配置。
  • 生产环境:推荐 Nginx 反向代理或细粒度 CORS 配置。
  • 兼容性需求:可使用 JSONP(仅 GET 请求)。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表