You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从全局Servlet过滤器转发请求至Servlet并处理不同JSP

Java Web(Tomcat 10)过滤器转发与Servlet路径处理方案

前置准备:补全MainController Servlet配置

你的web.xml缺少MainController的Servlet映射配置,这是请求转发的必要前提,先添加以下内容:

<servlet>
    <display-name>MainController</display-name>
    <servlet-name>MainController</servlet-name>
    <servlet-class>com.example.MainController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MainController</servlet-name>
    <url-pattern>/main</url-pattern> <!-- 自定义Servlet的访问路径 -->
</servlet-mapping>

问题1:在doFilter中转发非静态资源请求到Servlet

修改过滤器的doFilter方法,在非静态资源分支中使用RequestDispatcher将请求转发到MainController的映射路径,注意不要调用chain.doFilter(),避免请求重复传递:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    
    String path = req.getRequestURI().substring(req.getContextPath().length());
    
    // 放行/resources下的静态资源
    if (path.startsWith("/resources")) {
        chain.doFilter(request, response);
    } else {
        // 转发所有非静态请求到MainController
        req.getRequestDispatcher("/main").forward(req, resp);
    }
}

补充:如果需要保留原请求路径的完整信息,可以在转发时将路径作为请求参数传递,或者直接将Servlet映射到/*(更简洁的方案见下文)。


问题2:Servlet处理/和/*的不同JSP模板

优化方案:直接将Servlet映射到/*(替代过滤器转发逻辑)

更规范的做法是让MainController直接匹配所有请求,过滤器仅负责放行静态资源,这样逻辑更清晰:

  1. 修改web.xml的Servlet映射:
<servlet-mapping>
    <servlet-name>MainController</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
  1. 简化过滤器代码(仅放行静态资源,其余请求直接交给Servlet):
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
    HttpServletRequest req = (HttpServletRequest) request;
    String path = req.getRequestURI().substring(req.getContextPath().length());
    
    if (path.startsWith("/resources")) {
        chain.doFilter(request, response);
    } else {
        // 放行到MainController(已映射/*)
        chain.doFilter(request, response);
    }
}
  1. 修改MainController的doGet方法,精准处理不同路径:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String path = request.getRequestURI().substring(request.getContextPath().length());
    
    // 处理根路径请求(/)
    if ("/".equals(path)) {
        request.getRequestDispatcher("/pages/home.jsp").forward(request, response);
    } 
    // 处理所有其他路径请求(如/search、/test等)
    else {
        // 提取路径中的关键字(去掉开头的/)
        String keyword = path.substring(1);
        request.setAttribute("keyword", keyword);
        request.getRequestDispatcher("/pages/results.jsp").forward(request, response);
    }
}

额外说明:如果需要处理多级路径(如/search/java),可以用request.getPathInfo()获取/java部分,再做进一步解析。


思路纠正

  1. 过滤器的核心定位是通用拦截(如编码设置、权限校验),不要用它做请求转发的核心逻辑,Servlet通过url-pattern就能完成请求匹配,更符合规范。
  2. 静态资源放行要确保路径准确,Tomcat默认的DefaultServlet会自动处理静态资源,过滤器只需放行指定路径即可。
  3. 区分转发和重定向:forward是服务器内部跳转,浏览器地址栏不变;只有需要修改地址栏时才用sendRedirect。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:33:18