Spring MVC中@ModelAttribute的目的和用法是什么?


当前回答

ModelAttribute注释被用作Spring MVC Web应用程序的一部分,可以在两种场景中使用。

首先,它可以用于将数据注入到预jsp加载模型中。这在确保需要JSP来显示所有数据本身时特别有用。注入是通过将一个方法连接到模型来获得的。

其次,它可以用于从现有模型中读取数据,并将其分配给教练方法的参数。

具有一定https://dzone.com/articles/using-spring-mvc%E2%80%99s

其他回答

我知道这是一个老帖子,但我想我把我的帽子扔在戒指里,看看我是否能把水弄浑一点:)

我发现我最初难以理解@ModelAttribute是因为Spring决定将几个注释合并为一个注释。当我把它分成几个更小的注释时,它变得更清晰了:

对于参数注释,可以将@ModelAttribute看作是@Autowired + @Qualifier的等量物,即它试图从Spring托管模型中检索具有给定名称的bean。如果没有找到命名bean,它不会抛出错误或返回null,而是隐式地扮演@Bean的角色,即使用默认构造函数创建一个新实例,并将bean添加到模型中。

对于方法注释,可以认为@ModelAttribute相当于@Bean + @Before,也就是说,它将由用户代码构建的bean放在模型中,并且总是在请求处理方法之前调用它。

比方说,我看到@ModelAttribute如下所示(请不要从字面上理解!!):

@Bean("person")
@Before
public Person createPerson(){
  return new Person();
}

@RequestMapping(...)
public xxx handlePersonRequest( (@Autowired @Qualifier("person") | @Bean("person")) Person person, xxx){
  ...
}

如您所见,Spring做出了正确的决定,使@ModelAttribute成为一个包罗万象的注释;没有人想看到注释的大杂烩。

首先,模型在MVC Spring (MVC =模型,视图,控制器)中使用。也就是说,模型与“视图”一起使用。

这些观点是什么?视图可以被认为是“由我们的后端框架(在我们的例子中是Spring)在html页面的某些部分生成的一些可变数据的html页面”。

所以我们有了模型,它是一个包含数据的实体,被“注入”到视图中。

您可以使用Spring使用几个“视图”库:其中包括JSP、Thymeleaf、Mustache等。

例如,让我们假设我们正在使用Thymeleaf(它们都是相似的。更重要的是,除了JSP, Spring甚至不知道他正在使用哪些视图库。所有模型都是通过Spring的Servlet提供服务的。这意味着对于所有这些视图库,Spring代码都是相同的。你唯一需要改变的是这些html页面的语法,它们位于resources/static/templates中)

resources/static/templates   //All our view web pages are here

控制器负责路由。例如,我们的站点托管在localhost:8080上。我们需要一个显示学生的路径(URL)。让我们假设这在localhost:8080/students上可用。做这个的控制器是StudentController:

@Controller  //Not @RestController
   public class StudentController {

   @GetMapping(/students)
   public String getStudentView() {
       return "student";
   }
}

这段代码的作用是说,如果我们要

localhost: 8080 /学生

然后调用getStudentView()方法。但是注意它应该返回一个字符串。然而,当使用视图库时,控制器被@Controller(而不是@RestController)注释,spring所做的是寻找一个带有方法返回的String名称的html视图页面,在我们的例子中,它将在

/ /静态/模板/ student.html资源

这对于没有数据的静态页面来说已经足够好了。然而,如果我们需要一个带有一些数据的动态页面,Spring提供了另一个很大的优势:getStudentView()上面的方法,也会在底层传递一个模型给我们的视图“student.html”。我们的模型将包含可以使用视图库中的特定语法在“student.html”文件中访问的数据。例如,用百里香叶:

<div th:text="${attribute1}"> </div>

这将访问模型的属性“attribute1”。 我们可以通过模型传递不同的数据。这是通过给它分配各种属性来实现的。有不同的方式分配属性,使用@ModelAttribute:

