如何按路径指定Servlet错误页面?多语言404页面适配方案问询
解决同WAR下按区域路径返回本地化404页面的问题
根据你的需求,在不拆分WAR的前提下,有两种可靠的方案来实现按请求路径返回对应区域的404页面,我分别给你详细说明:
方案一:自定义错误处理Servlet(推荐,兼容所有Java EE版本)
这个方案利用容器的错误页面机制,先把所有404请求转发到一个自定义Servlet,再由Servlet根据原始请求路径判断区域,转发到对应本地化页面。
步骤1:配置web.xml
首先在web.xml里指定404错误的处理路径,并注册自定义Servlet:
<!-- 全局404错误指向自定义处理Servlet --> <error-page> <error-code>404</error-code> <location>/locale-error-handler</location> </error-page> <!-- 注册错误处理Servlet --> <servlet> <servlet-name>LocaleErrorHandler</servlet-name> <servlet-class>com.yourcompany.web.LocaleErrorHandlerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LocaleErrorHandler</servlet-name> <url-pattern>/locale-error-handler</url-pattern> </servlet-mapping>
步骤2:编写错误处理Servlet
在Servlet中,我们可以通过容器提供的属性获取原始请求的URI,然后判断请求属于哪个区域,再转发到对应404页面:
package com.yourcompany.web; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LocaleErrorHandlerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取引发404的原始请求路径 String originalUri = (String) request.getAttribute("javax.servlet.error.request_uri"); // 初始化请求转发器 RequestDispatcher dispatcher; // 根据原始路径判断区域 if (originalUri != null) { if (originalUri.startsWith("/a/")) { dispatcher = request.getRequestDispatcher("/a/404.html"); } else if (originalUri.startsWith("/b/")) { dispatcher = request.getRequestDispatcher("/b/404.html"); } else { // 处理不属于a/b区域的请求,返回默认404 dispatcher = request.getRequestDispatcher("/default-404.html"); } } else { // 极端情况:无法获取原始URI,返回默认页面 dispatcher = request.getRequestDispatcher("/default-404.html"); } // 转发到对应404页面 dispatcher.forward(request, response); } }
方案二:用Filter提前拦截不存在的资源
这个方案是在请求到达容器处理之前,先检查请求的资源是否存在,如果不存在,直接转发到对应区域的404页面,避免触发容器的默认404流程。
步骤1:编写Filter类
package com.yourcompany.web; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class Locale404Filter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String requestUri = request.getRequestURI(); ServletContext context = request.getServletContext(); // 检查请求的静态资源是否存在(动态资源如Servlet映射建议交给容器处理) boolean resourceExists = false; try { resourceExists = context.getResource(requestUri) != null; } catch (IOException e) { // 资源不存在时会抛出IO异常,直接标记为不存在 } if (!resourceExists) { // 根据路径转发到对应区域404 if (requestUri.startsWith("/a/")) { request.getRequestDispatcher("/a/404.html").forward(request, response); return; } else if (requestUri.startsWith("/b/")) { request.getRequestDispatcher("/b/404.html").forward(request, response); return; } } // 资源存在,继续执行后续请求链 filterChain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }
步骤2:配置Filter映射
在web.xml中注册Filter,并映射到所有请求:
<filter> <filter-name>Locale404Filter</filter-name> <filter-class>com.yourcompany.web.Locale404Filter</filter-class> </filter> <filter-mapping> <filter-name>Locale404Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意事项
- 确保
/a/404.html、/b/404.html和/default-404.html已经放置在Web应用的对应目录下 - 对于
方案一,主流容器(Tomcat、Jetty、WildFly等)都会自动传递javax.servlet.error.request_uri属性,无需额外配置 - 如果你的应用使用Java EE 7+,可以用
@WebServlet和@WebFilter注解替代web.xml配置,让代码更简洁
内容的提问来源于stack exchange,提问作者rslemos
相关产品推荐
相关产品推荐

