沈阳网站建设建设公司,网络服务器是指为网络提供资源并对这些资源进行管理的计算机,四川城乡与住房建设部网站,东莞常平镇第十二章 Spring MVC数据绑定和相应
12.1 数据绑定 在 Spring MVC 中#xff0c;当接收到客户端的请求时#xff0c;会根据请求参数和请求头等信息#xff0c;将参数以特定的方式转换并绑定到处理器的形参中#xff0c;这个过程称为数据绑定。数据绑定的流程大致如下…第十二章 Spring MVC数据绑定和相应
12.1 数据绑定 在 Spring MVC 中当接收到客户端的请求时会根据请求参数和请求头等信息将参数以特定的方式转换并绑定到处理器的形参中这个过程称为数据绑定。数据绑定的流程大致如下
Spring MVC 接收到客户端的请求后将请求对象 ServletRequest 传递给 DataBinder。DataBinder 将处理方法的形参对象传递进来准备将请求消息数据填充到形参对象中。DataBinder 调用 ConversionService 组件进行数据类型转换、数据格式化等工作将 ServletRequest 对象中的消息填充到形参对象中。DataBinder 调用 Validator 组件对已经绑定了请求消息数据的形参对象进行数据合法性校验。校验完成后生成数据绑定结果 BindingResult 对象。 Spring MVC 将 BindingResult 对象中的内容赋给处理方法的相应参数完成数据绑定。
需要注意的是数据绑定的过程中使用了 ConversionService 和 Validator 组件。ConversionService 组件用于将请求中的参数转换为处理器中需要的参数类型Validator 组件用于校验参数的合法性。在数据绑定过程中还可以使用自定义的 Converter 和 Validator 对象来实现更复杂的数据转换和校验逻辑。
数据绑定是 Spring MVC 中非常重要的一个环节它能够将客户端请求的参数和处理器方法的参数进行连接使得处理器能够正确地获取到需要的参数从而完成业务逻辑的处理。同时数据绑定也能够减少开发者的工作量提高开发效率。 12.2 简单数据的绑定
在 Spring MVC 中简单数据绑定是指将客户端请求中的参数直接绑定到服务器端处理方法的形参或形参的属性上而不是基于列表或多层级的数据。简单数据绑定一般分为以下三种 12.1.1 默认类型数据绑定
Spring MVC 框架默认支持一些数据类型当使用这些类型作为处理器的形参类型时Spring MVC 的参数处理适配器会默认识别这些类型并进行赋值。常见的默认类型如下
HttpServletRequest通过该类型的形参可以获取客户端请求的信息例如请求参数、请求头等。
RequestMapping(/submit)
public String submit(HttpServletRequest request, Model model) {// 获取请求参数String id request.getParameter(id);String name request.getParameter(name);// 处理业务逻辑return result;
}HttpServletResponse通过该类型的形参可以处理服务器端的响应信息例如设置响应头、写入响应体等。
RequestMapping(/submit)
public void submit(HttpServletResponse response) throws IOException {// 设置响应头response.setContentType(text/plain);// 写入响应体response.getWriter().write(success);
}HttpSession通过该类型的形参可以获取客户端的 session 对象从而获取 session 中存放的数据。
RequestMapping(/submit)
public String submit(HttpSession session, Model model) {// 获取 session 中的数据User user (User) session.getAttribute(user);// 处理业务逻辑return result;
}Model/ModelMap这两个类型都可以用来设置 model 数据并将 model 数据填充到 request 域中。
RequestMapping(/submit)
public String submit(Model model) {// 设置 model 数据model.addAttribute(id, 1);model.addAttribute(name, Tom);// 处理业务逻辑return result;
}
RequestMapping(/submit)
public String submit(ModelMap model) {// 设置 model 数据model.addAttribute(id, 1);model.addAttribute(name, Tom);// 处理业务逻辑return result;
}以上是常见的几种 Spring MVC 默认支持的数据类型它们可以方便地获取请求信息、处理响应信息、获取 session 中的数据以及设置 model 数据。 案例
假设有一个处理方法如下所示
RequestMapping(/user)
public String getUserInfo(HttpServletRequest request, HttpServletResponse response) {// 业务逻辑
}在上述处理方法中我们通过 HttpServletRequest 和 HttpServletResponse 参数来获取客户端请求和向客户端发送响应。在请求处理过程中参数处理适配器会自动识别这些参数类型并将 HttpServletRequest 和 HttpServletResponse 对象赋值给相应的参数。
如果处理方法的参数类型不是参数处理适配器默认识别的类型那么就需要手动编写代码进行处理。例如当处理方法的参数类型是自定义类型时我们需要通过自定义的转换器或者注解来将客户端请求中的参数值进行转换和赋值。 12.2.2 简单数据类型绑定
在 Spring MVC 中简单数据类型的绑定指的是将客户端请求中的简单类型参数例如 Integer、Double、String 等基本类型或其包装类型自动绑定到处理方法的形参上。通常情况下只需要保证客户端请求参数的名称和处理方法的形参名称一致即可Spring MVC 会自动将请求参数映射并匹配到处理方法的形参上完成数据绑定。
下面是一个示例代码
RequestMapping(/user)
public String getUserInfo(RequestParam(userId) Integer userId, RequestParam(userName) String userName) {// 处理请求参数例如查询用户信息等// ...
}在上述代码中处理方法的参数类型分别为 Integer 和 String客户端请求参数的名称分别为 “userId” 和 “userName”。由于请求参数名称和处理方法的形参名称一致因此 Spring MVC 会自动将请求参数映射到处理方法的形参上并完成数据绑定。
需要注意的是如果客户端请求参数的名称和处理方法的形参名称不一致或者请求参数的类型与处理方法的形参类型不一致那么就需要通过 RequestParam 注解或者其他方式来进行手动配置一致的话可以不写。例如可以通过 RequestParam 注解来指定请求参数的名称或者通过 ModelAttribute 注解来指定请求参数的类型和名称等。 RequestParam
RequestParam 注解是 Spring MVC 中常用的注解之一用于将客户端请求参数映射到处理方法的形参上。它有以下常用属性
属性名类型是否必填默认值描述valueString否“”指定客户端请求参数的名称用于与处理方法的形参名称进行映射。requiredboolean否true指定客户端请求参数是否为必填项。如果为 true但客户端请求中没有该参数则会抛出异常。defaultValueString否ValueConstants.DEFAULT_NONE指定客户端请求参数的默认值。如果客户端请求中没有该参数则会使用默认值。nameString否“”value 属性的别名。paramTypeString否“”指定客户端请求参数的类型。可以是 path、query、header、cookie 等用于指定参数来源。
需要注意的是value 和 name 属性等价都用于指定客户端请求参数的名称。在使用 RequestParam 注解时必须指定 value 或 name 属性中的一个。如果不指定这两个属性中的任意一个则会抛出异常。
示例代码
RequestMapping(/user)
public String getUserInfo(RequestParam(value userId, required true, defaultValue 0) Integer userId, RequestParam(name userName, required true) String userName) {// 处理请求参数例如查询用户信息等// ...
}在上述代码中RequestParam 注解指定了 value 和 name 属性用于指定客户端请求参数的名称。required 属性用于指定客户端请求参数是否为必填项defaultValue 属性用于指定客户端请求参数的默认值。 PathVariable 当请求的映射方式是 REST 风格时通常会将动态参数作为 URL 的一部分例如 /user/123 其中123 是动态参数表示用户的 ID。此时使用传统的方式将参数绑定到处理方法的形参中不再适用因为参数不再是请求参数而是 URL 的一部分。 为了解决这个问题Spring MVC 提供了 PathVariable 注解用于将 URL 中的占位符参数绑定到处理方法的形参中。例如在上述例子中我们可以通过以下方式获取用户 ID
RequestMapping(/user/{userId})
public String getUserInfo(PathVariable(userId) Integer userId) {// 处理请求参数例如查询用户信息等// ...
}在上述代码中PathVariable 注解用于将 URL 中的占位符参数 “{userId}” 绑定到处理方法的形参 “userId” 上。通过这种方式我们可以方便地获取 URL 中的动态参数并且不再需要通过传统的方式将参数作为请求参数绑定到处理方法中。 PathVariable 注解是 Spring MVC 中常用的注解之一用于将 URL 中的占位符参数绑定到处理方法的形参中。PathVariable 注解有以下两个常用属性 value用于指定 URL 中的占位符名称用于与处理方法的形参名称进行映射。例如在下面的例子中PathVariable 注解指定了 value 属性为 “userId”表示将 URL 中的占位符参数 “{userId}” 与处理方法的形参 “userId” 进行映射。 required用于指定该占位符参数是否为必填项。如果为 true但客户端请求中没有该参数则会抛出异常。默认值为 true。例如在下面的例子中PathVariable 注解指定了 required 属性为 false表示该占位符参数不是必填项如果客户端请求中没有该参数则会将形参 “userId” 的值设置为 null。
需要注意的是PathVariable 注解只能用于绑定简单数据类型例如 String、int、long 等。如果需要绑定复杂数据类型例如自定义对象则需要使用 RequestParam 或 RequestBody 注解。 如果 URL 中包含占位符参数需要在处理器方法中获取那么通常需要使用 PathVariable 注解来完成参数的绑定。但如果 URL 中的占位符参数名称和处理器方法的形参名称一样那么在这种情况下可以省略 PathVariable 注解Spring MVC 会自动将 URL 中的参数值绑定到对应的形参上。 12.2.3 POJO绑定
当客户端向服务器发送请求时请求中可能会包含多个不同类型的参数数据。如果使用简单数据类型进行绑定需要手动编写多个不同类型的参数操作比较繁琐。为解决这个问题可以使用 POJO 类型进行数据绑定。
POJOPlain Old Java Object是一个普通的 Java 对象不依赖于特定的框架或技术。使用 POJO 类型进行数据绑定就是将所有关联的请求参数封装在一个 POJO 对象中然后在方法中直接使用该对象作为形参来完成数据绑定。 本案例是一个用户注册案例要求将表单提交的数据绑定在处理器中定义的 User 类型的形参中。具体实现步骤如下
1. 创建 User 类
首先需要创建一个 User 类来表示用户信息。可以在该类中添加相应的属性和对应的 getter/setter 方法例如
public class User {private String username;private String password;private int age;public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getPassword() {return password;}public void setPassword(String password) {this.password password;}public int getAge() {return age;}public void setAge(int age) {this.age age;}
}2. 创建处理器方法
接下来需要创建一个处理器方法来处理用户注册请求。在方法的参数列表中直接使用 User 类型作为形参即可完成数据绑定。例如
RequestMapping(/register)
public String register(User user) {// 处理注册请求return success;
}3. 创建表单页面
在客户端需要创建一个表单页面用于向服务器发送请求。表单中的 input 标签的 name 属性需要与 User 类中的属性名相对应。例如
form action/register methodpostlabel用户名input typetext nameusername/labelbrlabel密码input typepassword namepassword/labelbrlabel年龄input typetext nameage/labelbrinput typesubmit value注册
/form4. 测试 POJO 绑定
最后启动应用程序并在浏览器中访问表单页面。在表单中填写相应的信息并提交表单后服务器应该能够正确地接收并处理请求。
在处理器方法中可以直接使用 User 对象来访问表单数据例如
RequestMapping(/register)
public String register(User user) {String username user.getUsername();String password user.getPassword();int age user.getAge();// 处理注册请求return success;
}使用 POJO 类型进行数据绑定可以大大简化代码的编写和维护。同时使用 POJO 类型还可以更好地封装数据增强代码的可读性和可维护性。 防止中文数据乱码
要防止客户端传入的中文数据出现乱码可以采取以下措施
在表单页面中设置字符编码 在表单页面的 head 标签中添加以下代码设置表单的字符编码为 utf-8
meta charsetutf-8在服务器端设置字符编码 在服务器端的配置文件中设置字符编码为 utf-8。例如在 Spring MVC 中可以在 web.xml 中添加以下代码
filterfilter-nameencodingFilter/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-param
/filterfilter-mappingfilter-nameencodingFilter/filter-nameurl-pattern/*/url-pattern
/filter-mapping在处理器方法中设置字符编码 在处理器方法中可以使用 RequestMapping 注解的 produces 属性来设置响应的字符编码为 utf-8。例如
RequestMapping(value /register, produces text/html;charsetUTF-8)
public String register(User user) {// 处理注册请求return success;
}通过以上措施可以有效地防止客户端传入的中文数据出现乱码。需要注意的是以上措施需要同时在客户端和服务器端进行设置才能生效。 12.2.4 自定义类型转换器
在 Spring MVC 中为了方便处理客户端提交的参数Spring 默认提供了一些常用的类型转换器可以将客户端提交的参数自动转换为处理器形参类型的数据。但是默认类型转换器并不能将提交的参数转换为所有的类型此时就需要开发者自定义类型转换器。
Spring 框架提供了 org.springframework.core.convert.converter.Converter 接口作为类型转换器开发者可以通过实现该接口来自定义类型转换器。Converter 接口定义了一个 convert 方法用于将源类型转换为目标类型并返回。具体转换规则可以由开发者自行定义。 Converter 接口是 Spring 框架中用来定义类型转换器的接口其代码如下所示
public interface ConverterS, T {/*** 将 S 类型转换为 T 类型** param source 源类型* return 转换后的目标类型*/T convert(S source);
}Converter 接口中有两个泛型参数分别代表源类型 S 和目标类型 T。接口中只有一个方法 convert该方法接收一个 S 类型的参数 source将其转换为一个 T 类型的对象并返回。 例子
好的下面以实现 Date 类型的数据绑定为例来演示自定义类型转换器的具体实现步骤。
1. 实现自定义类型转换器
首先需要实现一个自定义类型转换器将字符串类型的日期转换为 Date 类型的对象。具体实现步骤如下
1.1 创建一个实现 Converter 接口的类并指定泛型参数为 String 和 Date代码如下
public class StringToDateConverter implements ConverterString, Date {// 具体实现
}1.2 在类中重写 convert 方法将字符串类型的日期转换为 Date 类型的对象并返回代码如下
public class StringToDateConverter implements ConverterString, Date {Overridepublic Date convert(String source) {SimpleDateFormat dateFormat new SimpleDateFormat(yyyy-MM-dd);try {return dateFormat.parse(source);} catch (ParseException e) {throw new IllegalArgumentException(Invalid date format, please use yyyy-MM-dd);}}
}在该自定义类型转换器中使用 SimpleDateFormat 对字符串进行解析并捕获 ParseException 异常以便在日期格式不正确时进行提示。 2. 注册自定义类型转换器
接下来需要将自定义类型转换器注册到 Spring 容器中以便在数据绑定时生效。具体实现步骤如下
2.1 创建一个配置类实现 WebMvcConfigurer 接口代码如下
Configuration
public class WebMvcConfig implements WebMvcConfigurer {// 具体实现
}2.2 在配置类中重写 addFormatters 方法并在其中注册自定义类型转换器代码如下
Configuration
public class WebMvcConfig implements WebMvcConfigurer {Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new StringToDateConverter());}
}在 addFormatters 方法中通过调用 registry.addConverter 方法将自定义类型转换器注册到 Spring 容器中。 3. 使用自定义类型转换器
注册自定义类型转换器后就可以在处理器中使用 Date 类型的数据了。具体实现步骤如下
3.1 在处理器方法的参数中添加一个 Date 类型的参数代码如下
PostMapping(/user/register)
public String register(User user, Date birthday) {// 处理用户注册逻辑return success;
}在上述处理器中接收了一个 User 对象作为参数同时添加了一个 Date 类型的参数 birthday。
3.2 在客户端提交参数时使用 yyyy-MM-dd 格式的字符串表示日期例如
POST /user/register HTTP/1.1
Content-Type: application/x-www-form-urlencodednameTombirthday2023-04-11在客户端提交的参数中将日期以字符串的形式提交使用 yyyy-MM-dd 格式。
3.3 在处理器中使用 Date 类型的参数Spring 框架会自动调用自定义类型转换器将字符串类型的日期转换为 Date 类型的对象代码如下
PostMapping(/user/register)
public String register(User user, Date birthday) {user.setBirthday(birthday);// 处理用户注册逻辑return success;
}在处理器中将转换后的 Date 对象设置到 User 对象的 birthday 属性中即可完成数据绑定。 DateTimeFormat 是一个 Spring 提供的注解用于指定日期类型的格式化方式。可以将它应用于 Controller 方法的参数上以便自动将请求参数转换为指定格式的日期类型。
下面是一个示例
PostMapping(/save)
public String save(RequestParam(date) DateTimeFormat(pattern yyyy-MM-dd) Date date) {// 处理逻辑return success;
}在上述示例中我们使用了 DateTimeFormat 注解来指定日期类型的格式化方式将格式化模式设置为 “yyyy-MM-dd”表示接受的日期格式为 “年-月-日”。然后将 DateTimeFormat 注解应用于 Controller 方法的参数上以便将请求参数自动转换为指定格式的日期类型。
需要注意的是DateTimeFormat 注解只能用于 Controller 方法的参数上并且只能用于支持格式化的日期类型比如 Date、Calendar 和 LocalDate 等。如果需要使用自定义的格式化方式可以考虑实现 Formatter 接口或者使用全局的日期格式化器。 12.3 复杂数据绑定
当我们在开发Web应用时常常需要将请求参数绑定到Java对象上以便进行后续的业务逻辑处理这就是数据绑定。在Spring MVC中简单数据绑定已经足够应对大部分的数据绑定需求但是在实际开发中我们还会遇到一些比较复杂的数据绑定问题例如
数组的绑定集合的绑定复杂POJO的绑定JSON数据的绑定 12.3.1 数组绑定
在Spring MVC中我们可以使用RequestParam注解将请求参数绑定到一个数组上。需要注意的是当绑定数组时请求参数的名称必须与数组名称相对应并且请求参数的值应该用逗号分隔。
PostMapping(/save)
public String save(RequestParam(ids) Long[] ids) {// 处理逻辑return success;
}处理方法参数的类型为数组时默认情况下会将请求参数的名称与数组名称相对应此时可以不写RequestParam(“ids”) 12.3.2 集合绑定
与数组类似我们也可以使用RequestParam注解将请求参数绑定到一个集合上。需要注意的是当绑定集合时请求参数的名称必须与集合名称相对应并且请求参数的值应该用逗号分隔。
PostMapping(/save)
public String save(RequestParam(ids) ListLong ids) {// 处理逻辑return success;
}12.3.3 复杂POJO绑定
1. 属性为对象类型的数据绑定
当客户端请求中传递的参数比较复杂时使用简单 POJO 已经不能很好地满足需求这时可以考虑使用复杂 POJO 类型的数据绑定。复杂 POJO 类型的数据绑定不仅包含简单数据类型还包含对象类型、List 类型和 Map 类型等其他引用类型。 例子
下面通过一个获取用户订单信息的案例演示复杂 POJO 中属性为对象类型的数据绑定案例具体实现步骤如下
定义订单类和用户类 我们先定义一个订单类 Order 和一个用户类 User其中订单类中包含一个用户对象。
public class Order {private Long orderId;private User user;// getter和setter方法// 对象属性绑定public User getUser() {return user;}public void setUser(User user) {this.user user;}
}public class User {private String username;private String email;// getter和setter方法// 对象属性绑定public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getEmail() {return email;}public void setEmail(String email) {this.email email;}
}在订单类中我们通过定义 getUser() 和 setUser() 方法将订单对象中的用户属性绑定到用户对象中的相应属性上从而实现订单和用户属性的同步更新。
编写控制器方法 我们在控制器中定义一个方法用于接收用户订单信息并将信息绑定到订单对象中。 RequestMapping(/order)
public String getOrder(Order order) {System.out.println(订单号 order.getOrderId());System.out.println(用户名 order.getUser().getUsername());System.out.println(邮箱 order.getUser().getEmail());return success;
}在控制器方法中我们通过 RequestMapping 注解定义一个 /order 的请求映射然后通过 Order 类型的参数 order 接收请求中的订单信息并输出订单号、用户名、邮箱等信息。 编写前端页面 最后我们编写一个前端页面用户可以在页面中输入订单信息和用户信息然后提交表单将信息发送到控制器方法中进行处理。
form action/order methodpostlabel订单号/labelinput typetext nameorderIdbrlabel用户名/labelinput typetext nameuser.usernamebrlabel邮箱/labelinput typetext nameuser.emailbrinput typesubmit value提交
/form在前端页面中我们通过 标签定义一个表单然后通过 name 属性将表单中的各个输入框与订单和用户对象中的相应属性进行绑定。最后用户点击提交按钮后表单将被提交到 /order 请求中由控制器方法进行处理。
以上就是通过一个获取用户订单信息的案例演示复杂 POJO 中属性为对象类型的数据绑定的具体实现步骤。 2. 属性为List类型的数据绑定
本案例演示了如何在订单业务中实现用户和订单的一对多关系即一个订单对应多个用户。在实现过程中我们使用了复杂 POJO 中属性为 List 类型的数据绑定。
具体实现步骤如下
定义订单类和用户类 我们先定义一个订单类 Order 和一个用户类 User其中订单类中包含一个用户集合。
public class Order {private Long orderId;private ListUser users;// getter和setter方法// 集合属性绑定public ListUser getUsers() {return users;}public void setUsers(ListUser users) {this.users users;}
}public class User {private String username;private String email;// getter和setter方法// 对象属性绑定public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getEmail() {return email;}public void setEmail(String email) {this.email email;}
}在订单类中我们通过定义 getUsers() 和 setUsers() 方法将订单对象中的用户集合属性绑定到用户集合对象中从而实现订单和用户属性的同步更新。 编写控制器方法 在控制器中定义一个方法用于接收用户订单信息并将信息绑定到订单对象中。
RequestMapping(/order)
public String getOrder(Order order) {System.out.println(订单号 order.getOrderId());for(User user : order.getUsers()) {System.out.println(用户名 user.getUsername());System.out.println(邮箱 user.getEmail());}return success;
}在控制器方法中我们通过 RequestMapping 注解定义一个 /order 的请求映射然后通过 Order 类型的参数 order 接收请求中的订单信息并输出订单号、用户名、邮箱等信息。 编写前端页面 最后我们编写一个前端页面用户可以在页面中输入订单信息和用户信息然后提交表单将信息发送到控制器方法中进行处理。
form action/order methodpostlabel订单号/labelinput typetext nameorderIdbrh3用户信息/h3div idusersdiv classuserlabel用户名/labelinput typetext nameusers[0].usernamelabel邮箱/labelinput typetext nameusers[0].email/divdiv classuserlabel用户名/labelinput typetext nameusers[1].usernamelabel邮箱/labelinput typetext nameusers[1].email/div/divinput typesubmit value提交
/form在前端页面中我们通过 name 属性将信息绑定到 Order 类型的 order 参数中其中用户信息使用了集合类型并通过 users[index].username 和 users[index].email 的方式指定了用户的下标。
这样当用户提交表单时控制器方法就会自动将信息绑定到订单对象中并输出订单号、用户名、邮箱等信息。 3. 属性为Map类型的数据绑定
本案例演示了如何使用复杂 POJO 中属性为 Map 类型的数据绑定实现获取订单信息的功能。
具体实现步骤如下
定义订单类 我们先定义一个订单类 Order其中包含一个 Map 类型的属性 params用于存储订单的详细信息。
public class Order {private Long orderId;private MapString, Object params;// getter和setter方法// Map属性绑定public MapString, Object getParams() {return params;}public void setParams(MapString, Object params) {this.params params;}
}在订单类中我们通过定义 getParams() 和 setParams() 方法将订单对象中的 Map 类型属性绑定到 Map 类型对象中从而实现订单属性的同步更新。 编写控制器方法 在控制器中定义一个方法用于接收订单信息并将信息绑定到订单对象中。
RequestMapping(/order)
public String getOrder(Order order) {System.out.println(订单号 order.getOrderId());MapString, Object params order.getParams();for(Map.EntryString, Object entry : params.entrySet()) {System.out.println(entry.getKey() entry.getValue());}return success;
}在控制器方法中我们通过 RequestMapping 注解定义一个 /order 的请求映射然后通过 Order 类型的参数 order 接收请求中的订单信息并输出订单号、订单详细信息等信息。 编写前端页面 最后我们编写一个前端页面用户可以在页面中输入订单信息和详细信息然后提交表单将信息发送到控制器方法中进行处理。
form action/order methodpostlabel订单号/labelinput typetext nameorderIdbrh3订单详细信息/h3label收货人姓名/labelinput typetext nameparams[receiverName]brlabel收货地址/labelinput typetext nameparams[receiverAddress]brlabel收货人电话/labelinput typetext nameparams[receiverPhone]brinput typesubmit value提交
/form在前端页面中我们通过表单的 name 属性将订单号和订单详细信息绑定到 Order 对象中的属性中其中订单详细信息使用了 Map 类型的属性 params通过 name“params[key]” 的方式将详细信息的键值对绑定到 Map 中。
以上就是使用 Map 类型实现 POJO 数据绑定的完整流程。 12.3.4 JSON数据绑定
在Spring MVC中客户端请求中发送的数据通常为JSON格式。为了将HttpServletRequest中的数据转换成指定的对象或者将对象转换成指定格式的数据我们需要使用对应的消息转换器来实现。Spring提供了一个HttpMessageConverter接口作为消息转换器其中MappingJackson2HttpMessageConverter是HttpMessageConverter接口的实现类之一。
消息转换器的作用是将HTTP请求中的报文数据转换成指定对象或者将对象转换成指定格式的报文进行响应。需要注意的是HttpMessageConverter和之前所学习的Converter类型转换器是有区别的。Converter类型转换器用于对象之间的类型转换而HttpMessageConverter则用于请求消息和响应消息的格式转换。
下面是一个使用MappingJackson2HttpMessageConverter将请求报文数据转换成指定对象的例子
Controller
RequestMapping(/user)
public class UserController {PostMapping(/add)ResponseBodypublic Result addUser(RequestBody User user) {// 处理用户添加逻辑return new Result(success, 200);}
}在上述代码中RequestBody注解表示将请求报文中的数据解析成指定对象而**ResponseBody**注解表示将返回的对象转换成指定格式的数据进行响应。在这个例子中MappingJackson2HttpMessageConverter会将请求报文中的JSON数据解析成User对象并将User对象作为参数传递给addUser()方法。
需要注意的是在使用MappingJackson2HttpMessageConverter时需要确保Jackson库已经在项目中引入否则会出现异常。 例子
下面通过一个异步提交商品信息的案例来演示 Spring MVC 中的JSON 数据绑定。具体实现步骤如下
创建一个实体类Goods用于存储商品信息。
public class Goods {private String name;private String description;private double price;// 省略getter和setter方法
}
创建一个Controller类用于处理请求。
Controller
RequestMapping(/goods)
public class GoodsController {PostMapping(/add)ResponseBodypublic Result addGoods(RequestBody Goods goods) {// 处理添加商品逻辑return new Result(success, 200);}
}在前端页面中使用jQuery的ajax()方法将商品信息以JSON格式提交给后端Controller。
formlabel forname商品名称/labelinput typetext idnamebrlabel fordescription商品描述/labelinput typetext iddescriptionbrlabel forprice商品价格/labelinput typetext idpricebrbutton typebutton idsubmit提交/button
/form
script$(function() {$(#submit).click(function() {var data {name: $(#name).val(),description: $(#description).val(),price: $(#price).val()};$.ajax({url: /goods/add,type: POST,contentType: application/json,data: JSON.stringify(data),success: function(result) {alert(result.msg);}});});});
/script在上述代码中我们使用jQuery的ajax()方法异步提交商品信息到后端Controller。其中contentType属性设置请求的数据格式为JSONdata属性将商品信息以JSON格式提交给后端Controller。 在Spring MVC的配置文件中配置MappingJackson2HttpMessageConverter以支持JSON数据的绑定。
mvc:annotation-drivenmvc:message-convertersbean classorg.springframework.http.converter.json.MappingJackson2HttpMessageConverter//mvc:message-converters
/mvc:annotation-driven在上述代码中我们通过配置mvc:message-converters标签来配置MappingJackson2HttpMessageConverter以支持JSON数据的绑定。
需要注意的是在使用MappingJackson2HttpMessageConverter时需要确保Jackson库已经在项目中引入否则会出现异常。 12.4 页面跳转
客户端和服务器端之间的交互大致分为请求和响应。Spring MVC 在接收客户端的请求后会对请求进行不同方式的响应。Spring MVC 的响应方式可以分为页面跳转和数据回写两种。
当使用页面跳转的方式进行响应时Spring MVC 提供了多种方法来指定跳转页面包括方法的返回值可以定义为void类型、String类型和ModelAndView类型。
12.4.1 返回值为void类型的页面跳转
当Spring MVC方法的返回值为void类型时方法执行后会跳转到默认的页面。默认的页面由方法映射路径和视图解析器中的前缀、后缀拼接而成拼接格式为“前缀方法映射路径后缀”。
举个例子如果我们有一个方法映射路径为“/index”在视图解析器中配置了前缀为“/WEB-INF/views/”后缀为“.jsp”那么当这个方法返回void类型时Spring MVC 会默认跳转到“/WEB-INF/views/index.jsp”这个页面。
需要注意的是如果在Spring MVC的配置文件中没有配置视图解析器则会报HTTP Status 500错误。
以下是一个视图解析器的配置示例 在上述代码中我们配置了一个名为viewResolver的视图解析器将前缀设置为“/WEB-INF/views/”将后缀设置为“.jsp”。 12.4.2 返回值为String类型的页面跳转
当Spring MVC方法的返回值为String类型时控制器方法执行后Spring MVC会根据方法的返回值跳转到对应的资源。如果Spring MVC的配置文件中没有配置视图解析器处理器执行后会将请求转发到与方法返回值一致的映射路径。
在进行页面跳转之前可以根据需求在页面跳转时选择是否携带数据。下面分别对返回值为String类型时不携带数据页面跳转和携带数据页面跳转进行讲解。 不携带数据页面跳转 当方法的返回值为String类型时返回值可以直接指定要跳转的页面的名称或路径此时不会将数据传递给页面。
RequestMapping(/index)
public String index() {return index;
}在上述代码中当请求路径为/index时Spring MVC会返回名为index的页面。 携带数据页面跳转 当方法的返回值为String类型时可以通过Model来携带数据将需要传递的数据放入Model中然后将Model作为参数传递给方法Spring MVC会自动将数据传递给页面。
RequestMapping(/index)
public String index(Model model) {model.addAttribute(name, Tom);return index;
}在上述代码中我们将一个名为name的属性添加到Model中属性值为Tom然后将Model作为参数传递给方法Spring MVC会自动将数据传递给名为index的页面。
需要注意的是我们需要在页面中使用EL表达式来获取Model中的数据。
h1Hello, ${name}!/h112.4.3 返回值为ModelAndView类型的页面跳转
除了前面讲解的使用方法返回值和Model来实现页面跳转和数据传输外Spring MVC还提供了一个兼顾视图和数据的对象即ModelAndView。ModelAndView对象包含视图相关内容和模型数据这两个部分。
视图相关的内容可以设置逻辑视图的名称也可以设置具体的View实例模型数据则会在视图渲染过程中被合并到最终的视图输出。
ModelAndView 提供了设置视图和数据模型的方法如表所示
方法名描述setViewName(String viewName)设置逻辑视图名称setView(View view)设置具体的View实例addObject(String attributeName, Object attributeValue)向模型数据中添加属性addAllObjects(MapString, ? modelMap)向模型数据中添加多个属性getModel()获取模型数据getViewName()获取逻辑视图名称getView()获取具体的View实例getModelMap()获取模型数据Mapclear()清空模型数据和视图// 将该方法映射到 /showModelAndView 路径下
RequestMapping(/showModelAndView)
public ModelAndView showModelAndView() {// 创建 ModelAndView 实例ModelAndView modelAndView new ModelAndView();// 向 ModelAndView 实例中添加名称为 username 的数据modelAndView.addObject(username, heima);// 创建一个 User 对象并设置其属性User user new User();user.setPassword(password2);// 向 ModelAndView 实例中添加名称为 user 的数据modelAndView.addObject(user, user);// 设置 ModelAndView 实例的视图名称为 registermodelAndView.setViewName(register);// 返回 ModelAndView 实例return modelAndView;
}在上述代码中我们创建了一个名为 showModelAndView() 的方法并将其映射到 “/showModelAndView” 路径下。在该方法中我们创建了一个 ModelAndView 实例并使用 addObject() 方法向其中添加了名称为 “username” 和 “user” 的两个数据。接着我们创建了一个 User 对象并设置了其属性并将其添加到 ModelAndView 实例中。最后我们使用 setViewName() 方法设置了 ModelAndView 实例的视图名称为 “register”。最终我们返回该 ModelAndView 实例。
通过以上代码我们可以学习到如何创建 ModelAndView 实例并向其中添加数据以及如何设置其视图名称。这些操作可以帮助我们更加灵活地控制页面的跳转和数据的显示。 12.5 数据回写
Spring MVC 默认使用视图解析器将响应数据解析为视图并进行页面跳转但有时客户端希望服务器端在响应时不进行页面跳转而只是返回相关的数据。这时候我们可以选择直接将数据写入响应输出流中而不经过视图解析器。根据数据格式我们可以将回写到输出流的数据分为普通字符串和 JSON 数据。
1. 普通字符串的回写
如果想要回写普通字符串到输出流中我们可以使用 HttpServletResponse 对象的 getWriter() 方法获取输出流并将数据写入输出流中。下面是一个示例代码
RequestMapping(/writeString)
public void writeString(HttpServletResponse response) throws IOException {response.setContentType(text/plain;charsetUTF-8);PrintWriter writer response.getWriter();writer.write(Hello, world!);writer.flush();writer.close();
}在上述代码中我们创建了一个名为 writeString() 的方法并将其映射到 /writeString 路径下。在该方法中我们首先使用 setContentType() 方法设置响应的内容类型为 “text/plain;charsetUTF-8”然后使用 getWriter() 方法获取输出流并将字符串 “Hello, world!” 写入输出流中。最后我们使用 flush() 方法刷新输出流并关闭输出流。 2. JSON 数据的回写
如果想要回写 JSON 数据到输出流中我们可以使用 Spring MVC 提供的 ResponseBody 注解该注解会将返回值序列化为 JSON 数据并写入响应输出流中。下面是一个示例代码
RequestMapping(/writeJson)
ResponseBody
public MapString, Object writeJson() {MapString, Object resultMap new HashMap();resultMap.put(name, Tom);resultMap.put(age, 18);return resultMap;
}在上述代码中我们创建了一个名为 writeJson() 的方法并将其映射到 /writeJson 路径下。在该方法中我们创建了一个 Map 对象并向其中添加了两个键值对。最后我们使用 ResponseBody 注解将该 Map 对象序列化为 JSON 数据并写入响应输出流中。
通过以上代码我们可以学习到如何将普通字符串和 JSON 数据回写到响应输出流中这对于客户端请求数据时不需要页面跳转的场景非常有用。