一. SpringMVC参数绑定过程
1. 从客户端请求的key/value数据, 经过参数绑定, 将key/value数据绑定到controller方法的形参上。
2. 处理器适配器调用SpringMVC提供的参数绑定组件, 将key/value数据转换成controller方法的形参。
3. SpringMVC的参数绑定组件: SpringMVC提供了很多converter(转换器), 能够将任意类型转换为Java的类型。在特殊情况下需要自定义converter, 最常用的就是自定义日期类型转换的converter。
二. 简单类型的参数绑定
1. Java的一些简单类型在Web表单中常用的有: int、float、double、String、boolean, 以及它们的数组类型int[]、float[]、double[]、String[]、boolean[], 只要表单中name的值和处理器方法中的形参名称一致可以直接赋值成功。
2. 简单类型参数绑定
3. 简单数组类型参数绑定
二. 通过@RequestParam注解对简单类型的参数绑定
1. 如果使用@RequestParam注解, 不限制表单中name的值必须和处理器方法中的形参名一致, 可以指定。
2. 使用@RequestParam注解, 还可以通过设置required指定参数是否是必传参数。
3. 使用@RequestParam注解, 还可以通过设置defaultValue指定默认值。
4. 使用@RequestParam注解, 解决参数不一致的问题, 设置默认值和是否是必传参数例子:
三. pojo绑定
1. 表单中name的值和处理器方法中的形参的pojo的属性名一致, 才能成功绑定成功。
2. 页面中表单name的值
3. 处理器形参的pojo的属性名
四. 自定义参数绑定实现日期类型绑定和注解实现日期类型绑定
1. 对应处理器方法形参中pojo对象, 如果属性中有日期类型, 需要自定义参数绑定。
2. 自定义日期转换类, 将表单中字符串类型的日期转换成java.util.Date类型的日期
3. 需要向处理器适配器中注入自定义的参数绑定组件
4. 自定义参数绑定实现日期类型绑定使用起来有点复杂, Spring提供了注解绑定日期参数。只需要在pojo的属性上添加如下日期格式化注解就一步到位了。
五. 包装的pojo
1. 有的时候我们可能需要用到包装的pojo。只要表单的name值是包装的pojo属性名+.+包装的pojo实体类的属性名, SpringMVC就能够自动进行参数绑定。
2. 包装的pojo类
3. 页面中表单的name值
六. 包装List<pojo>的pojo
1. 通常在需要批量提交数据时, 将提交的数据绑定到包装List<pojo>的pojo类中。
2. 包装List<pojo>的pojo类
3. 页面中表单的name值
七. 包装Map的pojo
1. 包装map的pojo类
2. 页面中表单的name值
八. 中文乱码
1. SpringMVC解决post乱码, 在web.xml里配置如下过滤器
2. get乱码
2.1. tomcat默认的编码方式是ISO8859-1。
2.2. 在tomcat的conf/server.xml配置文件中添加URIEncoding="utf-8"
九. 例子
1. 新建一个名为SpringMVCReqParam的Java工程, 拷入相关jar包
2. 新建Product.java
package com.lywgames.domain;
import java.io.Serializable;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
// 商品id
private Integer id;
// 商品名称
private String name;
// 商品价格
private Double price;
// 商品创建时间
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createtime;
// 商品描述
private String detail;
// 商品图片
private String picture;
public Product() {}
public Product(Integer id, String name, Double price, Date createtime, String detail, String picture) {
this.id = id;
this.name = name;
this.price = price;
this.createtime = createtime;
this.detail = detail;
this.picture = picture;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
}
3. 新建ProductDetailVo.java
package com.lywgames.domain;
public class ProductDetailVo {
private Product product;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
4. 新建QueryVo.java
package com.lywgames.domain;
import java.util.List;
public class QueryVo {
private List<Product> products;
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
5. 新建ProductDetailMapVo.java
package com.lywgames.domain;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class ProductDetailMapVo {
private Map<String, String> product = new HashMap<String, String>();
public Map<String, String> getProduct() {
return product;
}
public void setProduct(Map<String, String> product) {
this.product = product;
}
public Product toProduct() {
Integer id = Integer.parseInt(product.get("id"));
String name = product.get("name");
Double price = Double.parseDouble(product.get("price"));
Date date = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
date = sdf.parse(product.get("createtime"));
} catch (ParseException e) {
e.printStackTrace();
}
String detail = product.get("detail");
String picture = product.get("picture");
return new Product(id, name, price, date, detail, picture);
}
}
6. 新建ProductMapper.java
package com.lywgames.mapper;
import java.util.List;
import com.lywgames.domain.Product;
public interface ProductMapper {
public List<Product> getProductList();
public Product getProductById(int id);
public int updateProduct(Product product);
public int deleteProductById(int id);
public int addProduct(Product product);
}
7. 新建ProductMapper.xml配置
8. 新建ProductService.java
package com.lywgames.service;
import java.util.List;
import com.lywgames.domain.Product;
public interface ProductService {
public List<Product> getProductList();
public Product getProductById(int id);
public int updateProduct(Product product);
public int deleteProductById(int id);
public int addProduct(Product product);
}
9. 新建ProductServiceImpl.java
package com.lywgames.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.lywgames.domain.Product;
import com.lywgames.mapper.ProductMapper;
import com.lywgames.service.ProductService;
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductMapper productMapper;
@Override
public List<Product> getProductList() {
return productMapper.getProductList();
}
@Override
public Product getProductById(int id) {
return productMapper.getProductById(id);
}
@Override
public int updateProduct(Product product) {
return productMapper.updateProduct(product);
}
@Override
public int deleteProductById(int id) {
return productMapper.deleteProductById(id);
}
@Override
public int addProduct(Product product) {
return productMapper.addProduct(product);
}
}
10. 新建ProductAction.java
package com.lywgames.web.action;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.lywgames.domain.Product;
import com.lywgames.domain.ProductDetailMapVo;
import com.lywgames.domain.ProductDetailVo;
import com.lywgames.domain.QueryVo;
import com.lywgames.service.ProductService;
@Controller
public class ProductAction {
@Resource
private ProductService productService;
@RequestMapping("productList")
public ModelAndView getProductList() {
ModelAndView modelAndView = new ModelAndView();
List<Product> productList = productService.getProductList();
modelAndView.addObject("productList", productList);
modelAndView.setViewName("productList");
return modelAndView;
}
@RequestMapping("getProductById")
public ModelAndView getProductById(int id) {
ModelAndView modelAndView = new ModelAndView();
Product product = productService.getProductById(id);
modelAndView.addObject("product", product);
modelAndView.setViewName("modifyProduct");
return modelAndView;
}
@RequestMapping("updateProduct")
public ModelAndView updateProduct(Product product, String picture, @RequestParam("picFile")MultipartFile picFile, HttpServletRequest req) {
if(picFile != null) {
String picOldName = picFile.getOriginalFilename();
if(picOldName != null && picOldName != "") {
String picNewName = UUID.randomUUID().toString() + picOldName.substring(picOldName.lastIndexOf("."));
File file = new File(req.getServletContext().getRealPath("/pic") + "/" + picNewName);
try {
picFile.transferTo(file);
product.setPicture(req.getRequestURL().substring(0, req.getRequestURL().indexOf(req.getServletPath())) + "/pic/" + picNewName);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
}else {
product.setPicture(picture);
}
}
ModelAndView modelAndView = new ModelAndView();
int result = productService.updateProduct(product);
System.out.println("update操作, mybatis返回值:" + result);
List<Product> productList = productService.getProductList();
modelAndView.addObject("productList", productList);
modelAndView.setViewName("productList");
return modelAndView;
}
@RequestMapping(value={"deleteProductById", "delete"}, method={RequestMethod.GET})
public ModelAndView deleteProductById(@RequestParam(value="id", required=true, defaultValue="0") Integer idInteger) {
ModelAndView modelAndView = new ModelAndView();
int result = productService.deleteProductById(idInteger);
System.out.println("delete操作, mybatis返回值:" + result);
List<Product> productList = productService.getProductList();
modelAndView.addObject("productList", productList);
modelAndView.setViewName("productList");
return modelAndView;
}
@RequestMapping("deleteBatch")
public ModelAndView deleteBatch(Integer[] ids) {
if(ids != null && ids.length > 0) {
for (Integer id : ids) {
int result = productService.deleteProductById(id);
System.out.println("delete操作, mybatis返回值:" + result);
}
}
ModelAndView modelAndView = new ModelAndView();
List<Product> productList = productService.getProductList();
modelAndView.addObject("productList", productList);
modelAndView.setViewName("productList");
return modelAndView;
}
@RequestMapping("batchAddProductUi")
public String updateProduct() {
return "batchAddProduct";
}
@RequestMapping(value="batchAddProduct", method={RequestMethod.POST})
public ModelAndView batchAddProduct(QueryVo vo, @RequestParam("picFile")MultipartFile[] picFile, HttpServletRequest req) {
if(vo.getProducts() != null && vo.getProducts().size() > 0) {
for (int i = 0; i < vo.getProducts().size(); i++) {
if(vo.getProducts().get(i).getPicture() != null) {
String picOldName = picFile[i].getOriginalFilename();
String picNewName = UUID.randomUUID().toString() + picOldName.substring(picOldName.lastIndexOf("."));
File file = new File(req.getServletContext().getRealPath("/pic") + "/" + picNewName);
try {
picFile[i].transferTo(file);
vo.getProducts().get(i).setPicture(req.getRequestURL().substring(0, req.getRequestURL().indexOf(req.getServletPath())) + "/pic/" + picNewName);
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
}
int result = productService.addProduct(vo.getProducts().get(i));
System.out.println("add操作, mybatis返回值:" + result);
}
}
ModelAndView modelAndView = new ModelAndView();
List<Product> productList = productService.getProductList();
modelAndView.addObject("productList", productList);
modelAndView.setViewName("productList");
return modelAndView;
}
@RequestMapping("productDetail1")
public ModelAndView productDetail1(ProductDetailVo vo) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("product", vo.getProduct());
modelAndView.setViewName("product");
return modelAndView;
}
@RequestMapping("productDetail2")
public ModelAndView productDetail2(ProductDetailMapVo vo) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("product", vo.toProduct());
modelAndView.setViewName("product");
return modelAndView;
}
}
11. 新建FormDateConverter.java
package com.lywgames.web.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* 自定义日期转换类, 将表单中字符串类型的日期转换成java.util.Date类型的日期
*/
public class FormDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
12. 新建applicationContext-dao.xml配置
13. 新建applicationContext-service.xml配置
14. 新建springmvc.xml配置
15. 新建jdbc.properties配置
16. 新建SqlMapConfig.xml配置
17. 修改web.xml配置
18. 新建index.jsp
19. 新建batchAddProduct.jsp
20. 新建modifyProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>修改商品信息</title>
</head>
<body>
<form action="updateProduct.action" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" value="${product.id }" />
<table width="100%" border=1>
<tr><td colspan="2" align="center">修改商品信息</td></tr>
<tr><td>商品名称</td><td><input type="text" name="name" value="${product.name }"/></td></tr>
<tr><td>商品价格</td><td><input type="text" name="price" value="${product.price }"/></td></tr>
<tr>
<td>生产日期</td>
<td>
<input type="text" name="createtime" value="<fmt:formatDate value="${product.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/>
</td>
</tr>
<tr><td>商品描述</td><td><input type="text" name="detail" value="${product.detail }"/></td></tr>
<tr>
<td>商品图片</td>
<td>
<c:if test="${product.picture != null}">
<img name="picture" alt="商品图片" src="${product.picture}" height="100px" width="100px"/>
<input type="hidden" name="picture" value="${product.picture }"/>
</c:if>
<input type="file" name="picFile"/>
</td>
</tr>
<tr><td colspan="2" align="center"><input type="submit" value="提交"></td></tr>
</table>
</form>
</body>
</html>
21. 新建product.jsp
22. 新建productList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>查询商品列表</title>
<script type="text/javascript">
function createForm(action, idName, id, nameName, name, priceName, price, detailName, detail, pictureName, picture, createtimeName, createtime){
var form = document.createElement('form');
form.style = "display:none;";
form.action = action;
form.method = 'post';
var iptId = document.createElement('input');
iptId.name = idName;
iptId.value = id;
form.appendChild(iptId);
var iptName = document.createElement('input');
iptName.name = nameName;
iptName.value = name;
form.appendChild(iptName);
var iptPrice = document.createElement('input');
iptPrice.name = priceName;
iptPrice.value = price;
form.appendChild(iptPrice);
var iptDetail = document.createElement('input');
iptDetail.name = detailName;
iptDetail.value = detail;
form.appendChild(iptDetail);
var iptPicture = document.createElement('input');
iptPicture.name = pictureName;
iptPicture.value = picture;
form.appendChild(iptPicture);
var iptCreatetime = document.createElement('input');
iptCreatetime.name = createtimeName;
iptCreatetime.value = createtime;
form.appendChild(iptCreatetime);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
function productDetail1(id,name,price,createtime,detail,picture){
createForm('productDetail1.action','product.id',id,'product.name',name,'product.price',price,'product.detail',detail,'product.picture',picture,'product.createtime',createtime)
}
function productDetail2(id,name,price,createtime,detail,picture){
createForm('productDetail2.action',"product['id']",id,"product['name']",name,"product['price']",price,"product['detail']",detail,"product['picture']",picture,"product['createtime']",createtime)
}
</script>
</head>
<body>
<form action="deleteBatch.action" method="post">
<table width="100%" border=1>
<tr>
<td colspan="7" align="center">查询商品列表</td>
</tr>
<tr>
<td>选择</td>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>商品图片</td>
<td>操作</td>
</tr>
<c:forEach items="${productList}" var="product">
<tr>
<td>
<input type="checkbox" name="ids" value="${product.id}">
</td>
<td>${product.name}</td>
<td>${product.price}</td>
<td>
<fmt:formatDate value="${product.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>
</td>
<td>${product.detail}</td>
<td><img src="${product.picture}" alt="商品图片" height="100px" width="100px" /></td>
<td>
<a href="getProductById.action?id=${product.id}">修改</a>
<a href="deleteProductById.action?id=${product.id}">删除</a>
<a href="javascript:productDetail1('${product.id}','${product.name}','${product.price}','<fmt:formatDate value="${product.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>','${product.detail}','${product.picture}')">详情1</a>
<a href="javascript:productDetail2('${product.id}','${product.name}','${product.price}','<fmt:formatDate value="${product.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>','${product.detail}','${product.picture}')">详情2</a>
</td>
</tr>
</c:forEach>
<tr>
<td colspan="7" align="center"><input type="submit" value="批量删除"/></td>
</tr>
</table>
</form>
</body>
</html>