10

Tôi đang sử dụng Spring 3.2.0. Theo this câu trả lời, tôi có cùng một phương pháp trong điều khiển chú thích của tôi mà thực hiện giao diện HandlerExceptionResolver như,MaxUploadSizeExceededException không gọi phương thức xử lý ngoại lệ trong Spring

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) { 

    Map<String, Object> model = new HashMap<String, Object>(0); 

    if (exception instanceof MaxUploadSizeExceededException) { 
     model.put("msg", exception.toString()); 
     model.put("status", "-1"); 
    } else { 
     model.put("msg", "Unexpected error : " + exception.toString()); 
     model.put("status", "-1"); 
    } 

    return new ModelAndView("admin_side/ProductImage"); 
} 

và cấu hình Spring bao gồm,

<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
    <property name="maxUploadSize"> 
     <value>10000</value> 
    </property> 
</bean> 

Khi kích thước tập tin lớn hơn, trước đó phương thức nên được gọi và nó sẽ tự động xử lý ngoại lệ nhưng nó không xảy ra chút nào. Phương thức resolveException() không bao giờ được gọi ngay cả khi ngoại lệ xảy ra. Cách xử lý ngoại lệ này là gì? Tui bỏ lỡ điều gì vậy?

Điều tương tự cũng được chỉ định here. Tôi không chắc tại sao nó không hoạt động trong trường hợp của tôi.


Tôi đã thử following approach với @ControllerAdvice nhưng không hoạt động.

package exceptionhandler; 

import org.springframework.http.HttpHeaders; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 
import org.springframework.web.context.request.WebRequest; 
import org.springframework.web.multipart.MaxUploadSizeExceededException; 
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 

@ControllerAdvice 
public final class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { 

    @ExceptionHandler(value = {MaxUploadSizeExceededException.class}) 
    protected ResponseEntity<Object> handleConflict(RuntimeException ex, WebRequest request) { 
     String bodyOfResponse = "This should be application specific"; 
     return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); 
    } 
} 

Tôi cũng đã cố gắng đặt chi tiết - Exception.

@ExceptionHandler(value={Exception.class}) 

Phương pháp ResponseEntity() không bao giờ được gọi trong mọi trường hợp.


Nói chung, tôi muốn xử lý ngoại lệ này cho mỗi cơ sở điều khiển (cấp bộ điều khiển), nếu có thể. Đối với điều này, một phương thức chú thích @ExceptionHandler chỉ nên hoạt động cho bộ điều khiển cụ thể đó, không phải trên toàn cầu cho toàn bộ ứng dụng, vì chỉ có một vài trang web trong ứng dụng của tôi xử lý việc tải lên tệp. Khi ngoại lệ này được gây ra, tôi chỉ muốn hiển thị thông báo lỗi thân thiện với người dùng trên trang hiện tại và không chuyển hướng đến trang lỗi được định cấu hình trong tệp web.xml. Nếu điều này thậm chí không khả thi, thì ngoại lệ này nên được xử lý mà không cần bất kỳ yêu cầu tùy chỉnh nào mà tôi vừa trình bày.

Không có cách tiếp cận nào phù hợp với tôi. Không có gì thêm về xử lý ngoại lệ này tôi có thể tìm thấy. Nó có yêu cầu cấu hình bổ sung ở đâu đó trong các tệp XML hay không?


Những gì tôi nhận được sau khi ngoại lệ được ném có thể hiển thị trong snap shot sau đây.

enter image description here

+0

Không rõ nếu bạn đã thử điều đó, nhưng '@ ExceptionHandler' chỉ bắt ngoại lệ được ném từ Bộ điều khiển được xác định trong, chứ không phải trên toàn cầu (ví dụ: * "Tôi muốn xử lý ngoại lệ này cho mỗi bộ điều khiển" * về cơ bản là tùy chọn duy nhất) – kryger

+0

@ kryger: Phương thức được chú thích bằng '@ ExceptionHandler' không bao giờ được gọi trong bất kỳ trường hợp nào, không ở cấp điều khiển. Nó được gọi với các ngoại lệ khác nhưng không phải với 'MaxUploadSizeExceededException'. – Tiny

+0

bạn đã giải quyết vấn đề này chưa? – tibi

Trả lời

8

Theo stacktrace gửi của bạn ngoại trừ MaxUploadSizeExceeded được ném trước yêu cầu đã đạt đến servlet phối. Do đó, ngoại lệ của bạn không được gọi bởi vì tại thời điểm ngoại lệ được ném, bộ điều khiển đích vẫn chưa được xác định.

Nếu bạn nhìn vào stacktrace bạn có thể thấy rằng ngoại lệ được ném trong HiddenHttpMethodFilter nhận tất cả thông số của yêu cầu nhiều phần của bạn - và cũng là thông số tải lên dữ liệu "to lớn" của bạn.

Điện thoại HiddenHttpMethodFilter có cần thiết cho bộ điều khiển của bạn để xử lý tải lên nhiều phần không? Nếu không, hãy loại trừ bộ lọc này khỏi bộ điều khiển xử lý tải lên của bạn.

+0

Điều đó đã được thực hiện! Cảm ơn bạn đã xác định chính xác miền vấn đề. – Tiny

1

@ExcpetionHandler của bạn không hoạt động vì những phương pháp chú thích chỉ cho phép các loại trở lại của ModelAndView hoặc String, từ những gì tôi nhớ. Xem this posting để biết thêm chi tiết.

+0

Điều đó đã được thử với ** một kiểu trả về của chuỗi ** cũng được hiểu là tên dạng xem nhưng tiếc là không ai trong số chúng làm việc cho tôi. – Tiny

+0

