数据绑定是将用户的输入绑定到领域模型的一种特性,有了数据绑定,类型总是String 的http请求,可用于填充不同类型的对象属性,使得from bean(如之前的ProductForm
实例)变得多余。
为了高效的使用数据绑定,我们要使用Sping 的表单标签库。
例子
- 工程目录
- Book 与Category类
public class Book implements Serializable{ private long id ; private String isbn ; private String title ; private Category category ; private String author ; public Book(){ } public Book(long id ,String isbn,String title , Category category, String author){ this.id = id ; this.isbn = isbn ; this.title = title ; this.category = category ; this.author = author ; } // gettters and setters here }
然后
public class Category implements Serializable{ private int id ; private String name ; public Category (){ } public Category(int id ,String name ){ this.id = id ; this.name = name ; } // getters and setters here }
- BookServiceImpl
/** * 进行后台的一些处理 * @author lsj * */ @Service public class BookServiceImpl implements BookService { /** * this implementation is not thread safe */ private List<Category> categories ; private List<Book> books; public BookServiceImpl(){ categories = new ArrayList<Category>() ; Category category1 = new Category(1, "computer") ; Category category2 = new Category(2, "health") ; Category category3 = new Category(3,"film ") ; categories.add(category1) ; categories.add(category2) ; categories.add(category3) ; books = new ArrayList<Book>() ; books.add(new Book(1, "2", "3", category1, "4")) ; books.add(new Book(2, "3", "4", category1, "5")) ; } @Override public List<Category> getAllCategories() { return categories ; } @Override public Category getCategory(int id) { //根据id进行查询 for (Category category: categories){ if (id == category.getId()){ return category ; } } return null ; } @Override public List<Book> getAllBooks() { return books ; } @Override public Book save(Book book) { book.setId(getNextId() ); books.add(book) ; return book ; } @Override public Book update(Book book) { int bookCnt = books.size() ; //能否像上面一样用增强的for循环? for (int i =0; i<bookCnt ;i++){ Book savedBook = books.get(i) ; if (savedBook.getId() == book.getId()){ books.set(i, book) ; return book ; } } return book ; } @Override public Book get(long id) { for (Book book :books){ if (book.getId()== id){ return book ; } } return null ; } @Override public long getNextId() { long id = 0; for (Book book :books){ long bookId = book.getId() ; if (bookId>id){ id = bookId ; } } return id+1; } }
- Controller类
@Controller public class BookController { /** * BookService是一个接口,对其添加 autowired注释后,可以使 * BookService的一个实现类被注入到Controller中 */ @Autowired private BookService bookService ; private static final Log logger = LogFactory.getLog(BookController.class) ; @RequestMapping(value ="/book_input") public String inputBook (Model model){ List<Category> categories = bookService.getAllCategories() ; model.addAttribute("categories" , categories); model.addAttribute("book", new Book()) ; return "BookAddForm" ; } @RequestMapping(value ="/book_edit/{id}") public String editBook(Model model, @PathVariable long id ){ List<Category> categories = bookService.getAllCategories() ; model.addAttribute("categories" , categories) ; Book book = bookService.get(id) ; model.addAttribute("book" , book) ; return "BookEditForm" ; } @RequestMapping(value ="/book_save") public String saveBook (@ModelAttribute Book book){ /** * 注意modelAttribute 的两种用法: * 1.将输入的或者创建的参数对象添加到Model对象中,上面就是,默认使用key ="book" * 2.如果是标注的方法,则将在每次调用请求处理方法前调用被标注的方法 */ Category category = bookService.getCategory(book.getCategory().getId()) ; book.setCategory(category); bookService.save(book); return "redirect:/book_list" ; } @RequestMapping(value="/book_update") public String updateBook(@ModelAttribute Book book){ logger.info("updateBook called"); Category category = bookService.getCategory(book.getCategory().getId()) ; book.setCategory(category); bookService.update(book); return "redirect:/book_list" ; } @RequestMapping(value ="/book_list") public String listBooks(Model model){ logger.info("book_list" ); List<Book> books = bookService.getAllBooks() ; model.addAttribute("books" , books) ; return "BookList"; } }
- web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- springmvc-config.xml
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--一个用于扫描控制器类,一个用于扫描服务类 --> <context:component-scan base-package="app05a.controller"/> <context:component-scan base-package="app05a.service"/> <mvc:annotation-driven/> <mvc:resources mapping="/css/**" location="/css/"/> <mvc:resources mapping="/*.html" location="/"/> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
其它视图略