Spring模型和请求对象

时间:2016-01-14 09:42:21

标签: spring spring-mvc

在Spring中,为什么我们不能简单地使用请求对象在应用程序中携带数据?为什么我们切换到使用模型对象?另外,我在一本流行的Spring书中读到,它仍然是一个请求对象(即使在Spring应用程序中),它可以完成大部分的数据传输工作。这是否意味着我们在Spring中创建的模型以某种方式链接到引擎盖下的请求对象?

1 个答案:

答案 0 :(得分:2)

  

在Spring中,为什么我们不能简单地使用请求对象来传输数据   在应用程序中?

您可以使用HttpServletRequest甚至WebRequest作为方法参数,然后检查这两个以便从中提取数据。例如,如果要获取名为page的查询字符串的值:

@RequestMapping("/users")
public void listUsers(HttpServletRequest request) {
    String page = request.getParameter("page");
    ...
}
  

为什么我们切换到使用模型对象?

您可以简单地从HttpServletRequest读取并最终在任何控制器方法中写入HttpServletResponse,但spring也提供了更好的抽象来处理典型的Web场景。例如,如果您的page参数是必需的int参数,默认值为1,那么您只需编写:

@RequestMapping("/users")
public void listUsers(@RequestParam(defaultValue = "1") Integer page) {
    ...
}

Spring会自动执行所有字符串到int的转换,并为您填充默认值。或者假设您要自动验证json或xml Request Body并返回验证错误。通过这些更高的抽象,您将定义一个包含其中所有验证逻辑的model object,并在引用它的方法参数之前简单地添加@Valid注释,就是这样!

@RequestMappting(value = "/users", method = POST)
public void addNewUser(@RequestBody @Valid User user) {
    // automatically validates the user
    // and send validation error, if user wasn't valid
}

当然,您可以通过检查HttpServletRequest来做同样的事情,但这会非常麻烦。

  

这是否意味着我们在Spring中创建的模型以某种方式链接到   引擎盖下的请求对象?

它们不一定是链接到它们,但通常这些模型对象将从请求参数填充。

例如,spring使用HttpMessageConverter将请求主体转换为方法参数。 HttpMessageConverter负责从HTTP请求消息转换为对象并从对象转换为HTTP响应主体。例如,FormHttpMessageConverter将表单数据转换为MultiValueMap<String, String>。此类有一个read方法,用于读取请求正文并将其转换为MultiValueMap<String, String>。此方法如下所示:

public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String, ?>> clazz,
            HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {

        MediaType contentType = inputMessage.getHeaders().getContentType();
        Charset charset = (contentType.getCharSet() != null ? contentType.getCharSet() : this.charset);
        String body = StreamUtils.copyToString(inputMessage.getBody(), charset);

        String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
        MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(pairs.length);
        for (String pair : pairs) {
            int idx = pair.indexOf('=');
            if (idx == -1) {
                result.add(URLDecoder.decode(pair, charset.name()), null);
            }
            else {
                String name = URLDecoder.decode(pair.substring(0, idx), charset.name());
                String value = URLDecoder.decode(pair.substring(idx + 1), charset.name());
                result.add(name, value);
            }
        }
        return result;
}

String body = StreamUtils.copyToString(inputMessage.getBody(), charset);,它实际上会读取请求正文并将其转换为String