目录

该文详细的通过Spring IOC、MyBatis、Servlet、Maven及Spring整合MyBatis的等技术完成一个简单的图书管理功能,实现图书列表、删除、多删除、编辑、新增功能。梳理前面学习的内容《Spring整合MyBatis(Maven+MySQL)一》《Spring整合MyBatis(Maven+MySQL)二》,做一个完整的示例完成一个简单的图书管理功能,主要使用到的技术包含Spring、MyBatis、Maven、MySQL及简单MVC等。最后的运行效果如下所示:

项目结构如下:

一、新建一个基于Maven的Web项目

1.1、创建一个简单的Maven项目,项目信息如下:

1.2、修改层面信息,在项目上右键选择属性,再选择“Project Facets”,先设置java运行环境为1.7,先去掉"Dynamic Web Module"前的勾,然后保存关闭;再打开勾选上"Dynamic Web Module",版本选择“3.0”;这里在左下解会出现一个超链接,创建“Web Content”,完成关闭。

1.3、修改项目的部署内容。项目上右键属性,选择“Deplyment Assembly”,删除不需要发布的内容如:带“test”的两个目录,WebContent目录,再添加一个main下的webapp目录。

修改后的结果如下所示:

1.4、修改项目内容。将WebContent下的内容复制到/src/main/webapp下,再删除WebContent目录,修改后的结果如下所示:

1.5、添加“服务器运行时(Server Runtime)”,添加后的结果如下:

二、创建数据库与表

启动MySQL,创建数据库,新建表books,插入测试数据,完成后的表如下所示:

创建表的sql脚本如下:

