文章目录
数据绑定
- 定义:
- 基本流程:客户端发送请求——》服务器接收请求,到数据库中查询结果——》把结果集封装为模型数据,然后返回给前台,进行响应
- 需求:后台方法要获取前端传过来的参数
- 传统方法:利用诸如doGet等方法处理请求,该方法的形参有request对象——》通过request对象获取前台参数——》存在一问题:获取的参数都是String类型——》需要转换为其他类型——》诸如转换数据类型,封装等操作框架完成
- 获取参数后要封装为实体对象——》繁琐的操作——》框架完成(自动拿出HTTP请求参数,封装到实体对象中)
- 需要获取谁——》形参列表定义谁——》框架自动数据绑定
底层原理
-
数据绑定实现流程:HandlerAdapter通过调用HttpMessageConverter组件(作用:拿出HTTP请求参数,然后数据类型转换或封装等,将封装【绑定后的】结果直接赋值给业务方法的形参),完成数据绑定
-
数据绑定后,则业务方法可直接利用形参进行业务处理
-
前台参数——数据绑定——封装为实体对象——业务方法的形参
常用数据绑定类型
数据绑定效果展示
- 基本数据类型
- 不传值,则代表null(基本数据类型的数据绑定不行,会报错,因为值不可为null,包装类可以)
-
包装类
-
数组
基础代码(准备)
- 添加依赖
- 创建控制器类(Controller注解)和DAO类(通过注解依赖注入,DAO类中的Map对象模拟数据库来存储数据)
- JSP页面
- web.xml和springmvc.xml(开启注解扫描+消息转换器+视图解析器)
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</mvc:message-converters>
</mvc:annotation-driven>
- 以下为都需要的代码
DAO类
@Repository
public class CourseDAO {
private Map<Integer,Course> courses = new HashMap<Integer, Course>(); //courses替代数据库功能
public void add(Course course){
courses.put(course.getId(),course);
}
public Collection<Course> getAll(){
return courses.values();
}
}
- 数据库存取数据类,此处将map对象模拟成数据库
- Controller类中需要使用DAO——》依赖注入——>Autowired注解完成自动装载——》则IOC容器自动创建对象,并注入到Controller类中——》业务方法中可以使用
@Autowired
private CourseDAO courseDAO;
index.jsp
- 用于显示数据库中所有course对象信息(列表形式)
//部分
<c:forEach items="${courses}" var="course">
//foreach遍历方式,取出key=courses对应的集合类对象(见handler类,此处为map),依次赋值给course
<tr>
<td><input type='checkbox' class='check_item'/></td>
<td>${course.id}</td> //ER表达式取出数据
<td>${course.name}</td>
<td>${course.price}</td>
<td>${course.author.name}</td> //注意级联对象的使用
<td>
<button class="btn btn-primary btn-sm edit_btn">
<span class="glyphicon glyphicon-pencil">编辑</span>
</button>
<button class="btn btn-danger btn-sm delete_btn">
<span class="glyphicon glyphicon-trash">删除</span>
</button>
</td>
</tr>
</c:forEach>
- forEach标签遍历集合
基本数据类型和包装类
@RequestMapping(value = "/baseType")
@ResponseBody
public String baseType(@RequestParam(value = "id") int id){
return "id:"+id;
}
@RequestMapping(value = "/packageType") //URL请求值
@ResponseBody
public String packageType(@RequestParam(value = "id") Integer id){
return "id:"+id;
}
-
注解RequestParam作用 :将前端请求中的id值绑定到形参的id上
-
RequestBody:直接将业务方法的返回值,即字符串响应(返回)给客户端,不跳转到另一个JSP页面
-
使用方法
-
URL中添加?以及属性名=属性值
数组类型
@RequestMapping(value = "/arrayType")
@ResponseBody
public String arrayType(String[] name){
StringBuffer sbf = new StringBuffer();
for (String item:name){
sbf.append(item).append(" ");
}
return sbf.toString();
}
- 使用方法:添加?+属性名=属性值+&+属性名=属性值
对象类型
@RequestMapping(value = "/pojoType")
public ModelAndView pojoType(Course course){
courseDAO.add(course);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDAO.getAll());
return modelAndView; //因为要跳转另一个JSP页面,所以使用modelAndView
}
- jsp关键代码
<form class="form-horizontal" role="form" action="pojoType" method="post"> //关注action
<div class="form-group">
<label class="col-sm-1 control-label">课程编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="id" placeholder="请输入课程编号"> //关注name=id,和实体类属性名相对应
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="name" placeholder="请输入课程名称">//关注name=name,和实体类属性名相对应
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程价格</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="price" placeholder="请输入课程价格">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="author.id" placeholder="请输入讲师编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="author.name" placeholder="请输入讲师姓名"> //关注级联对象的使用方法
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-3">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
</form>
- 创建course类(级联对象)
public class Course {
private int id;
private String name;
private double price;
private Author author; //对象级联:对象的一属性为对象
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
}
list类型
处理器
@RequestMapping(value = "/listType")
public ModelAndView listType(CourseList courseList){
for(Course course:courseList.getCourses()){
courseDAO.add(course);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDAO.getAll());
return modelAndView;
}
- List集合无法直接完成数据绑定——》需要实体类(CourseList),定义一集合类型的属性,然后通过该类给这个属性绑定
实体类
- 实体类要有setter和getter方法
public class CourseList {
private List<Course> courses;
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}
JSP页面
<form class="form-horizontal" role="form" action="listType" method="post"> //action
<div class="form-group">
<label class="col-sm-1 control-label">课程1编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].id" placeholder="请输入课程编号"> //name属性值,通过下标设置
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师姓名</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].author.name" placeholder="请输入讲师姓名"> //关注级联对象的数据绑定
</div>
</div>
- name对应形参对象(CourseList)的属性(id)
Map类型
处理器
@RequestMapping(value = "/mapType")
public ModelAndView mapType(CourseMap courseMap){
for(String key:courseMap.getCourses().keySet()){ //foreach遍历操作前台传来的course对象集合
//遍历key,通过key找到对应的对象
Course course = courseMap.getCourses().get(key);
courseDAO.add(course);//保存到数据库
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("courses",courseDAO.getAll()); //取出数据库中所有对象
return modelAndView;
}
- 同样不能直接数据绑定,放在实体类中
- 类比list类型来进行数据绑定,从而获取前端传来的课程对象
- 需要页面,所以要使用ModelAndView(带有视图信息)
实体类
public class CourseMap {
private Map<String,Course> courses;
public void setCourses(Map<String, Course> courses) {
this.courses = courses;
}
public Map<String, Course> getCourses() {
return courses;
}
}
JSP页面
- 程序部分,没按顺序来
<form class="form-horizontal" role="form" action="mapType" method="post"> //设置action
<div class="form-group">
<label class="col-sm-1 control-label">课程1编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses['one'].id" placeholder="请输入课程编号"> //设置name
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程1名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses['one'].name" placeholder="请输入课程名称">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">讲师编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses['one'].author.id" placeholder="请输入讲师编号">
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程2编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses['two'].id" placeholder="请输入课程编号">
</div>
</div>
- 类比list的下标,map用键值,one难道是自定义(?)
- 主要修改action和name
- 永远记住:name处填写实体类的属性名相关
Set对象
- 同样不能直接完成数据绑定,要创建实体类对象,set对象作为类属性
- 注意点(不同点):set对象要完成初始化才能数据绑定
处理器
@RequestMapping(value = "/setType")
public ModelAndView setType(CourseSet courseSet){
for (Course course:courseSet.getCourses()){ //取出前端传来的course对象集合数据
courseDAO.add(course); //存储在数据库中
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index"); //跳转index页面
modelAndView.addObject("courses",courseDAO.getAll()); //取出数据库中所有course对象数据
return modelAndView; //返回
}
实体类
public class CourseSet {
private Set<Course> courses = new HashSet<Course>();
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
public Set<Course> getCourses() {
return courses;
}
public CourseSet(){ //需要先添加对象,完成初始化,才能完成数据绑定
courses.add(new Course());
courses.add(new Course());
}
}
JSP页面
<form class="form-horizontal" role="form" action="setType" method="post"> //action值
<div class="form-group">
<label class="col-sm-1 control-label">课程1编号</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].id" placeholder="请输入课程编号"> //name值
</div>
</div>
<div class="form-group">
<label class="col-sm-1 control-label">课程1名称</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="courses[0].name" placeholder="请输入课程名称"> //name值
</div>
</div>
- 居然可以通过下标0,1,2
JSON格式
处理器
@RequestMapping(value = "/jsonType")
@ResponseBody //不跳转页面
public Course jsonType(@RequestBody Course course){ //注解responsebody表示需要在客户端直接拿到对象(JSP页面的成功回调函数)
//将json格式参数封装到course对象中
course.setPrice(course.getPrice()+100);
return course; //返回course对象
}
- 同样无法直接完成Json格式数据绑定——》借助jar包,添加如下依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
</dependency>
-
加载json.jsp——》前端传递Json格式数据给后台——》绑定到course对象中,然后业务处理,具体如下:
- 在JSP页面的初始化函数中,定义(初始化)Json格式数据(实际是发送时course转换为Json)
- 通过ajax请求,将json格式对象参数发送给后台
- 将Json格式参数绑定到course对象中
- 业务处理,然后将修改后的对象返回给前台
- 因为dataType:“json”, //表示要求服务端返回Json格式
- 所以框架会将返回的course对象解析为Json格式
JSP页面
- json.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> //引入jQuery
<script type="text/javascript">
$(function(){ //页面初始化函数
var course = {
"id":"8",
"name":"SSM框架整合",
"price":"200"
};
$.ajax({
url:"jsonType", //处理请求的业务方法
data:JSON.stringify(course), //请求时将course变量转换为Json格式
type:"post",
contentType:"application/json;charse=UTF-8", //表示客户端发送的是Json格式数据,设置编码,避免中文乱码
dataType:"json", //表示要求服务端返回Json格式
success:function(data){ //成功回调函数
alert(data.name+"---"+data.price); //取出后台返回的对象,并展示对象的属性值(alert)
}
})
})
</script>
<body>
</body>
</html>
- 加载JSP页面——》将course对象转换为Json格式,并发送到jsontype(RequestMapping参数)对应的这一业务方法中——》数据绑定到course对象中