1. 跨域问题背景与Tomcat部署场景解析
作为Java开发者,我们经常遇到前后端分离项目中的跨域问题。当Tomcat同时承担静态资源服务和Java Web服务时,跨域配置会变得尤为复杂。最近我在部署一个老项目时就遇到了这个典型场景:Tomcat的webapp目录下既有静态HTML/JS文件,又部署了基于Spring MVC的war包应用。
跨域问题的本质是浏览器的同源策略限制。当你的前端页面部署在http://frontend.com,而API服务在http://backend.com时,浏览器会阻止前端页面发起的跨域请求。这种安全机制虽然必要,却给开发带来了挑战。
关键理解:跨域限制是浏览器行为,不是服务器限制。服务器需要明确告知浏览器"我允许哪些来源的请求"。
在Tomcat环境中,我们通常面临三种部署模式:
- 纯静态资源服务(如官网HTML文件)
- 纯Java Web服务(如Spring Boot应用)
- 混合模式(静态资源+Web服务共存)
每种模式的跨域解决方案各有特点,特别是第三种混合模式最容易出现配置冲突。下面我将详细拆解各种场景的解决方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Tomcat纯静态资源服务的跨域配置
2.1 基础配置方法
对于仅提供静态文件服务的Tomcat,跨域配置相对简单。我们只需要修改Tomcat的全局配置文件:
xml复制<!-- Tomcat/conf/web.xml -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这段配置做了以下几件事:
- 允许所有来源(*)
- 允许常见HTTP方法
- 允许所有请求头
- 应用到所有URL(/*)
2.2 生产环境的安全考量
虽然上述配置简单有效,但在生产环境中直接允许所有来源(*)存在安全隐患。建议根据实际情况调整:
xml复制<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://yourdomain.com,https://yourotherdomain.com</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
注意事项:
- 明确列出允许的域名,不要使用通配符
- 如果需要传递Cookie等凭证信息,必须设置support.credentials为true
- 此时allowed.origins不能为*,必须指定具体域名
3. Java Web应用的跨域解决方案
3.1 传统Spring MVC项目配置
对于部署在Tomcat中的war包应用,我们通常有以下几种跨域解决方案:
方案一:自定义过滤器
java复制public class CustomCorsFilter 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("Acc
