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>");
                // Stack trace да чыгарыш мүмкүн
                // 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 аркылуу) негизги коду жана каталардын түрлөрүн иштетүү үчүн оңой. Экинчи ыкма (фильтр аркылуу) көбүрөөк ийкемдүү, ал кошумча логика жүргүзүүгө мүмкүндүк берет (мисалы, логдоо) жана кайра багыттоо алдында же иштетүүдө.