如何从全局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直接匹配所有请求,过滤器仅负责放行静态资源,这样逻辑更清晰:
- 修改
web.xml的Servlet映射:
<servlet-mapping> <servlet-name>MainController</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
- 简化过滤器代码(仅放行静态资源,其余请求直接交给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); } }
- 修改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部分,再做进一步解析。
思路纠正
- 过滤器的核心定位是通用拦截(如编码设置、权限校验),不要用它做请求转发的核心逻辑,Servlet通过
url-pattern就能完成请求匹配,更符合规范。 - 静态资源放行要确保路径准确,Tomcat默认的DefaultServlet会自动处理静态资源,过滤器只需放行指定路径即可。
- 区分转发和重定向:
forward是服务器内部跳转,浏览器地址栏不变;只有需要修改地址栏时才用sendRedirect。
内容的提问来源于stack exchange,提问作者bhu1st
相关产品推荐
相关产品推荐

