2012-06-28 18 views
23

Tôi có ứng dụng Spring MVC sử dụng công nghệ FreeMarker làm công nghệ Xem (Nhưng có thể công nghệ xem không thực sự quan trọng đối với câu hỏi của tôi). Tôi cần chặn tất cả các ngoại lệ có thể bị ném trong khi yêu cầu.Làm cách nào để xử lý các ngoại lệ được ném trong khi hiển thị chế độ xem trong Spring MVC?

Tôi đã triển khai HandlerExceptionResolver nhưng trình phân giải này chỉ được thực thi khi ngoại lệ xảy ra trong bộ điều khiển. Nhưng khi một bộ điều khiển trả về một ModelAndView và ngoại lệ xảy ra khi render khung nhìn (Vì một biến không được tìm thấy hoặc một cái gì đó như thế này) thì trình phân giải ngoại lệ không được gọi và thay vào đó tôi nhận được một dấu vết ngăn xếp trong cửa sổ trình duyệt.

Tôi cũng đã thử sử dụng một phương thức xử lý ngoại lệ trong bộ điều khiển trả về dạng xem và chú thích nó bằng @ExceptionHandler nhưng điều này cũng không hoạt động (Nhiều khả năng một lần nữa vì ngoại lệ không được ném trong bộ điều khiển nhưng trong chế độ xem) .

Vì vậy, có một số cơ chế Mùa xuân, nơi tôi có thể đăng ký trình xử lý ngoại lệ để ghi lại các lỗi xem?

+0

[Cấu hình] (http://developingdeveloper.wordpress.com/2008/03/09/handling-exceptions-in-spring-mvc-part-2/) có giúp được không? – nobeh

+0

@nobeh Không, tiếc là không. Bài viết này chỉ giải thích cách sử dụng các công cụ HandlerExceptionResolver. Đó là những gì tôi đã sử dụng nhưng nó chỉ bắt ngoại lệ được ném trong bộ điều khiển, không phải trong chế độ xem. – kayahr

Trả lời

21

Trả trước từ: nếu bạn chỉ cần trang lỗi "tĩnh" mà không cần chuẩn bị mô hình logic và logic, bạn nên điền <error-page>Thẻ vào web.xml của mình (xem ví dụ bên dưới).

Nếu không, có thể có những cách tốt hơn để làm điều này, nhưng hoạt động này đối với chúng tôi:

Chúng tôi sử dụng một servlet <filter> trong web.xml mà bắt tất cả các trường hợp ngoại lệ và kêu gọi tùy chỉnh ErrorHandler của chúng tôi, cùng chúng tôi sử dụng trong mùa xuân HandlerExceptionResolver.

<filter> 
    <filter-name>errorHandlerFilter</filter-name> 
    <filter-class>org.example.filter.ErrorHandlerFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>errorHandlerFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

Việc thực hiện trông về cơ bản như thế này:

public class ErrorHandlerFilter implements Filter { 

    ErrorHandler errorHandler; 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 
    try { 
     filterChain.doFilter(request, response); 
    } catch (Exception ex) { 
     // call ErrorHandler and dispatch to error jsp 
     String errorMessage = errorHandler.handle(request, response, ex); 
     request.setAttribute("errorMessage", errorMessage); 
     request.getRequestDispatcher("/WEB-INF/jsp/error/dispatch-error.jsp").forward(request, response); 
    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
    errorHandler = (ErrorHandler) WebApplicationContextUtils 
     .getRequiredWebApplicationContext(filterConfig.getServletContext()) 
     .getBean("defaultErrorHandler"); 
    } 

    // ... 
} 

Tôi tin rằng điều này sẽ làm việc khá nhiều như nhau cho Freemarker mẫu. Tất nhiên nếu xem lỗi của bạn ném một lỗi, bạn có nhiều hơn hoặc ít hơn trong số các tùy chọn.

Để cũng bắt lỗi như 404 và chuẩn bị mô hình cho nó, chúng tôi sử dụng một bộ lọc được ánh xạ tới các ERROR phối:

<filter> 
    <filter-name>errorDispatcherFilter</filter-name> 
    <filter-class>org.example.filter.ErrorDispatcherFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>errorDispatcherFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>ERROR</dispatcher> 
</filter-mapping> 

<error-page> 
    <error-code>404</error-code> 
    <location>/WEB-INF/jsp/error/dispatch-error.jsp</location> 
</error-page> 
<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/WEB-INF/jsp/error/dispatch-error.jsp</location> 
</error-page> 

Các doFilter-Thực hiện trông như thế này:

@Override 
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 

    final HttpServletRequest request = (HttpServletRequest) servletRequest; 

    // handle code(s) 
    final int code = (Integer) request.getAttribute("javax.servlet.error.status_code"); 
    if (code == 404) { 
    final String uri = (String) request.getAttribute("javax.servlet.error.request_uri"); 
    request.setAttribute("errorMessage", "The requested page '" + uri + "' could not be found."); 
    } 

    // notify chain 
    filterChain.doFilter(servletRequest, servletResponse); 
} 
+0

