14

我正在使用 Spring 3.2.0。根据这个答案,我在带注释的控制器中有相同的方法,它实现了HandlerExceptionResolver接口,例如,

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");
}

Spring 配置包括,

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

当文件大小超过时,应该调用前面的方法,它应该自动处理异常,但它根本不会发生。resolveException()即使发生异常,也不会调用该方法。处理这个异常的方法是什么?我错过了什么吗?

此处也指定了相同的内容。我不确定为什么它在我的情况下不起作用。


我已经尝试了以下方法@ControllerAdvice但它也没有奏效。

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);
    }
}

我也试图把冗长的 - Exception

@ExceptionHandler(value={Exception.class})

ResponseEntity()在任何情况下都不会调用该方法。


一般来说,如果可能的话,我想按控制器基础(控制器级别)处理这个异常。为此,一个@ExceptionHandler带注释的方法应该只对那个特定的控制器有效,而不是对整个应用程序全局有效,因为我的应用程序中只有几个网页处理文件上传。当这个异常发生时,我只想在当前页面显示一个用户友好的错误信息,而不是重定向到web.xml文件中配置的错误页面。如果这甚至不可行,那么无论如何都应该处理这个异常,而不需要我刚才表达的任何自定义要求。

这两种方法都不适合我。我找不到更多关于处理这个异常的信息。它是否需要在 XML 文件中的某处或其他地方进行额外配置?


抛出异常后我得到的内容可以在以下快照中看到。

在此处输入图像描述

4

7 回答 7

8

根据您发布的堆栈跟踪,在请求到达调度程序 servlet之前MaxUploadSizeExceeded引发异常。因此,您的异常处理程序不会被调用,因为在抛出异常时目标控制器尚未确定。

如果您查看堆栈跟踪,您会看到异常被抛出,HiddenHttpMethodFilter它获取您的多部分请求的所有参数 - 以及您的“大”上传数据参数。

您的控制器是否HiddenHttpMethodFilter需要处理多部分上传?如果没有,请将此过滤器从您的上传处理控制器中排除。

于 2013-04-09T15:05:46.970 回答
3

您可以像这样将 CommonsMultipartResolver 的 resolveLazily 属性配置为 true:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="resolveLazily" value="true"/>
</bean>
于 2013-08-21T09:14:11.993 回答
2

从Dirk Lachowski 发布的答案HiddenHttpMethodFilter中,我排除了一些用于从.

HiddenHttpMethodFilter最初被赋予了一个 URL 模式,如/*. 因此,将这些页面移动到单独的目录/文件夹中并指定不同的 URL 模式(如/xxx/*. 为避免这种情况,我OncePerRequestFilter在自己的类中继承并排除了这些用于多部分上传的页面,这些页面按预期工作,在当前页面上显示用户友好的错误消息。

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;
        }
    }
}

在我的web.xml文件中,这个过滤器 -filter.HiddenHttpMethodFilter被指定而不是org.springframework.web.filter.HiddenHttpMethodFilter如下。

<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>

我仍然希望应该/可以有一种公平的方式来处理有问题的异常以及org.springframework.web.filter.HiddenHttpMethodFilter

于 2013-04-10T12:08:33.557 回答
1

您的 @ExcpetionHandler 不起作用,因为据我所知,这些带注释的方法仅允许返回 ModelAndView 或 String 类型。有关详细信息,请参阅此帖子

于 2013-04-05T19:46:58.373 回答
1

我的解决方案:首先为实现 HandlerExceptionResolver 的类定义 bean。

 <bean id="classForBeanException" class="XXXX.path.To.classForBeanException" />
于 2013-04-08T09:50:42.137 回答
1

在处理异常的 ControllerAdvice 中,您可以使用这样的代码。它对我有用。这是在 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;
}
于 2016-02-26T08:55:48.447 回答
0

无论如何要获取在管理 MaxUploadSizeExceededException 的 ExceptionHandler 的控制器方法中定义的 @RequestParam 参数?似乎在到达 Controller 方法之前被抛出。

于 2019-11-15T14:32:22.537 回答