Подтвердить что ты не робот

Spring MVC: объясните, пожалуйста, разницу между @RequestParam и @ModelAttribute

Я новичок в Spring MVC. Пожалуйста, помогите мне распаковать документацию.

Documentation

Spring Документация MVC заявляет (основное внимание):

  • @ModelAttribute в аргументе метода указывает, что аргумент должен быть извлечен из модели. Если в модели нет, аргумент должен быть сначала создан, а затем добавлен в модель. После присутствия в модели поля аргументов должны быть заполнены из всех параметров запроса, имеющих соответствующие имена. Класс WebDataBinder сопоставляет имена параметров запроса - включая параметры строки запроса и поля формы - для моделирования полей атрибутов по имени.

  • @RequestParam связывает параметры запроса с параметром метода в вашем контроллере.

Отказ от ответственности /Clarifier

Я знаю, что @ModelAttribute и @RequestParam не одно и то же, не являются взаимоисключающими, не выполняют одну и ту же роль и могут использоваться одновременно, как в this вопрос - действительно, @RequestParam можно использовать для заполнения полей @ModelAttribute. Мой вопрос больше ориентирован на разницу между их внутренними разработками.

Вопрос:

В чем разница между @ModelAttribute (используется для аргумента метода, а не метода) и @RequestParam? В частности:

  • Источник: У @RequestParam и @ModelAttribute есть тот же источник информация/население, т.е. параметры запроса в URL-адресе, которые могут быть представлены как элементы формы/модели, которые были POST ed?
  • Использование: Правильно ли выбраны переменные, полученные с помощью @RequestParam (если они не переданы в модель), а переменные, полученные с помощью @ModelAttribute, автоматически отправляются в возвращаемую модель?

Или в очень простых примерах кодирования, какова реальная рабочая разница между этими двумя примерами?

Пример 1: @RequestParam:

// foo and bar are thrown away, and are just used (e.g.) to control flow?
@RequestMapping(method = RequestMethod.POST)
public String testFooBar(@RequestParam("foo") String foo,
@RequestParam("bar") String bar, ModelMap model) {
    try {
     doStuff(foo, bar);
    }
    // other code
  }

Пример 2: @ModelAttribute:

// FOOBAR CLASS
// Fields could of course be explicitly populated from parameters by @RequestParam
public class FooBar{
    private String foo;
    private String bar;
   // plus set() and get() methods
}

// CONTROLLER
// Foo and Bar become part of the model to be returned for the next view?
@RequestMapping(method = RequestMethod.POST)
public String setupForm(@ModelAttribute("fooBar") FooBar foobar) {
   String foo = fooBar.getFoo();
   String bar = fooBar.getBar();
   try {
      doStuff(foo, bar);
   }
   // other code
}

Мое настоящее понимание:

@ModelAttribute и @RequestParam оба опросят параметры запроса для информации, но они используют эту информацию по-разному:

  • @RequestParam просто заполняет автономные переменные (которые, конечно же, могут быть полями в классе @ModelAttribute). Эти переменные будут выброшены, когда контроллер будет выполнен, если они не были отправлены в модель.

  • @ModelAttribute заполняет поля класса, который затем заполняет атрибут модели, который будет передан обратно в представление

Правильно ли это?

4b9b3361

Ответ 1

@RequestParam просто заполняет автономные переменные (которые, конечно, могут быть полями в классе @ModelAttribute). Эти переменные будут выброшены, когда контроллер будет выполнен, если только они не были загружены в модель.

Не путайте слово "модель" с сеансом. HTTP-разговор обычно: HTTP.GET, ответ сервера, затем HTTP.POST. Когда вы используете аннотацию @ModelAttribute, вы всегда создаете экземпляр того, что вы аннотировали, и это заставляет вас думать, что "подача вещи в модель" может привести к тому, что переменные будут всплывать. Это неверно, как только HttpServletRequest закончил, эти переменные больше не должны быть частью разговора браузера/сервера, если они не были сохранены в сеансе.

@ModelAttribute заполняет поля класса, который затем заполняет атрибут модели, который будет передан обратно в представление

Да! Чтобы быть верным, @ModelAttribute сообщает Spring использовать связующее веб-данные по умолчанию для заполнения экземпляра чего-либо данными из HttpServletRequest. Выбор для передачи этих данных обратно в представление зависит от программиста. Когда у вас есть метод, аннотированный с помощью @ModelAttribute, он вызывается каждый раз, когда код попадает в этот сервлет. Когда у вас есть @ModelAttribute как один из параметров метода, мы говорим о привязке данных к входящей Http-форме.

Вызов @RequestParam - это ярлык для выражения request.getParameter("foo"); под капотом Java HttpServletRequest позволяет вам получать значения из объекта запроса, выполняя поиск ключа- > значение. Возвращаемое значение имеет тип Object. Это то, что вы набрали бы много, если бы вы не использовали Spring в своем веб-приложении.

Spring, затем эта абстракция сделает шаг вперед, когда вы начнете использовать @ModelAttribute. В этой аннотации используется понятие привязки данных. Цель привязки данных заключается в том, что код в вашем контроллере не должен вызывать request.getParameter("foo1") для каждого элемента формы. Представьте, что у вас есть веб-форма с 5 полями. Без привязки данных программист должен вручную извлечь и проверить каждое из этих полей. Программист должен убедиться, что запрос содержит свойство, что значение свойства существует, и что значение свойства имеет тип, ожидаемый для каждого поля. Использование @ModelAttribute сообщает Spring выполнить эту работу для вас.

