`
z10one
  • 浏览: 9617 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

404 错误页面 转自百度空间

阅读更多
自定义 Tomcat 404错误页面 Tomcat 的错误页面是由 org.apache.catalina.valves.ErrorReportValve 类输出来的。如果想自定义错误页面,不需要修改该类。Servlet 规范声明了相关的API,只需要在每个 web 应用的 web.xml 里定义。可按照错误类型、错误代码配置。例如:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

<display-name>Welcome to Tomcat</display-name>
<description>
     Welcome to Tomcat
</description>

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

<error-page>
  <exception-type>java.lang.Exception</exception-type>
  <location>/errorpages/exception.jsp</location>
 </error-page>

</web-app>

注意错误页面必须以“/”开头,这样任何path的404错误页面及exception错误都会映射到这两个文件。然后在本web引用的errorpages下面放置404.jsp, exception.jsp两个文件。

错误页面 404.jsp:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<html>
<header>
<title>404 page</title>
<body>

<pre>
<%
    Enumeration<String> attributeNames = request.getAttributeNames();
    while (attributeNames.hasMoreElements())
    {
        String attributeName = attributeNames.nextElement();
        Object attribute = request.getAttribute(attributeName);
   out.println("request.attribute['" + attributeName + "'] = " + attribute);
    }
%>
</pre>

代码中输出了所有的 request 中的变量。从中也可以看到访问哪个文件出错,跳到哪个错误页面了,从而进行更详细、更人性化的错误处理。例如,提示可能的正确网址等等。

例如:访问一个不存在的页面 page_not_exist.html,显示的信息为:

request.attribute['javax.servlet.forward.request_uri'] = /page_not_exists.html
request.attribute['javax.servlet.forward.context_path'] =
request.attribute['javax.servlet.forward.servlet_path'] = /page_not_exists.html
request.attribute['javax.servlet.forward.path_info'] = /errorpages/404.jsp
request.attribute['javax.servlet.error.message'] = /page_not_exists.html
request.attribute['javax.servlet.error.status_code'] = 404
request.attribute['javax.servlet.error.servlet_name'] = default
request.attribute['javax.servlet.error.request_uri'] = /page_not_exists.html

注意,该错误页面必须大于512字节,否则IE将不予显示。因为IE默认只显示大于512字节的错误页面。Firefox中正常显示。可以添加一些其他信息,将页面大小扩充到512字节以上。如果仍不能显示,请检查IE设置,将该选项选中。




异常处理页面 exception.jsp:

<%@ page contentType="text/html; charset=UTF-8" isErrorPage="true" %>
<%@ page import="java.io.*" %>
<html>
<header>
<title>exception page</title>
<body>
<hr/>
<pre>
<%
response.getWriter().println("Exception: " + exception);

if(exception != null)
{
   response.getWriter().println("<pre>");
   exception.printStackTrace(response.getWriter());
   response.getWriter().println("</pre>");
}

response.getWriter().println("<hr/>");
%>

注意isErrorPage熟悉必须为true,才能使用exception对象。exception即捕捉到的异常。此处可以对exception进行处理,比如记录日志、重定向等等。这里把exception trace打印出来了。

500、505 等错误页面的处理类似于404。

----------------------------------------------------------------------------------

还有一种方法是,自定义ErrorReportValve。适合context比较多的情况。自己实现一个ErrorReportValve,就可以适用于所有的404、505、500等错误了。实现后需打成 jar 包,放置到 tomcat 的全局lib里,并配置到tomcat 的server.xml里:

      <Host name="localhost" appBase="webapps"

            unpackWARs="true" autoDeploy="true" errorReportValveClass="com.helloweenpad.xxxxx.OurCustomizedErrorReportValve"

            xmlValidation="false" xmlNamespaceAware="false">

相关 tomcat 的文档为:


errorReportValveClass

Java class name of the error reporting valve which will be used by this Host. The responsability of this valve is to output error reports. Setting this property allows to customize the look of the error pages which will be generated by Tomcat. This class must implement the org.apache.catalina.Valve interface. If none is specified, the value org.apache.catalina.valves.ErrorReportValve will be used by default.


实现方式见 Tomcat 的 org.apache.catalina.valves.ErrorReportValve 类:




/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package org.apache.catalina.valves;


import java.io.IOException;
import java.io.Writer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.Globals;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.StringManager;

/**
* <p>Implementation of a Valve that outputs HTML error pages.</p>
*
* <p>This Valve should be attached at the Host level, although it will work
* if attached to a Context.</p>
*
* <p>HTML code from the Cocoon 2 project.</p>
*
* @author Remy Maucherat
* @author Craig R. McClanahan
* @author <a href=" Ken Barozzi</a> Aisa
* @author <a href=" Mazzocchi</a>
* @author Yoav Shapira
* @version $Revision: 543307 $ $Date: 2007-06-01 01:08:24 +0200 (Fri, 01 Jun 2007) $
*/

public class ErrorReportValve
    extends ValveBase {


    // ----------------------------------------------------- Instance Variables


    /**
     * The descriptive information related to this implementation.
     */
    private static final String info =
        "org.apache.catalina.valves.ErrorReportValve/1.0";


    /**
     * The StringManager for this package.
     */
    protected static StringManager sm =
        StringManager.getManager(Constants.Package);


    // ------------------------------------------------------------- Properties


    /**
     * Return descriptive information about this Valve implementation.
     */
    public String getInfo() {

        return (info);

    }


    // --------------------------------------------------------- Public Methods


    /**
     * Invoke the next Valve in the sequence. When the invoke returns, check
     * the response state, and output an error report is necessary.
     *
     * @param request The servlet request to be processed
     * @param response The servlet response to be created
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void invoke(Request request, Response response)
        throws IOException, ServletException {

        // Perform the request
        getNext().invoke(request, response);

        Throwable throwable =
            (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);

        if (response.isCommitted()) {
            return;
        }

        if (throwable != null) {

            // The response is an error
            response.setError();

            // Reset the response (if possible)
            try {
                response.reset();
            } catch (IllegalStateException e) {
                ;
            }

            response.sendError
                (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

        }

        response.setSuspended(false);

        try {
            report(request, response, throwable);
        } catch (Throwable tt) {
            ;
        }

    }


    // ------------------------------------------------------ Protected Methods


    /**
     * Prints out an error report.
     *
     * @param request The request being processed
     * @param response The response being generated
     * @param throwable The exception that occurred (which possibly wraps
     * a root cause exception
     */
    protected void report(Request request, Response response,
                          Throwable throwable) {

        // Do nothing on non-HTTP responses
        int statusCode = response.getStatus();

        // Do nothing on a 1xx, 2xx and 3xx status
        // Do nothing if anything has been written already
        if ((statusCode < 400) || (response.getContentCount() > 0))
            return;

        String message = RequestUtil.filter(response.getMessage());
        if (message == null)
            message = "";

        // Do nothing if there is no report for the specified status code
        String report = null;
        try {
            report = sm.getString("http." + statusCode, message);
        } catch (Throwable t) {
            ;
        }
        if (report == null)
            return;

        StringBuffer sb = new StringBuffer();

        sb.append("<html><head><title>");
        sb.append(ServerInfo.getServerInfo()).append(" - ");
        sb.append(sm.getString("errorReportValve.errorReport"));
        sb.append("</title>");
        sb.append("<style><!--");
        sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
        sb.append("--></style> ");
        sb.append("</head><body>");
        sb.append("<h1>");
        sb.append(sm.getString("errorReportValve.statusHeader",
                               "" + statusCode, message)).append("</h1>");
        sb.append("<HR size=\"1\" noshade=\"noshade\">");
        sb.append("<p><b>type</b> ");
        if (throwable != null) {
            sb.append(sm.getString("errorReportValve.exceptionReport"));
        } else {
            sb.append(sm.getString("errorReportValve.statusReport"));
        }
        sb.append("</p>");
        sb.append("<p><b>");
        sb.append(sm.getString("errorReportValve.message"));
        sb.append("</b> <u>");
        sb.append(message).append("</u></p>");
        sb.append("<p><b>");
        sb.append(sm.getString("errorReportValve.description"));
        sb.append("</b> <u>");
        sb.append(report);
        sb.append("</u></p>");

        if (throwable != null) {

            String stackTrace = getPartialServletStackTrace(throwable);
            sb.append("<p><b>");
            sb.append(sm.getString("errorReportValve.exception"));
            sb.append("</b> <pre>");
            sb.append(RequestUtil.filter(stackTrace));
            sb.append("</pre></p>");

            int loops = 0;
            Throwable rootCause = throwable.getCause();
            while (rootCause != null && (loops < 10)) {
                stackTrace = getPartialServletStackTrace(rootCause);
                sb.append("<p><b>");
                sb.append(sm.getString("errorReportValve.rootCause"));
                sb.append("</b> <pre>");
                sb.append(RequestUtil.filter(stackTrace));
                sb.append("</pre></p>");
                // In case root cause is somehow heavily nested
                rootCause = rootCause.getCause();
                loops++;
            }

            sb.append("<p><b>");
            sb.append(sm.getString("errorReportValve.note"));
            sb.append("</b> <u>");
            sb.append(sm.getString("errorReportValve.rootCauseInLogs",
                                   ServerInfo.getServerInfo()));
            sb.append("</u></p>");

        }

        sb.append("<HR size=\"1\" noshade=\"noshade\">");
        sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
        sb.append("</body></html>");

        try {
            try {
                response.setContentType("text/html");
                response.setCharacterEncoding("utf-8");
            } catch (Throwable t) {
                if (container.getLogger().isDebugEnabled())
                    container.getLogger().debug("status.setContentType", t);
            }
            Writer writer = response.getReporter();
            if (writer != null) {
                // If writer is null, it's an indication that the response has
                // been hard committed already, which should never happen
                writer.write(sb.toString());
            }
        } catch (IOException e) {
            ;
        } catch (IllegalStateException e) {
            ;
        }
       
    }


    /**
     * Print out a partial servlet stack trace (truncating at the last
     * occurrence of javax.servlet.).
     */
    protected String getPartialServletStackTrace(Throwable t) {
        StringBuffer trace = new StringBuffer();
        trace.append(t.toString()).append('\n');
        StackTraceElement[] elements = t.getStackTrace();
        int pos = elements.length;
        for (int i = 0; i < elements.length; i++) {
            if ((elements[i].getClassName().startsWith
                 ("org.apache.catalina.core.ApplicationFilterChain"))
                && (elements[i].getMethodName().equals("internalDoFilter"))) {
                pos = i;
            }
        }
        for (int i = 0; i < pos; i++) {
            if (!(elements[i].getClassName().startsWith
                  ("org.apache.catalina.core."))) {
                trace.append('\t').append(elements[i].toString()).append('\n');
            }
        }
        return trace.toString();
    }

}
分享到:
评论

相关推荐

    网站备份文件扫描工具

    7.结果过滤功能,可过滤大小小于指定字节的文件,可过滤文件类型为未知以及文件大小为未知的结果,最大限度清除垃圾结果(可过滤比如自定义404错误页面 或者防盗链组件生成的页面)。 目前支持23个变量分别为:...

    vivi百度知道小偷 7.2.rar

    vivi百度知道小偷是由vivi工作室制作并发布!如有雷同,均属盗版! vivi百度知道小偷 7.2 更新说明:2012.12.12 1.修复搜索页 2.后台添加更新提醒(授权功能) 3.增加后台某些错误提示 程序功能简介: 1....

    PhpColor百度知道小偷 2.0.zip

    PhpColor百度知道小偷采用为php编写,由于百度页面的更新,旧的版本已经无法使用了,请需要的朋友们下载新版本吧。 PhpColor百度知道小偷 2.0 更新日志: 1、已实现php与html分离。 2、修复windows下的伪静态...

    vivi百度知道小偷程序 v7.2.rar

    5.四种采集方式,兼容98%空间服务器,独立模板风格.搜索引擎蜘蛛访问记录 6.内容页description,自动获取答案内容的前240个字符!有利于SEO! 7.tags链接自动获取。内容过滤功能(授权功能)。包含自定义词语的内容将不...

    最新百度知道问答自动采集(免维护) v22.5

    服务器,虚拟主机,VPS,都可以运行,如需要伪静态,需要空间或服务器支持伪静态。另外,目前有部分用户反映国外的空间有可能会有些异常,其他暂时没发现问题。采用云采集规则,自动更新。 随风PHP问答采集云版安装...

    PhpColor百度知道小偷 v2.0

    由于百度页面的更新,旧的版本已经无法使用了,请需要的朋友们下载新版本吧。 同时本版也已实现php与html分离。 20110614更新 1、修复windows下的伪静态规则 2、修复不开启缓存仍旧生成缓存文件的BUG 3、...

    ASP新华字典 v2013 修正版.zip

    ASP新华字典共收录汉字二万多个,可以根据拼音、笔划...修复了搜索出现500错误页面。 首页随即热门查询字,网站隔日快照没问题。 数据库已压缩,大大的提高网站访问速度。 广告位置在js.js里面。js转换请百度转换下。

    仿百度贴吧程序贴吧123 GB2312终结版

    增加了利用404错误页面进行跳转的功能(在国外主机上受限) 修复了后台管理中批量删除隐藏帖子的错误 修复了后台因为权限设置导致的漏洞 修改了js调用 解决了前台管理员编辑帖子不能自动保留的问题 解决了英文字符...

    vivi百度知道小偷 v7.2

    5.四种采集方式,兼容98%空间服务器,独立模板风格.搜索引擎蜘蛛访问记录 6.内容页description,自动获取答案内容的前240个字符!有利于SEO! 7.tags链接自动获取。内容过滤功能(授权功能)。包含自定义词语的内容将不...

    友情链接自动收录系统 v3.0 utf8.rar

    6、增加了百度、GOOGLE的site查询 7、帮助页面改版 请先修改程序目录下INCLUDE/CONN.PHP配置文件,然后运行! 为什么我的网站出现错误? 请确保您所购买的空间或服务器支持PHP_CURL模块,只要是正常的空间都会...

    淘宝客女包单页面源码 1.5.rar

    百度优化紧急修复V1.0版本的错误,推出V1.5版 1.1.5版修复了V1.0浏览器兼容的问题,测试了遨游 IE7.0 IE8.0 FF等主流浏览器,解决了兼容问题! 2.1.5版修复了高分辨率下,层错位的问题。定义了层的位置。 3.1.5版...

Global site tag (gtag.js) - Google Analytics