简介
数据绑定是将用户参数输入值绑定到领域模型的一种特性。在Spring MVC的Controller和View参数数据传递中,所有HTTP请求参数的类型均为字符串。如果模型需要绑定的类型为double或int,则需要手动进行类型转换。而有了数据绑定后,就不再需要手动将HTTP请求中String类型转换为模型需要的类型。数据绑定的另一个好处是,当输入验证失败时,会重新生成一个HTML表单,无需重新填入输入字段
在Spring MVC中,为了方便 高效的使用数据绑定,还需要学习表单标签库
表单标签库
表单标签库中包含可以用在JSP页面中渲染HTML元素的标签,JSP页面使用Spring表单标签库时,必须在JSP页面开头处声明taglib指令 代码如下
<%taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
表单包含元素如下
数据绑定
1:创建ch2_4应用并导入相关的JAR包
2:创建Web和Spring MVC配置类
在src目录下创建名为config的包 并创建WebConfig和SpringMVCConfig配置类
Webconfig代码如下
package config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.DispatcherServlet; public class WebConfig implements WebApplicationInitializer{ @Override public void onStartup(ServletContext arg0) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMVCConfig.class);//注册Spring MVC的Java配置类SpringMVCConfig ctx.setServletContext(arg0);//和当前ServletContext关联 /** * 注册Spring MVC的DispatcherServlet */ javax.servlet.ServletRegistration.Dynamic servlet = arg0.addServlet("dispatcher", new DispatcherServlet(ctx)); servlet.addMapping("/"); servlet.setLoadOnStartup(1); /** * 注册字符编码过滤器 */ javax.servlet.FilterRegistration.Dynamic filter = arg0.addFilter("characterEncodingFilter", CharacterEncodingFilter.class); filter.setInitParameter("encoding", "UTF-8"); filter.addMappingForUrlPatterns(null, false, "/*"); } }
SpringMVCConfig代码如下
package config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @EnableWebMvc @ComponentScan(basePackages = {"controller","service"}) public class SpringMVCConfig implements WebMvcConfigurer { /** * 配置视图解析器 */ @Bean public InternalResourceViewResolver getViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; } /** * 配置静态资源 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/html/**").addResourceLocations("/html/"); //addResourceHandler指的是对外暴露的访问路径 //addResourceLocations指的是静态资源存放的位置 } }
3:创建View层
包含两个JSP页面 一个是信息输入页面userAdd.jsp 一个是信息显示页面userList.jsp
userAdd.jsp代码如下
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form:form modelAttribute="user" method="post" action=" ${pageContext.request.contextPath }/user/save"> <fieldset> <legend>添加一个用户</legend> <p> <label>用户名:</label> <form:input path="userName"/> </p> <p> <label>爱好:</label> <form:checkboxes items="${hobbys}" path="hobby" /> </p> <p> <label>朋友:</label> <form:checkbox path="friends" value="张三"/>张三 <form:checkbox path="friends" value="李四"/>李四 <form:checkbox path="friends" value="王五"/>王五 <form:checkbox path="friends" value="赵六"/>赵六 </p> <p> <label>职业:</label> <form:select path="carrer"> <option/>请选择职业 <form:options items="${carrers }"/> </form:select> </p> <p> <label>户籍:</label> <form:select path="houseRegister"> <option/>请选择户籍 <form:options items="${houseRegisters }"/> </form:select> </p> <p> <label>个人描述:</label> <form:textarea path="remark" rows="5"/> </p> <p id="buttons"> <input id="reset" type="reset"> <input id="submit" type="submit" value="添加"> </p> </fieldset> </form:form> </body> </html>
userList.jsp代码如下
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>用户列表</h1> <a href="<c:url value="${pageContext.request.contextPath }/user/input"/>">继续添加</a> <table> <tr> <th>用户名</th> <th>兴趣爱好</th> <th>朋友</th> <th>职业</th> <th>户籍</th> <th>个人描述</th> </tr> <!-- JSTL标签,请参考本书的相关内容 --> <c:forEach items="${users}" var="user"> <tr> <td>${user.userName }</td> <td> <c:forEach items="${user.hobby }" var="hobby"> ${hobby } </c:forEach> </td> <td> <c:forEach items="${user.friends }" var="friend"> ${friend } </c:forEach> </td> <td>${user.carrer }</td> <td>${user.houseRegister }</td> <td>${user.remark }</td> </tr> </c:forEach> </table> </body> </html>
4:创建领域模型
在src目录下创建pojo包 并创建User类
package pojo; public class User { private String userName; private String[] hobby;//兴趣爱好 private String[] friends;//朋友 private String carrer; private String houseRegister; private String remark; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String[] getHobby() { return hobby; } public void setHobby(String[] hobby) { this.hobby = hobby; } public String[] getFriends() { return friends; } public void setFriends(String[] friends) { this.friends = friends; } public String getCarrer() { return carrer; } public void setCarrer(String carrer) { this.carrer = carrer; } public String getHouseRegister() { return houseRegister; } public void setHouseRegister(String houseRegister) { this.houseRegister = houseRegister; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
5:创建Service层
Service层使用静态集合变量users模拟数据库存储用户信息,包括添加用户和查询用户两个功能
UserService接口类代码如下
package service; import java.util.ArrayList; import pojo.User; public interface UserService { boolean addUser(User u); ArrayList<User> getUsers(); }
UserServiceImpl实现类代码如下
package service; import java.util.ArrayList; import org.springframework.stereotype.Service; import pojo.User; @Service public class UserServiceImpl implements UserService{ //使用静态集合变量users模拟数据库 private static ArrayList<User> users = new ArrayList<User>(); @Override public boolean addUser(User u) { if(!"IT民工".equals(u.getCarrer())){//不允许添加IT民工 users.add(u); return true; } return false; } @Override public ArrayList<User> getUsers() { return users; } }
6:创建Controller层
在Controller类的UserController中定义了请求处理方法 代码如下
package controller; import java.util.HashMap; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import pojo.User; import service.UserService; @Controller @RequestMapping("/user") public class UserController { // 得到一个用来记录日志的对象,这样打印信息的时候能够标记打印的是那个类的信息 private static final Log logger = LogFactory.getLog(UserController.class); @Autowired private UserService userService; @RequestMapping(value = "/input") public String inputUser(Model model) { HashMap<String, String> hobbys = new HashMap<String, String>(); hobbys.put("篮球", "篮球"); hobbys.put("乒乓球", "乒乓球"); hobbys.put("电玩", "电玩"); hobbys.put("游泳", "游泳"); // 如果model中没有user属性,userAdd.jsp会抛出异常,因为表单标签无法找到 // modelAttribute属性指定的form backing object model.addAttribute("user", new User()); model.addAttribute("hobbys", hobbys); model.addAttribute("carrers", new String[] { "教师", "学生", "coding搬运工", "IT民工", "其它" }); model.addAttribute("houseRegisters", new String[] { "北京", "上海", "广州", "深圳", "其它" }); return "userAdd"; } @RequestMapping(value = "/save") public String addUser(@ModelAttribute User user, Model model) { if (userService.addUser(user)) { logger.info("成功"); return "redirect:/user/list"; } else { logger.info("失败"); HashMap<String, String> hobbys = new HashMap<String, String>(); hobbys.put("篮球", "篮球"); hobbys.put("乒乓球", "乒乓球"); hobbys.put("电玩", "电玩"); hobbys.put("游泳", "游泳"); // 这里不需要model.addAttribute("user", new // User()),因为@ModelAttribute指定form backing object model.addAttribute("hobbys", hobbys); model.addAttribute("carrers", new String[] { "教师", "学生", "coding搬运工", "IT民工", "其它" }); model.addAttribute("houseRegisters", new String[] { "北京", "上海", "广州", "深圳", "其它" }); return "userAdd"; } } @RequestMapping(value = "/list") public String listUsers(Model model) { List<User> users = userService.getUsers(); model.addAttribute("users", users); return "userList"; } }
7:测试应用 启动主类后 通过地址
http://localhost:8080/ch2_4/user/input测试应用接口
测试效果如下