问题
I'm using Spring 3.2.0. According to this answer, I have the same method in my annotated controller which implements the HandlerExceptionResolver
interface such as,
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");
}
and the Spring configuration includes,
<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>10000</value>
</property>
</bean>
When the file size exceeds, the preceding method should be invoked and it should automatically handle the exception but it doesn't happen at all. The method resolveException()
is never called even though the exception occurs. What is the way to handle this exception? Am I missing something?
The same thing is also specified here. I'm not sure why it doesn't work in my case.
I have tried the following approach with @ControllerAdvice but it didn't work either.
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);
}
}
I have also tried to put the verbose - Exception
.
@ExceptionHandler(value={Exception.class})
The method ResponseEntity()
is never invoked in any case.
In general, I want to handle this exception per controller base (controller level), if possible. For this, one @ExceptionHandler
annotated method should only be active for that particular controller, not globally for the entire application, since there are only a few web pages in my application that handle file uploading. When this exception is caused, I just want to show a user-friendly error message on the current page and not to redirect to the error page configured in the web.xml
file. If this is not even feasible, then this exception should be handled anyway without any custom requirements I have just expressed.
Neither of approaches worked for me. Nothing more about handling this exception I could find. Does it require additional configuration somewhere in XML files or otherwise?
What I'm getting after the exception is thrown can be visible in the following snap shot.
回答1:
According to your posted stacktrace the MaxUploadSizeExceeded
exception is thrown before the request has reached the dispatcher servlet. Therefore your exceptionhandler isn't called because at the point the exception is thrown the target controller has yet to be determined.
If you look at the stacktrace you can see that the exception is thrown in the HiddenHttpMethodFilter
that gets all parameters of your multipart-request - and also your "to big" upload-data parameter.
Is the HiddenHttpMethodFilter
needed for your controller handling the multipart-upload? If not, exclude this filter from your upload-handling controllers.
回答2:
You can config the CommonsMultipartResolver's resolveLazily property to true like this:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="resolveLazily" value="true"/>
</bean>
回答3:
From the answer posted by Dirk Lachowski, I have excluded some of the pages which are used for multipart-upload from HiddenHttpMethodFilter.
HiddenHttpMethodFilter was originally given a URL pattern like /*
. Therefore, it was tedious to move these pages in a separate directory/folder and specify a different URL patter like /xxx/*
. To avoid this, I have inherited OncePerRequestFilter in my own class and excluded these pages used for multipart-upload that worked as expected showing a user-friendly error message on the current page.
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;
}
}
}
And in my web.xml
file, this filter - filter.HiddenHttpMethodFilter
was specified instead of org.springframework.web.filter.HiddenHttpMethodFilter as follows.
<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>
I'm still hoping that there should/could be a fair way to handle the exception in question along with org.springframework.web.filter.HiddenHttpMethodFilter
回答4:
Your @ExcpetionHandler isn't working because those annotated methods only allow return types of ModelAndView or String, from what I remember. See this posting for further details.
回答5:
My solution :First define bean for class that implements HandlerExceptionResolver .
<bean id="classForBeanException" class="XXXX.path.To.classForBeanException" />
回答6:
In your ControllerAdvice which is handling the Exception you can have code like this.It worked for me.This is in spring 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;
}
回答7:
Is there anyway to get the @RequestParam arguments defined in the controller method in the ExceptionHandler that manages the MaxUploadSizeExceededException? Seems to be being thrown before getting to the Controller method.
来源:https://stackoverflow.com/questions/14298265/maxuploadsizeexceededexception-doesnt-invoke-the-exception-handling-method-in-s