@Controller  //Not @RestController
   public class StudentController {

   @ModelAttribute(name = "attribute1")
   public int assignAttribute1() {
      return 123454321
   }   // Think it as "model.attribute1 = 123454321"

   @GetMapping(/students)
   public String getStudentView() {
       return "student";
   }
}

上面的代码将为模型(在底层创建)分配一个名为“attribute1”的属性(将其视为一个键),值为12354321。比如“模特”。Attribute1 = 123454321”。

最后,当我们访问url时,模型被传递给视图

localhost: 8080 /学生

注意:所有用@ModelAttribute标注的方法都是在视图返回之前调用的。一旦创建了所有属性,模型就会传递给我们的视图。简单地说,在getStudentView()方法被调用之后,所有带有@ModelAttribute的方法都被调用。

也就是说,上面写的html代码将从浏览器中被视为:

<div> 123454321 </div> // th:text is a command of 
//THymeleaf, and says to substitute the text
// between the tags with the attribute "attribute1" 
// of our model passed to this view.

这是@ModelAttribute的基本用法。

还有另一个重要的用例:

模型可能需要在相反的方向:即,从视图到控制器。在上面描述的情况下,模型从控制器传递到视图。但是,假设用户从我们的html页面发回一些数据。我们可以用模型属性@ModelAttribute捕获它。这已经被其他人描述过了

在方法层面

1.当注释在方法级别上使用时,它表明了它的目的 方法是添加一个或多个模型属性

@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("india", "india");
}

在方法参数处 1. 当用作方法参数时,它表示应该从模型检索参数。当不存在时,应该首先实例化,然后添加到模型中,一旦出现在模型中,参数字段应该从所有具有匹配名称的请求参数中填充。因此,它将表单数据绑定到bean。

 @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
  public String submit(@ModelAttribute("employee") Employee employee) {
  return "employeeView";
  }

@ModelAttribute将使用您指定的名称(@ModelAttribute(“Testing”)Test Test)创建一个属性,在给定的示例中作为Testing,Test是bean测试,是bean的引用,而Testing将在模型中可用,以便您可以进一步在jsp页面上使用它来检索存储在ModelAttribute中的值。

所以我会试着用更简单的方式来解释。让我们有:

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }
}

正如Spring MVC文档中所描述的那样——@ModelAttribute注释可以用于方法或方法参数。当然我们可以在一个控制器中同时使用这两种方法。

1.方法注释

@ModelAttribute("cities")
 public List<String> checkOptions(){
 return new Arrays.asList(new[]{"Sofia","Pleven","Ruse"});//and so on
}

这种方法的目的是在模型中添加属性。因此,在我们的案例中,cities key将拥有列表new Arrays.asList(new[]{"Sofia","Pleven","Ruse"})作为模型中的值(您可以将模型看作map(key:value))。在同一个控制器中,在@RequestMapping方法之前调用控制器中的@ModelAttribute方法。

在这里,我们希望向Model添加将在表单中用于显示给用户的公共信息。例如,它可以用来填充HTML选择:

2.方法参数

public String findPerson(@ModelAttriute(value="person") Person person) {
    //..Some logic with person
    return "person.jsp";
}

An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. So in this case we expect that we have in the Model person object as key and we want to get its value and put it to the method argument Person person. If such does not exists or (sometimes you misspell the (value="persson")) then Spring will not find it in the Model and will create empty Person object using its defaults. Then will take the request parameters and try to data bind them in the Person object using their names.

name="Dmitrij"&countries=Lesoto&sponsor.organization="SilkRoad"&authorizedFunds=&authorizedHours=&

我们有了name,它会使用setName(String name)绑定到person。name。因此,在

//..Some logic with person

我们可以访问这个值为“Dimitrij”的填充名称。

当然,Spring可以绑定更复杂的对象,比如List、map、List Of Sets Of Maps等等,但在幕后,它实现了数据绑定的魔力。

我们可以同时拥有带模型注释的方法和参数中带有@ModelAttribute的请求方法处理程序。那我们就得统一规则。 当然,我们有很多不同的情况——@ModelAttribute方法也可以在@ControllerAdvice中定义,等等……