Sobes.tech
Middle

Tətbiqdə başqa servlet tərəfindən atılan istisnaları necə idarə etmək olar?

sobes.tech Süni İntellekt

AI-dan cavab

Standart servlet memarlığında, bir servlet tərəfindən atılan istisnalar, cari sorğu çərçivəsində başqa bir servlet tərəfindən birbaşa işlənə bilməz. Hər bir sorğu ayrı bir thread-də işlənir və bu thread, bir servlet-in həyat dövrü ilə əlaqəlidir.

Ancaq, aşağıdakı yanaşmaları istifadə edərək oxşar davranış əldə etmək mümkündür:

  1. Servlet konteynerinin xəta idarəetmə mexanizmi:

    • web.xml faylında müəyyən istisna növləri və ya HTTP vəziyyət kodları üçün xəta səhifələri konfiqurasiya edilə bilər. Servlet konteyneri (məsələn, Tomcat, Jetty) bu səhifəyə yönləndirəcək.
    • Xəta səhifəsində (başqa servlet və ya JSP ola bilər) sorğu atributlarından istisna haqqında məlumat əldə etmək olar.
    • Atributlar request.getAttribute() vasitəsilə mövcuddur. Açarlar 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>Xəta!</h2>");
            out.println("<p>Status kodu: " + statusCode + "</p>");
            out.println("<p>Servlet: " + (servletName != null ? servletName : "Naməlum") + "</p>");
            out.println("<p>Sorğu URI: " + (requestUri != null ? requestUri : "Naməlum") + "</p>");
            if (throwable != null) {
                out.println("<p>Xəta tipi: " + throwable.getClass().getName() + "</p>");
                out.println("<p>Mesaj: " + throwable.getMessage() + "</p>");
                // Debug üçün stack trace göstərilə bilər
                // throwable.printStackTrace(out);
            }
            out.println("</body></html>");
        }
    }
    
  2. Servlet filtrlərindən istifadə:

    • Filtr doFilter zəncirini try-catch blokunda bükə bilər.
    • Əgər servlet zəncirində istisna atılırsa, filtr onu tutacaq.
    • catch blokunda filtr istisnayı özünə işləyə və ya sorğunu xüsusi xəta işləyicisinə (mümkün olan başqa servlet) yönləndirə bilər, məsələn, 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("/*") // Bütün sorğulara tətbiq olunur
    public class ExceptionHandlingFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // Filtrin başlanması
        }
    
        @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); // Sorğunu növbəti mərhələyə göndər
            } catch (Exception e) {
                // Servlet və ya növbəti filtr tərəfindən atılan istisnanı tutmaq
                System.err.println("Sorğunun işlənməsi zamanı xəta: " + httpRequest.getRequestURI());
                e.printStackTrace(); // Xətanın qeydiyyatı
    
                // Xəta haqqında məlumatların saxlanması
                httpRequest.setAttribute("javax.servlet.error.exception", e);
                httpRequest.setAttribute("javax.servlet.error.message", e.getMessage());
                httpRequest.setAttribute("javax.servlet.error.request_uri", httpRequest.getRequestURI());
                // Status kodu təyin edilə bilər
                httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 Internal Server Error
    
                // Xəta işləyicisinə yönləndirmək
                httpRequest.getRequestDispatcher("/errorServlet").forward(httpRequest, httpResponse);
            }
        }
    
        @Override
        public void destroy() {
            // Filtr resurslarının təmizlənməsi
        }
    }
    

Bu iki yanaşma xəta idarəetməsini mərkəzləşdirməyə və istifadəçiyə konteynerin standart xəta mesajlarının göstərilməsinin qarşısını almağa imkan verir. Birinci üsul (web.xml vasitəsilə) daha sadədir və əsas status kodlarının və istisna tiplərinin idarə olunmasına imkan verir. İkinci üsul (filtr vasitəsilə) daha çevikdir və əlavə loqlama və ya digər xüsusi işləmə imkanları təqdim edir.