Nhìn vào ảnh chụp nhanh trong phần thân câu hỏi, có thể nhận thấy rằng trình duyệt không biểu thị trạng thái 500 vì toàn bộ yêu cầu bị từ chối và không được xử lý. – Tiny

+0

Phương thức này chỉ được gọi với các ngoại lệ ngoại trừ ngoại lệ trong câu hỏi 'MaxUploadSizeExceededException'. – Tiny

1

Giải pháp của tôi: Đầu tiên xác định bean cho lớp thực hiện HandlerExceptionResolver.

<bean id="classForBeanException" class="XXXX.path.To.classForBeanException" /> 
2

Từ answer được đăng bởi Dirk Lachowski, tôi đã loại trừ một số trang được sử dụng để tải lên nhiều phần từ HiddenHttpMethodFilter.

HiddenHttpMethodFilter ban đầu được cung cấp một mẫu URL như /*. Do đó, thật tẻ nhạt khi di chuyển các trang này trong một thư mục/thư mục riêng biệt và chỉ định một tệp URL khác nhau như /xxx/*. Để tránh điều này, tôi đã thừa kế OncePerRequestFilter trong lớp học của riêng mình và loại trừ các trang này được sử dụng để tải lên nhiều phần hoạt động như mong đợi hiển thị thông báo lỗi thân thiện với người dùng trên trang hiện tại.

package filter; 

import java.io.IOException; 
import java.util.Locale; 
import javax.servlet.FilterChain; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletRequestWrapper; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.util.Assert; 
import org.springframework.util.StringUtils; 
import org.springframework.web.filter.OncePerRequestFilter; 

public final class HiddenHttpMethodFilter extends OncePerRequestFilter { 

    /** 
    * Default method parameter: <code>_method</code> 
    */ 
    public static final String DEFAULT_METHOD_PARAM = "_method"; 

    private String methodParam = DEFAULT_METHOD_PARAM; 

    /** 
    * Set the parameter name to look for HTTP methods. 
    * 
    * @see #DEFAULT_METHOD_PARAM 
    */ 
    public void setMethodParam(String methodParam) { 
     Assert.hasText(methodParam, "'methodParam' must not be empty"); 
     this.methodParam = methodParam; 
    } 

    private boolean excludePages(String page) { 
     //Specifically, in my case, this many pages so far have been excluded from processing avoiding the MaxUploadSizeExceededException in this filter. One could use a RegExp or something else as per requirements. 
     if (page.equalsIgnoreCase("Category.htm") || page.equalsIgnoreCase("SubCategory.htm") || page.equalsIgnoreCase("ProductImage.htm") || page.equalsIgnoreCase("Banner.htm") || page.equalsIgnoreCase("Brand.htm")) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 

     String servletPath = request.getServletPath(); 

     if (excludePages(servletPath.substring(servletPath.lastIndexOf("/") + 1, servletPath.length()))) { 
      String paramValue = request.getParameter(this.methodParam); 
      //The MaxUploadSizeExceededException was being thrown at the preceding line. 
      if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) { 
       String method = paramValue.toUpperCase(Locale.ENGLISH); 
       HttpServletRequest wrapper = new filter.HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method); 
       filterChain.doFilter(wrapper, response); 
      } else { 
       filterChain.doFilter(request, response); 
      } 
     } else { 
      filterChain.doFilter(request, response); 
     } 
    } 

    /** 
    * Simple {@link HttpServletRequest} wrapper that returns the supplied 
    * method for {@link HttpServletRequest#getMethod()}. 
    */ 
    private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper { 

     private final String method; 

     public HttpMethodRequestWrapper(HttpServletRequest request, String method) { 
      super(request); 
      this.method = method; 
     } 

     @Override 
     public String getMethod() { 
      return this.method; 
     } 
    } 
} 

Và trong tập tin web.xml của tôi, bộ lọc này - filter.HiddenHttpMethodFilter đã được chỉ định thay vì org.springframework.web.filter.HiddenHttpMethodFilter như sau.

<filter> 
    <filter-name>multipartFilter</filter-name> 
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>multipartFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

<filter> 
    <filter-name>httpMethodFilter</filter-name> 
    <filter-class>filter.HiddenHttpMethodFilter</filter-class> 
    <!--<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> This was removed replacing with the preceding one--> 
</filter> 
<filter-mapping> 
    <filter-name>httpMethodFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

tôi vẫn hy vọng rằng có nên/có thể là một cách công bằng để xử lý các ngoại lệ trong câu hỏi cùng với org.springframework.web.filter.HiddenHttpMethodFilter

2

Bạn có thể cấu hình bất động sản resolveLazily của CommonsMultipartResolver true như thế này:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
<property name="resolveLazily" value="true"/> 
</bean> 
+0

[This] (http://forum.springsource.org/showthread.php?134044-Handling-MaxUploadSizeExceededException-in-Spring&p=435534#post435534) là chuỗi của tôi trên diễn đàn Spring chính thức. Không may mắn sau khi làm điều này! – Tiny

+0

cố gắng sử dụng @HttpExceptionHandler –

+0

@jet ma cảm ơn, điều này đã giúp tôi) – Ales

1

Trong ControllerAdvice của bạn đang xử lý Ngoại lệ, bạn có thể có mã như thế này.Đã làm việc cho tôi.Đây là vào mùa xuân 4.0+

@ExceptionHandler(Exception.class) 
public @ResponseBody BaseResponse onException(Exception e, HttpServletResponse response) { 
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 

    BaseResponse resp = new BaseResponse(); 
    if(e instanceof MaxUploadSizeExceededException){ 
     resp.setCode(FileUploadFailed.SIZE_EXCEED); 
     resp.setMessage("Maximum upload size exceeded"); 
    } 
    return resp; 
}