Spring学习总结(六)——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>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">properties</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">project.build.sourceEncoding</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>UTF-8<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">project.build.sourceEncoding</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">spring.version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>4.3.0.RELEASE<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">spring.version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">properties</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">Spring框架核心库 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-context<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>${spring.version}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> aspectJ AOP 织入器 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.aspectj<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>aspectjweaver<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>1.8.9<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> Spring Web </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-web<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>${spring.version}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">mybatis-spring适配器 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.mybatis<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>mybatis-spring<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>1.3.0<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">Spring java数据库访问包,在本例中主要用于提供数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>spring-jdbc<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>${spring.version}<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">mysql数据库驱动 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>mysql<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>mysql-connector-java<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>5.1.38<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">log4j日志包 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.apache.logging.log4j<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>log4j-core<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>2.6.1<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> mybatis ORM框架 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.mybatis<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>mybatis<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>3.4.1<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> JUnit单元测试工具 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>junit<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>junit<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>4.10<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">c3p0 连接池 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>c3p0<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>c3p0<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>0.9.1.2<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> jstl </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>javax.servlet<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">groupId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>jstl<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">artifactId</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>1.2<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">version</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependency</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">dependencies</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</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">
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">1 引入属性文件,在配置中占位使用 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">context:property-placeholder </span><span style="color: rgba(255, 0, 0, 1)">location</span><span style="color: rgba(0, 0, 255, 1)">="classpath*:db.properties"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">2 配置C3P0数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="datasource"</span><span style="color: rgba(255, 0, 0, 1)"> class</span><span style="color: rgba(0, 0, 255, 1)">="com.mchange.v2.c3p0.ComboPooledDataSource"</span><span style="color: rgba(255, 0, 0, 1)"> destroy-method</span><span style="color: rgba(0, 0, 255, 1)">="close"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">驱动类名 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="driverClass"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="${jdbc.driver}"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> url </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="jdbcUrl"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="${jdbc.url}"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 用户名 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="user"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="${jdbc.uid}"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 密码 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="password"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="${jdbc.pwd}"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数  </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="acquireIncrement"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="5"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 初始连接池大小 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="initialPoolSize"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="10"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 连接池中连接最小个数 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="minPoolSize"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="5"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 连接池中连接最大个数 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="maxPoolSize"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="20"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">bean</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">3 会话工厂bean sqlSessionFactoryBean </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="sqlSessionFactory"</span><span style="color: rgba(255, 0, 0, 1)"> class</span><span style="color: rgba(0, 0, 255, 1)">="org.mybatis.spring.SqlSessionFactoryBean"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 数据源 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="dataSource"</span><span style="color: rgba(255, 0, 0, 1)"> ref</span><span style="color: rgba(0, 0, 255, 1)">="datasource"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 别名 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="typeAliasesPackage"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.bookstore.entities"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> sql映射文件路径 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="mapperLocations"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="classpath*:com/zhangguo/bookstore/mapper/*Mapper.xml"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">bean</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">4 自动扫描对象关系映射 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="org.mybatis.spring.mapper.MapperScannerConfigurer"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="sqlSessionFactoryBeanName"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="sqlSessionFactory"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 指定要自动扫描接口的基础包,实现接口 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="basePackage"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.bookstore.mapper"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">bean</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">5 声明式事务管理 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">定义事物管理器,由spring管理事务 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">bean </span><span style="color: rgba(255, 0, 0, 1)">id</span><span style="color: rgba(0, 0, 255, 1)">="transactionManager"</span><span style="color: rgba(255, 0, 0, 1)"> class</span><span style="color: rgba(0, 0, 255, 1)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="dataSource"</span><span style="color: rgba(255, 0, 0, 1)"> ref</span><span style="color: rgba(0, 0, 255, 1)">="datasource"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">property</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">bean</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">支持注解驱动的事务管理,指定事务管理器 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tx:annotation-driven </span><span style="color: rgba(255, 0, 0, 1)">transaction-manager</span><span style="color: rgba(0, 0, 255, 1)">="transactionManager"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">6 容器自动扫描IOC组件  </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">context:component-scan </span><span style="color: rgba(255, 0, 0, 1)">base-package</span><span style="color: rgba(0, 0, 255, 1)">="com.zhangguo.bookstore"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">context:component-scan</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)">7 aspectj支持自动代理实现AOP功能 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">aop:aspectj-autoproxy </span><span style="color: rgba(255, 0, 0, 1)">proxy-target-class</span><span style="color: rgba(0, 0, 255, 1)">="true"</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">aop:aspectj-autoproxy</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</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;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> List&lt;Book&gt;<span style="color: rgba(0, 0, 0, 1)"> getAllBooks() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bookdao.getAllBooks();
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> Book getBookById(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bookdao.getBookById(id);
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> add(Book entity) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(entity.getTitle()==<span style="color: rgba(0, 0, 255, 1)">null</span>||entity.getTitle().equals(""<span style="color: rgba(0, 0, 0, 1)">)){
        </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Exception("书名必须不为空"<span style="color: rgba(0, 0, 0, 1)">);
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bookdao.add(entity);
}

@Transactional
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> add(Book entity1,Book entityBak){
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> rows=0<span style="color: rgba(0, 0, 0, 1)">;
    rows</span>=<span style="color: rgba(0, 0, 0, 1)">bookdao.add(entity1);
    rows</span>=<span style="color: rgba(0, 0, 0, 1)">bookdao.add(entityBak);
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> rows;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span> delete(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> id) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> bookdao.delete(id);
}

</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 多删除
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> delete(String[] ids){
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> rows=0<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (String idStr : ids) {
        </span><span style="color: rgba(0, 0, 255, 1)">int</span> id=<span style="color: rgba(0, 0, 0, 1)">Integer.parseInt(idStr);
        rows</span>+=<span style="color: rgba(0, 0, 0, 1)">delete(id);
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> rows;
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> update(Book entity) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> 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 {

</span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> BookService bookservice;

@BeforeClass
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> before(){
    ApplicationContext ctx</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> ClassPathXmlApplicationContext("applicationContext.xml"<span style="color: rgba(0, 0, 0, 1)">);
    bookservice</span>=ctx.getBean(BookService.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testGetAllBooks() {
    List</span>&lt;Book&gt; books=<span style="color: rgba(0, 0, 0, 1)">bookservice.getAllBooks();
    assertNotNull(books);
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testAdd() {
    Book entity</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Book(0, "Hibernate 第七版", 78.1, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        assertEquals(</span>1<span style="color: rgba(0, 0, 0, 1)">, bookservice.add(entity));
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
        e.printStackTrace();
    }
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testDeleteInt() {
    assertEquals(</span>1, bookservice.delete(9<span style="color: rgba(0, 0, 0, 1)">));
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testDeleteStringArray() {
    String[] ids</span>={"7","11","12"<span style="color: rgba(0, 0, 0, 1)">};
    assertEquals(</span>3<span style="color: rgba(0, 0, 0, 1)">, bookservice.delete(ids));
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testUpdate() {
    Book entity</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Book(7, "Hibernate 第二版", 79.1, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        assertEquals(</span>1<span style="color: rgba(0, 0, 0, 1)">, bookservice.update(entity));
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
        e.printStackTrace();
    }
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testGetBookById()
{
    assertNotNull(bookservice.getBookById(</span>1<span style="color: rgba(0, 0, 0, 1)">));
}

@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testAddDouble(){
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">因为书名相同,添加第二本会失败,用于测试事务</span>
    Book entity1=<span style="color: rgba(0, 0, 255, 1)">new</span> Book(0, "Hibernate 第八版", 78.1, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
    Book entity2</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> Book(0, "Hibernate 第八版", 78.1, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
    assertEquals(</span>2<span style="color: rgba(0, 0, 0, 1)">, 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>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">listener</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>Spring容器加载监听器<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">listener-class</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>org.springframework.web.context.ContextLoaderListener<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">listener-class</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">listener</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">context-param</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>设置Spring加载时的配置文件位置,默认位置在web-inf/lib下<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">description</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">param-name</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>contextConfigLocation<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">param-name</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">param-value</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>classpath*:applicationContext.xml<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">param-value</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">context-param</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</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");

     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获得要执行的方法名</span>
     String act = request.getParameter("act"<span style="color: rgba(0, 0, 0, 1)">);
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果用户没有提供方法名</span>
     <span style="color: rgba(0, 0, 255, 1)">if</span> (act == <span style="color: rgba(0, 0, 255, 1)">null</span> || act.equals(""<span style="color: rgba(0, 0, 0, 1)">)) {
         </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 默认方法</span>
         act = "execute"<span style="color: rgba(0, 0, 0, 1)">;
     }
    
     </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据方法名获得方法信息获得方法信息</span>
    

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();
}
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> execute(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException {
    response.sendError(</span>400, "请使用参数act指定您要访问的方法"<span style="color: rgba(0, 0, 0, 1)">);
}

}

十一、完成图书管理功能

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
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> init() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException {
    bookservice </span>= CtxUtil.getBean(BookService.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 图书列表Action</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String ListBook(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute(</span>"books"<span style="color: rgba(0, 0, 0, 1)">, bookservice.getAllBooks());
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "ListBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 删除图书Action</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String Delete(HttpServletRequest request, HttpServletResponse response) {
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> id = Integer.parseInt(request.getParameter("id"<span style="color: rgba(0, 0, 0, 1)">));
    request.setAttribute(</span>"message", bookservice.delete(id) &gt; 0 ? "删除成功!" : "删除失败!"<span style="color: rgba(0, 0, 0, 1)">);
    request.setAttribute(</span>"books"<span style="color: rgba(0, 0, 0, 1)">, bookservice.getAllBooks());
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "ListBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 多删除图书Action</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String Deletes(HttpServletRequest request, HttpServletResponse response) {
    String[] ids </span>= request.getParameterValues("ids"<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (ids!=<span style="color: rgba(0, 0, 255, 1)">null</span>&amp;&amp;ids.length &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
        request.setAttribute(</span>"message", bookservice.delete(ids) &gt; 0 ? "删除成功!" : "删除失败!"<span style="color: rgba(0, 0, 0, 1)">);
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        request.setAttribute(</span>"message", "请选择删除项!"<span style="color: rgba(0, 0, 0, 1)">);
    }
    request.setAttribute(</span>"books"<span style="color: rgba(0, 0, 0, 1)">, bookservice.getAllBooks());
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "ListBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 添加图书Action</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String AddBook(HttpServletRequest request, HttpServletResponse response) {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "AddBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 保存添加图书Action</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String AddBookPost(HttpServletRequest request, HttpServletResponse response) {
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        String title </span>= request.getParameter("title"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 0, 255, 1)">double</span> price = Double.parseDouble(request.getParameter("price"<span style="color: rgba(0, 0, 0, 1)">));

        SimpleDateFormat simpleDateFormat </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleDateFormat("yyyy-MM-dd"<span style="color: rgba(0, 0, 0, 1)">);
        Date publishDate </span>= simpleDateFormat.parse(request.getParameter("publishDate"<span style="color: rgba(0, 0, 0, 1)">));

        Book entity </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Book(0<span style="color: rgba(0, 0, 0, 1)">, title, price, publishDate);
        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (bookservice.add(entity) &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
            request.setAttribute(</span>"model", <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Book());
            request.setAttribute(</span>"message", "添加成功!"<span style="color: rgba(0, 0, 0, 1)">);
        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            request.setAttribute(</span>"model"<span style="color: rgba(0, 0, 0, 1)">, entity);
            request.setAttribute(</span>"message", "添加失败!"<span style="color: rgba(0, 0, 0, 1)">);
        }
    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception exp) {
        request.setAttribute(</span>"message"<span style="color: rgba(0, 0, 0, 1)">, exp.getMessage());
        exp.printStackTrace();
    }
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> "AddBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
}

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">编辑图书Action</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String EditBook(HttpServletRequest request, HttpServletResponse response) {
        </span><span style="color: rgba(0, 0, 255, 1)">int</span> id = Integer.parseInt(request.getParameter("id"<span style="color: rgba(0, 0, 0, 1)">));
        Book model</span>=<span style="color: rgba(0, 0, 0, 1)">bookservice.getBookById(id);
        request.setAttribute(</span>"model"<span style="color: rgba(0, 0, 0, 1)">, model);
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> "EditBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 保存编辑图书Action</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String EditBookPost(HttpServletRequest request, HttpServletResponse response) {
        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> id=Integer.parseInt(request.getParameter("id"<span style="color: rgba(0, 0, 0, 1)">));
            
            String title </span>= request.getParameter("title"<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">double</span> price = Double.parseDouble(request.getParameter("price"<span style="color: rgba(0, 0, 0, 1)">));

            SimpleDateFormat simpleDateFormat </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleDateFormat("yyyy-MM-dd"<span style="color: rgba(0, 0, 0, 1)">);
            Date publishDate </span>= simpleDateFormat.parse(request.getParameter("publishDate"<span style="color: rgba(0, 0, 0, 1)">));

            Book entity </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Book(id, title, price, publishDate);
            request.setAttribute(</span>"message", bookservice.update(entity) &gt; 0 ? "更新成功!" : "更新失败!"<span style="color: rgba(0, 0, 0, 1)">);
            request.setAttribute(</span>"model"<span style="color: rgba(0, 0, 0, 1)">, entity);
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception exp) {
            request.setAttribute(</span>"message"<span style="color: rgba(0, 0, 0, 1)">, exp.getMessage());
            exp.printStackTrace();
        }
        </span><span style="color: rgba(0, 0, 255, 1)">return</span> "EditBook.jsp"<span style="color: rgba(0, 0, 0, 1)">;
    }

}

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 作好了铺垫。示例中隐约的实现了一些 MVC 的功能,这远远不够,在 URL 的处理、表单验证、自动映射表单等方面还可以完善,只想有一个抛砖引玉的作用就满意了,谢谢您的阅读,谢谢!

示例下载

github 下载与预览