有时我写了一篇有关Java异常处理的文章,但是当涉及到Web应用程序时,我们需要的不仅仅是Java中的异常处理。
Servlet异常
如果您注意到,doGet()和doPost()方法将抛出ServletException
和IOException
,那么让我们看看从应用程序中抛出这些异常时会发生什么。 我将编写一个简单的Servlet,它将抛出ServletException。 MyExceptionServlet.java
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错误
我确定当您尝试访问不存在的URL时,您肯定已经看到404错误。 让我们看看我们的servlet容器如何响应404错误。 如果我们发送无效URL的请求,则会得到响应HTML,如下图所示。
同样,它是服务器代表我们生成的通用HTML,对用户几乎没有价值。
Servlet异常和错误处理
Servlet API支持可在部署描述符中配置的自定义Exception和Error Handler servlet,这些servlet的全部目的是处理应用程序引发的Exception或Error并发送对用户有用HTML响应。 我们可以提供指向应用程序主页的链接或一些详细信息,以使用户知道出了什么问题。
因此,首先我们需要创建一个自定义的Exception and Error Handler 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 {// Analyze the servlet exceptionThrowable 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";}// Set response content typeresponse.setContentType("text/html");PrintWriter out = response.getWriter();out.write("<html><head><title>Exception/Error Details</title></head><body>");if(statusCode != 500){out.write("<h3>Error Details</h3>");out.write("<strong>Status Code</strong>:"+statusCode+"<br>");out.write("<strong>Requested URI</strong>:"+requestUri);}else{out.write("<h3>Exception Details</h3>");out.write("<ul><li>Servlet Name:"+servletName+"</li>");out.write("<li>Exception Name:"+throwable.getClass().getName()+"</li>");out.write("<li>Requested URI:"+requestUri+"</li>");out.write("<li>Exception Message:"+throwable.getMessage()+"</li>");out.write("</ul>");}out.write("<br><br>");out.write("<a href=\"index.html\">Home Page</a>");out.write("</body></html>");}
}
让我们看看如何在部署描述符中配置它,然后我们将了解它的实现及其工作方式。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://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非常容易。 每个错误页面元素应具有错误代码或异常类型元素。 我们在location元素中定义异常处理程序servlet。
基于上面的配置,如果应用程序抛出404错误或ServletException,它将由AppExceptionHandler servlet处理。
当出现此类异常和错误情况时,servlet容器将调用Exception Handler servlet的相应HTTP方法,并传递请求和响应对象。 请注意,我已经提供了doGet()和doPost()方法的实现,以便它可以处理GET和POST请求并使用通用方法来处理它们。
在servlet容器调用servlet来处理异常之前,它会在请求中设置一些属性以获取有关异常的有用信息,其中一些是javax.servlet.error.exception , javax.servlet.error.status_code , javax.servlet。 error.servlet_name和javax.servlet.error.request_uri 。
作为例外,状态代码始终为500,与“内部服务器错误”相对应,对于其他类型的错误,我们将获得不同的错误代码,例如404、403等。
使用状态代码,我们的实现将不同类型HTML响应呈现给用户。 它还提供了到应用程序主页的超链接。
现在,当我们点击抛出ServletException的servlet时,我们将得到如下图所示的响应。
如果我们尝试访问一个无效的URL,这将导致404响应,我们将得到如下图所示的响应。
它看起来不是很好,并且可以帮助用户轻松地了解发生了什么并为他们提供前往正确位置的方法。 它还避免将应用程序敏感信息发送给用户。 我们应该始终为我们的Web应用程序配备适当的异常处理程序。
如果要在单个异常处理程序中处理运行时异常和所有其他异常,则可以将异常类型提供为Throwable。
<error-page><exception-type>java.lang.Throwable</exception-type><location>/AppExceptionHandler</location>
</error-page>
如果有多个错误页面条目,那么假设一个用于Throwable,一个用于IOException,并且应用程序抛出FileNotFoundException,则它将由IOException的错误处理程序处理。
您还可以将JSP页面用作异常处理程序,仅提供jsp文件的位置而不是servlet映射。
这就是Web应用程序中异常处理的全部,希望您喜欢它。
- 下载ServletExceptionHandling项目
翻译自: https://www.javacodegeeks.com/2013/08/servlet-exception-and-error-handling-example-tutorial.html