Ako spracovať v aplikácii výnimky, ktoré boli vyhodené iným servletem?
sobes.tech AI
Odpoveď od AI
V štandardnej servletovej architektúre výnimky, ktoré vyhodí jeden servlet, nemôžu byť priamo spracované iným servletom v rámci aktuálnej požiadavky. Každá požiadavka sa spracováva samostatným vláknom, ktoré je spojené s životným cyklom jedného servleta.
Avšak, je možné dosiahnuť podobné správanie pomocou nasledujúcich prístupov:
-
Použitie mechanizmu spracovania chýb kontajnera servletov:
- V
web.xmlje možné nakonfigurovať stránky chýb pre určité typy výnimiek alebo kódy stavu HTTP. Kontajner servletov (napríklad Tomcat, Jetty) presmeruje na túto stránku pri výskyte výnimky. - Na stránke chyby (ktorá môže byť iným servletom alebo JSP) je možné získať informácie o výnimke z atribútov požiadavky.
- Atribúty sú dostupné cez
request.getAttribute(). Kľúče zahŕňajújavax.servlet.error.exception,javax.servlet.error.exception_type,javax.servlet.error.message,javax.servlet.error.request_uri.
<error-page> <exception-type>java.lang.RuntimeException</exception-type> <location>/errorServlet</location> </error-page> <error-page> <error-code>500</error-code> <location>/errorServlet</location> </error-page>// ErrorServlet.java import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/errorServlet") public class ErrorServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 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"); String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><body>"); out.println("<h2>Chyba!</h2>"); out.println("<p>Kód stavu: " + statusCode + "</p>"); out.println("<p>Servlet: " + (servletName != null ? servletName : "Neznáme") + "</p>"); out.println("<p>URI požiadavky: " + (requestUri != null ? requestUri : "Neznáme") + "</p>"); if (throwable != null) { out.println("<p>Typ výnimky: " + throwable.getClass().getName() + "</p>"); out.println("<p>Správa: " + throwable.getMessage() + "</p>"); // Výpis stack trace pre ladenie // throwable.printStackTrace(out); } out.println("</body></html>"); } } - V
-
Použitie servlet filterov:
- Filter môže obaliť reťazec
doFilterdo blokutry-catch. - Ak servlet v reťazci vyhodí výnimku, filter ju zachytí.
- Vo vnútri bloku
catchmôže filter buď sám spracovať výnimku, alebo presmerovať požiadavku na špeciálny spracovateľ chýb (možno iný servlet) pomocourequest.getRequestDispatcher("/errorServlet").forward(request, response).
// ExceptionHandlingFilter.java import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter("/*") // Filter sa aplikuje na všetky požiadavky public class ExceptionHandlingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // Inicializácia filtra } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; try { chain.doFilter(request, response); // Odovzdanie požiadavky ďalej v reťazci (k servlete alebo ďalším filtrom) } catch (Exception e) { // Zachytenie výnimky, ktorú vyhodil servlete alebo ďalší filter System.err.println("Vyskytla sa chyba pri spracovaní požiadavky pre URI: " + httpRequest.getRequestURI()); e.printStackTrace(); // Logovanie chyby // Uloženie informácií o chybe pre spracovateľa httpRequest.setAttribute("javax.servlet.error.exception", e); httpRequest.setAttribute("javax.servlet.error.message", e.getMessage()); httpRequest.setAttribute("javax.servlet.error.request_uri", httpRequest.getRequestURI()); // Môže sa nastaviť kód stavu, ak je známy httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 Interná chyba servera // Presmerovanie na servlet spracovania chýb httpRequest.getRequestDispatcher("/errorServlet").forward(httpRequest, httpResponse); } } @Override public void destroy() { // Uvoľnenie zdrojov filtra } } - Filter môže obaliť reťazec
Tieto dva prístupy umožňujú centralizovanú správu chýb a zabraňujú zobrazovaniu štandardných správ o chybe kontajnera používateľovi. Prvý spôsob (cez web.xml) je jednoduchší pre základnú správu kódov stavu a typov výnimiek. Druhý spôsob (cez filter) poskytuje väčšiu flexibilitu, umožňujúc vykonávanie dodatočej logiky (napríklad logovanie) pred presmerovaním alebo spracovaním.