404 错误页面 转自百度空间

zmosquito 2012-11-07

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

<web-appxmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5">

<display-name>WelcometoTomcat</display-name>

<description>

WelcometoTomcat

</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:

<%@pagecontentType="text/html;charset=UTF-8"%>

<%@pageimport="java.io.*"%>

<%@pageimport="java.util.*"%>

<html>

<header>

<title>404page</title>

<body>

<pre>

<%

Enumeration<String>attributeNames=request.getAttributeNames();

while(attributeNames.hasMoreElements())

{

StringattributeName=attributeNames.nextElement();

Objectattribute=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:

<%@pagecontentType="text/html;charset=UTF-8"isErrorPage="true"%>

<%@pageimport="java.io.*"%>

<html>

<header>

<title>exceptionpage</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进行处理,比如记录日志、重定向等等。这里把exceptiontrace打印出来了。

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

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

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

<Hostname="localhost"appBase="webapps"

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

xmlValidation="false"xmlNamespaceAware="false">

相关tomcat的文档为:

errorReportValveClass

JavaclassnameoftheerrorreportingvalvewhichwillbeusedbythisHost.Theresponsabilityofthisvalveistooutputerrorreports.SettingthispropertyallowstocustomizethelookoftheerrorpageswhichwillbegeneratedbyTomcat.Thisclassmustimplementtheorg.apache.catalina.Valveinterface.Ifnoneisspecified,thevalueorg.apache.catalina.valves.ErrorReportValvewillbeusedbydefault.

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

/*

*LicensedtotheApacheSoftwareFoundation(ASF)underoneormore

*contributorlicenseagreements.SeetheNOTICEfiledistributedwith

*thisworkforadditionalinformationregardingcopyrightownership.

*TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0

*(the"License");youmaynotusethisfileexceptincompliancewith

*theLicense.YoumayobtainacopyoftheLicenseat

*

*http://www.apache.org/licenses/LICENSE-2.0

*

*Unlessrequiredbyapplicablelaworagreedtoinwriting,software

*distributedundertheLicenseisdistributedonan"ASIS"BASIS,

*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.

*SeetheLicenseforthespecificlanguagegoverningpermissionsand

*limitationsundertheLicense.

*/

packageorg.apache.catalina.valves;

importjava.io.IOException;

importjava.io.Writer;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServletResponse;

importorg.apache.catalina.Globals;

importorg.apache.catalina.connector.Request;

importorg.apache.catalina.connector.Response;

importorg.apache.catalina.util.RequestUtil;

importorg.apache.catalina.util.ServerInfo;

importorg.apache.catalina.util.StringManager;

/**

*<p>ImplementationofaValvethatoutputsHTMLerrorpages.</p>

*

*<p>ThisValveshouldbeattachedattheHostlevel,althoughitwillwork

*ifattachedtoaContext.</p>

*

*<p>HTMLcodefromtheCocoon2project.</p>

*

*@authorRemyMaucherat

*@authorCraigR.McClanahan

*@author<ahref="KenBarozzi</a>Aisa

*@author<ahref="Mazzocchi</a>

*@authorYoavShapira

*@version$Revision:543307$$Date:2007-06-0101:08:24+0200(Fri,01Jun2007)$

*/

publicclassErrorReportValve

extendsValveBase{

//-----------------------------------------------------InstanceVariables

/**

*Thedescriptiveinformationrelatedtothisimplementation.

*/

privatestaticfinalStringinfo=

"org.apache.catalina.valves.ErrorReportValve/1.0";

/**

*TheStringManagerforthispackage.

*/

protectedstaticStringManagersm=

StringManager.getManager(Constants.Package);

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

/**

*ReturndescriptiveinformationaboutthisValveimplementation.

*/

publicStringgetInfo(){

return(info);

}

//---------------------------------------------------------PublicMethods

/**

*InvokethenextValveinthesequence.Whentheinvokereturns,check

*theresponsestate,andoutputanerrorreportisnecessary.

*

*@paramrequestTheservletrequesttobeprocessed

*@paramresponseTheservletresponsetobecreated

*

*@exceptionIOExceptionifaninput/outputerroroccurs

*@exceptionServletExceptionifaservleterroroccurs

*/

publicvoidinvoke(Requestrequest,Responseresponse)

throwsIOException,ServletException{

//Performtherequest

getNext().invoke(request,response);

Throwablethrowable=

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

if(response.isCommitted()){

return;

}

if(throwable!=null){

//Theresponseisanerror

response.setError();

//Resettheresponse(ifpossible)

try{

response.reset();

}catch(IllegalStateExceptione){

;

}

response.sendError

(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

}

response.setSuspended(false);

try{

report(request,response,throwable);

}catch(Throwablett){

;

}

}

//------------------------------------------------------ProtectedMethods

/**

*Printsoutanerrorreport.

*

*@paramrequestTherequestbeingprocessed

*@paramresponseTheresponsebeinggenerated

*@paramthrowableTheexceptionthatoccurred(whichpossiblywraps

*arootcauseexception

*/

protectedvoidreport(Requestrequest,Responseresponse,

Throwablethrowable){

//Donothingonnon-HTTPresponses

intstatusCode=response.getStatus();

//Donothingona1xx,2xxand3xxstatus

//Donothingifanythinghasbeenwrittenalready

if((statusCode<400)||(response.getContentCount()>0))

return;

Stringmessage=RequestUtil.filter(response.getMessage());

if(message==null)

message="";

//Donothingifthereisnoreportforthespecifiedstatuscode

Stringreport=null;

try{

report=sm.getString("http."+statusCode,message);

}catch(Throwablet){

;

}

if(report==null)

return;

StringBuffersb=newStringBuffer();

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("<HRsize=\"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){

StringstackTrace=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>");

intloops=0;

ThrowablerootCause=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>");

//Incaserootcauseissomehowheavilynested

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("<HRsize=\"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(Throwablet){

if(container.getLogger().isDebugEnabled())

container.getLogger().debug("status.setContentType",t);

}

Writerwriter=response.getReporter();

if(writer!=null){

//Ifwriterisnull,it'sanindicationthattheresponsehas

//beenhardcommittedalready,whichshouldneverhappen

writer.write(sb.toString());

}

}catch(IOExceptione){

;

}catch(IllegalStateExceptione){

;

}

}

/**

*Printoutapartialservletstacktrace(truncatingatthelast

*occurrenceofjavax.servlet.).

*/

protectedStringgetPartialServletStackTrace(Throwablet){

StringBuffertrace=newStringBuffer();

trace.append(t.toString()).append('\n');

StackTraceElement[]elements=t.getStackTrace();

intpos=elements.length;

for(inti=0;i<elements.length;i++){

if((elements[i].getClassName().startsWith

("org.apache.catalina.core.ApplicationFilterChain"))

&&(elements[i].getMethodName().equals("internalDoFilter"))){

pos=i;

}

}

for(inti=0;i<pos;i++){

if(!(elements[i].getClassName().startsWith

("org.apache.catalina.core."))){

trace.append('\t').append(elements[i].toString()).append('\n');

}

}

returntrace.toString();

}

}

相关推荐