Sobes.tech
Middle

Басқа сервлет тастап кеткен қателерді қолданбада қалай өңдеу керек?

sobes.tech AI

AI-дан жауап

Стандартты сервлет архитектурасында бір сервлет тастап кеткен қателіктер басқа сервлет тарапынан тікелей өңделе алмайды. Әр сұрау жеке ағыммен өңделеді, ол бір сервлеттің өмірлік циклымен байланысты.

Алайда, мұндай мінез-құлыққа жету үшін келесі тәсілдерді қолдануға болады:

  1. Сервлет контейнерінің қателерін өңдеу механизмін пайдалану:

    • web.xml файлына белгілі бір қателер түрлері немесе HTTP күй кодтары үшін қателік беттерін орнатуға болады. Сервлет контейнері (мысалы, Tomcat, Jetty) қате пайда болғанда осы бетке бағыттайды.
    • Қате бетінде (ол басқа сервлет немесе JSP болуы мүмкін) сұрау атрибуттарынан қате туралы ақпарат алуға болады.
    • Атрибуттар request.getAttribute() арқылы қол жетімді. Кілттерге 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>Қате!</h2>");
            out.println("<p>Күй коды: " + statusCode + "</p>");
            out.println("<p>Сервлет: " + (servletName != null ? servletName : "Белгісіз") + "</p>");
            out.println("<p>Сұрау URI: " + (requestUri != null ? requestUri : "Белгісіз") + "</p>");
            if (throwable != null) {
                out.println("<p>Қате түрі: " + throwable.getClass().getName() + "</p>");
                out.println("<p>Хабарлама: " + throwable.getMessage() + "</p>");
                // Қажет болса, стек трассасын шығару
                // throwable.printStackTrace(out);
            }
            out.println("</body></html>");
        }
    }
    
  2. Сервлет фильтрлерін пайдалану:

    • Фильтр doFilter тізбегін try-catch блогында орауы мүмкін.
    • Егер сервлет тізбегінде қате тасталса, фильтр оны ұстайды.
    • catch блогында фильтр қателікті өңдей алады немесе оны арнайы қате өңдеу бетіне бағыттай алады (request.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("/*") // Барлық сұрауларға қолданылады
    public class ExceptionHandlingFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // Фильтрді инициализациялау
        }
    
        @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); // Сұрауды келесі сервлетке немесе фильтрге өткізу
            } catch (Exception e) {
                // Қате тасталғанда оны ұстау
                System.err.println("Сұрауды өңдеу кезінде қате пайда болды: " + httpRequest.getRequestURI());
                e.printStackTrace(); // Қате туралы лог
    
                // Қате туралы ақпаратты сақтау
                httpRequest.setAttribute("javax.servlet.error.exception", e);
                httpRequest.setAttribute("javax.servlet.error.message", e.getMessage());
                httpRequest.setAttribute("javax.servlet.error.request_uri", httpRequest.getRequestURI());
                // Статус кодын орнату
                httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 ішкі сервер қатесі
    
                // Қате өңдеу сервлетіне бағыттау
                httpRequest.getRequestDispatcher("/errorServlet").forward(httpRequest, httpResponse);
            }
        }
    
        @Override
        public void destroy() {
            // Фильтр ресурстарын босату
        }
    }
    

Бұл екі тәсіл қателерді орталықтандырып өңдеуге және контейнердің әдепкі қате хабарламаларын пайдаланушыға көрсетпеуге мүмкіндік береді. Бірінші әдіс (web.xml арқылы) негізгі күй кодтары мен қателер түрлерін өңдеуге оңай. Екінші әдіс (фильтр арқылы) икемділікті арттырады, қосымша логика жүргізуге мүмкіндік береді (мысалы, логтау) және қателерді өңдеу немесе қайта бағыттау алдында қосымша әрекеттер жасауға мүмкіндік береді.