Tomcat: ExceptionHasndler не работает для MultiPartException, но работает правильно для IllegalArgumentException

У меня есть такой контроллер:

@PostMapping("/rest_upload1")
public ResponseEntity upload1(@RequestParam("file") MultipartFile multipartFile) throws IOException {
  throw new IllegalArgumentException();
}

и в конфигурации у меня есть настройки:

spring.http.multipart.max-file-size=100MB
spring.http.multipart.max-request-size=100MB

это означает, что spring выдаст MultipartException, если размер файла превышает 100 МБ.

Чтобы обработать это исключение, я написал обработчик:

@ControllerAdvice
public class RestExceptionHandlerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public ResponseEntity<ApiError> handleException(MultipartException e) {
         logger.warn("MultipartException:", e);
         ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST,
                String.valueOf(HttpStatus.BAD_REQUEST),
                ExceptionUtils.getRootCauseMessage(e),
                Collections.emptyList());
        return new ResponseEntity<ApiError>(apiError, HttpStatus.BAD_REQUEST);        
    }

В случае ошибки этот код вызывает (я вижу это в отладке)

но в браузере я не вижу ответа:

введите здесь описание изображения

введите здесь описание изображения

Я много времени гуглил и смотрел, что все в порядке. И я попытался добавить обработчик для IllegalArgumentException:

@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public ResponseEntity<ApiError> handleException(IllegalArgumentException e) {

    ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST,
                String.valueOf(HttpStatus.BAD_REQUEST),
                ExceptionUtils.getRootCauseMessage(e),
                Collections.emptyList());

    return new ResponseEntity<ApiError>(apiError, HttpStatus.BAD_REQUEST);            
}

И я загружаю файл менее 100 МБ. В этом случае результат отличается:

введите здесь описание изображения

Но в любом случае код ответа неверен.

Что может быть не так?

P.S.

Я старался:

@ExceptionHandler(MultipartException.class)
@ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE)
@ResponseBody
public String handleException(MultipartException e) {
    return ExceptionUtils.getRootCauseMessage(e);      
}

это выглядит так же, как здесь:

Как обрабатывать исключение максимального размера файла в Spring Boot?< /а>

P.S.2

Я нашел обходной путь, но это похоже на ошибку в sring:

Я добавил зависимости:

compile "org.apache.commons:commons-io:1.3.2"
compile "commons-fileupload:commons-fileupload:1.3.3"

зарегистрировать бины:

@Bean
public MultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
     multipartResolver.setMaxUploadSize(10);
     return multipartResolver;
}

и написал:

@ControllerAdvice
public class UploadExceptionHandler {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE)
    @ResponseBody
    public String handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        return e.getMessage();
    }
}

person gstackoverflow    schedule 20.11.2017    source источник
comment
comment
@pvpkiran вы видите существенную разницу между моим кодом и решением?   -  person gstackoverflow    schedule 20.11.2017
comment
@pvpkiran пожалуйста прочитайте обновление темы   -  person gstackoverflow    schedule 20.11.2017
comment
Вы пробовали с ErrorController, как это было предложено в принятом ответе в сообщении, которое я дал   -  person pvpkiran    schedule 20.11.2017
comment
@pvpkiran Я не понимаю, что такое контроллер ошибок. Вы можете уточнить?   -  person gstackoverflow    schedule 20.11.2017
comment
ErrorController — это интерфейс в среде Spring, который вы можете реализовать и добавить свою собственную реализацию. Вот пример github.com/ksoichiro/spring-boot-practice/blob/master/contents/   -  person pvpkiran    schedule 20.11.2017
comment
@pvpkiran, ErrorController требует реализации String getErrorPath(), но я хочу вернуть только String   -  person gstackoverflow    schedule 20.11.2017


Ответы (1)


Не очень умные разработчики Tomcat добавили новую функцию, которую нам нужно отключить/переопределить.

Он работает после того, как я добавил:

    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {

        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

        tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {

            // connector other settings...

            // configure maxSwallowSize
            if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
                // -1 means unlimited, accept bytes
                ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }

        });

        return tomcat;

    }
person gstackoverflow    schedule 20.11.2017