参考文章:(https://www.cnblogs.com/HD/p/4107674.html) 和
(https://blog.csdn.net/qq_33530388/article/details/72784199)
一、基本数据类型
Controller代码:
@RequestMapping("/addFruits")
public ModelAndView add(int id) {
ModelAndView mav = new ModelAndView("showFruits");
return mav;
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
</table>
</form>
注意:对于基本数据类型,表单提交的数据不能为 null 或 "",否则会出现数据转换的异常。所以,在开发过程中,对于可能为空的数据,最好将参数的数据类型定义为包装类型。
二、包装类型
Controller代码:
@RequestMapping("/addFruits")
public ModelAndView add(Integer id) {
ModelAndView mav = new ModelAndView("showFruits");
return mav;
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
</table>
</form>
和基本数据类型基本一样,不同之处在于从表单传过来的数据可以为 "" 或null
三、自定义对象类型
Model代码:
public class Fruits {
private String id;
private Date createDate;
}
Controller代码:
@RequestMapping("/addFruits")
public ModelAndView add(Fruits fruitsObject) {
ModelAndView mav = new ModelAndView("showFruits");
//参数 fruitsObject 会默认被当做值加入到ModelAndView 中(),相当于:
//mav.addObject("theFirstParam", fruitsObject);
//其中,addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
//如果参数为基本数据类型或包装类型,则不会默认填充到ModelAndView 中。
return mav;
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
<tr>
<td>
请输入日期:
</td>
<td>
<input type="date" name="createDate">
</td>
</tr>
</table>
</form>
按照上述的配置,就可以将表单中的数据封装到Control里了。但是运行上述代码时,会发现报错,报错的信息是:无法将 String 类型的 createDate 转换为 Date 类型的。
因此,对于表单中有日期类型的数据,需要我们自己定义转换器
自定义转换器主要有以下几种方式:
方式一:自定义日期转换器
自定义转换器代码:
package converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
//需要实现Converter接口,这里是将String类型转换成Date类型
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
// 实现 将日期串转成日期类型(格式是yyyy-MM-dd)
SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd");
try {
// 转换成功后直接返回
return sm.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
//如果数据绑定失败,返回null
return null;
}
}
springmvc配置文件代码:
<!--注解驱动,后续需要研究一下改驱动的实现原理-->
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- converters转换器,converters为FormattingConversionServiceFactoryBean的属性之一 -->
<property name="converters">
<list>
<!-- converters 的实现类DateConverter -->
<bean class="converter.DateConverter" />
</list>
</property>
</bean>
方式二:引入jar包,调用其它类提供的日期转换器
待补充
四、自定义复合对象类型
Model代码:
public class Fruits {
private String id;
private Date createDate;
//产品详细信息
private FruitItem fruitItem;
}
//产品详细信息
public class FruitItem {
private String id;
private String name;
private double price;
}
Controller代码:
@Controller
public class FruitsController {
@RequestMapping("/addFruits")
public ModelAndView add(Fruits fruitsObject) {
ModelAndView mav = new ModelAndView("showFruits");
//参数 fruitsObject 会默认被当做值加入到ModelAndView 中(),相当于:
//mav.addObject("theFirstParam", fruitsObject);
//其中,addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
//如果参数为基本数据类型或包装类型,则不会默认填充到ModelAndView 中。
return mav;
}
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
请输入编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
<tr>
<td>
请输入日期:
</td>
<td>
<input type="date" name="createDate">
</td>
</tr>
<tr>
<td>
请输入产品编号:
</td>
<td>
<input name="fruitItem.id" value="11">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItem.name" value="">
</td>
</tr>
<tr>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItem.price" value="">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
Fruits 对象中有 fruitItem 属性,Control层代码保持不变,在表单中需要按照 "属性名(对象类型的属性).属性名" 来命名 input 的 name。
五、数组绑定
数组的绑定指的是前台传来多个同一类型的数据,我们在controller中使用数组形参来接收前台传来的数据。在controller中,我们需要将这些id号全部获取并放到一个数组中。
Controller代码:
@Controller
public class FruitsController {
@RequestMapping("/addFruits")
public ModelAndView add(String[] id) {
ModelAndView mav = new ModelAndView("showFruits");
for(String str : id){
System.out.println(str);
}
return mav;
}
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
请勾选编号:
</td>
<td>
<input type="checkbox" name="id" value="1">
<input type="checkbox" name="id" value="2">
<input type="checkbox" name="id" value="3">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
注意:Contrlller 方法中的参数 名称(id) 与表单中 input中的 name(id) 保持一致。
六、List绑定
List 需要绑定在对象上,不能直接写在 control 方法的参数中
Model代码:
//产品详细信息
public class FruitItem {
private String name;
private double price;
}
public class Fruits {
private String id;
//产品详细信息List
private List<FruitItem> fruitItemList;
}
Controller代码:
@RequestMapping("/addFruits")
public ModelAndView add(Fruits fruitsObject) {
ModelAndView mav = new ModelAndView("showFruits");
//参数 fruitsObject 会默认被当做值加入到ModelAndView 中(),相当于:
//mav.addObject("theFirstParam", fruitsObject);
//其中,addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
//如果参数为基本数据类型或包装类型,则不会默认填充到ModelAndView 中。
return mav;
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
请输入编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemList[0].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemList[0].price" value="">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemList[1].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemList[1].price" value="">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
值得一提的是,Spring会创建一个以最大下标值为size的List对象,所以,如果表单中有动态添加行、删除行的情况,就需要特别注意,譬如一个表格,用户在使用过程中经过多次删除行、增加行的操作之后,下标值就会与实际大小不一致,这时候,List中的对象,只有在表单中对应有下标的那些才会有值,否则会为null。
七、Set绑定:
Set和List类似,也需要绑定在对象上,而不能直接写在Controller方法的参数中。但是,绑定Set数据时,必须先在Set对象中add相应的数量的模型对象。
Model代码:
//产品详细信息
public class FruitItem {
private String name;
private double price;
}
public class Fruits {
private String id;
private Date createDate;
//产品详细信息List
private Set<FruitItem> fruitItemSet = new HashSet<FruitItem>();
public Fruits(){
fruitItemSet.add(new FruitItem());
fruitItemSet.add(new FruitItem());
fruitItemSet.add(new FruitItem());
}
}
Controller代码:
@Controller
public class FruitsController {
@RequestMapping("/addFruits")
public ModelAndView add(Fruits fruitsObject) {
ModelAndView mav = new ModelAndView("showFruits");
for(FruitItem fruitItem : fruitsObject.getFruitItemSet()){
System.out.println(fruitItem.getName() + " -- " + fruitItem.getPrice());
}
//参数 fruitsObject 会默认被当做值加入到ModelAndView 中(),相当于:
//mav.addObject("theFirstParam", fruitsObject);
//其中,addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
//如果参数为基本数据类型或包装类型,则不会默认填充到ModelAndView 中。
return mav;
}
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
请输入编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemSet[0].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemSet[0].price" value="">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemSet[1].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemSet[1].price" value="">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
基本和List绑定类似。
需要特别提醒的是,如果最大下标值大于Set的size,则会抛出org.springframework.beans.InvalidPropertyException异常。所以,在使用时需要先有些不便。
八、Map绑定:
Model代码:
Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数中。
//产品详细信息
public class FruitItem {
private String name;
private double price;
}
public class Fruits {
private String id;
//产品详细信息List
private Map<String, FruitItem> fruitItemMap = new HashMap<String, FruitItem>();
}
Controller代码:
@Controller
public class FruitsController {
@RequestMapping("/addFruits")
public ModelAndView add(Fruits fruitsObject) {
ModelAndView mav = new ModelAndView("showFruits");
for(Entry<String, FruitItem> fruitItemMap : fruitsObject.getFruitItemMap().entrySet()){
System.out.println(fruitItemMap.getKey() + " -- " + fruitItemMap.getValue().getName() + " -- " + fruitItemMap.getValue().getPrice());
}
//参数 fruitsObject 会默认被当做值加入到ModelAndView 中(),相当于:
//mav.addObject("theFirstParam", fruitsObject);
//其中,addObject 里第一个参数是根据 add() 的参数类型自动转成小驼峰命名,第二个参数是 add() 的参数名。
//如果参数为基本数据类型或包装类型,则不会默认填充到ModelAndView 中。
return mav;
}
}
表单代码:
<form action="addFruits" method="post">
<table>
<tr>
<td>
请输入编号:
</td>
<td>
<input name="id" value="10">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemMap[x].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemMap[x].price" value="">
</td>
</tr>
<tr>
<td>
请输入产品名称:
</td>
<td>
<input name="fruitItemMap[y].name" value="">
</td>
<td>
请输入产品价格:
</td>
<td>
<input name="fruitItemMap[y].price" value="">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>