Vandaag gaan we kijken naar Servlet Exception en Foutafhandeling. Een tijdje geleden schreef ik een bericht over Exception Handling in Java, maar als het gaat om webapplicaties, hebben we meer nodig dan de normale foutafhandeling in Java.
Servlet Exception
Als je opmerkt, gooien de methoden doGet() en doPost() javax.servlet.ServletException
en IOException
. Laten we eens kijken wat er gebeurt wanneer we deze uitzondering vanuit onze applicatie gooien. Ik zal een eenvoudige servlet schrijven die de ServletException zal veroorzaken.
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.");
}
}
Wanneer we nu deze servlet aanroepen via de browser met de GET-methode, krijgen we een reactie zoals in de onderstaande afbeelding. Aangezien de browser alleen HTML begrijpt, verwerkt de servlet-container de uitzondering en genereert een HTML-reactie. Deze logica is specifiek voor de servlet-container. Ik gebruik Tomcat en krijg deze foutpagina. Als je andere servers zoals JBoss of Glassfish gebruikt, krijg je mogelijk een andere HTML-foutreactie. Het probleem met deze reactie is dat deze geen waarde heeft voor de gebruiker. Het toont ook de klassen van onze applicatie en servergegevens aan de gebruiker, wat geen zin heeft voor de gebruiker en niet goed is vanuit het oogpunt van beveiliging.
Servletfout
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 Uitzondering en Foutafhandeling
De Servlet API biedt ondersteuning voor aangepaste Uitzondering en Fout Handler servlets die we kunnen configureren in het inzetdescripteur. Het hele doel van deze servlets is om de Uitzondering of Fout af te handelen die door de toepassing wordt gegenereerd en een nuttige HTML-reactie naar de gebruiker te sturen. We kunnen een link naar de startpagina van de toepassing verstrekken of enkele details om de gebruiker te laten weten wat er misging. Dus allereerst moeten we een aangepaste Uitzondering en Fout Handler servlet maken. We kunnen meerdere uitzonderings- en foutafhandelingservlets voor de toepassing hebben, maar voor de eenvoud zal ik een enkele servlet maken en deze gebruiken voor zowel uitzonderingen als fouten. 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 {
// Analyseer de servlet-uitzondering
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";
}
// Stel het inhoudstype van de reactie in
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("");
}
}
Laten we eens kijken hoe we het kunnen configureren in het inzetdescripteur en dan zullen we begrijpen hoe de implementatie ervan is en hoe het werkt.
<?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>
Zoals je kunt zien, is het heel eenvoudig om uitzonderingsbehandelingsservlets voor de applicatie te specificeren met behulp van het error-page-element. Elk error-page-element moet ofwel een error-code– of een exception-type-element hebben. We definiëren het uitzonderingsbehandelingsservlet in het location-element. Op basis van bovenstaande configuratie, als de applicatie een 404-fout of ServletException genereert, wordt deze afgehandeld door het AppExceptionHandler-servlet. Wanneer een dergelijke uitzondering of foutscenario zich voordoet, roept de servletcontainer de overeenkomstige HTTP-methode van het Uitzonderingsbehandelingsservlet aan en geeft het het verzoek- en responsobject door. Let op dat ik de implementatie van zowel de doGet()- als de doPost()-methoden heb gegeven, zodat het GET- en POST-verzoeken kan afhandelen en een gemeenschappelijke methode gebruikt om ze te verwerken. Voordat de servletcontainer de servlet aanroept om de uitzondering af te handelen, stelt het enkele attributen in het verzoek in om nuttige informatie over de uitzondering te krijgen, enkele daarvan zijn javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name en javax.servlet.error.request_uri. Voor uitzonderingen is de statuscode altijd 500, wat overeenkomt met de “Interne serverfout”, voor andere soorten fouten krijgen we verschillende foutcodes zoals 404, 403, enz. Met de statuscode presenteert onze implementatie verschillende soorten HTML-respons aan de gebruiker. Het biedt ook een hyperlink naar de startpagina van de applicatie. Wanneer we nu onze servlet raken die een ServletException genereert, krijgen we een reactie zoals de onderstaande afbeelding. Als we proberen toegang te krijgen tot een ongeldige URL die resulteert in een 404-reactie, krijgen we een reactie zoals de onderstaande afbeelding.
Ziet het er niet goed uit en helpt het de gebruiker om gemakkelijk te begrijpen wat er is gebeurd en biedt het hen een manier om naar de juiste locatie te gaan? Het vermijdt ook het verzenden van gevoelige informatie van de applicatie naar de gebruiker. We zouden altijd uitzonderingsbehandelaars moeten hebben voor onze webapplicatie. Als je runtime-uitzonderingen en alle andere uitzonderingen in een enkele uitzonderingshandler wilt afhandelen, kun je exception-type opgeven als Throwable.
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
Als er meerdere foutpagina-ingangen zijn, laten we zeggen een voor Throwable en een voor IOException en de toepassing werpt FileNotFoundException op, dan zal deze worden afgehandeld door de foutafhandelaar van IOException. U kunt ook een JSP-pagina gebruiken als uitzonderingsafhandelaar, geef gewoon de locatie van het jsp-bestand op in plaats van servlet-toewijzing. Dat is alles voor servlet-uitzonderingsafhandeling in een webtoepassing, ik hoop dat je het leuk vond.
Download Servlet Uitzonderingsafhandeling Voorbeeld Project
Bekijk ook andere artikelen in deze serie: