Spring Web MVC - проверка параметров отдельных запросов - PullRequest
47 голосов
/ 01 июня 2011

Я запускаю веб-приложение в Spring Web MVC 3.0, и у меня есть несколько методов контроллера, сигнатуры которых примерно следующие:

@RequestMapping(value = "/{level1}/{level2}/foo", method = RequestMethod.POST)
public ModelAndView createFoo(@PathVariable long level1,
        @PathVariable long level2,
        @RequestParam("foo_name") String fooname,
        @RequestParam(value = "description", required = false) String description);

Я хотел бы добавить некоторую проверку - например,description должно быть ограничено определенной длиной или fooname должно содержать только определенные символы.Если эта проверка не пройдена, я хочу вернуть сообщение пользователю, а не просто выбросить какое-то непроверенное исключение (что произойдет в любом случае, если я позволю данным просочиться до уровня DAO).Я знаю о JSR303, но не работал с ним и не совсем понимаю, как применять его в контексте Spring.

Из того, что я понимаю, другой вариант - привязать @RequestBody квесь объект домена и добавьте туда ограничения проверки, но в настоящее время мой код настроен на прием отдельных параметров, как показано выше.

Какой самый простой способ применить проверку к входным параметрам с использованием этого подхода?

Ответы [ 3 ]

38 голосов
/ 29 августа 2016

Теперь это представляется возможным (пробовал в Spring 4.1.2), см. https://raymondhlee.wordpress.com/2015/08/29/validating-spring-mvc-request-mapping-method-parameters/

Выдержка из приведенной выше страницы:

  1. Добавление MethodValidationPostProcessor в Spring @Класс конфигурации:

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
    
  2. Добавить @ Подтверждено для класса контроллера

  3. Использовать @Size непосредственно перед @ RequestParam

    @RequestMapping("/hi")
    public String sayHi(@Size(max = 10, message = "name should at most 10 characters long") @RequestParam("name") String name) {
        return "Hi " + name;
    

    }

  4. Обрабатывать ConstraintViolationException в методе @ExceptionHandler

29 голосов
/ 01 июня 2011

Нет ничего встроенного, чтобы сделать это, не все же в любом случае. В текущих версиях выпуска вам все равно нужно будет использовать WebDataBinder для привязки ваших параметров к объекту, если вам нужна автоматическая проверка. Это стоит научиться делать, если вы используете SpringMVC, даже если это не ваш первый выбор для этой задачи.

Это выглядит примерно так:

public ModelAndView createFoo(@PathVariable long level1,
        @PathVariable long level2,
        @Valid @ModelAttribute() FooWrapper fooWrapper,
        BindingResult errors) {
  if (errors.hasErrors() {
     //handle errors, can just return if using Spring form:error tags.
  }
}

public static class FooWrapper {
  @NotNull
  @Size(max=32)
  private String fooName;
  private String description;
//getset
}

Если у вас есть Hibernate Validator 4 или более поздней версии на вашем пути к классам и вы используете настройку диспетчера по умолчанию, он должен «Просто работать».

Редактирование с тех пор, как комментарии стали довольно большими:

Любой объект, который находится в сигнатуре вашего метода и не является «ожидаемым», который Spring знает, как внедрить, например, HttpRequest, ModelMap и т. Д., Будет привязан к данным. Это достигается для простых случаев, просто сопоставляя имена параметров запроса с именами свойств бинов и вызывающими сеттерами. @ModelAttribute - это просто личный стиль, в этом случае он ничего не делает. Интеграция JSR-303 с @Valid по параметру метода проходит через WebDataBinder. Если вы используете @RequestBody, вы используете маршаллер объекта, основанный на типе контента, который Spring определяет для тела запроса (обычно только из заголовка http.) Сервлет диспетчера (на самом деле AnnotationMethodHandlerAdapter) не имеет способа 'щелкнуть ключом проверки' для любого произвольного маршаллера. Он просто передает содержимое веб-запроса в конвертер сообщений и возвращает объект. Объект BindingResult не генерируется, поэтому в любом случае устанавливать ошибки некуда.

Вы все еще можете просто вставить свой валидатор в контроллер и запустить его на полученном объекте, он просто не имеет волшебной интеграции с @Valid в параметре запроса, заполняющем для вас BindingResult.

17 голосов
/ 16 ноября 2012

Если у вас есть несколько параметров запроса, которые необходимо проверить (с помощью Http GET или POST ). Вы также можете создать пользовательский класс модели и использовать @ Valid вместе с @ ModelAttribute для проверки параметров. Таким образом, вы можете использовать Hibernate Validator или javax.validator api для проверки параметров. Это выглядит примерно так:

Способ запроса:

@RequestMapping(value="/doSomething", method=RequestMethod.GET)
public Model dosomething(@Valid @ModelAttribute ModelRequest modelRequest, BindingResult result, Model model) {

    if (result.hasErrors()) {
        throw new SomeException("invalid request params");
    }

    //to access the request params
    modelRequest.getFirstParam();
    modelRequest.getSecondParam();

    ...   
}

ModelRequest класс :

class ModelRequest {

    @NotNull
    private String firstParam;

    @Size(min = 1, max = 10, message = "You messed up!")
    private String secondParam;

    //Setters and getters

    public void setFirstParam (String firstParam) {
        this.firstParam = firstParam;
    }

    public String getFirstParam() {
        return firstParam;
    }

    ...
}

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...