今天我们将研究Servlet异常和错误处理。之前我写过一篇关于Java异常处理的文章,但是在Web应用程序中,我们需要更多的异常处理能力。
Servlet异常
如果你注意到,doGet()和doPost()方法抛出javax.servlet.ServletException
和IOException
,让我们看看当我们从应用程序中抛出这些异常时会发生什么。我将编写一个简单的Servlet来抛出ServletException。
package com.journaldev.servlet.exception;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/MyExceptionServlet")
public class MyExceptionServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
throw new ServletException("GET method is not supported.");
}
}
现在当我们通过浏览器使用GET方法调用此Servlet时,我们会得到如下图所示的响应。由于浏览器只能理解HTML,当我们的应用程序抛出异常时,Servlet容器会处理异常并生成一个HTML响应。这个逻辑是特定于Servlet容器的。我正在使用Tomcat并得到这个错误页面。如果你使用其他服务器,比如JBoss或Glassfish,你可能会得到不同的错误HTML响应。这个响应的问题在于对用户来说毫无价值。它显示了我们的应用程序类和服务器详细信息,这对用户来说毫无意义,而且从安全角度来看也不好。
Servlet錯誤
I am sure you must have seen 404 error when you are trying to hit a URL that doesn’t exists. Let’s see how our servlet container responds to 404 error. If we send request for an invalid URL, we get response HTML like below image. Again it’s a generic HTML generated by server on our application behalf and hold little to no value to the user.
Servlet異常和錯誤處理
Servlet API提供了支持自定義異常和錯誤處理servlet的功能,我們可以在部署描述符中進行配置。這些servlet的整個目的是處理應用程序引發的異常或錯誤,並向用戶發送有用的HTML響應。我們可以提供應用程序主頁的鏈接或一些詳細信息,讓用戶知道出了什麼問題。所以首先,我們需要創建一個自定義的異常和錯誤處理servlet。我們可以為應用程序設置多個異常和錯誤處理servlet,但為了簡單起見,我將創建一個單獨的servlet並將其用於異常和錯誤。 AppExceptionHandler.java
package com.journaldev.servlet.exception;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/AppExceptionHandler")
public class AppExceptionHandler extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processError(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processError(request, response);
}
private void processError(HttpServletRequest request,
HttpServletResponse response) throws IOException {
// 分析servlet異常
Throwable throwable = (Throwable) request
.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
String servletName = (String) request
.getAttribute("javax.servlet.error.servlet_name");
if (servletName == null) {
servletName = "Unknown";
}
String requestUri = (String) request
.getAttribute("javax.servlet.error.request_uri");
if (requestUri == null) {
requestUri = "Unknown";
}
// 設置響應內容類型
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.write("Exception/Error Details ");
if(statusCode != 500){
out.write("Error Details
");
out.write("Status Code:"+statusCode+"
");
out.write("Requested URI:"+requestUri);
}else{
out.write("Exception Details
");
out.write("- Servlet Name:"+servletName+"
");
out.write("- Exception Name:"+throwable.getClass().getName()+"
");
out.write("- Requested URI:"+requestUri+"
");
out.write("- Exception Message:"+throwable.getMessage()+"
");
out.write("
");
}
out.write("
");
out.write("Home Page");
out.write("");
}
}
讓我們看看如何在部署描述符中配置它,然後我們將理解它的實現方式和工作原理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletExceptionHandling</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/AppExceptionHandler</location>
</error-page>
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
</web-app>
如您所见,使用error-page元素非常容易为应用程序指定异常处理程序servlet。每个error-page元素应该有error-code或exception-type元素。我们在如果我们尝试访问一个无效的URL,将导致404响应,我们将得到如下图像所示的响应。
这样看起来不错,并且有助于用户轻松理解发生了什么,并为他们提供了前往正确位置的方法。它还避免向用户发送应用程序敏感信息。我们应该始终为我们的Web应用程序设置异常处理程序。如果您想在单个异常处理程序中处理运行时异常和所有其他异常,可以将exception-type设置为Throwable。
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
如果有多个错误页面条目,假设一个用于Throwable,一个用于IOException,应用程序抛出FileNotFoundException,那么它将由IOException的错误处理程序处理。您还可以使用JSP页面作为异常处理程序,只需提供jsp文件的位置,而不是servlet映射。这就是Web应用程序中的servlet异常处理,希望您喜欢。
查看此系列中的其他文章: