写在前面:为了应付面试,前几天刚刚完SSM框架黑马的全部的视频,并且做了笔记,最后还跟视频着做了SSM的整合小案例,说实话这玩意然我觉得只学了个大概,感觉的还在后头,于是想多学着做几个小demo,然后自己做一个项目带去面试,在B站上面学了kuang神的SSM整合案例,觉得讲的还不错,当然自己敲的时候从中还遇到很多的问题,特来记录一下。
实现一个书籍的管理系统,可以实现对书籍进行增删改的操作。
IDEA
MySQL 5.7
Tomcat 8.5
Maven 3.6
要求:需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单的前端知识;
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名', -- COMMENT 给字段名注释
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
上面三个注解的作用可以直接生成我们常用的实体类方法,但是需要导入
<!--导入Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--Servlet - JSP -->
<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.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--导入Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!--添加事务-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
</dependencies>
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
mybatis-config.xml
<?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>
</configuration>
准备数据库配置文件
编写mybatis-config.xml
<!--为pojo类取别名-->
<typeAliases>
<package name="com.liuzeyu.pojo"/>
</typeAliases>
<!--直接映射到扫描的接口包-->
<mappers>
<package name="com.liuzeyu.dao"/>
</mappers>
public interface BookMapper {
//增加一个Book
void addBook(Books books);
//根据id删除一个book
void deleteBookById(@Param("bookId") int id);
//更新Booke
int updateBook(Books books);
//根据id查询
Books queryBookById(@Param("bookId") int id);
//查询全部
List<Books> findAll();
//根据名称模糊查询
List<Books> queryBook(@Param("bookName") String name);
}
<?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.liuzeyu.dao.BookMapper">
<!--新增books-->
<select id="addBook" parameterType="books">
insert into books(bookName,bookCounts,detail) values(#{bookName},#{bookCounts},#{detail});
</select>
<!--根据id删除books-->
<delete id="deleteBookById" parameterType="INT">
delete from ssmbuild.books where bookID = #{bookId};
</delete>
<!--更新books-->
<update id="updateBook" parameterType="books">
update books set bookName = #{bookName},bookCounts=#{bookCounts},detail=#{detail} where bookID=#{bookID};
</update>
<!--根据id查询-->
<select id="queryBookById" parameterType="INT" resultType="books">
select * from books where bookId=#{bookId};
</select>
<!--查询全部-->
<select id="findAll" resultType="Books">
select * from books;
</select>
<!--根据名称模糊查询-->
<select id="queryBook" resultType="Books">
select * from books where bookName LIKE #{bookName};
</select>
</mapper>
其中@Param就是为了和接口的配置文件中的变量做映射的关系
public interface BookService {
//增加一个Book
void addBook(Books books);
//根据id删除一个book
void deleteBookById(int id);
//更新Booke
int updateBook(Books books);
//根据id查询
Books queryBookById(int id);
//查询全部
List<Books> findAll();
//根据名称模糊查询
List<Books> queryBook(String name);
}
public class BookServiceImpl implements BookService{
private BookMapper bookMapper = null;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public void addBook(Books books) {
bookMapper.addBook(books);
}
public void deleteBookById(int id) {
bookMapper.deleteBookById(id);
}
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
public Books queryBookById(int id) {
Books books = bookMapper.queryBookById(id);
return books;
}
public List<Books> findAll() {
List<Books> booksList = bookMapper.findAll();
return booksList;
}
public List<Books> queryBook(String name) {
return bookMapper.queryBook(name);
}
}
OK,到此处我们持久层和业务层的代码编写告一段落。
在resources下准备spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--配置spring整合mybatis,这里的数据源使用c3p0-->
<!--1. 加载数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>
<!--2. 配置数据库连接-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver}"/>
<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>
<!--3. 配置SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--指定mybatis全局配置文件(指定非spring的配置文件)-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--配置扫描dao的接口包,动态实现dao(动态代理dao)接口注入到IOC容器中-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--给出要扫描的dao包-->
<property name="basePackage" value="com.liuzeyu.dao"/>
</bean>
</beans>
在resources下准备spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" 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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--1. 扫描service相关的bean-->
<context:component-scan base-package="com.liuzeyu.service"/>
<!--2. BookServiceImpl注入到IOC容器-->
<bean id="bookService" class="com.liuzeyu.service.impl.BookServiceImpl">
<!--扫描到spring-dao将接口加入到容器中,ref从容器中取出-->
<property name="bookMapper" ref="bookMapper"></property>
</bean>
<!--3. 配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据库连接池-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--添加aop的事务的织入:横切service层-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<tx:attributes>
<!-- read-only:用于指定事务是否只读,通常查询方法设置为只读
propagation:指定事务的传播行为,默认值为REQUIRED用于增删改,SUPPORT用于查询-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务的切入-->
<aop:config>
<aop:pointcut id="txPoint" expression="execution(* com.liuzeyu.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>
</beans>
<?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_3_1.xsd"
version="3.1">
<!--添加前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置启动加载的配置文件,注意这里加载主配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置处理请求乱码-->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*
15
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置springmvc-->
<!--1. 开启springmvc注解驱动-->
<mvc:annotation-driven/>
<!--2. 静态资源默认servlet配置-->
<mvc:default-servlet-handler/>
<!--3. 配置jsp显示的视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4. 扫描web相关的bean-->
<context:component-scan base-package="com.liuzeyu.controller"/>
</beans>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:spring-mvc.xml"/>
</beans>
整合先告一段落。
@Controller
@RequestMapping("/books") //父目录
public class BookController {
@Autowired //自动装配BookService
private BookService bookService = null;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>$Title$</title>
<style>
a{
text-decoration: none;
color: black;
font-size: 18px;
}
h3{
width: 180px;
height: 40px;
text-align: center;
margin: 100px auto;
line-height: 40px;
background: deepskyblue;
border-radius: 4px;
}
</style>
</head>
<body>
<h3>
<a href="books/allBooks">展示所有书籍</a>
</h3>
</body>
</html>
/**
* 处理展示所有书籍
* @param model
* @return
*/
@RequestMapping("allBooks")
public String list(Model model){
List<Books> list = bookService.findAll();
System.out.println(list);
model.addAttribute("list",list);
return "allBooks";
}
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 14:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
<%--引入bootstrap的cdn--%>
<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">
<h2>
<small>书籍列表 —— 显示所有书籍</small>
</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a href="/addBook.jsp" class="btn btn-primary pull-right">新增</a>
<span>
<form action="/books/queryBook" method="post">
<input type="text" name="bookName" placeholder="书籍名称">
<input type="submit" value="搜索">
</form>
</span>
<a href="/books/allBooks" class="btn btn-primary pull-right">显示全部</a>
<span style="color: red">${nill}</span>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12"></div>
<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="${list}">
<tr>
<td>${book.getBookID()}</td>
<td>${book.getBookName()}</td>
<td>${book.getBookCounts()}</td>
<td>${book.getDetail()}</td>
<td>
<a href="/books/query/${book.bookID}" class="button">修改</a>
<a href="/books/deleteBook/${book.bookID}" class="button">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</body>
</html>
使用JSTL与EL语法来展示数据。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 14:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
<%--引入bootstrap的cdn--%>
<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">
<h2>
<small>书籍列表 —— 显示所有书籍</small>
</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a href="/addBook.jsp" class="btn btn-primary pull-right">新增</a>
<span>
<form action="/books/queryBook" method="post">
<input type="text" name="bookName" placeholder="书籍名称">
<input type="submit" value="搜索">
</form>
</span>
<a href="/books/allBooks" class="btn btn-primary pull-right">显示全部</a>
<span style="color: red">${nill}</span>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12"></div>
<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="${list}">
<tr>
<td>${book.getBookID()}</td>
<td>${book.getBookName()}</td>
<td>${book.getBookCounts()}</td>
<td>${book.getDetail()}</td>
<td>
<a href="/books/query/${book.bookID}" class="button">修改</a>
<a href="/books/deleteBook/${book.bookID}" class="button">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</body>
</html>
/**
* 处理保存书籍
* @param books
* @return
*/
@RequestMapping("addBook")
public String save(Books books){
bookService.addBook(books);
return "redirect:allBooks";
//写成redirect:/books/allBooks可以,写成redirect:books/allBooks就不行
//allBooks是相对路径
//写成redirect:/books/allBooks是绝对路径
}
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 14:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
<%--引入bootstrap的cdn--%>
<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">
<h2>
<small>书籍列表 —— 显示所有书籍</small>
</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a href="/addBook.jsp" class="btn btn-primary pull-right">新增</a>
<span>
<form action="/books/queryBook" method="post">
<input type="text" name="bookName" placeholder="书籍名称">
<input type="submit" value="搜索">
</form>
</span>
<a href="/books/allBooks" class="btn btn-primary pull-right">显示全部</a>
<span style="color: red">${nill}</span>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12"></div>
<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="${list}">
<tr>
<td>${book.getBookID()}</td>
<td>${book.getBookName()}</td>
<td>${book.getBookCounts()}</td>
<td>${book.getDetail()}</td>
<td>
<a href="/books/query/${book.bookID}" class="button">修改</a>
<a href="/books/deleteBook/${book.bookID}" class="button">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</body>
</html>
/**
* 删除书籍
* @param id
* @return
*/
@RequestMapping("deleteBook/{bookID}")
public String delete(@PathVariable("bookID") Integer id){
bookService.deleteBookById(id);
return "redirect:/books/allBooks";
}
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 14:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
<%--引入bootstrap的cdn--%>
<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">
<h2>
<small>书籍列表 —— 显示所有书籍</small>
</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a href="/addBook.jsp" class="btn btn-primary pull-right">新增</a>
<span>
<form action="/books/queryBook" method="post">
<input type="text" name="bookName" placeholder="书籍名称">
<input type="submit" value="搜索">
</form>
</span>
<a href="/books/allBooks" class="btn btn-primary pull-right">显示全部</a>
<span style="color: red">${nill}</span>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12"></div>
<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="${list}">
<tr>
<td>${book.getBookID()}</td>
<td>${book.getBookName()}</td>
<td>${book.getBookCounts()}</td>
<td>${book.getDetail()}</td>
<td>
<a href="/books/query/${book.bookID}" class="button">修改</a>
<a href="/books/deleteBook/${book.bookID}" class="button">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</body>
</html>
/**
* 根据id查询books
* @param id
* @param model
* @return
*/
@RequestMapping("query/{bookID}")
public String update(@PathVariable("bookID") Integer id,Model model){
Books books = bookService.queryBookById(id);
model.addAttribute("books",books);
return "forward:/update.jsp"; //写成redirect:/update.jsp为什么获取不到数据
}
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 11:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>新增书籍</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/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="/books/updateBooks" method="post">
<input type="hidden" name="bookID" value="${books.getBookID()}">
书籍名称:<input type="text" name="bookName" value="${books.getBookName()}"><br><br><br>
书籍数量:<input type="text" name="bookCounts" value="${books.getBookCounts()}"><br><br><br>
书籍详情:<input type="text" name="detail" value="${books.getDetail()}"><br><br><br>
<input type="submit" value="更新">
</form>
</div>
/**
* 更新books
* @param books
* @return
*/
@RequestMapping("updateBooks")
public String update(Books books){
bookService.updateBook(books);
return "redirect:allBooks";
}
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: liuzeyu
Date: 2020/5/1
Time: 14:13
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
<%--引入bootstrap的cdn--%>
<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">
<h2>
<small>书籍列表 —— 显示所有书籍</small>
</h2>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a href="/addBook.jsp" class="btn btn-primary pull-right">新增</a>
<span>
<form action="/books/queryBook" method="post">
<input type="text" name="bookName" placeholder="书籍名称">
<input type="submit" value="搜索">
</form>
</span>
<a href="/books/allBooks" class="btn btn-primary pull-right">显示全部</a>
<span style="color: red">${nill}</span>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12"></div>
<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="${list}">
<tr>
<td>${book.getBookID()}</td>
<td>${book.getBookName()}</td>
<td>${book.getBookCounts()}</td>
<td>${book.getDetail()}</td>
<td>
<a href="/books/query/${book.bookID}" class="button">修改</a>
<a href="/books/deleteBook/${book.bookID}" class="button">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</body>
</html>
@RequestMapping("queryBook")
public String queryBook(String bookName,Model model){
List<Books> list = bookService.queryBook("%"+bookName+"%");
if(list == null || list.size() == 0){
model.addAttribute("nill","没有查到此类书籍");
}
model.addAttribute("list",list);
return "allBooks";
}
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=809080
HTTP Status 500 – Internal Server Error
Type Exception Report
Message Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
Root Cause
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!
其实出现问题的具体原理还尚未清楚,但是处理方法很简单,只需要将
useSSL=false 即可
<!--配置处理请求乱码-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*
找到过滤器的配置,发现少了初始化编码格式
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
重定向和转发的区别
*
* a.浏览器地址有无变化
* 转发之后,地址栏无变化
* 重定向之后,地址有变化
* b.目的地
* 转发的目的地有限制,只能转发同一个web应用的(tomcat容器中)
* 重定向的目的地没有限制
* c.能否共享request和response
* 转发可以共享,重定向不行
*
* d.发送的请求次数(可以按F12的newtwork窗口查看)
* 重定向发送两次,如果成功一次是304,一次是200
* 转发只发送一次,成功的状态码200
web资源的结构是
-web
-WEB-INF
-pages
-allBooks.jsp
-web.xml
-index.jsp
-addBook.jsp
-update.jsp
问题:Controller方法的reuturn写的路径该如何写?forward和redirec的路径又该怎么写?
这个问题直接涉及到JavaWeb的知识。
在idea中,tomcat项目部署后,web资源目录被部署到哪里了?
ssm(项目名)
-out
-artifacts
-ssm_kuang_book_war_exploded(这个目录下的文件就是项目中web下的目录部署后的)
几处需要注意的返回值写法!!
return "/allBooks";
return "allBooks";
和queryBook方法类似,切记不能写后缀.jsp。
return "redirect:/books/allBooks"; //绝对路径写法
return "redirect:allBooks //相对路径写法
return "redirect:books/allBooks"; //就不行
@RequestMapping("query/{bookID}")
public String update(@PathVariable("bookID") Integer id,Model model){
Books books = bookService.queryBookById(id);
model.addAttribute("books",books);
return "forward:/update.jsp"; //写成redirect:/update.jsp为什么获取不到数据
}
/**
* 更新books
* @param books
* @return
*/
@RequestMapping("updateBooks")
public String update(Books books){
bookService.updateBook(books);
return "redirect:allBooks";
}
这里的return “forward:/update.jsp”;必须使用forward,否则不能将request查询到的对象显示出来,因为forward可以在一次请求和响应间共享数据,而且数据包含在request域中也只能在一次的请求和响应间存在。如果换成重定向数据将在第一次请求时丢失,第二次请求将不再携带数据,所以不能使用重定向。
BookController全部代码:
/**
* Created by liuzeyu on 2020/5/1.
*/
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService = null;
/**
* 处理展示所有书籍
* @param model
* @return
*/
@RequestMapping("allBooks")
public String list(Model model){
List<Books> list = bookService.findAll();
System.out.println(list);
model.addAttribute("list",list);
return "/allBooks";
}
/**
* 处理保存书籍
* @param books
* @return
*/
@RequestMapping("addBook")
public String save(Books books){
bookService.addBook(books);
return "redirect:allBooks";
//写成redirect:/books/allBooks可以,写成redirect:books/allBooks就不行
//allBooks是相对路径
//写成redirect:/books/allBooks是绝对路径
}
/**
* 删除书籍
* @param id
* @return
*/
@RequestMapping("deleteBook/{bookID}")
public String delete(@PathVariable("bookID") Integer id){
bookService.deleteBookById(id);
return "redirect:/books/allBooks";
}
/**
* 根据id查询books
* @param id
* @param model
* @return
*/
@RequestMapping("query/{bookID}")
public String update(@PathVariable("bookID") Integer id,Model model){
Books books = bookService.queryBookById(id);
model.addAttribute("books",books);
return "forward:/update.jsp"; //写成redirect:/update.jsp为什么获取不到数据
}
/**
* 更新books
* @param books
* @return
*/
@RequestMapping("updateBooks")
public String update(Books books){
bookService.updateBook(books);
return "redirect:allBooks";
}
@RequestMapping("queryBook")
public String queryBook(String bookName,Model model){
List<Books> list = bookService.queryBook("%"+bookName+"%");
if(list == null || list.size() == 0){
model.addAttribute("nill","没有查到此类书籍");
}
model.addAttribute("list",list);
return "allBooks";
}
}
已经接触了两个SSM整合小案例,发现整合的手段不尽相同,最大的区别在于配置文件的整合顺序,但是配置内容都是大同小异。此项目还有很多需要优化的地方,例如可以增加登录注册功能,并且添加拦截器过滤器等,许多值得优化的地方值得我再去深入学习SSM。
Github:https://github.com/liuzeyu12a/ssm-/tree/master
如有出入,恳请指教
不积跬步无以至千里,不积小流无以成江海。