一、复杂POJO数组绑定的使用场景
使用简单POJO类型已经可以完成多数的数据绑定,但有时客户端请求中传递的参数比较复杂。例如,在用户查询订单时,页面传递的参数可能包括订单编号、用户名称等信息,这就包含了订单和用户两个对象的信息。如果将订单和用户的所有查询条件都封装在一个简单POJO中,显然会比较混乱,这时可以考虑使用复杂POJO类型的数据绑定。
二、复杂POJO的3种属性的类型
所谓的复杂POJO,就是POJO属性的类型不止包含简单数据类型,还包含对象类型、List类型和Map类型等其他引用类型。接下来分别对复杂POJO中属性为对象类型的数据绑定、属性为List类型的数据绑定和属性为Map类型的数据绑定进行讲解。
三、属性为对象类型的数据绑定
下面通过一个获取用户订单信息的案例,演示复杂POJO中对象类型的数据绑定,案例具体实现步骤如下。
1、创建一个订单类Order,用于封装订单信息,Order类的具体代码如下所示。
java
public class Order {
private String orderId; //订单id
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
}
2、修改User.java类,在User类中新增Order类型的属性order,并定义相应的getter和setter方法。修改后User类的具体代码如下所示。
java
public class User{
private String username; //用户名
private String password; //用户密码
private Order order;
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 Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
3、在UserController.java类中定义方法findOrderWithUser( ),用于获取客户端请求中的User信息,findOrderWithUser( )方法的具体代码如下所示。
java
@RequestMapping("/findOrderWithUser")
public void findOrderWithUser(User user) {
String username = user.getUsername();
String orderId = user.getOrder().getOrderId();
System.out.println("username="+username+",
orderId="+orderId);
}
4、创建一个订单信息文件order.jsp,在order.jsp文件中创建一个表单,表单中包含用户名和订单编号。表单提交时将用户名和订单编号信息发送到处理器。order.jsp的具体代码如下所示。
html
<%@ page language="java" contentType="text/html;
charset=UTF-8" pageEncoding="UTF-8"%>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>订单信息</title></head><body><form
action="${pageContext.request.contextPath }/findOrderWithUser"method="post">
所属用户:<input type="text" name="username" /><br />
订单编号:<input type="text" name="order.orderId" /><br />
<input type="submit" value="查询" />
</form> </body></html>
四、复杂POJO数组绑定的格式
在复杂POJO数据绑定时,如果数据需要绑定到POJO属性对象的属性中,客户端请求的参数名(本例中指form表单内各元素name的属性值)的格式必须为"属性对象名称.属性",其中"属性对象名称"要和POJO的属性对象名称一致,"属性"要和属性对象所属类的属性一致。
5、启动chapter12项目,在浏览器中访问订单页面order.jsp,访问地址为http://localhost:8080/chapter12/order.jsp。在所示的表单中,填写所属用户为"享受",订单编号为"9527",单击"查询"按钮,控制台打印信息如下图所示。
java
username=享受,oederId=9527
五、属性为List类型的数据绑定
接下来通过一个获取用户订单信息的例子,演示复杂POJO中属性为List类型的数据绑定,案例具体实现步骤如下
1、修改User.java类,将User类中订单属性修改为List类型。由于用户一般拥有多个收货地址,在User类中新增List类型的地址属性。
java
package org.example;
public class User{
private String username; //用户名
private String password; //用户密码
private List<Order> orders; //用户订单
private List<String> address; //订单地址
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 List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public List<String> getAddress() {
return address;
}
public void setAddress(List<String> address) {
this.address = address;
}
}
2、创建一个订单处理器类OrderController,在OrderController类中定义showOrders( ) 方法,用于展示用户的订单信息。OrderController类的具体代码如下所示。
java
@Controller
public class OrderController {// 获取用户中的订单信息
@RequestMapping("/showOrders")
public void showOrders(User user) {
List<Order> orders = user.getOrders();List<String> addressList = user.getAddress();
System.out.println("订单:");for (int i = 0; i <orders.size() ; i++)
{
Order order = orders.get(i);
String address = addressList.get(i);
System.out.println("订单Id:"+order.getOrderId());
System.out.println("订单配送地址:"+address);
}
}
}
3、创建一个订单信息文件orders.jsp,在orders.jsp中创建一个表单用于提交用户的订单信息。表单提交时,表单数据分别封装到User的订单属性orders和地址属性address中。orders.jsp的具体代码如下所示。
html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head><title>订单信息</title></head>
<body>
<form action="${pageContext.request.contextPath }/showOrders"
method="post">
<table width="220px" border="1">
<tr>
<td>订单号</td>
<td>订单名称</td>
<td>配送地址</td>
</tr>
<tr>
<td>
<input name="orders[0].orderId" value="1" type="text">
</td>
<td>
<input name="orders[0].orderName" value="Java基础教程"
type="text">
</td>
<td><input name="address" value="北京海淀" type="text"></td>
</tr>
<tr>
<td>
<input name="orders[1].orderId" value="2" type="text">
</td>
<td>
<input name="orders[1].orderName" value="JavaWeb案例"
type="text">
</td>
<td><input name="address" value="北京昌平" type="text"></td>
</tr>
<tr>
<td>
<input name="orders[2].orderId" value="3" type="text">
</td>
<td>
<input name="orders[2].orderName" value="SSM框架实战"
type="text">
</td>
<td><input name="address" value="北京朝阳" type="text"></td>
</tr>
</table>
<input type="submit" value="订单信息"/>
</form>
</body>
</html>
4、启动chapter12项目,在浏览器中访问订单信息页面orders.jsp,访问地址为http://localhost:8080/chapter12/orders.jsp。
5、在orders.jsp显示效果图所示的页面中,单击左下角"订单信息"按钮,orders.jsp表单中的订单信息发送到服务器端的showOrders()方法进行处理,控制台打印信息如图所示。
java
订单Id:1
订单配送地址:北京海淀
订单Id:2
订单配送地址:北京昌平
订单Id:3
订单配送地址:北京朝阳
从图中所示的打印信息可以得出,客户端中的请求参数成功绑定到了showOrders()方法的user形参中,完成了复杂POJO中属性为List类型的数据绑定。
六、复杂POJO数组绑定的编写要求
在复杂POJO数据绑定时,如果数据绑定到List类型的属性,客户端请求的参数名称(本例中指form表单内各元素name的属性值)编写必须符合以下要求。
①如果List的泛型为简单类型,则客户端参数名称必须和POJO类中List属性所属类中的属性名称保持一致。
②如果List的泛型参数为对象类型,则客户端参数名称必须与POJO类的层次结构名称保持一致,并使用数组格式描述对象在List中的位置,即客户端参数名称必须和最终绑定在List中的某个对象的某个属性的名称保持一致。
七、属性为Map类型的数据绑定
接下来,通过一个获取订单信息的案例,演示复杂POJO中属性为Map类型的数据绑定,具体实现如下。
1、修改Order.java类,在Order类中新增HashMap类型的属性productInfo,用于封装订单中的商品信息,其中productInfo的键用来存放商品的类别,productInfo的值用来存放商品类别对应的商品。
java
public class Order {
private String orderId; //订单id
private HashMap<String,Product> productInfo; //商品信息
}
2、修改OrderController.java类,在OrderController类中新增getOrderInfo()方法,用于获取客户端提交的订单信息,并将获取到的订单信息打印在控制台。getOrderInfo()方法的具体代码如下所示。
java
@RequestMapping("/orderInfo")
public void getOrderInfo(Order order) {
String orderId = order.getOrderId(); //获取订单id
//获取商品信息
HashMap<String, Product> orderInfo = order.getProductInfo();
Set<String> keys = orderInfo.keySet();
System.out.println("订单id:"+orderId); System.out.println("订单商品信息:");
for (String key : keys) { Product product = orderInfo.get(key);
String proId = product.getProId();String proName = product.getProName();
System.out.println( key+"类~"+"商品id:"+proId+",商品名称:"+proName);}}
3、创建一个订单信息页面order_info.jsp,在order_info.jsp中创建一个表单用于提交订单信息。表单提交时,表单数据分别封装到Order的orderId属性和商品信息属性productInfo中。
html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>订单信息</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/orderInfo"
method="post">
<table border="1">
<tr>
<td colspan="2">
订单id:<input type="text" name="orderId" value="1">
</td>
</tr>
<tr>
<td>商品Id</td>
<td>商品名称</td>
</tr>
<tr>
<td>
<input name="productInfo['生鲜'].proId" value="1"
type="text">
</td>
<td>
<input name="productInfo['生鲜'].proName"
value="三文鱼" type="text">
</td>
</tr>
<tr>
<td>
<input name="productInfo['酒水'].proId" value="2"
type="text">
</td>
<td>
<input name="productInfo['酒水'].proName" value="红牛"
type="text">
</td>
</tr>
</table>
<input type="submit" value="提交"/>
</form>
</body>
</html>
八、数据绑定到Map类型的属性时的参数命名要求
在复杂POJO数据绑定时,如果数据绑定到Map类型的属性,客户端请求的参数名称(本例中指form表单内各元素name的属性值)必须与POJO类的层次结构名称保持一致,并使用键值的映射格式描述对象在Map中的位置,即客户端参数名称必须和要绑定的Map中的具体对象的具体属性的名称保持一致。
4、启动chapter12项目,在浏览器中访问订单信息页面order_info.jsp,访问地址为http://localhost:8080/chapter12/order_info.jsp。
5、在order_info.jsp显示效果图所示的页面中,单击左下角"提交"按钮,order_info.jsp表单中的订单信息发送到服务器端的getOrderInfo()方法进行处理,控制台打印信息如图所示。
java
订单id:1
订单商品信息:
酒水类~商品id:2,商品名称:红牛
生鲜类~商品id:1,商品名称:三文鱼
由图所示打印的信息可以得出,客户端中的请求参数成功绑定到了getOrderInfo()方法的order形参中,完成了复杂POJO中属性为Map类型的数据绑定。