在 Spring Boot 中实现伪静态,核心是通过 URL 重写将动态路径(如 /user/123)伪装成静态文件路径(如 /user-123.html),本质上是让前端看到 “静态后缀”(.html/.htm 等),但后端仍按动态接口逻辑处理。
Spring Boot 支持两种主流实现方式:基于 Spring MVC 拦截器 / 路径匹配(推荐,无需额外依赖)和 基于 Tuckey URLRewriteFilter(功能更强,支持复杂规则)。
一、核心概念
伪静态的核心是:
前端请求:http://xxx.com/user-123.html(带静态后缀)
后端转发:内部将请求转发到 http://xxx.com/user/123(真实动态接口)
浏览器地址栏:保持显示 .html 后缀,不暴露真实接口路径
二、方式一:Spring MVC 原生实现(无依赖,简单场景)
利用 Spring MVC 的 @RequestMapping 路径匹配特性,直接接收带静态后缀的请求,或通过拦截器统一重写 URL。
场景 1:直接匹配静态后缀(最简单)
无需额外配置,直接在 Controller 中声明带 .html 后缀的路径,本质是 “接口路径本身就带静态后缀”,适合少量接口。
实现步骤:
编写 Controller,方法路径包含 .html:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StaticMockController {
// 匹配请求:/user-123.html
@GetMapping("/user-{id}.html")
public String getUser(@PathVariable Long id) {
return "查询用户ID:" + id; // 真实业务逻辑
}
// 匹配请求:/article/2025/01-01.html
@GetMapping("/article/{year}/{month}-{day}.html")
public String getArticle(
@PathVariable Integer year,
@PathVariable Integer month,
@PathVariable Integer day) {
return "查询 " + year + "年" + month + "月" + day + "日 文章";
}
}
启动项目,直接访问:
http://localhost:8080/user-123.html → 返回 查询用户ID:123
http://localhost:8080/article/2025/01-01.html → 正常返回文章信息
优点:
零配置、无依赖,适合少量固定格式的伪静态接口。
缺点:
接口路径与静态后缀强耦合,大量接口时维护麻烦。
场景 2:拦截器统一重写 URL(推荐,批量处理)
通过 Spring MVC 拦截器,将所有带 .html 后缀的请求,统一去掉后缀并转发到真实动态路径(如 /user-123.html → /user/123)。
实现步骤:
编写 URL 重写拦截器:
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 伪静态拦截器:将 .html 后缀的请求重写为动态路径
*/
public class StaticRewriteInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI(); // 原始请求路径:/user-123.html
// 1. 只处理 .html 后缀的请求
if (requestURI.endsWith(".html")) {
// 2. 重写规则:将 "-" 替换为 "/",去掉 .html 后缀
// 例:/user-123.html → /user/123
String newUri = requestURI
.replace(".html", "") // 去掉后缀
.replaceFirst("-", "/"); // 将第一个 "-" 改为 "/"(可按需调整规则)
// 3. 转发到新路径(服务器内部跳转,浏览器地址栏不变)
request.getRequestDispatcher(newUri).forward(request, response);
return false; // 拦截器处理完成,不再继续执行后续流程
}
// 非 .html 后缀请求,放行
return true;
}
}
注册拦截器(配置类):
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new StaticRewriteInterceptor())
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns("/static/**"); // 排除静态资源(如 CSS/JS/图片)
}
}
编写真实动态接口(无静态后缀):
@RestController
public class UserController {
// 真实接口路径:/user/123(被转发后的请求会命中此方法)
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return "查询用户ID:" + id;
}
}
测试访问:
前端请求:http://localhost:8080/user-123.html
拦截器重写:/user-123.html → /user/123
后端响应:正常返回 查询用户ID:123,地址栏仍显示 .html 后缀。
自定义重写规则:
可根据需求修改 newUri 的生成逻辑,例如:
规则 1:/article-2025-01-01.html → /article/2025/01/01
String newUri = requestURI.replace(".html", "").replace("-", "/");
规则 2:/product-iphone15.html → /product?name=iphone15
String prefix = requestURI.split("-")[0].replace(".html", ""); // /product
String param = requestURI.split("-")[1].replace(".html", ""); // iphone15
String newUri = prefix + "?name=" + param;
三、方式二:Tuckey URLRewriteFilter(复杂场景)
Tuckey URLRewriteFilter 是一个强大的 Java URL 重写工具,支持正则表达式、条件匹配等复杂规则,类似 Apache 的 mod_rewrite。
实现步骤:
引入依赖(Maven):
org.tuckeyurlrewritefilter4.0.3
在 src/main/resources 下创建配置文件 urlrewrite.xml(核心规则配置):
^/user-(\d+)\.html$/user/$1^/article-(\d{4})-(\d{2})-(\d{2})\.(html|htm)$/article/$1/$2/$3^/product-(\w+)\.html$/product?name=$1^/static/.*$
注册 URLRewriteFilter(配置类):
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;
@Configuration
public class UrlRewriteConfig {
@Bean
public FilterRegistrationBeanurlRewriteFilter() {
FilterRegistrationBeanregistration = new FilterRegistrationBean<>();
registration.setFilter(new UrlRewriteFilter());
registration.addUrlPatterns("/*"); // 拦截所有请求
registration.addInitParameter("confPath", "classpath:urlrewrite.xml"); // 配置文件路径
registration.setName("urlRewriteFilter");
registration.setOrder(1); // 过滤器执行顺序(确保优先于其他过滤器)
return registration;
}
}
编写真实动态接口(与方式一相同):
@RestController
public class UserController {
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return "查询用户ID:" + id;
}
}
测试访问:
http://localhost:8080/user-456.html → 转发到 /user/456 → 正常响应
http://localhost:8080/article-2025-11-27.html → 转发到 /article/2025/11/27
优点:
规则集中管理,支持复杂正则、多后缀匹配(.html/.htm)、条件判断等。
与业务代码解耦,无需修改 Controller。
缺点:
需引入额外依赖,配置稍复杂。
四、关键注意事项
1. 排除静态资源
无论是拦截器还是 Tuckey 过滤器,都要排除真实静态资源(如 /static/css/、/static/js/、...