Java伪静态案例如何适配

wen java案例 29

本文目录导读:

Java伪静态案例如何适配

  1. 伪静态原理
  2. Tomcat实现伪静态
  3. Spring MVC实现伪静态
  4. 多环境适配方案
  5. Nginx反向代理适配
  6. 拦截器适配实现
  7. 最佳实践建议
  8. 注意事项

我来详细说明Java伪静态的适配方法,从基础配置到最佳实践。

伪静态原理

伪静态是将动态URL(如 article.jsp?id=123)转化为静态URL(如 article/123.html),实现方式主要有两种:

  • URL重写(Rewrite):服务器层面转换
  • RESTful风格:框架层面实现

Tomcat实现伪静态

1 Tuckey URLRewrite Filter

<!-- pom.xml 依赖 -->
<dependency>
    <groupId>org.tuckey</groupId>
    <artifactId>urlrewritefilter</artifactId>
    <version>4.0.4</version>
</dependency>

web.xml配置:

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <!-- 配置文件路径 -->
    <init-param>
        <param-name>confPath</param-name>
        <param-value>/WEB-INF/urlrewrite.xml</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

urlrewrite.xml规则示例:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
    "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite>
    <!-- 文章详情页 -->
    <rule>
        <from>^/article/(\d+)\.html$</from>
        <to>/article.jsp?id=$1</to>
    </rule>
    <!-- 分类页面 -->
    <rule>
        <from>^/category/(\w+)/page/(\d+)\.html$</from>
        <to>/category.jsp?name=$1&amp;page=$2</to>
    </rule>
    <!-- 用户页面 -->
    <rule>
        <from>^/user/(\w+)/profile\.html$</from>
        <to>/user/profile.jsp?username=$1</to>
    </rule>
    <!-- 防止静态资源被重写 -->
    <rule>
        <from>^/(css|js|images|fonts|upload)/.*$</from>
        <to last="true">-</to>
    </rule>
</urlrewrite>

Spring MVC实现伪静态

1 使用@RequestMapping

@Controller
public class ArticleController {
    // 映射 /article/123.html
    @RequestMapping("/article/{id}.html")
    public String viewArticle(@PathVariable("id") Long id, Model model) {
        Article article = articleService.getById(id);
        model.addAttribute("article", article);
        return "article_detail";
    }
    // 映射 /category/java/page/1.html
    @RequestMapping("/category/{name}/page/{page}.html")
    public String categoryPage(@PathVariable("name") String name,
                                @PathVariable("page") Integer page,
                                Model model) {
        // 处理逻辑
        return "category";
    }
}

2 配置后缀匹配

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 开启后缀模式匹配
        configurer.setUseRegisteredSuffixPatternMatch(true);
        configurer.setUseSuffixPatternMatch(true);
    }
}

3 自定义PathMatch策略

@Configuration
public class CustomWebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 自定义路径匹配器
        UrlPathHelper pathHelper = new UrlPathHelper();
        pathHelper.setRemoveSemicolonContent(true);
        pathHelper.setDefaultEncoding("UTF-8");
        configurer.setUrlPathHelper(pathHelper);
        // 添加自定义后缀
        configurer.addPathPrefix("api", c -> true);
    }
}

多环境适配方案

1 环境配置文件

# application-dev.yml
server:
  servlet:
    encoding:
      force-response: true
  tomcat:
    uri-encoding: UTF-8
# application-prod.yml
server:
  servlet:
    session:
      timeout: 1800
  tomcat:
    additional-tld-skip-patterns: "*.jar"

2 动态配置

@Component
public class UrlRewriteConfig {
    @Value("${urlrewrite.enabled:true}")
    private boolean enabled;
    @Value("${urlrewrite.static-paths:css,js,images}")
    private String staticPaths;
    @Bean
    public FilterRegistrationBean<UrlRewriteFilter> urlRewriteFilter() {
        FilterRegistrationBean<UrlRewriteFilter> filter = 
            new FilterRegistrationBean<>();
        if (enabled) {
            UrlRewriteFilter rewriteFilter = new UrlRewriteFilter();
            filter.setFilter(rewriteFilter);
            filter.addUrlPatterns("/*");
            // 根据环境加载不同配置文件
            String configPath = "/WEB-INF/urlrewrite-" + 
                System.getProperty("spring.profiles.active") + ".xml";
            filter.addInitParameter("confPath", configPath);
        }
        return filter;
    }
}

