Когда мы должны использовать @ModelAttribute, и как это работает - PullRequest
2 голосов
/ 10 октября 2019

Здравствуйте, у меня есть вопрос об аннотации @ModelAttribute. Как я понимаю, мы используем @ModelAttribute в аргументах метода для получения данных из модели. Но довольно сложно понять, когда и как его использовать. (Примеры кода взяты из книги Spring in Action 5). В этом случае в приведенном ниже коде в методе public String processOrder () мы не используем аннотацию @ModelAttribute для @ Valid Order order

    @Controller
    @RequestMapping("/orders")
    @SessionAttributes("order")
    public class OrderController {

      private OrderRepository orderRepo;

      public OrderController(OrderRepository orderRepo) {
        this.orderRepo = orderRepo;
      }

      @GetMapping("/current")
      public String orderForm(@AuthenticationPrincipal User user, 
          @ModelAttribute Order order) {
        if (order.getDeliveryName() == null) {
          order.setDeliveryName(user.getFullname());
        }
        //following conditions

        return "orderForm";
      }


      @PostMapping
      public String processOrder(@Valid Order order, Errors errors,  // <<< Here
          SessionStatus sessionStatus, 
          @AuthenticationPrincipal User user) {

        if (errors.hasErrors()) {
          return "orderForm";
        }

        order.setUser(user);

        orderRepo.save(order);
        sessionStatus.setComplete();

        return "redirect:/";
      }


    }

но в этом случае класс DesignTacoController, @ModelAttribute для метода processDesign () используется в @Valid Taco taco:

    @Slf4j
    @Controller
    @RequestMapping("/design")
    public class DesignTacoController {



      @PostMapping
 public String processDesign(@Valid @ModelAttribute("design") Taco design, // <<< Here   
 Errors errors, Model model) {
        if (errors.hasErrors()) {
          return "design";
        }

        // Save the taco design...
        // We'll do this in chapter 3
        log.info("Processing design: " + design);

        return "redirect:/orders/current";
      }

И затемв следующей главе автор удаляет @ModelAttribute из метода processDesign () из того же класса DesignTacoController.

    @Controller
    @RequestMapping("/design")
    @SessionAttributes("order")
    @Slf4j
    public class DesignTacoController {

      @ModelAttribute(name = "order")
      public Order order() {
        return new Order();
      }

      @ModelAttribute(name = "design")
      public Taco design() {
        return new Taco();
      }


      @PostMapping
      public String processDesign(
          @Valid Taco taco, Errors errors, // <<< Here 
          @ModelAttribute Order order) {

        log.info("   --- Saving taco");

        if (errors.hasErrors()) {
          return "design";
        }

        Taco saved = tacoRepo.save(taco);
        order.addDesign(saved);

        return "redirect:/orders/current";
      }

И в этом фрагменте кода (из приведенного выше кода):

    @PostMapping
          public String processDesign(
              @Valid Taco taco, Errors errors, // <<< Here 
              @ModelAttribute Order order) {
    ....
    }

цитата из книги: «Параметр Order помечен @ModelAttribute, чтобы указать, что его значение должно исходить из модели и что Spring MVC не должен пытаться привязать к нему параметры запроса». Это я не понимаю, что автор имел в виду здесь, потому что во всех руководствах говорится, что когда @ModelAttribute используется в качестве аргументов метода, он привязывает к нему параметры запроса. Связывает данные формы с компонентом POJO, атрибут модели заполняется данными из отправленной формы.

1 Ответ

1 голос
/ 11 октября 2019

Документация достаточно ясна по этому вопросу:

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods

@ ModelAttribute

Для доступа к существующему атрибуту вмодель (создается, если она отсутствует) с привязкой и проверкой данных. См. @ModelAttribute, а также Model и DataBinder.

Обратите внимание, что использование @ModelAttribute необязательно (например, для установки его атрибутов). См. «Любой другой аргумент» в конце этой таблицы.

.

Любой другой аргумент

Если методАргумент не соответствует ни одному из более ранних значений в этой таблице, и это простой тип (как определено BeanUtils # isSimpleProperty, он разрешается как @RequestParam. В противном случае он разрешается как @ ModelAttribute .

Так что, по сути, это необязательно. Вы можете использовать просто, чтобы сделать это явным, именно так разрешается аргумент, или вам может потребоваться использовать, если связывание не должно происходить (указав binding = false) См. Далее: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html. Обычно я предпочитаю указывать его независимо.

...