Tôi chưa sử dụng trình xử lý lỗi tùy chỉnh. Tất cả những gì tôi muốn làm là - nếu việc xử lý mẫu không thành công, sau đó chuyển hướng người dùng đến một trang lỗi tĩnh. Trình duyệt hiển thị nội dung trang lỗi nhưng nó cũng hiển thị dấu vết ngăn xếp. Bất kì manh mối nào? Tôi đang sử dụng Spring. Chỉ đơn giản là servlets với freemarker cho các view. – sbidwai

+1

Xin chào, cảm ơn bạn vì điều này, tôi nhận được 'org.springframework.beans.factory.NoSuchBeanDefinitionException: Không có bean tên 'defaultErrorHandler' được định nghĩa' trên init. Tôi có cần phải xác định điều này trong một servlet.xml? – Ernest

+0

Có cách nào để làm điều này về phía trước: 'request.getRequestDispatcher ("/WEB-INF/jsp/lỗi/dispatch-error.jsp "). Forward (request, response);' bằng cách sử dụng một ViewResolver hiện có? – FelipeKunzler

0

Không chắc liệu giải pháp của tôi có hoạt động với sự cố bạn đang gặp phải hay không. Ill chỉ gửi cách tôi bắt ngoại lệ của tôi để đảm bảo không có vết đống là chương trình bên trong trình duyệt:

tôi đã thực hiện một lớp AbstractController với một phương pháp mà sẽ xử lý một cuộc xung đột cụ thể như thế này:

public class AbstractController { 

    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler({OptimisticLockingFailureException.class}) 
    @ResponseBody 
    public void handleConflict() { 
    //Do something extra if you want 
    } 
} 

Bằng cách này bất cứ khi nào ngoại lệ xảy ra, người dùng sẽ thấy trạng thái HTTPResponse mặc định. (ví dụ 404 Không tìm thấy vv ..)

Tôi mở rộng lớp này trên tất cả các lớp điều khiển của mình để đảm bảo lỗi được chuyển hướng đến AbstractController. Bằng cách này tôi không cần phải sử dụng ExceptionHandler trên một bộ điều khiển cụ thể nhưng tôi có thể thêm toàn cầu cho tất cả các bộ điều khiển của tôi. (bằng cách mở rộng lớp AbstractController).

Chỉnh sửa: Sau khi tiếp tục câu hỏi của bạn, tôi nhận thấy bạn đang gặp lỗi trong chế độ xem của mình. Không chắc chắn nếu cách này sẽ bắt lỗi đó ..

Hy vọng điều này sẽ giúp !!

+0

Đã thử điều này. Tôi đã thêm một phương thức như vậy trực tiếp vào bộ điều khiển và không phải trong một số lớp cơ sở của nó, nhưng điều này không tạo ra sự khác biệt. Trình xử lý ngoại lệ này được gọi khi ngoại lệ được ném trong phương thức bộ điều khiển, nhưng không phải khi ngoại lệ được ném trong khung nhìn. – kayahr

+0

hoặc nếu lỗi xảy ra trong bộ lọc servlet. Tôi nghĩ câu trả lời được chấp nhận là câu trả lời duy nhất xử lý bất kỳ lỗi nào ở bất cứ đâu. – ticktock

+0

Điều này sẽ không hoạt động. Việc xử lý mẫu xảy ra SAU bộ điều khiển và lời khuyên điều khiển được gọi. Vì vậy, cách duy nhất tôi có thể nghĩ đến là thêm handline để lọc theo đề xuất của câu trả lời được chấp nhận. Không đẹp nhưng có ý nghĩa. –

6

Bạn có thể mở rộng DispatcherServlet.

Trong web.xml của bạn, hãy thay thế DispatcherServlet chung cho lớp của riêng bạn.

<servlet> 
    <servlet-name>springmvc</servlet-name> 
    <servlet-class>com.controller.generic.DispatcherServletHandler</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

Sau đó tạo DispatcherServletHandler lớp của riêng bạn và kéo dài từ DispatcherServlet:

public class DispatcherServletHandler extends DispatcherServlet { 

    private static final String ERROR = "error"; 
    private static final String VIEW_ERROR_PAGE = "/WEB-INF/views/error/view-error.jsp"; 

    @Override 
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 
     try{ 
      super.doService(request, response); 
     } catch(Exception ex) { 
      request.setAttribute(ERROR, ex); 
      request.getRequestDispatcher(VIEW_ERROR_PAGE).forward(request, response); 
     } 
    } 
} 

Và trong trang đó chúng tôi chỉ có thể hiện một thông điệp tới người sử dụng.

Các vấn đề liên quan