如何在应用程序上下文级别处理 404
How to handle 404 in application context level
我在 tomcat 7 网络服务器中部署了 2 applications/projects。上下文路径不同,如 "project1"、"project2"。当我使用这些上下文路径点击 URLs 时,相应的应用程序加载并正常工作。
有效的 URL 是:
http://localhost:8080/project1
http://localhost:8080/project2
现在,当我使用正确的主机名和不正确的上下文路径(如 /project3 遇到任何错误 URL 时,它会给我错误消息
404 not found 并向用户显示一个奇怪的屏幕。
我想向最终用户显示包含正确消息的正确页面。我怎样才能在网络服务器级别做到这一点?
您可以调整 Tomcat 的 conf/web.xml
文件以显示 404 错误默认页面以外的其他页面 - 请参阅 here 示例。
摘录:
<error-page>
<error-code>404</error-code>
<location>/NotFound.jsp</location>
</error-page>
理论上,您应该可以修改默认 tomcat 网络应用程序的 web.xml,但根据 this,这不适用于 Tomcat 7.
您的另一个选择是扩展标准 ErrorReportValve
。我从现有的 ErrorReportValve
代码中非常自由地 "borrowed":
public class Custom404Valve extends ErrorReportValve{
public void invoke(Request request, Response response) throws IOException, ServletException {
if(request.getStatusCode() != 404){
super.invoke();
return;
}
// Perform the request
getNext().invoke(request, response);
if (response.isCommitted()) {
if (response.setErrorReported()) {
try {
response.flushBuffer();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
response.getCoyoteResponse().action(ActionCode.CLOSE_NOW, null);
}
return;
}
response.setSuspended(false);
//this is where your code really matters
//everything prior are just precautions I lifted
//from the stock valve.
try {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
String theErrorPage = loadErrorPage();
Writer writer = response.getReporter();
writer.write(theErrorPage);
response.finishResponse();
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
if (request.isAsyncStarted()) {
request.getAsyncContext().complete();
}
}
protected String loadErrorPage() {
BufferedReader reader = null;
StringBuilder errorMessage = new StringBuilder();
try{
File file = new File("YourErrorPage.html");
reader = new BufferedReader(new FileReader(file));
while (reader.ready()) {
errorMessage.append(reader.readLine());
}
}catch (IOException e){
e.printStackTrace();
}finally{
try{
reader.close();
}catch (IOException e) {
e.printStackTrace();
}
}
return errorMessage.toString();
}
}
您现在需要做的就是配置自定义阀门:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Valve className="com.foo.bar.Custom404Valve"/>
</Host>
我在 tomcat 7 网络服务器中部署了 2 applications/projects。上下文路径不同,如 "project1"、"project2"。当我使用这些上下文路径点击 URLs 时,相应的应用程序加载并正常工作。
有效的 URL 是:
http://localhost:8080/project1
http://localhost:8080/project2
现在,当我使用正确的主机名和不正确的上下文路径(如 /project3 遇到任何错误 URL 时,它会给我错误消息 404 not found 并向用户显示一个奇怪的屏幕。
我想向最终用户显示包含正确消息的正确页面。我怎样才能在网络服务器级别做到这一点?
您可以调整 Tomcat 的 conf/web.xml
文件以显示 404 错误默认页面以外的其他页面 - 请参阅 here 示例。
摘录:
<error-page>
<error-code>404</error-code>
<location>/NotFound.jsp</location>
</error-page>
理论上,您应该可以修改默认 tomcat 网络应用程序的 web.xml,但根据 this,这不适用于 Tomcat 7.
您的另一个选择是扩展标准 ErrorReportValve
。我从现有的 ErrorReportValve
代码中非常自由地 "borrowed":
public class Custom404Valve extends ErrorReportValve{
public void invoke(Request request, Response response) throws IOException, ServletException {
if(request.getStatusCode() != 404){
super.invoke();
return;
}
// Perform the request
getNext().invoke(request, response);
if (response.isCommitted()) {
if (response.setErrorReported()) {
try {
response.flushBuffer();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
response.getCoyoteResponse().action(ActionCode.CLOSE_NOW, null);
}
return;
}
response.setSuspended(false);
//this is where your code really matters
//everything prior are just precautions I lifted
//from the stock valve.
try {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
String theErrorPage = loadErrorPage();
Writer writer = response.getReporter();
writer.write(theErrorPage);
response.finishResponse();
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
if (request.isAsyncStarted()) {
request.getAsyncContext().complete();
}
}
protected String loadErrorPage() {
BufferedReader reader = null;
StringBuilder errorMessage = new StringBuilder();
try{
File file = new File("YourErrorPage.html");
reader = new BufferedReader(new FileReader(file));
while (reader.ready()) {
errorMessage.append(reader.readLine());
}
}catch (IOException e){
e.printStackTrace();
}finally{
try{
reader.close();
}catch (IOException e) {
e.printStackTrace();
}
}
return errorMessage.toString();
}
}
您现在需要做的就是配置自定义阀门:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Valve className="com.foo.bar.Custom404Valve"/>
</Host>