Если вы комментируете метод в своем контроллере с помощью @ModelAttribute("fooBar") FooBar fooBar Экземпляр FooBar всегда будет создан Spring и указан в вашем методе. Когда вступает в действие привязка данных, это когда эта аннотация используется в параметрах метода; Spring смотрит экземпляр HttpServletRequest и видит, может ли он соответствовать данным в запросе правильному свойству экземпляра FooBar. Это основано на соглашении свойств java, где у вас есть поле типа foo и общедоступные геттеры и сеттеры, называемые getFoo и setFoo. Это может показаться волшебным, но если вы нарушите соглашение, ваша привязка данных Spring перестанет работать, потому что он не сможет узнать, где привязать данные из вашего HttpServletRequest. Вы все равно получите экземпляр FooBar, но свойства не будут заданы никакими значениями из запроса.

Ответ 2

@ModelAttribute аннотированные параметры обрабатываются зарегистрированными ServletModelAttributeMethodProcessor (или ModelAttributeMethodProcessor) и @RequestParam аннотированными параметрами обрабатываются зарегистрированными RequestParamMethodArgumentResolver или RequestParamMapMethodArgumentResolver в зависимости от типа параметра.

Здесь объяснение того, как Spring использует эти HandlerMethodArgumentResolvers для разрешения аргументов для ваших методов обработчика:

В обоих случаях @ModelAttribute и @RequestParam значения, подлежащие привязке, извлекаются из ServletRequest параметров.

Вы можете посмотреть исходный код упомянутых выше типов, но вот простые детали.

Для @ModelAttribute, Spring создаст экземпляр типа параметра. Он проверит поля этого экземпляра и попытается привязать значения параметров к ним на основе стратегии именования/сглаживания, состоящей из имени @ModelAttribute и имен полей. Обычно он использует группу экземпляров Converter для преобразования из String (значения параметров всегда String) для любого типа целевого поля Integer, Date и т.д. Вы также можете зарегистрировать свой собственный Converter типы для пользовательских преобразований. Вы также можете вставлять типы POJO.

Для @RequestParam Spring будут использовать те же экземпляры Converter для преобразования из значений параметров непосредственно в тип аннотированных параметров.

Обратите внимание, что значения параметров не выбрасываются. Они сохраняются в HttpServletRequest для продолжительности цикла обработки запроса контейнера. Вы всегда можете получить к ним доступ через соответствующие методы.

Ответ 3

@ModelAttribute (параметр) загружает атрибут модели из @SessionAttributes или из @ModelAttribute (метод).

Вам не нужно просто связывать значения с запросом, но он будет делать это после загрузки из @SessionAttributes.

@RequestParam связывает параметр запроса с объектом.

Ответ 4

  • На уровне метода

Когда аннотация используется на уровне метода, она указывает, что целью этого метода является добавление одного или нескольких атрибутов модели. Такие методы поддерживают те же типы аргументов, что и методы @RequestMapping, но не могут быть сопоставлены непосредственно с запросами.

@ModelAttribute
public void addAttributes(Model model) {
    model.addAttribute("msg", "Welcome to the Netherlands!");
}

Метод, который добавляет атрибут msg ко всем моделям, определенным в классе контроллера.

Spring -MVC всегда будет делать вызов первым для этого метода, прежде чем он вызовет любые методы обработчика запросов. То есть, методы @ModelAttribute вызывается до того, как будут вызваны методы контроллера, аннотированные с помощью @RequestMapping. Логика последовательности состоит в том, что объект модели должен быть создан до того, как любая обработка начнется внутри методов контроллера.

Также важно, чтобы вы комментировали соответствующий класс как @ControllerAdvice. Таким образом, вы можете добавлять значения в Model, которые будут определены как глобальные. Это фактически означает, что для каждого запроса существует значение по умолчанию для каждого метода в части ответа.

  • В качестве аргумента метода

При использовании в качестве аргумента метода он указывает, что аргумент должен быть извлечен из модели. если нет, он должен быть сначала создан, а затем добавлен в модель и один раз представлен в модели, поля аргументов должны быть заполнены из всех параметров запроса, имеющих соответствующие имена.

В фрагменте кода, который следует за атрибутом пользовательской модели, заполняется данными из формы, переданной в конечную точку addUser. Spring MVC делает это за кулисами перед вызовом метода отправки:

**@RequestMapping**(value = "/addUser", method = RequestMethod.POST)
public String submit(@ModelAttribute("user") User user) {
    return "userView";
}

Таким образом, он связывает данные формы с bean. Контроллер, аннотированный с помощью @RequestMapping, может иметь пользовательский аргумент класса, аннотированный с помощью @ModelAttribute.

Это то, что обычно называют связыванием данных в Spring -MVC, общем механизме, который избавляет вас от необходимости отдельно анализировать каждое поле формы.

Ответ 5

@ModelAttribute: связывает весь объект Java (например, Employee). поддерживает несколько параметров запроса

@RequestParam: связывает один параметр запроса (например, firstName)

В целом,
@RequestParam лучше всего читать небольшое количество параметров.

@ModelAttribute используется, когда у вас есть форма с большим количеством полей.

и

@ModelAttribute предоставляет дополнительные функции, такие как привязка данных, проверка и предварительная подготовка формы.