404 错误页面 转自百度空间
自定义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();
}
}