Обработчик исключений Spring, не может получить доступ к атрибутам запроса - PullRequest
0 голосов
/ 05 апреля 2019

у меня этот контроллер использует пружинную загрузку 2.1

@Controller
@AllArgsConstructor
@ControllerAdvice
public class AdminPoolsController {

@PostMapping("admin/pools/edit")
    public String update(@Valid final PoolDto pool,
                         @RequestParam(name = "image-upload", required = false) final MultipartFile file,
                         final BindingResult bindingResult,
                         final RedirectAttributes redirectAttrs) throws IOException {
        //some logic
    }


    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public String fileSizeLimitExc(
            final HttpServletRequest request,
            final RedirectAttributes redirectAttributes,
            final MaxUploadSizeExceededException exc
    ) {
        final Object id = request.getAttribute("id");
        redirectAttributes.addFlashAttribute(
                "errors",
                ImmutableMap.of(
                        "logo",
                        String.format(
                                "File exceeded max size of %d bytes",
                                exc.getMaxUploadSize()
                        )
                )
        );
        return "redirect:/admin/pools/edit" + (id == null ? "" : "?id=" + id.toString());
    }

}

Как вы видите, у меня есть PoolDto в методе POST, у этого DTO есть id, привязка происходит через html форму

<input type="hidden" name="id" id="id" th:value="${pool.id}">

В HTML-форме я могу предоставить файл, используя тип входного файла, но этот файл имеет ограниченный размер, поэтому я ловлю MaxUploadSizeExceededException Моя проблема в том, что HttpServletRequest внутри метода обработки ошибок не имеет никаких атрибутов запроса, в моем случае я хочу получить id из исходного запроса, но он всегда равен нулю. Как я могу поймать оригинальные атрибуты запроса, используя ExceptionHandler?

Ответы [ 3 ]

1 голос
/ 05 апреля 2019

Если запрос достигает максимального размера загрузки, тело запроса никогда не обрабатывается полностью.Вместо этого он отменяется при достижении лимита.Поэтому данные, передаваемые в теле запроса, недоступны.Это не относится к Spring Boot.Это более фундаментальное ограничение.

Чтобы передать какой-то идентификатор, у вас есть три основных варианта:

  1. Поместите идентификатор в URL, например, admin/pool/edit/123 или admin/pool/edit?id=123

  2. Сохраните идентификатор в файле cookie.

  3. Сохраните идентификатор в сеансе.Идентификатор сеанса сохраняется в файле cookie.

0 голосов
/ 05 апреля 2019

может быть, это может помочь:

@Controller
@AllArgsConstructor
@ControllerAdvice
public class AdminPoolsController {

@PostMapping("admin/pools/edit")
    public String update(@Valid final PoolDto pool,
                         @RequestParam(name = "image-upload", required = false) final MultipartFile file,
                         final BindingResult bindingResult,
                         final RedirectAttributes redirectAttrs,HttpServletRequest request) throws IOException {
        //some logic

           // set it before throwing MaxUploadSizeExceededException  
           request.setAttribute("id",pool.getId());

    }


    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public String fileSizeLimitExc(
            final HttpServletRequest request,
            final RedirectAttributes redirectAttributes,
            final MaxUploadSizeExceededException exc
    ) {
        final Object id = request.getAttribute("id");
        redirectAttributes.addFlashAttribute(
                "errors",
                ImmutableMap.of(
                        "logo",
                        String.format(
                                "File exceeded max size of %d bytes",
                                exc.getMaxUploadSize()
                        )
                )
        );
        return "redirect:/admin/pools/edit" + (id == null ? "" : "?id=" + id.toString());
    }

}
0 голосов
/ 05 апреля 2019

Как сказал @Codo, невозможно сохранить тело запроса, поэтому я использовал его решение с параметром GET ? Id = 123 , но вместо этого я не сохраняю его в куки, я использую см. заголовок, это мое решение

private static final Pattern ID_PATTERN = Pattern.compile("\\?id=([0-9]+)");

@ExceptionHandler(MaxUploadSizeExceededException.class)
    public String fileSizeLimitExc(
            final NativeWebRequest request,
            final RedirectAttributes redirectAttributes,
            final MaxUploadSizeExceededException exc
    ) {
        redirectAttributes.addFlashAttribute(
                "errors",
                ImmutableMap.of(
                        "logo",
                        String.format(
                                "File exceeded max size of %d bytes",
                                ((FileUploadBase.FileSizeLimitExceededException) exc.getCause().getCause()).getActualSize()
                        )
                )
        );

        final StringBuilder redirectUrl = new StringBuilder("redirect:/admin/pools/edit");
        this.poolId(request).ifPresent(id -> redirectUrl.append("?id=").append(id));
        return redirectUrl.toString();
    }

    /**
     * Get pool id from exception handler method
     *
     * @param request Native request
     * @return Pool id if present
     */
    private Optional<String> poolId(final NativeWebRequest request) {
        final String referer = request.getHeader("referer");
        final Matcher matcher = ID_PATTERN.matcher(referer);

        final Optional<String> id;
        if (matcher.find()) {
            id = Optional.of(matcher.group(1));
        } else {
            id = Optional.empty();
        }
        return id;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...