Nginx反向代理适配

# nginx.conf
server {
    listen 80;
    server_name www.example.com;
    # 静态资源直接访问
    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
    # 伪静态规则
    location / {
        # 文章详情
        if ($request_uri ~* "^/article/(\d+)\.html$") {
            set $article_id $1;
            rewrite ^ /article.jsp?id=$article_id break;
        }
        # 分类列表
        if ($request_uri ~* "^/category/(\w+)/page/(\d+)/?$") {
            set $category_name $1;
            set $page_num $2;
            rewrite ^ /category.jsp?name=$category_name&page=$page_num break;
        }
        # 转发到Tomcat
        proxy_pass http://tomcat_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

拦截器适配实现

@Component
public class PseudoStaticInterceptor implements HandlerInterceptor {
    private static final Pattern STATIC_PATTERN = 
        Pattern.compile(".*\\.(html|htm|shtml)$");
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        // 检查是否为伪静态请求
        if (STATIC_PATTERN.matcher(requestURI).matches()) {
            // 解析伪静态URL
            Map<String, String> params = parsePseudoStaticUrl(requestURI);
            // 设置请求参数
            if (params != null && !params.isEmpty()) {
                request.setAttribute("pseudoStaticParams", params);
            }
        }
        return true;
    }
    private Map<String, String> parsePseudoStaticUrl(String url) {
        Map<String, String> params = new HashMap<>();
        // 示例:/article/123.html
        Pattern articlePattern = Pattern.compile("/article/(\\d+)\\.html");
        Matcher matcher = articlePattern.matcher(url);
        if (matcher.find()) {
            params.put("id", matcher.group(1));
            params.put("type", "article");
        }
        return params;
    }
}

最佳实践建议

1 统一配置管理

@Component
@ConfigurationProperties(prefix = "pseudo-static")
public class PseudoStaticProperties {
    private boolean enabled = true;
    private String suffix = ".html";
    private Map<String, String> rules = new HashMap<>();
    // getters and setters
}
// application.yml
pseudo-static:
  enabled: true
  suffix: .html
  rules:
    article: "/article/{id}"
    category: "/category/{name}/page/{page}"
    user: "/user/{username}/profile"

2 性能优化

@Component
public class PseudoStaticCache {
    @Autowired
    private CacheManager cacheManager;
    public void cacheStaticUrl(String path, Object value) {
        Cache cache = cacheManager.getCache("pseudoStatic");
        if (cache != null) {
            cache.put(path, value);
        }
    }
    public Object getFromCache(String path) {
        Cache cache = cacheManager.getCache("pseudoStatic");
        if (cache != null) {
            Cache.ValueWrapper wrapper = cache.get(path);
            return wrapper != null ? wrapper.get() : null;
        }
        return null;
    }
}

3 测试用例

@SpringBootTest
@AutoConfigureMockMvc
public class PseudoStaticTest {
    @Autowired
    private MockMvc mockMvc;
    @Test
    public void testArticleStaticUrl() throws Exception {
        mockMvc.perform(get("/article/123.html")
                .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(view().name("article_detail"))
                .andExpect(model().attributeExists("article"));
    }
    @Test
    public void testCategoryPagination() throws Exception {
        mockMvc.perform(get("/category/java/page/2.html")
                .accept(MediaType.TEXT_HTML))
                .andExpect(status().isOk())
                .andExpect(view().name("category"));
    }
    @Test
    public void testInvalidUrl() throws Exception {
        mockMvc.perform(get("/invalid/url.html")
                .accept(MediaType.TEXT_HTML))
                .andExpect(status().isNotFound());
    }
}

注意事项

  1. URL规范化:统一使用小写字母,避免大小写问题
  2. SEO优化:保持URL语义化,包含关键词
  3. 安全性:防止路径遍历攻击,验证参数合法性
  4. 兼容性:注意不同容器的配置差异
  5. 调试工具:使用浏览器开发者工具监控URL请求

是Java伪静态的完整适配方案,根据实际需求选择合适的实现方式。

抱歉,评论功能暂时关闭!