/*
Navicat MySQL Data Transfer Source Server : localhost
Source Server Version : 50536
Source Host : localhost:3306
Source Database : db1 Target Server Type : MYSQL
Target Server Version : 50536
File Encoding : 65001 Date: 2016-07-06 22:05:07
*/ SET FOREIGN_KEY_CHECKS=0; -- ----------------------------
-- Table structure for `books`
-- ----------------------------
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`title` varchar(100) NOT NULL COMMENT '书名',
`price` decimal(10,2) DEFAULT NULL COMMENT '价格',
`publishDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '出版日期',
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of books
-- ----------------------------
INSERT INTO `books` VALUES ('1', 'Java编程思想', '98.50', '2005-01-02 00:00:00');
INSERT INTO `books` VALUES ('2', 'HeadFirst设计模式', '55.70', '2010-11-09 00:00:00');
INSERT INTO `books` VALUES ('3', '第一行Android代码', '69.90', '2015-06-23 00:00:00');
INSERT INTO `books` VALUES ('4', 'C++编程思想', '88.50', '2004-01-09 00:00:00');
INSERT INTO `books` VALUES ('5', 'HeadFirst Java', '55.70', '2013-12-17 00:00:00');
INSERT INTO `books` VALUES ('6', '疯狂Android', '19.50', '2014-07-31 00:00:00');

需特别注意的是书名是唯一键。

 

三、添加依赖包

项目主要依赖的jar包有Spring核心包、Spring AOP包、MyBatis ORM包、MyBatis-Spring适配包、JSTL、JUnit、Log4j2等,具体的pom.xml文件如下:

 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhangguo</groupId>
<artifactId>BookStore</artifactId>
<version>0.0.1</version>
<packaging>war</packaging> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.0.RELEASE</spring.version>
</properties> <dependencies>
<!--Spring框架核心库 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- aspectJ AOP 织入器 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!--mybatis-spring适配器 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--Spring java数据库访问包,在本例中主要用于提供数据源 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!--log4j日志包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.1</version>
</dependency>
<!-- mybatis ORM框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- JUnit单元测试工具 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<!--c3p0 连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>

如果是第一次依赖相关的包,则需要下载时间,请耐心等待,如果下载失败请手动下载后复制到本地的资源库中。依赖后的项目结果如下:

四、新建POJO实体层

为了实现与数据库中的books表进行关系映射新建一个Book类,具体代码如下:

package com.zhangguo.bookstore.entities;

import java.util.Date;

/**
* 图书实体
*/
public class Book {
/**
* 编号
*/
private int id;
/**
* 书名
*/
private String title;
/**
* 价格
*/
private double price;
/**
* 出版日期
*/
private Date publishDate; public Book(int id, String title, double price, Date publishDate) {
this.id = id;
this.title = title;
this.price = price;
this.publishDate = publishDate;
} public Book() {
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public double getPrice() {
return price;
} public void setPrice(double price) {
this.price = price;
} public Date getPublishDate() {
return publishDate;
} public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
}
 

五、新建MyBatis SQL映射层

这个项目中我们采用接口与xml结束的形式完成关系与对象间的映射,在接口中定义一些数据访问的方法,在xml文件中定义实现数据访问需要的sql脚本。图书数据访问映射接口如下:

 
package com.zhangguo.bookstore.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.zhangguo.bookstore.entities.Book;

/**
* 图书数据访问接口
*/
public interface BookDAO {
/**
* 获得所有图书
*/
public List<Book> getAllBooks();
/**
* 根据图书编号获得图书对象
*/
public Book getBookById(@Param("id") int id);
/**
* 添加图书
*/
public int add(Book entity);
/**
* 根据图书编号删除图书
*/
public int delete(int id);
/**
* 更新图书
*/
public int update(Book entity);
}
 

为MyBatis ORM创建的映射文件BookMapper.xml(命名尽量都遵循一个规则,便于扫描,这里约定以实体名+Mapper)如下:

 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间应该是对应接口的包名+接口名 -->
<mapper namespace="com.zhangguo.bookstore.mapper.BookDAO">
<!--id应该是接口中的方法,结果类型如没有配置别名则应该使用全名称 -->
<!--获得所有图书 -->
<select id="getAllBooks" resultType="Book">
select id,title,price,publishDate from books
</select>
<!--获得图书对象通过编号 -->
<select id="getBookById" resultType="Book">
select id,title,price,publishDate from books where id=#{id}
</select>
<!-- 增加 -->
<insert id="add">
insert into books(title,price,publishDate)
values(#{title},#{price},#{publishDate})
</insert>
<!-- 删除 -->
<delete id="delete">
delete from books where id=#{id}
</delete>
<!-- 更新 -->
<update id="update">
update books set title=#{title},price=#{price},publishDate=#{publishDate}
where id=#{id}
</update>
</mapper>

六、完成Spring整合MyBatis配置

6.1、在源代码的根目录下新建 db.properties文件,用于存放数据库连接信息,文件内容如下:

 
#mysql jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8
jdbc.uid=root
jdbc.pwd=root
 

6.2、在源代码的根目录下新建 applicationContext.xml文件,用于整合MyBatis与Spring,该文件是整个项目的控制中心,非常关键,具体的内容如下:

 
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!--1 引入属性文件,在配置中占位使用 -->
<context:property-placeholder location="classpath*:db.properties" /> <!--2 配置C3P0数据源 -->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!--驱动类名 -->
<property name="driverClass" value="${jdbc.driver}" />
<!-- url -->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 用户名 -->
<property name="user" value="${jdbc.uid}" />
<!-- 密码 -->
<property name="password" value="${jdbc.pwd}" />
<!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
<property name="acquireIncrement" value="5"></property>
<!-- 初始连接池大小 -->
<property name="initialPoolSize" value="10"></property>
<!-- 连接池中连接最小个数 -->
<property name="minPoolSize" value="5"></property>
<!-- 连接池中连接最大个数 -->
<property name="maxPoolSize" value="20"></property>
</bean> <!--3 会话工厂bean sqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="datasource"></property>
<!-- 别名 -->
<property name="typeAliasesPackage" value="com.zhangguo.bookstore.entities"></property>
<!-- sql映射文件路径 -->
<property name="mapperLocations" value="classpath*:com/zhangguo/bookstore/mapper/*Mapper.xml"></property>
</bean> <!--4 自动扫描对象关系映射 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!-- 指定要自动扫描接口的基础包,实现接口 -->
<property name="basePackage" value="com.zhangguo.bookstore.mapper"></property>
</bean> <!--5 声明式事务管理 -->
<!--定义事物管理器,由spring管理事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!--支持注解驱动的事务管理,指定事务管理器 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!--6 容器自动扫描IOC组件 -->
<context:component-scan base-package="com.zhangguo.bookstore"></context:component-scan> <!--7 aspectj支持自动代理实现AOP功能 -->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
 

共有7处配置,第7处配置非必要,另外关于事务管理可以选择AOP拦截式事务管理。

七、创建服务层

创建BookService服务类,完成图书管理业务,有些项目中也叫业务层,这里我们叫服务层,具体实现如下:

 
package com.zhangguo.bookstore.service;

import java.util.List;
import javax.annotation.Resource; import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.mapper.BookDAO; @Service
public class BookService{ @Resource
BookDAO bookdao; public List<Book> getAllBooks() {
return bookdao.getAllBooks();
} public Book getBookById(int id){
return bookdao.getBookById(id);
} public int add(Book entity) throws Exception {
if(entity.getTitle()==null||entity.getTitle().equals("")){
throw new Exception("书名必须不为空");
}
return bookdao.add(entity);
} @Transactional
public int add(Book entity1,Book entityBak){
int rows=0;
rows=bookdao.add(entity1);
rows=bookdao.add(entityBak);
return rows;
} public int delete(int id) {
return bookdao.delete(id);
} /**
* 多删除
*/
public int delete(String[] ids){
int rows=0;
for (String idStr : ids) {
int id=Integer.parseInt(idStr);
rows+=delete(id);
}
return rows;
} public int update(Book entity) {
return bookdao.update(entity);
} }
 

服务层不只是一个dao的接力棒,认为他可有可无,其实是因为我们现在的的示例中没有涉及到更多的复杂业务,所以显得比较空,实现开发可能有更多的业务逻辑要在这里处理。另外给bookdao成员变量注解为自动装配,service类注解为IOC组件。

 

八、JUnit测试服务类

为了确保服务类中的每个方法正确,先使用JUnit进行单元测试,测试代码如下:

 
package com.zhangguo.bookstore.test;

import static org.junit.Assert.*;
import java.util.Date;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.service.BookService; public class TestBookService { static BookService bookservice; @BeforeClass
public static void before(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
bookservice=ctx.getBean(BookService.class);
} @Test
public void testGetAllBooks() {
List<Book> books=bookservice.getAllBooks();
assertNotNull(books);
} @Test
public void testAdd() {
Book entity=new Book(0, "Hibernate 第七版", 78.1, new Date());
try {
assertEquals(1, bookservice.add(entity));
} catch (Exception e) {
e.printStackTrace();
}
} @Test
public void testDeleteInt() {
assertEquals(1, bookservice.delete(9));
} @Test
public void testDeleteStringArray() {
String[] ids={"7","11","12"};
assertEquals(3, bookservice.delete(ids));
} @Test
public void testUpdate() {
Book entity=new Book(7, "Hibernate 第二版", 79.1, new Date());
try {
assertEquals(1, bookservice.update(entity));
} catch (Exception e) {
e.printStackTrace();
}
} @Test
public void testGetBookById()
{
assertNotNull(bookservice.getBookById(1));
} @Test
public void testAddDouble(){
//因为书名相同,添加第二本会失败,用于测试事务
Book entity1=new Book(0, "Hibernate 第八版", 78.1, new Date());
Book entity2=new Book(0, "Hibernate 第八版", 78.1, new Date());
assertEquals(2, bookservice.add(entity1, entity2));
}
}
 

所有的测试均通过,有一个想法就是能否测试完成后数据库还原,如删除的数据在测试后不被真正删除。

 

九、加载Spring容器与获得容器对象

9.1、修改web.xml文件,添加加载Spring容器用的监听器,修改后的结果如下:

 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0" >
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <listener>
<description>Spring容器加载监听器</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<description>设置Spring加载时的配置文件位置,默认位置在web-inf/lib下</description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
</web-app>
 

类org.springframework.web.context.ContextLoaderListener处在Spring-web.jar包中,要记得在pom.xml中添加依赖,测试是否加载成功的简单办法是:重新启动tomcat查看控制信息。

9.2、为了方便获得Spring容器实例,定义一个CtxUtil工具类,工具类的代码如下:

 
package com.zhangguo.bookstore.action;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; /**
* Spring容器上下文工具类,用于获取当前的Spring容器
* 实现了接口ApplicationContextAware且该类被Spring管理
*则会自动调用setApplicationContext方法获取Spring容器对象
*/
@Component
public class CtxUtil implements ApplicationContextAware { public static ApplicationContext ctx; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ctx=applicationContext;
}
/**
* 根据类型获得bean
*/
public static <T> T getBean(Class<T> clazz){
return ctx.getBean(clazz);
}
/**
* 根据名称名称获得bean
*/
public static Object getBean(String name){
return ctx.getBean(name);
} }
 
 

十、简单MVC控制器封装

为了实现一个简单的MVC基础控制器,定义了一个叫BaseController的Servlet,可以让其它的Servlet继承该Servlet获得部分MVC功能,具体代码如下:

 
package com.zhangguo.bookstore.action;

import java.io.IOException;
import java.lang.reflect.*; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* Servlet基类
* 自定义控制器基类
*/
public class BaseController extends HttpServlet {
private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8"); // 获得要执行的方法名
String act = request.getParameter("act"); // 如果用户没有提供方法名
if (act == null || act.equals("")) {
// 默认方法
act = "execute";
} // 根据方法名获得方法信息获得方法信息
Method method;
try {
// 在对象中获得类型信息,在类型中获得方法通过方法名,与参数类型
method = this.getClass().getMethod(act, HttpServletRequest.class, HttpServletResponse.class);
// 调用方法,在当前对象中调用,传递参数request与response,获得返回结果
String targetUri = method.invoke(this, request, response) + "";
// 如果返回的url是以redirect开始,则是重定向
if (targetUri.startsWith("redirect:")) {
response.sendRedirect(targetUri.substring(9, targetUri.length()));
} else {
// 转发
request.getRequestDispatcher(targetUri).forward(request, response);
}
} catch (Exception e) {
response.sendError(400, e.getMessage());
e.printStackTrace();
}
} public void execute(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.sendError(400, "请使用参数act指定您要访问的方法");
}
}
 
 

十一、完成图书管理功能

11.1、定义BookController控制器

该控制器继承BaseController,中间每一个参数为(HttpServletRequest request,HttpServletResponse response)的方法都充当一个Action,代码如下:

 
package com.zhangguo.bookstore.action;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.zhangguo.bookstore.entities.Book;
import com.zhangguo.bookstore.service.BookService; @WebServlet("/BookController.do")
public class BookController extends BaseController {
private static final long serialVersionUID = 1L; BookService bookservice; @Override
public void init() throws ServletException {
bookservice = CtxUtil.getBean(BookService.class);
} // 图书列表Action
public String ListBook(HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("books", bookservice.getAllBooks());
return "ListBook.jsp";
} // 删除图书Action
public String Delete(HttpServletRequest request, HttpServletResponse response) {
int id = Integer.parseInt(request.getParameter("id"));
request.setAttribute("message", bookservice.delete(id) > 0 ? "删除成功!" : "删除失败!");
request.setAttribute("books", bookservice.getAllBooks());
return "ListBook.jsp";
} // 多删除图书Action
public String Deletes(HttpServletRequest request, HttpServletResponse response) {
String[] ids = request.getParameterValues("ids");
if (ids!=null&&ids.length > 0) {
request.setAttribute("message", bookservice.delete(ids) > 0 ? "删除成功!" : "删除失败!");
} else {
request.setAttribute("message", "请选择删除项!");
}
request.setAttribute("books", bookservice.getAllBooks());
return "ListBook.jsp";
} // 添加图书Action
public String AddBook(HttpServletRequest request, HttpServletResponse response) {
return "AddBook.jsp";
} // 保存添加图书Action
public String AddBookPost(HttpServletRequest request, HttpServletResponse response) {
try {
String title = request.getParameter("title");
double price = Double.parseDouble(request.getParameter("price")); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date publishDate = simpleDateFormat.parse(request.getParameter("publishDate")); Book entity = new Book(0, title, price, publishDate);
if (bookservice.add(entity) > 0) {
request.setAttribute("model", new Book());
request.setAttribute("message", "添加成功!");
} else {
request.setAttribute("model", entity);
request.setAttribute("message", "添加失败!");
}
} catch (Exception exp) {
request.setAttribute("message", exp.getMessage());
exp.printStackTrace();
}
return "AddBook.jsp";
} //编辑图书Action
public String EditBook(HttpServletRequest request, HttpServletResponse response) {
int id = Integer.parseInt(request.getParameter("id"));
Book model=bookservice.getBookById(id);
request.setAttribute("model", model);
return "EditBook.jsp";
} // 保存编辑图书Action
public String EditBookPost(HttpServletRequest request, HttpServletResponse response) {
try {
int id=Integer.parseInt(request.getParameter("id")); String title = request.getParameter("title");
double price = Double.parseDouble(request.getParameter("price")); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date publishDate = simpleDateFormat.parse(request.getParameter("publishDate")); Book entity = new Book(id, title, price, publishDate);
request.setAttribute("message", bookservice.update(entity) > 0 ? "更新成功!" : "更新失败!");
request.setAttribute("model", entity);
} catch (Exception exp) {
request.setAttribute("message", exp.getMessage());
exp.printStackTrace();
}
return "EditBook.jsp";
} }

11.2、图书列表与删除

定义视图ListBook.jsp,用于完成图书管理,实现图书的列表、删除与多删除功能,页面脚本如下:

 
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>图书管理</title>
</head>
<body>
<div class="main">
<h2 class="title"><span>图书管理</span></h2>
<form action="BookController.do?act=Deletes" method="post">
<table border="1" width="100%" class="tab">
<tr>
<th><input type="checkbox" id="chbAll"></th>
<th>编号</th>
<th>书名</th>
<th>价格</th>
<th>出版日期</th>
<th>操作</th>
</tr>
<c:forEach var="book" items="${books}">
<tr>
<th><input type="checkbox" name="ids" value="${book.id}"></th>
<td>${book.id}</td>
<td>${book.title}</td>
<td>${book.price}</td>
<td><fmt:formatDate value="${book.publishDate}" pattern="yyyy年MM月dd日"/></td>
<td>
<a href="BookController.do?act=Delete&id=${book.id}" class="abtn">删除</a>
<a href="BookController.do?act=EditBook&id=${book.id}" class="abtn">编辑</a>
</td>
</tr>
</c:forEach>
</table>
<p style="color: red">${message}</p>
<p>
<a href="BookController.do?act=AddBook" class="abtn">添加</a>
<input type="submit" value="删除选择项" class="btn"/>
</p>
</form>
</div>
</body>
</html>
 

运行时效果如下图所示:

11.3、新增图书功能

定义页面AddBook.jsp完成添加图书功能,在控制器中有两个Action对应新增功能,一个是AddBook,完成页面展示;另一个是AddBookPost处理保存事件,页面脚本如下:

 
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>新增图书</title>
</head>
<body>
<div class="main">
<h2 class="title"><span>新增图书</span></h2>
<form action="BookController.do?act=AddBookPost" method="post">
<fieldset>
<legend>图书</legend>
<p>
<label for="title">图书名称:</label>
<input type="text" id="title" name="title" value="${model.title}"/>
</p>
<p>
<label for="title">图书价格:</label>
<input type="text" id="price" name="price" value="${model.price}"/>
</p>
<p>
<label for="title">出版日期:</label>
<input type="text" id="publishDate" name="publishDate" value="${model.publishDate}"/>
</p>
<p>
<input type="submit" value="保存" class="btn">
</p>
</fieldset>
</form>
<p style="color: red">${message}</p>
<p>
<a href="BookController.do?act=ListBook" class="abtn">返回列表</a>
</p>
</div>
</body>
</html>
 

运行成功时的状态如下:

11.4、编辑图书功能

定义页面EditBook.jsp完成更新图书功能,在控制器中有两个Action对应更新功能,一个是EditBook,完成页面展示与加载要编辑图书实体的信息;另一个是EditBookPost处理保存事件,页面脚本如下:

 
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="styles/main.css" type="text/css" rel="stylesheet" />
<title>编辑图书</title>
</head>
<body>
<div class="main">
<h2 class="title"><span>编辑图书</span></h2>
<form action="BookController.do?act=EditBookPost" method="post">
<fieldset>
<legend>图书</legend>
<p>
<label for="title">图书名称:</label>
<input type="text" id="title" name="title" value="${model.title}"/>
</p>
<p>
<label for="title">图书价格:</label>
<input type="text" id="price" name="price" value="${model.price}"/>
</p>
<p>
<label for="title">出版日期:</label>
<input type="text" id="publishDate" name="publishDate" value="<fmt:formatDate value="${model.publishDate}" pattern="yyyy-MM-dd"/>"/>
</p>
<p>
<input type="hidden" id="id" name="id" value="${model.id}"/>
<input type="submit" value="保存" class="btn">
</p>
</fieldset>
</form>
<p style="color: red">${message}</p>
<p>
<a href="BookController.do?act=ListBook" class="abtn">返回列表</a>
</p>
</div>
</body>
</html>
 

运行时的状态如下所示:

 

11.5、首页与样式

定义index.jsp页面,让其转发到指定的控制器(有点类似路由功能了),页面代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<jsp:forward page="BookController.do?act=ListBook"></jsp:forward>

定义了一个简陋的样式main.css,样式表脚本如下:

 
@CHARSET "UTF-8";

* {
margin: 0;
padding: 0;
font-family: microsoft yahei;
font-size: 14px;
} body {
padding-top: 20px;
} .main {
width: 90%;
margin: 0 auto;
border: 1px solid #777;
padding: 20px;
} .main .title {
font-size: 20px;
font-weight: normal;
border-bottom: 1px solid #ccc;
margin-bottom: 15px;
padding-bottom: 5px;
color: blue;
} .main .title span {
display: inline-block;
font-size: 20px;
background : blue;
color: #fff;
padding: 0 8px;
background: blue;
} a {
color: blue;
text-decoration: none;
} a:hover {
color: orangered;
} .tab td, .tab, .tab th {
border: 1px solid #777;
border-collapse: collapse;
} .tab td, .tab th {
line-height: 26px;
height: 26px;
padding-left: 5px;
} .abtn {
display: inline-block;
height: 20px;
line-height: 20px;
background: blue;
color: #fff;
padding: 0 5px;
}
.btn {
height: 20px;
line-height: 20px;
background: blue;
color: #fff;
padding: 0 8px;
border:0;
} .abtn:hover,.btn:hover{
background: orangered;
color: #fff;
}
p{
padding:5px 0;
}
fieldset{
border: 1px solid #ccc;
padding:5px 10px;
}
fieldset legend{
margin-left:10px;
font-size:16px;
}
 
 

十二、总结与示例下载

这个Demo起到了承前启后的作用,通过该示例将前面学习过的Spring IOC、MyBatis、JSP、Servlet、Maven及Spring整合MyBatis的内容进行巩固,也为后面学习Spring MVC作好了铺垫

demo

1. IDEA,出现 invalid bound statement (not found)解决办法

<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

2. 新建的IDEA工程,没有JUnit,要在Project Setting 增加 Junit

3.创建一个新的Maven Web工程,然后倒入相关的java和resources代码

4.注意配置文件的路径

5. 关于maven的配置文件,如果公司有私服,使用公司的私服,没有的话,就设置阿里云的镜像,加快maven jar包的下载

最新文章

  1. jQuery插件 -- Cookie插件jquery.cookie.js(转)
  2. Incorrect string value: &#39;\xF0\x90\x8D\x83...&#39; for column 通用解决方案
  3. 微信公众账号开发教程(三) 实例入门:机器人(附源码) ——转自http://www.cnblogs.com/yank/p/3409308.html
  4. oracle参数与启停
  5. 更改nginx网站根目录
  6. Linux编辑器的选择使用
  7. 模板类-bitset
  8. Java基础-异常、断言
  9. 分布式系列十五: MongoDB数据库
  10. oracle 11.2.0.4 rac 修改 ip vip scan ip
  11. svg常见形状
  12. 标签页(tab)切换的原生js,jquery和bootstrap实现
  13. Java基础知识(JAVA之IO流)
  14. 解决Ecipse和搜狗输入法快捷键冲突问题
  15. maven中properties标签定义变量
  16. mysql的Navicat查看数据库的ER图
  17. linux tar 命令
  18. am335x USB 驱动框架记录
  19. MySQL 中文乱码解决
  20. HDU 2485 Destroying the bus stations(!最大流∩!费用流∩搜索)

热门文章

  1. Python之Flask框架一
  2. 如何为Form表单的多个提交按钮指定不同的Action地址?
  3. 技术大佬:我去,这个容易被忽略的小程序Image图片属性,竟然这么屌!
  4. 《腾讯网UED体验设计之旅》读后感
  5. [JavaWeb基础] 031.dom4j写入xml的方法
  6. HTML转义字符&amp;url编码表
  7. MySql轻松入门系列————第一站 从源码角度轻松认识mysql整体框架图
  8. 带你学够浪:Go语言基础系列-环境配置和 Hello world
  9. HTML元素跟随鼠标一起移动,网页中回到顶部按钮的实现
  10. C# Winform 学习(四)