了解模型分辨率的工作原理

时间:2016-06-23 20:17:40

标签: java spring spring-mvc

我是Spring MVC的新手。管理一些应用程序运行,但我对某些方向的工作方式有一些疑问,无法找到我正在寻找的解释。特别是在这种方法中:

@Controller
@RequestMapping("/hello")
public class HelloController{

   @RequestMapping(method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }

}

我知道"Hello Spring MVC Framework!"(名称message)正在传递给视图。但有两件事让我感到担忧,并发现有点不寻常:

  1. 为什么modelprintHello方法声明为输入参数?而不是说作为局部变量?
  2. model无法传递给视图显式,这是否会以某种方式在幕后发生?

4 个答案:

答案 0 :(得分:2)

  

为什么model被声明为printHello方法的输入参数?而不是说作为局部变量?

您可以将其声明为局部变量,并在需要时返回:

@RequestMapping("/hello")
public ModelMap printHello() {
    return new ModelMap("message", "Hello Spring MVC Framework!");
}

但是这样你就不会利用Spring的数据绑定(绑定请求属性(GET请求的查询参数)来建模)。

此外,您不提供任何视图名称(如原始示例return "hello"中所示),因此Spring MVC将使用默认DefaultRequestToViewNameTranslator推断它,该默认Controller使用不带hello后缀的控制器名称逻辑视图名称(在您的示例中,它将是HelloController,因为您的控制器是ModelAndView)。有关详细信息,请参阅documentation

此外,您可以返回新的Model个实例,而不仅仅是ModelMap@RequestMapping(path = "/hello", method = RequestMethod.GET) public String printHello(Model model, @ModelAttribute("form") SearchForm form, BindingResult result) { model.addAttribute("anotherUsefulValue", myService.getSomeValue()); // 'hello' view will get the model with both 'form' and 'anotherUsefulValue' attributes // and 'form' attribute will have 'text' field filled from request's // query parameter 'text'. return "hello"; } class SearchForm { private String text; // ... getter and setter } 。在这种情况下,您可以显式设置视图名称和模型属性。

但使用Model作为处理程序方法参数的主要优点是数据绑定。

当您提供Model 某些模型属性(将请求绑定到)作为方法参数时,您将获得已经添加(并使用请求参数填充)模型属性的模型实例到您的模型然后如果需要,可以为其添加其他属性。

form

使用此方法,您可以使用名为text的文本字段从某些html form执行GET请求,当您提交此表单时,您的模型将包含已实例化SearchForm的属性text 1}}对象作为值。此对象的字段text<form:form method="GET" action="/hello" modelAttribute="form"> <form:input path="text" /> <input type="submit"> </form> 查询参数作为值。

使用spring-form JSP Tag Library的示例:

/hello?text=12345

或者只输入网址model。并且您会看到formtext属性12345字段等于anotherUsefulValue 它还具有您的anotherUsefulValue属性。您只需将Spring的数据绑定与自定义模型属性结合起来。

当然,您可以手动创建新模型,并在方法的form参数中设置formmodel属性。但它只是更多的样板。

  

DispatcherServlet无法传递给视图显式,所以这会在幕后以某种方式发生吗?

当然。 Spring的Front Controller为你做了很多其他事情。这一切都在documentation中描述。

The request processing workflow in Spring Web MVC (high level)

Front Controller只知道你的控制器方法返回了什么,并且可以理解它是新模型还是你的方法没有返回任何模型然后send使用它传递给你的控制器方法的模型作为参数。

答案 1 :(得分:1)

您提供的@RequestMapping注释会神奇地。我在文字和隐喻意义上都这么说。它基本上可以减少一切通常涉及的混乱的手工布线。

  1. 该模型是许多可选输入参数之一。如果您愿意,您可以提供更多,更少或更少。在这种情况下,你想使用ModalMap,所以你说,&#34;我想使用ModalMap&#34;通过包括论点。如果您有来自请求的参数,例如标题中的参数,您可以添加参数并转换为它们。

  2. 这类似于Spring的@Autowire。当您自动装配服务时,您从不在任何地方明确说出new FooService(),但Spring会自动为您创建和管理它。您基本上将大部分布线工作卸载到Spring,并且它处理所有样板,同时您处理完全需要它处理的内容。

  3. 在这种情况下,您将一个带有值的ModalMap从get请求传递给客户端,然后在页面上加载该值。

    补充阅读+来源:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html

答案 2 :(得分:1)

model对象视为参数传递,类似于我在代码中添加的HttpServletRequest对象。 Spring生成一个隐式模型对象,该对象在整个请求生命周期中都可用,类似于JSP可用的隐式request对象。因此,根据单个请求生命周期,此隐式模型对象将在控制器和视图之间共享。

@Controller
@RequestMapping("/hello")
public class HelloController{

   @RequestMapping(method = RequestMethod.GET)
   public String printHello(ModelMap model, HttpServletRequest req) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }

}

以下是spring docs的说明。在哪里提到传递给使用@RequestMapping注释的方法的输入参数的重要性

  

Map / Model / ModelMap用于丰富将要的隐式模型   暴露在网络视图中。

答案 3 :(得分:0)

Spring-MVC框架为每个请求创建的 model对象。这就是为什么它不是本地变量的原因。由于框架创建的对象本身也已经有了引用,因此框架负责将其传递给View。