编写一个Servlet来检查JSP是否存在,如果不存在则转发给另一个JSP

时间:2010-03-24 10:53:18

标签: java jsp servlets servlet-filters

更新

澄清捕获404的一般错误捕获器对我来说没有足够的粒度。我只有在jsp位于特定目录中时才需要这样做,并且只有当文件名包含某个字符串时才需要这样做。

/ UPDATE

我的任务是编写一个servlet来拦截对特定目录中的JSP和JSP的调用,检查文件是否存在以及它是否仅转发到该文件,如果没有,那么我将去转发到默认的JSP。 我按如下方式设置了web.xml:

<servlet>
 <description>This is the description of my J2EE component</description>
 <display-name>This is the display name of my J2EE component</display-name>
 <servlet-name>CustomJSPListener</servlet-name>
 <servlet-class> ... CustomJSPListener</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
  <servlet-name>CustomJSPListener</servlet-name>
  <url-pattern>/custom/*</url-pattern>
</servlet-mapping>

servlet的doGet方法如下:

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  logger.debug(String.format("Intercepted a request for an item in the custom directory [%s]",request.getRequestURL().toString()));
  String requestUri = request.getRequestURI();
            // Check that the file name contains a text string
  if (requestUri.toLowerCase(Locale.UK).contains("someText")){
   logger.debug(String.format("We are interested in this file [%s]",requestUri));
   File file = new File(requestUri);
   boolean fileExists = file.exists();
   logger.debug(String.format("Checking to see if file [%s] exists [%s].",requestUri,fileExists));
                    // if the file exists just forward it to the file
   if (fileExists){
    getServletConfig().getServletContext().getRequestDispatcher(
          requestUri).forward(request,response);
   } else {
                    // Otherwise redirect to default.jsp
    getServletConfig().getServletContext().getRequestDispatcher(
            "/custom/default.jsp").forward(request,response);
   }
  } else {
                    // We aren't responsible for checking this file exists just pass it on to the requeseted jsp
   getServletConfig().getServletContext().getRequestDispatcher(
           requestUri).forward(request,response);   
  }
 }

这似乎导致tomcat出现错误500,我认为这是因为servlet重定向到同一个文件夹,然后由servlet再次拦截,导致无限循环。 有一个更好的方法吗?我相信我可以使用过滤器来做到这一点,但我对它们知之甚少。

3 个答案:

答案 0 :(得分:8)

File file = new File(requestUri);

这是错误的。 java.io.File知道没有关于它正在运行的webapp上下文。文件路径将相对于当前工作目录,这取决于启动应用程序服务器的方式。例如,它可能与C:/Tomcat/bin相关,而不是您期望的webapp根目录。你不想拥有它。

使用ServletContext#getRealPath()将相对Web路径转换为绝对磁盘文件系统路径。 ServletContext在servlet中由继承的getServletContext()方法提供。因此,以下应指出正确的文件:

String absoluteFilePath = getServletContext().getRealPath(requestUri);
File file = new File(absoluteFilePath);

if (new File(absoluteFilePath).exists()) { 
    // ...
}

或者,如果目标容器没有在物理磁盘文件系统上扩展WAR,而是在内存中扩展,那么最好使用ServletContext#getResource()

URL url = getServletContext().getResource(requestUri);

if (url != null) { 
    // ...
}

答案 1 :(得分:3)

这可以通过更简单,更内置的方式完成。

web.xml包含<error-page>元素。你可以这样做:

<error-page>
    <error-code>404</error-code>
    <location>/pageNotFound.jsp</location>
<error-page>

答案 2 :(得分:0)

我要做的是为初始servlet请求创建一个虚拟目录,然后转发到真实目录或404类型页面。无论你是在发布前锋,为什么不重定向到另一个目录呢?这样可以避免任何循环问题。