Oggi esamineremo l’Eccezione del Servlet e la Gestione degli Errori. Qualche tempo fa ho scritto un post su Gestione delle Eccezioni in Java, ma quando si tratta di applicazioni web, abbiamo bisogno di più della normale gestione delle eccezioni in Java.
Eccezione del Servlet
Se notate, i metodi doGet() e doPost() lanciano javax.servlet.ServletException
e IOException
, vediamo cosa succede quando lanciamo queste eccezioni dalla nostra applicazione. Scriverò un semplice servlet che lancerà l’Eccezione del Servlet.
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.");
}
}
Ora, quando invochiamo questo servlet attraverso il browser con il metodo GET, otteniamo una risposta come nell’immagine sottostante. Poiché il browser comprende solo HTML, quando la nostra applicazione genera un’eccezione, il container del servlet elabora l’eccezione e genera una risposta HTML. Questa logica è specifica del container del servlet. Sto utilizzando Tomcat e ottenendo questa pagina di errore. Se si utilizzano altri server come JBoss o Glassfish, è possibile ottenere una risposta HTML di errore diversa. Il problema con questa risposta è che non ha alcun valore per l’utente. Inoltre, mostra le classi della nostra applicazione e i dettagli del server all’utente, il che non ha senso per l’utente e non è buono dal punto di vista della sicurezza.
Errore del 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.
Eccezione del Servlet e Gestione degli Errori
La Servlet API fornisce supporto per servlet personalizzati di gestione di eccezioni e errori che possiamo configurare nel descrittore di distribuzione. Lo scopo principale di queste servlet è gestire l’eccezione o l’errore generato dall’applicazione e inviare una risposta HTML utile all’utente. Possiamo fornire un collegamento alla homepage dell’applicazione o alcuni dettagli per far sapere all’utente cosa è andato storto. Quindi, innanzitutto, dobbiamo creare una servlet personalizzata per la gestione di eccezioni e errori. Possiamo avere molteplici servlet di gestione di eccezioni e errori per l’applicazione, ma per semplicità ne creerò una singola e la utilizzerò sia per le eccezioni che per gli errori. 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 {
// Analizza l'eccezione del 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";
}
// Imposta il tipo di contenuto della risposta
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("");
}
}
Vediamo come configurarla nel descrittore di distribuzione e poi capiremo la sua implementazione e come funziona.
<?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>
Come puoi vedere, è molto facile specificare i gestori di eccezioni per l’applicazione utilizzando l’elemento error-page. Ogni elemento error-page dovrebbe avere un elemento error-code o exception-type. Definiamo il gestore dell’eccezione servlet nell’elemento location. In base alla configurazione sopra, se l’applicazione genera un errore 404 o ServletException, sarà gestito dal servlet AppExceptionHandler. Quando appare uno scenario di eccezione e errore del genere, il contenitore servlet invocherà il metodo HTTP corrispondente del servlet Gestore eccezioni e passerà l’oggetto richiesta e risposta. Nota che ho fornito l’implementazione sia dei metodi doGet() che doPost() in modo che possa gestire le richieste GET e POST e utilizzare un metodo comune per elaborarle. Prima che il contenitore servlet invochi il servlet per gestire l’eccezione, imposta alcuni attributi nella richiesta per ottenere informazioni utili sull’eccezione, alcuni di essi sono javax.servlet.error.exception, javax.servlet.error.status_code, javax.servlet.error.servlet_name e javax.servlet.error.request_uri. Per l’eccezione, il codice di stato è sempre 500 che corrisponde all'”Errore interno del server”, per altri tipi di errore otteniamo diversi codici di errore come 404, 403, ecc. Utilizzando il codice di stato, la nostra implementazione presenta diversi tipi di risposta HTML all’utente. Fornisce anche un collegamento ipertestuale alla home page dell’applicazione. Ora, quando colpiremo il nostro servlet che sta generando ServletException, otterremo una risposta come nell’immagine seguente. Se proviamo ad accedere a un URL non valido che causerà una risposta 404, otterremo una risposta come nell’immagine seguente.
Non sembra buono e aiuta l’utente a capire facilmente cosa è successo e fornisce loro un modo per raggiungere la posizione corretta. Inoltre, evita di inviare informazioni sensibili dell’applicazione all’utente. Dovremmo sempre avere gestori di eccezioni in posizione per la nostra applicazione web. Se vuoi gestire le eccezioni in fase di esecuzione e tutte le altre eccezioni in un singolo gestore di eccezioni, puoi fornire exception-type come Throwable.
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/AppExceptionHandler</location>
</error-page>
Se ci sono molteplici voci di pagine di errore, ad esempio una per Throwable e una per IOException, e l’applicazione genera FileNotFoundException, sarà gestita dal gestore di errori di IOException. Puoi anche utilizzare una pagina JSP come gestore delle eccezioni, fornendo solo la posizione del file JSP anziché il mapping del servlet. Questo è tutto per la gestione delle eccezioni del servlet nelle applicazioni web, spero che ti sia piaciuto.
Scarica il progetto di esempio sulla gestione delle eccezioni del servlet
Consulta gli altri articoli di questa serie: