You need to enable JavaScript to run this app. 如何使用Spring框架实现Java Web应用的子域名适配功能?
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Spring框架实现Java Web应用的子域名适配功能?

Spring Boot 子域名适配落地实现方案

前置校验(优先排除非代码问题)

  • 确认泛域名A解析已生效:本地ping任意子域名,返回IP为你的VPS地址即配置正确
  • 确认反向代理(Nginx/Caddy等)已透传Host请求头,大多数公开方案失效都是因为代理层丢失Host头,Nginx参考配置如下:
location / {
    proxy_pass http://127.0.0.1:8080; # 替换为Spring应用实际监听端口
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

如果Spring应用直接对外暴露端口、没有用反向代理,可跳过本条校验

核心实现步骤

1. 自定义子域名映射注解

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SubdomainMapping {
    // 匹配的子域名,填*则适配所有子域名
    String value() default "*";
}

2. 实现子域名匹配逻辑

import org.springframework.web.servlet.mvc.condition.RequestCondition;
import javax.servlet.http.HttpServletRequest;

public class SubdomainRequestCondition implements RequestCondition<SubdomainRequestCondition> {
    private final String expectedSubdomain;

    public SubdomainRequestCondition(String expectedSubdomain) {
        this.expectedSubdomain = expectedSubdomain;
    }

    @Override
    public SubdomainRequestCondition combine(SubdomainRequestCondition other) {
        // 方法注解优先级高于类注解,直接使用方法维度的配置
        return new SubdomainRequestCondition(other.expectedSubdomain);
    }

    @Override
    public SubdomainRequestCondition getMatchingCondition(HttpServletRequest request) {
        String host = request.getHeader("Host");
        if (host == null) return null;
        // 去除端口后缀
        host = host.split(":")[0];
        // 替换为你自己的主域名,注意保留前缀的.
        String mainDomainSuffix = ".yourdomain.com";
        if (!host.endsWith(mainDomainSuffix)) {
            // 主域名访问时不触发子域名匹配逻辑
            return null;
        }
        // 提取子域名片段
        String subdomain = host.substring(0, host.length() - mainDomainSuffix.length());
        // 匹配规则:通配符优先级低于精确匹配
        if ("*".equals(expectedSubdomain) || expectedSubdomain.equals(subdomain)) {
            return this;
        }
        return null;
    }

    @Override
    public int compareTo(SubdomainRequestCondition other, HttpServletRequest request) {
        return "*".equals(this.expectedSubdomain) ? 1 : -1;
    }
}

务必将上述代码中mainDomainSuffix的yourdomain.com替换为你实际的自有主域名

3. 注册自定义匹配规则到Spring MVC

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;

public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    @Override
    protected RequestCondition<?> getCustomMethodCondition(Method method) {
        SubdomainMapping annotation = AnnotationUtils.findAnnotation(method, SubdomainMapping.class);
        return annotation == null ? null : new SubdomainRequestCondition(annotation.value());
    }
}

4. 替换Spring默认的请求映射处理器

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new CustomRequestMappingHandlerMapping();
    }
}

5. 接口使用示例

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SubdomainTestController {
    // 匹配admin.yourdomain.com的请求
    @GetMapping("/hello")
    @SubdomainMapping("admin")
    public String adminAccess() {
        return "admin子域名访问成功";
    }

    // 匹配所有其他子域名的请求
    @GetMapping("/hello")
    @SubdomainMapping("*")
    public String commonSubdomainAccess() {
        return "通用子域名访问成功";
    }

    // 匹配主域名yourdomain.com的请求
    @GetMapping("/hello")
    public String mainDomainAccess() {
        return "主域名访问成功";
    }
}

常见问题排查

  • 本地测试可修改系统hosts文件,添加admin.yourdomain.com 127.0.0.1记录,无需部署到VPS即可验证逻辑
  • 如果需要适配多级子域名(如a.b.yourdomain.com),调整SubdomainRequestCondition中的子域名提取逻辑即可
  • 若使用Spring Cloud Gateway等网关组件,需在网关层提前透传Host头到下游Spring应用

内容的提问来源于stack exchange,提问作者thebossdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 08:51:01