1.环境要求
环境:
- IDEA2019.2
- MySQL5.5
- Tomcat8
- Maven3.6
2.数据库环境
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
CREATE TABLE `books`(
`bookId` INT NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT 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,'从进门到进牢');
3.基本环境搭建
-
新建一个maven项目ssmbuild
-
导入相关pom依赖
<!--依赖:junit,数据库驱动,连接池,servlet,jsp,mybatis,mybatis-spring,spring-->
<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.47</version>
</dependency>
<!--数据库链接池: c3p0:dbcp-->
<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>
<scope>provided</scope>
</dependency>
</dependencies>
- maven资源过滤设置
<!--静态资源导出-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
</build>
- idea链接MySQL数据库,需要设置serverTimezone为CST
- 建立基本结构框架和配置框架
- com.liu.pojo
- com.liu.dao
- com.liu.service
- com.liu.controller
- 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>
- 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">
</beans>
4.Mybatis层编写
- 在resources目录下编写数据库配置文件database.properties
jdbc.driver=com.mysql.jdbc.Driver
# 如果使用的是MySQL8.0+的配置,需要增加一个时区的配置(在url后添加&serverTimezone=Asia/Shanghai)
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
- 编写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>
<!--配置数据源,交给Spring去做-->
<typeAliases>
<package name="com.liu.pojo"/>
</typeAliases>
</configuration>
- 编写实体类,在pojo包中编写Books类
package com.liu.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 23862
*/
@Data
@AllArgsConstructor //有参构造
@NoArgsConstructor //无参构造
public class Books {
private int bookId;
private String bookName;
private int bookCounts;
private String detail;
}
- 在dao包中编写接口BookMapper
package com.liu.dao;
import com.liu.pojo.Books;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author 23862
*/
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();
}
- 在dao包中编写BookMapper.xml文件
<?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.liu.dao.BookMapper">
<!--一个mapper对应一个接口-->
<insert id="addBook" parameterType="Books">
insert into ssmbuild.books (bookName, bookCounts, detail)
VALUES (#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBookId" parameterType="int">
delete from ssmbuild.books
where bookId = #{bookId}
</delete>
<update id="updateBook" parameterType="Books">
update ssmbuild.books
set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
where bookId = #{bookId};
</update>
<select id="queryBookById" resultType="Books">
select *
from ssmbuild.books
where bookId = #{bookId}
</select>
<select id="queryAllBook" resultType="Books">
select *
from ssmbuild.books;
</select>
<!--写完每个mapper后需要将其注册到mybatis-config.xml文件中-->
</mapper>
- 将BookMapper.xml绑定到配置文件mybatis-config.xml中
<mappers>
<!--注册BookMapper.xml到此处-->
<!--当dao包下的接口和配置文件名字相同时使用class,不同时使用resource-->
<mapper class="com.liu.dao.BookMapper"/>
</mappers>
- 在service包下编写接口BookService
package com.liu.service;
import com.liu.pojo.Books;
import java.util.List;
/**
* @author 23862
*/
public interface BookService {
//增加一本书
int addBook(Books books);
//删除一本书
int deleteBookById(int id);
//更新一本书
int updateBook(Books books);
//查询一本书
Books queryBookById(int id);
//查询全部的书
List<Books> queryAllBook();
}
- 在service包下编写接口BookService的实现类BookServiceImpl
package com.liu.service;
import com.liu.dao.BookMapper;
import com.liu.pojo.Books;
import java.util.List;
/**
* @author 23862
*/
public class BookServiceImpl implements BookService{
//service层调用dao层:组合dao(即把dao层放进来私有化)
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();
}
}
5.Spring层编写
5.1编写spring-dao.xml
-
在resources目录下编写spring-dao.xml文件,整合dao层
-
此处写入头文件后点击右上角出现的蓝色文字,选择添加到ApplicationContext中
- 查看项目结构可看到添加成功,尽量保证所有配置文件都在一个ApplicationContext中
- 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">
<!--1.关联数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>
<!--2.数据库连接池
常见的几种连接池:
dbcp:半自动化操作,不能自动连接
c3p0:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中!)
druid和hikari在公司中会经常用到
-->
<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"/>
<!--设置关闭连接后自动提交为否-->
<property name="autoCommitOnClose" value="false"/>
<!--设置获取连接超时时间为10秒-->
<property name="checkoutTimeout" value="10000"/>
<!--设置获取连接失败后的重试次数为2-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!--3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源,通过ref引用dataSource-->
<property name="dataSource" ref="dataSource"/>
<!--绑定mybatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--4.配置dao接口扫描包,动态的实现了dao接口的spring容器注入-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--如果通过继承的方式就可以注入session就使用sqlSessionFactoryBeanName
如果私有化构造就使用sqlSessionTemplateBeanName.
value需要与上面3中的id一致-->
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描dao包-->
<property name="basePackage" value="com.liu.dao"/>
</bean>
</beans>
5.2编写spring-service.xml
-
在resources目录下编写spring-service.xml文件,整合service层
-
此处写入头文件后点击右上角出现的蓝色文字,选择添加到ApplicationContext中。查看项目结构可看到添加成功,尽量保证所有配置文件都在一个ApplicationContext中
-
先通过applicationContext.xml文件将spring-dao.xml和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"
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"/>
</beans>
- 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"
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">
<!--此处多增加了头文件内容,否则无法使用context标签-->
<!--1.扫描service下的包-->
<context:component-scan base-package="com.liu.service"/>
<!--2.将我们的所有业务类,注入到Spring,可以通过配置或者注解实现-->
<bean id="BookServiceImpl" class="com.liu.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--3.声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--此外还可添加aop事务支持-->
</beans>
6.SpringMVC层编写
-
在项目中添加web支持
-
在resources目录下创建spring-mvc.xml文件,此处写入头文件后点击右上角出现的蓝色文字,选择添加到ApplicationContext中。查看项目结构可看到添加成功,尽量保证所有配置文件都在一个ApplicationContext中
-
在web/WEB-INF下的web.xml文件中编辑以下内容
<?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">
<!--DispatchServlet-->
<servlet>
<servlet-name>springmvc</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>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过期时间为15分钟-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
- 通过applicationContext.xml文件将spring-dao.xml和spring-service.xml以及spring-mvc.xml文件整合起来
<import resource="classpath:spring-mvc.xml"/>
- 编写spring-mvc.xml文件,整合mvc层
<?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
http://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.liu.controller"/>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
- 在/web/WEB-INF目录下创建jsp目录
- 配置Tomcat
- 在项目结构中Artifacts选项卡中WEB-INF目录下创建lib目录并导入jar包,否则无法启动Tomcat
至此项目基本结构搭建完毕,可在spring-mvc.xml文件左上角的绿色矩阵中查看项目结构
7.controller层编写
- 在controller包下新建BookController类
@Controller
@RequestMapping("/book")
public class BookController {
//controller层调service层
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;
//查询全部书籍,返回书籍展示页面
@RequestMapping("/allBook")
public String list (Model model){
List<Books> list = bookService.queryAllBook();
model.addAttribute("list",list);
return "allBook";
}
}
- 在jsp目录下新建allBook.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示</title>
</head>
<body>
<h1>书籍展示</h1>
</body>
</html>
- 美化index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<style>
a{
text-decoration: none;
color: black;
font-size: 18px;
}
h3{
width: 180px;
height: 38px;
margin: 100px auto;
text-align: center;
line-height: 38px;
background: deepskyblue;
border-radius: 5px;
}
</style>
</head>
<body>
<h3>
<a href="${pageContext.request.contextPath}/book/allBook">进入书籍页面</a>
</h3>
</body>
</html>
8.关于运行后出现的问题
运行后发现找不到bean,报错500
检查步骤:
-
查看这个bean是否注入成功
发现在spring-service.xml文件中bean注入成功了
-
使用Junit进行单元测试,看代码能否查询出结果
在test/java目录下新检测试类MyTset,看能否查询出books
import com.liu.pojo.Books;
import com.liu.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookServiceImpl = (BookService) context.getBean("BookServiceImpl");//看能不能取出注入的bean BookServiceImpl
for (Books books : bookServiceImpl.queryAllBook()) {
System.out.println(books);
}
}
}
发现可以查询出books
结论:问题不在底层,是spring出现了问题
- 去BookController类中手动注入bean
@Controller
@RequestMapping("/book")
public class BookController {
//controller层调service层
/* @Autowired //自动装配属性
@Qualifier("BookServiceImpl") //指定别名*/
private BookService bookService = new BookServiceImpl();
//查询全部书籍,并返回到一个书籍展示页面
@RequestMapping("/allBook")
public String list(Model model){
List<Books> list = bookService.queryAllBook();
model.addAttribute("list",list);
return "allBook";
}
}
运行发现点击”进入书籍页面“后依旧报错500,发现空指针异常
但是刚刚测试类中查出了books,代码一定没有空指针
-
发现是SpringMVC整合的时候没调用到service层的bean,可能的问题有:
-
applicationContext.xml中没有注入bean
检查发现applicationContext.xml中已经整合了三个xml文件
-
在web.xml中,我也绑定过配置文件
检查发现web.xml中绑定classpath出错,我配置的Spring-mvc.xml中确实没有service bean,所以报空指针
应该绑定applicationContext.xml文件,改正后如下:
-
<!--DispatchServlet-->
<servlet>
<servlet-name>springmvc</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>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
启动Tomcat运行成功
点击后:
运行正常!
9.编写查询全部书籍方法的前端页面
- 美化allBook.jsp页面
<%@ 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>
<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>
</tr>
</thead>
<%--书籍从数据库中查询出来,从这个list中遍历出来:使用foreach--%>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookId}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
10.编写添加书籍功能
-
在BookController类中添加跳转到添加书籍页面的方法
//跳转到增加书籍页面 @RequestMapping("/toAddBook") public String toAddPaper(){ return "addBook"; }
-
在allBook.jsp页面中添加部分代码
<%@ 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="row">
<div class="col-md-4 column">
<%--toAddBook--%>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
</div>
</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>
</tr>
</thead>
<%--书籍从数据库中查询出来,从这个list中遍历出来:使用foreach--%>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookId}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
- 在jsp文件夹中新建并编写addBook.jsp页面
<%@ 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/addBook" method="post">
<div class="form-group">
<label>书籍名称:</label>
<%--name中的名字必须和实体类一样,否则为null--%>
<%--添加required标签使当前行必须填写完才能提交--%>
<input type="text" name="bookName" class="form-control" required>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" required>
</div>
<div class="form-group">
<label>书籍描述:</label>
<input type="text" name="detail" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="添加">
</div>
</form>
</div>
</body>
</html>
- 在BookController类中添加上添加书籍的请求方法
//添加书籍的请求
@RequestMapping("/addBook")
public String addBook(Books books){
System.out.println("addBook=>"+books);
bookService.addBook(books);
//重定向到我们的@RequestMapping("/allBook")请求
return "redirect:/book/allBook";
}
- 运行tomcat
- 点击按钮,进入书籍展示页面
- 点击新增书籍按钮
- 添加书籍信息后点击添加按钮
- 发现跳转回了书籍展示页面,书籍成功添加
11.编写修改和删除功能
11.1修改功能
- 在allBook.jsp页面中添加代码
<%--书籍从数据库中查询出来,从这个list中遍历出来:使用foreach--%>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookId}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<%--添加修改和删除按钮--%>
<td>
<a href="#">修改</a>
|
<a href="#">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
- 在jsp文件夹中新建updateBook.jsp页面
<%@ 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">
<div class="form-group">
<label>书籍名称:</label>
<%--name中的名字必须和实体类一样,否则为null--%>
<%--添加required标签使当前行必须填写完才能提交--%>
<input type="text" name="bookName" class="form-control" required>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" required>
</div>
<div class="form-group">
<label>书籍描述:</label>
<input type="text" name="detail" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>
- 在BookController类中添加上跳转到修改页面的方法
//跳转到修改页面
@RequestMapping("/toUpdate")
public String toUpdatePaper(int id,Model model){
Books books = bookService.queryBookById(id);
model.addAttribute("QBook",books);
return "updateBook";
}
- 更改allBook.jsp页面中的代码
<%--添加修改和删除按钮--%>
<td>
<a href="${pageContext.request.contextPath}/book/toUpdate?id=${book.bookId}">修改</a>
|
<a href="#">删除</a>
</td>
- 更改updateBook.jsp页面中的代码
<form action="${pageContext.request.contextPath}/book/updateBook" method="post">
<div class="form-group">
<label>书籍名称:</label>
<%--name中的名字必须和实体类一样,否则为null--%>
<%--添加required标签使当前行必须填写完才能提交--%>
<%--添加values属性并给予默认值--%>
<input type="text" name="bookName" class="form-control" value="${QBook.bookName}" required>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" value="${QBook.bookCounts}" required>
</div>
<div class="form-group">
<label>书籍描述:</label>
<input type="text" name="detail" class="form-control" value="${QBook.detail}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
- 测试当前功能
发现点击修改按钮后按照预想出现了默认值
- 在BookController类中添加上修改书籍的方法
//修改书籍
@RequestMapping("/updateBook")
public String updateBook(Books books){
System.out.println("updateBook=>"+books);
bookService.updateBook(books);
return "redirect:/book/allBook";
}
-
运行tomcat,进入修改页面修改值后发现修改失败
-
发现失败原因是修改方法没写需要修改对象的id,系统不知道需要修改那个对象。
-
在BookController类中添加代码
//修改书籍 @RequestMapping("/updateBook") public String updateBook(Books books){ System.out.println("updateBook=>"+books); bookService.updateBook(books); /*查看SQL语句是否被执行,并在控制台输出books的信息*/ int i = bookService.updateBook(books); if (i>0){ System.out.println("添加books成功"+books); } return "redirect:/book/allBook"; }
-
在updateBook.jsp中添加代码
<form action="${pageContext.request.contextPath}/book/updateBook" method="post">
<%--出现的问题:我们提交了修改的SQL请求,但是修改失败--%>
<%--看一下SQL语句是否执行成功,发现SQL执行失败,修改未完成--%>
<%--发现失败原因是没有给SQL语句需要查询对象的id,
导致与BookMapper.xmL文件中的更新书籍SQL语句不匹配--%>
<%--解决方法:前端传递隐藏域(设置type="hidden")--%>
<input type="hidden" name="bookId" value="${QBook.bookId}">
<div class="form-group">
<label>书籍名称:</label>
<%--name中的名字必须和实体类一样,否则为null--%>
<%--添加required标签使当前行必须填写完才能提交--%>
<%--添加values属性并给予默认值--%>
<input type="text" name="bookName" class="form-control" value="${QBook.bookName}" required>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" value="${QBook.bookCounts}" required>
</div>
<div class="form-group">
<label>书籍描述:</label>
<input type="text" name="detail" class="form-control" value="${QBook.detail}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
- 再次运行成功修改书籍信息
- 在mybatis-config.xml配置文件中配置日志功能(注意setting标签要写在typeAliases标签之上)
<!--配置日志功能-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
11.2删除功能
- 修改allBook.jsp中的代码
<%--添加修改和删除按钮--%>
<td>
<a href="${pageContext.request.contextPath}/book/toUpdate?id=${book.bookId}">修改</a>
|
<%--使用了restful风格--%>
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
</td>
- 在BookController类中添加上删除书籍的方法
//删除书籍
@RequestMapping("/deleteBook/{bookId}")
public String deleteBook(@PathVariable("bookId")int id){
bookService.deleteBookById(id);
return "redirect:/book/allBook";
}
- 运行tomcat测试删除功能
- 点击删除
成功删除书籍
12. 编写搜索功能
- 在BookMapper.java接口中添加代码
//搜索书名查询书籍
Books queryBookByName(@Param("bookName") String bookName);
- 在BookMapper.xml文件中添加代码
<select id="queryBookByName" resultType="Books">
select *
from ssmbuild.books
where bookName = #{bookName}
</select>
- 在BookService.java接口中添加代码
//搜索书名查询书籍
Books queryBookByName(String bookName);
- 在BookServiceImpl类中添加代码
public Books queryBookByName(String bookName) {
return bookMapper.queryBookByName(bookName);
}
- 在allBook.jsp中新增显示全部书籍按钮
<div class="col-md-4 column">
<%--toAddBook--%>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示全部书籍</a>
</div>
- 修改allBook.jsp并新增搜索功能代码
<div class="row">
<div class="col-md-4 column">
<%--toAddBook--%>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示全部书籍</a>
</div>
<div class="col-md-4 column"></div>
<div class="col-md-4 column">
<%--查询书籍--%>
<form class="form-inline" action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float: right">
<span style="color: red;font-weight: bold">${error}</span>
<input type="text" name="queryBookName" class="form-control" placeholder="请输入要查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>
</div>
- 在BookController类中添加代码
//查询书籍
@RequestMapping("/queryBook")
public String queryBook(String queryBookName,Model model){
Books books = bookService.queryBookByName(queryBookName);
/*在控制台中显示查询到的书籍信息,并以报错格式显示*/
System.err.println("queryBook=>"+books);
List<Books> list = new ArrayList<Books>();
list.add(books);
if (books==null){
list = bookService.queryAllBook();
model.addAttribute("error","未查到书籍");
}
model.addAttribute("list",list);
return "allBook";
}
- 运行查看效果
- 查询到书籍页面
- 查询书籍“123”后页面
13.关于SSM四层架构
entity层
A:entity就是属性类,通常定义在model层里面,相当于MVC的M层,属于数据模型层
B:一般得实体类对应一个数据表,其中的属性定义数据表中的字段,实体类的字段数量 >= 数据库表中需要操作的字段数量
dao层
A:dao层叫做数据访问层,全称为data access object,属于一种比较底层基础的操作,具体到对某个表的增删改查,换句话说,某个dao一定是和数据库中的某一张表一一对应的,而且其中也只是封装了增删改查得方法
service层
A:service层即为业务逻辑层,可以理解为对一个或者多个dao进行得再次封装,主要是针对具体的问题的操作,把一些数据层的操作进行组合,间接与数据库打交道(提供操作数据库的方法)。要做这一层的话,要先设计接口,再实现类。
controller层
A:负责请求转发,接收页面过来的参数,传给service处理,接到返回值,并再次传给页面
mapper层
A:数据存储对象,相当于DAO层,mapper层直接与数据库打交道(执行SQL语句),接口提供给service层。
SSM 是 Spring + SpringMVC + Mybatis集成的框架。
一、entity层
同类: model层 = entity层 = domain层
作用: 用于存放我们的实体类,与数据库中的属性值基本保持一致。
二、mapper层
同类: mapper层 = dao层
作用: 对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的
三、service层
同类: 只有一个 service层
作用: service层 是针对 controller层的 controller,也就是针对我们使用者。service的 impl 是把mapper和service进行整合的文件。
四、controller层
同类: controller层 = web 层
作用: 控制器,导入service层,因为service中的方法是我们使用到的,controller通过接收前端传过来的参数进行业务操作,再将处理结果返回到前端。
SSM框架
SSM框架是spring MVC ,Spring和Mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层(web),controller层,service层,dao层四层,使用spring MVC负责请求的转发和视图管理。Spring实现业务对象管理,Mybatis作为数据对象的持久化引擎。
表现层(web):通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。
业务逻辑层(service):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。
数据访问层(dao):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等。
DataBase ===> Entity ===> Mapper.xml ===> Dao.Java ===> Service.java ===> Controller.java ===> html css js(thymeleaf)
各层解释说明
层 | 描述 |
---|---|
实体层entity | 数据库在项目中的类,主要用于定义与数据库对象应的属性,提供get/set方法,tostring方法,有参无参构造函数。 |
持久层dao | 与数据库交互,dao层首先会创建dao接口,接着就可以在配置文件中定义该接口的实现类;接着就可以在模块中调用dao的接口进行数据业务的处理,而不用关注此接口的具体实现类是哪一个类,dao层的数据源和数据库连接的参数都是在配置文件中进行配置的。 |
业务层service | 控制业务,业务模块的逻辑应用设计,和dao层一样都是先设计接口,再创建要实现的类,然后在配置文件中进行配置其实现的关联。接下来就可以在service层调用接口进行业务逻辑应用的处理。 |
实现层Impl | 实现service接口的所有方法,整合service和dao |
控制层controller | controller层主要调用Service层里面的接口控制具体的业务流程,控制的配置也要在配置文件中进行。Controller和Service的区别是:Controller负责具体的业务模块流程的控制;Service层负责业务模块的逻辑应用设计 |
更详细内容参考:https://blog.csdn.net/cjw12581/article/details/107430183