0%

SSM整合搭建

预备条件

项目结构

image-20210528182518627

建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
create database `BookSale`;
use `BookSale`;

create table `books`(
bookID int NOT NULL AUTO_INCREMENT primary key ,
bookName varchar(20),
bookCounts int,
detail text(100)
)engine innodb default charset=utf8;

insert into books (bookName, bookCounts, detail)
values ('Java',1,'从入门到放弃'),
('MySQL',10,'从删库到跑路'),
('Linux',5,'从进门到进牢');

导包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<dependencies>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
<!--数据库连接池:c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

<!--servlet,jsp,jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>

<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.19.RELEASE</version>
</dependency>

<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>

静态资源过滤

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

Mybatis层

database.properties

1
2
3
4
5
driver=com.mysql.jdbc.Driver
# MySQL8.0以上需要添加时区配置:&serverTimezone=Asia/Shanghai
url=jdbc:mysql://localhost:3306/booksale?useUnicode=true&characterEncoding=utf-8
username=root
password=123456

实体类Books.java

1
2
3
4
5
6
7
8
9
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}

BookMapper.java

1
2
3
4
5
6
7
8
public interface BookMapper {
int addBook(Books books);
int deleteBookById(@Param("bookId") int id);
int updateBook(Books books);
Books queryBookById(@Param("bookId") int id);
List<Books> queryAllBook();
List<Books> queryBookByName(String bookName);
}

BookMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lan5th.dao.BookMapper">
<insert id="addBook" parameterType="Books">
insert into `books` (bookName,bookCounts,detail)
values (#{bookName},#{bookCounts},#{detail});
</insert>

<delete id="deleteBookById" parameterType="int">
delete from `books` where bookID = #{bookId};
</delete>

<update id="updateBook" parameterType="Books">
update `books`
set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail}
where bookID=#{bookID};
</update>

<select id="queryBookById" resultType="Books">
select * from `books` where bookID=#{bookId};
</select>

<select id="queryAllBook" resultType="Books">
select * from `books`;
</select>

<select id="queryBookByName" resultType="Books">
select * from `books` where bookName like #{bookName};
</select>
</mapper>

BookService.java

1
2
3
4
5
6
7
8
public interface BookService {
public int addBook(Books books);
public int deleteBookById(int id);
public int updateBook(Books books);
public Books queryBookById(int id);
public List<Books> queryAllBook();
public List<Books> queryBookByName(String name);
}

BookServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Service("BookServiceImpl")
public class BookServiceImpl implements BookService{
private BookMapper bookMapper;

public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}

public int addBook(Books books) {
return bookMapper.addBook(books);
}

public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}

public int updateBook(Books books) {
return bookMapper.updateBook(books);
}

public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}

public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}

public List<Books> queryBookByName(String name) {
//添加模糊查询标志
name = "%" + name + "%";
return bookMapper.queryBookByName(name);
}
}

mybatis配置文件mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--日志-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

<!--别名-->
<typeAliases>
<package name="com.lan5th.pojo"/>
</typeAliases>

<mappers>
<mapper class="com.lan5th.dao.BookMapper"/>
</mappers>
</configuration>

Spring层

spring-dao.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>

<!--连接池
dbcp:半自动化,不能自动连接
c3p0:自动化的加载配置文件,可以自动设置到对象中
druid:整合Springboot使用
hikari:Springboot默认使用
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--c3p0私有属性-->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!--关闭链结构不自动commit-->
<property name="autoCommitOnClose" value="false"/>
<!--获取链接超时时间-->
<property name="checkoutTimeout" value="10000"/>
<!--获取链接失败重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>

<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>

<!--配置dao接口扫描包,动态实现dao接口注入-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注意ByName是value而不是ref-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.lan5th.dao"/>
</bean>
</beans>

spring-service.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--扫描包-->
<context:component-scan base-package="com.lan5th.service"/>

<!--业务类注入,可以使用配置或注解实现,这里使用配置-->
<bean id="bookServiceImpl" class="com.lan5th.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>

<!--声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<!--aop事务支持-->
</beans>

