1. 绑定简单数据类型
1.1 需求
编辑商品信息,需要根据商品id查询商品信息,然后展示到页面。
请求的url:/itemEdit.action
参数:id(商品id)
响应结果:商品编辑页面,展示商品详细信息。
1.2 Controller参数绑定
要根据id查询商品数据,需要从请求的参数中把请求的id取出来。Id应该包含在Request对象中。可以从Request对象中取id。
@RequestMapping("/itemEdit")
public ModelAndView itemEdit(HttpServletRequest request) {
//从Request中取id
String strId = request.getParameter("id");
Integer id = null;
//如果id有值则转换成int类型
if (strId != null && !"".equals(strId)) {
id = new Integer(strId);
} else {
//出错
return null;
}
Items items = itemService.getItemById(id);
//创建ModelAndView
ModelAndView modelAndView = new ModelAndView();
//向jsp传递数据
modelAndView.addObject("item", items);
//设置跳转的jsp页面
modelAndView.setViewName("editItem");
return modelAndView;
}
如果想获得Request对象只需要在Controller方法的形参中添加一个参数即可。Springmvc框架会自动把Request对象传递给方法。
1.3 默认支持的参数类型
- HttpServletRequest : 通过request对象获取请求信息
- HttpServletResponse :通过response处理响应信息
- HttpSession :通过session对象得到session中存放的对象
- Model/ModelMap :ModelMap是Model接口的实现类,通过Model或ModelMap向页面传递数据,如下:
//调用service查询商品信息
Items item = itemService.findItemById(id);
model.addAttribute("item", item);
页面通过${item.XXXX}获取item对象的属性值
使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。
如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替
代。不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据。
如果使用Model则方法可以改造成:
@RequestMapping("/itemEdit")
public String itemEdit(HttpServletRequest request, Model model) {
//从Request中取id
String strId = request.getParameter("id");
Integer id = null;
//如果id有值则转换成int类型
if (strId != null && !"".equals(strId)) {
id = new Integer(strId);
} else {
//出错
return null;
}
Items items = itemService.getItemById(id);
//创建ModelAndView
//ModelAndView modelAndView = new ModelAndView();
//向jsp传递数据
//modelAndView.addObject("item", items);
model.addAttribute("item", items);
//设置跳转的jsp页面
//modelAndView.setViewName("editItem");
//return modelAndView;
return "editItem";
}
1.4 绑定简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。从Request取参数的方法可以进一步简化。
@RequestMapping("/itemEdit")
public String itemEdit(Integer id, Model model) {
Items items = itemService.getItemById(id);
//向jsp传递数据
model.addAttribute("item", items);
//设置跳转的jsp页面
return "editItem";
}
支持的数据类型
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
说明:对于布尔类型的参数,请求的参数值为true或false。
处理器方法:
public String editItem(Model model,Integer id,Boolean status) throws Exception
请求url:
http://localhost:8080/xxx.action?id=2&status=false@RequestParam
使用@RequestParam常用于处理简单类型的绑定
value:参数名字,即入参的请求参数名字,如value=“item_id”表示请求的参数区中的名字为item_id的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue:默认值,表示如果请求中没有同名参数时的默认值,定义如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) {
}
形参名称为id,但是这里使用value=" item_id"限定请求的参数名为item_id,所以页面传递参数的名必须为item_id。
注意:如果请求参数中没有item_id将跑出异常:
HTTP Status 500 - Required Integer parameter 'item_id' is not present
这里通过required=true限定item_id参数为必需传递,如果不传递则报400错误,可以使用defaultvalue设置默认值,
即使required=true也可以不传item_id参数值
2. 绑定pojo类型
2.1 需求
请求的url:/updateitem.action
参数:表单中的数据。
响应内容:更新成功页面
2.2 使用pojo接收表单数据
如果提交的参数很多,或者提交的表单中的内容很多的时候可以使用pojo接收数据。要求pojo对象中的属性名和表单中input的name属性一致。
页面定义如下;
<input type="text" name="name"/>
<input type="text" name="price"/>
Pojo定义:
public class Items {
private Integer id;
private String name;
private Float price;
private String pic;
}
请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性
@RequestMapping("/updateitem")
public String updateItem(Items items) {
itemService.updateItem(items);
return "success";
}
注意:提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定
的内容。
2.4 解决post乱码问题
在web.xml中加入:
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
以上可以解决post请求乱码问题。
对于get请求中文参数出现乱码解决方法有两个:
1.修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"/>
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
2.对参数进行重新编码
String userName new
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
3. 绑定包装pojo
3.1 需求
包装对象定义如下:
Public class QueryVo {
private Items items;
}
页面定义:
<input type="text" name="items.name" />
<input type="text" name="items.price" />
Controller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
3.2 接收查询条件
@RequestMapping("/queryitem")
public String queryItem(QueryVo queryVo) {
System.out.println(queryVo.getItems().getName());
System.out.println(queryVo.getItems().getPrice());
return null;
}
4. 自定义参数绑定
4.1 需求
由于日期数据有很多种格式,所以springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。在springmvc这可以在处理器适配器上自定义Converter进行参数绑定。如果使用可以在此标签上进行扩展。
4.2 自定义Converter
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
4.3 配置Converter
方式1
<!-- 加载注解驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 转换器配置 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.springmvc.convert.DateConverter"/>
</set>
</property>
</bean>
方式2
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描带Controller注解的类 -->
<context:component-scan base-package="cn.itcast.springmvc.controller" />
<!-- 转换器配置 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.itcast.springmvc.convert.DateConverter"/>
</set>
</property>
</bean>
<!-- 自定义webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
</bean>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
<!-- 注解处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!-- 加载注解驱动 -->
<!-- <mvc:annotation-driven/> -->
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<!-- jsp前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- jsp后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
注意:此方法需要独立配置处理器映射器、适配器,不再使用<mvc:annotation-driven/>
4. 绑定数组
4.1 需求
要求商品列表页面中的每个商品前有一个checkbook,选中多个商品后点击删除按钮把商品id传递给Controller,根据商品id删除商品信息。
4.2 Jsp中实现
<c:forEach items="${itemList }" var="item">
<tr>
<td><input name="ids" value="${item.id}" type="checkbox"></td>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
生成html代码如下:
页面选中多个checkbox向controller方法传递
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<tr>
<td><input name="ids" value="1" type="checkbox"></td>
<td>台式机</td>
<td>3000.0</td>
<td>2016-02-03 13:22:53</td>
<td></td>
<td><a href="/springmvc-web/itemEdit.action?id=1">修改</a></td>
</tr>
<tr>
<td><input name="ids" value="2" type="checkbox"></td>
<td>笔记本</td>
<td>6000.0</td>
<td>2015-02-09 13:22:57</td>
<td></td>
<td><a href="/springmvc-web/itemEdit.action?id=2">修改</a></td>
</tr>
<tr>
<td><input name="ids" value="3" type="checkbox"></td>
<td>背包</td>
<td>200.0</td>
<td>2015-02-06 13:23:02</td>
<td></td>
<td><a href="/springmvc-web/itemEdit.action?id=3">修改</a></td>
</tr>
</table>
4.3 Controller
Controller方法中可以用String[]接收,或者pojo的String[]属性接收。两种方式任选其一即可。
定义如下:
@RequestMapping("/queryitem")
public String queryItem(QueryVo queryVo, String[] ids) {
System.out.println(queryVo.getItems().getName());
System.out.println(queryVo.getItems().getPrice());
System.out.println(ids.toString());
return null;
}
或者
public class QueryVo {
private Items items;
private String[] ids;
public String[] getIds() {
return ids;
}
public void setIds(String[] ids) {
this.ids = ids;
}
}
5 将表单的数据绑定到List
5.1 需求
要想实现商品数据的批量修改,需要在商品列表中可以对商品信息进行修改,并且可以批量提交修改后的商品数据。
5.2 接收商品列表的pojo
List中存放对象,并将定义的List放在包装类中,使用包装pojo对象接收。
public class QueryVo {
private Items items;
private String[] ids;
private List<Items> itemList;
public List<Items> getItemList() {
return itemList;
}
public void setItemList(List<Items> itemList) {
this.itemList= itemList;
}
get/set...
}
5.3 Jsp改造
页面定义如下:
<tr>
<td>
<input type="text" name=" itemsList[0].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemsList[0].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemsList[0].price" value="${item.price}"/>
</td>
</tr>
<tr>
<td>
<input type="text" name=" itemsList[1].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemsList[1].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemsList[1].price" value="${item.price}"/>
</td>
</tr>
Name属性必须是包装pojo的list属性+下标+元素属性(接收参数)。
展示的Jsp做如下改造:
<c:forEach items="${itemList }" var="item">
<tr>
<td><input name="ids" value="${item.id}" type="checkbox"></td>
<td>
<input name="id" value="${item.id}" type="hidden">
<input name="name" value="${item.name }" type="text">
</td>
<td><input name="name" value="${item.price }" type="text"></td>
<td><input name="name" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>" type="text"></td>
<td><input name="name" value="${item.detail }" type="text"></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
varStatus属性常用参数总结下:
${status.index} 输出行号,从0开始。
${status.count} 输出行号,从1开始。
${status.current} 当前这次迭代的(集合中的)项
${status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。
5.4 Controller
@RequestMapping("/queryitem")
public String queryItem(QueryVo queryVo, String[] ids) {
System.out.println(queryVo.getItems().getName());
System.out.println(queryVo.getItems().getPrice());
System.out.println(ids.toString());
return null;
}
注意:接收List类型的数据必须是pojo的属性,方法的形参为List类型无法正确接收到数据。