数据绑定是将用户的输入绑定到领域模型的一种特性,有了数据绑定,类型总是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>
其它视图略