SpringMVC层

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>springmvc</servlet-name>\
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--需要绑定spring配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--
/:匹配所有请求,不包括jsp
/*:匹配所有请求,包括jsp-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!--乱码过滤-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!--session-->
<session-config>
<session-timeout>155</session-timeout>
</session-config>
</web-app>

springmvc.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<!--1.注解驱动-->
<mvc:annotation-driven/>
<!--2.静态资源过滤-->
<mvc:default-servlet-handler/>
<!--3.扫描包:controller-->
<context:component-scan base-package="com.lan5th.controller"/>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="springmvc.xml"/>
</beans>

业务实现

BookController.java

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
@Qualifier("bookServiceImpl")
private BookService bookService;

//...业务方法
}

查询功能

1
2
3
4
5
6
7
//查询全部书籍
@RequestMapping("/allBookP")
public String allBook(Model model){
List<Books> books = bookService.queryAllBook();
model.addAttribute("books",books);
return "allBook";
}

全部书籍页面allBook.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>全部书籍</title>
<!--BootStrap美化界面-->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>书籍列表</small>
</h1>
</div>
</div>
<div class="col-md-4 column">
<!--新增书籍-->
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/addBookP">新增书籍</a>
</div>
<div class="col-md-4 column">
<span style="color: red">${error}</span>
</div>
<div class="col-md-4 column form-inline">
<!--查询书籍-->
<form action="${pageContext.request.contextPath}/book/queryBookName" method="post" style="float: right">
<input type="text" name="bookName" class="form-control" placeholder="请输入查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>书籍编号</th>
<th>书籍名称</th>
<th>书籍数量</th>
<th>书记详情</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="book" items="${books}">
<tr>
<td>${book.bookID}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<td>
<a href="${pageContext.request.contextPath}/book/updateBookP?id=${book.bookID}" >修改</a>
|
<!--delete方法以RestFul风格编写-->
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

添加功能

1
2
3
4
5
6
7
8
9
10
11
12
//跳转添加书籍页面
@RequestMapping("/addBookP")
public String addBookPage(Model model){
return "addBook";
}

//添加书籍业务
@RequestMapping("/addBook")
public String addBook(Books books){
bookService.addBook(books);
return "redirect:/book/allBookP";
}

添加书籍页面addBook.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改书籍</title>
<!--BootStrap美化界面-->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/updateBook" method="post">
<!--前端需要隐式传递id,否则Controller无法执行updateBook方法-->
<input type="hidden" name="bookID" value="${book.bookID}">
<div class="form-group">
<label for="bkname">书籍名称:</label>
<input type="text" name="bookName" class="form-control" id="bkname" value="${book.bookName}" required>
</div>
<div class="form-group">
<label for="bkcount">书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" id="bkcount" value="${book.bookCounts}" required>
</div>
<div class="form-group">
<label for="bkdetail">书籍描述:</label>
<input type="text" name="detail" class="form-control" id="bkdetail" value="${book.detail}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>

修改/删除功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//跳转更新书籍页面
@RequestMapping("/updateBookP")
public String updateBookPage(int id, Model model){
Books books = bookService.queryBookById(id);
//给前端传递书原本的属性,以方便修改
model.addAttribute("book",books);
return "updateBook";
}

//更新书籍业务
@RequestMapping("/updateBook")
public String updateBook(Books books, Model model){
bookService.updateBook(books);
return "redirect:/book/allBookP";
}

//delete方法以RestFul风格编写
@RequestMapping("/deleteBook/{bookId}")
public String deleteBook(@PathVariable("bookId") int id){
bookService.deleteBookById(id);
return "redirect:/book/allBookP";
}

更新书籍页面updateBook.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改书籍</title>
<!--BootStrap美化界面-->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/updateBook" method="post">
<!--前端需要隐式传递id,否则Controller无法执行updateBook方法-->
<input type="hidden" name="bookID" value="${book.bookID}">
<div class="form-group">
<label for="bkname">书籍名称:</label>
<input type="text" name="bookName" class="form-control" id="bkname" value="${book.bookName}" required>
</div>
<div class="form-group">
<label for="bkcount">书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" id="bkcount" value="${book.bookCounts}" required>
</div>
<div class="form-group">
<label for="bkdetail">书籍描述:</label>
<input type="text" name="detail" class="form-control" id="bkdetail" value="${book.detail}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>

搜索查询功能实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//按名搜索查询功能实现
@RequestMapping("/queryBookName")
public String queryBookName(String bookName, Model model){
List<Books> books = null;
//模糊查询,空字符串查询全部内容
books = bookService.queryBookByName(bookName);
//判断列表是否为空,给前端传递错误信息
if (books.isEmpty()){
model.addAttribute("error","未查到指定书名!");
} else {
model.addAttribute("books",books);
}
return "allBook";
}

页面效果展示

首页

image-20210529202905441

全部书籍页面

image-20210529202939763

新增书籍页面

image-20210529203006891

修改书籍页面

image-20210529203043369

查询失败页面

image-20210529203118477

实际排错思路

image-20210529103625931