前言
本文将整合Spring、Mybatis、SpringMVC三大框架,并写一个简单的CRUD的Demo程序
一.准备工作
分析需求:没啥需求,就是单表CRUD
准备数据库和表:
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 '书名',
`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,'从进门到进牢');
查看数据:
搭建Maven环境,添加相应的依赖:
在构建maven项目的时候,记得去设置里面调一下maven的版本和仓库,不然会用idea自带的maven
<dependencies>
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--spring处理事物依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.11</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<!--druid连接池依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
<!--spring整合mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--springmvc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp/jakarta.servlet.jsp-api -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
依赖有点多,都配好就行了,注意一定要配本地仓库还有选自己maven的配置,要不然它默认去国外仓库下载,要等非常久!!!!(踩过坑)
二.开始搭建
1.首先建立包结构
老生常谈了,MVC架构模式的包:
2.编写Mybatis配置文件
编写的时候碰到这个爆红:
错误是: URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)
解决办法:在下面加入这个uri即可,不知道idea发什么颠,第一次碰见这问题
因为我们不是单纯使用Mybatis,所以Mybatis很多配置我们可以让Spring帮我们完成,所以在这个配置文件中只写一些系统级的配置;
在此之前我们先把与数据库表对应的pojo类还有Mapper接口给写了,到时候一起配置:
pojo类:标准的pojo,对应数据库表,可以使用lombok简化
package com.jtl.library.pojo;
import java.util.Objects;
/**
*@description: pojo类,对应ssmbuild库中的books表
*
*/
public class Book {
private Integer bookId;
private String bookName;
private Integer bookCounts;
private String detail;
public Book(){
}
public Book(Integer bookId, String bookName, Integer bookCounts, String detail) {
this.bookId = bookId;
this.bookName = bookName;
this.bookCounts = bookCounts;
this.detail = detail;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Integer getBookCounts() {
return bookCounts;
}
public void setBookCounts(Integer bookCounts) {
this.bookCounts = bookCounts;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(bookId, book.bookId) && Objects.equals(bookName, book.bookName) && Objects.equals(bookCounts, book.bookCounts) && Objects.equals(detail, book.detail);
}
@Override
public int hashCode() {
return Objects.hash(bookId, bookName, bookCounts, detail);
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", bookCounts=" + bookCounts +
", detail='" + detail + '\'' +
'}';
}
}
BookMapper接口:
package com.jtl.library.mapper;
import com.jtl.library.pojo.Book;
import java.util.List;
/**
* @author jtl
* 操作books这张表的Mapper
*/
public interface BookMapper {
//增加书籍
int insert(Book book);
//通过id删除书籍
int deleteById(int id);
//更新书籍
int update(Book book);
//通过id查找书籍
Book selectById(int id);
//通过名字模糊查询书籍
List<Book> selectByName(String name);
//查找所有书籍
List<Book> selectAll();
}
准备工作做完了,下面是mybatis核心配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--使用Mybatis自己的标准日志-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--给pojo起别名-->
<typeAliases>
<package name="com.jtl.library.pojo"/>
</typeAliases>
<mappers>
<!-- <mapper resource="BookMapper.xml"/>-->
<package name="com.jtl.library.mapper"/>
</mappers>
</configuration>
首先配置了日志,然后给pojo包下面的类起别名,再配置了mapper所在包的位置,这样的话mybatis就知道你的接口都写着哪个包下面了,他就会去找对应的映射文件
BookMapper SQL映射文件:
<?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.jtl.library.mapper.BookMapper">
<insert id="insert">
insert into books values
(#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteById">
delete from books where id = #{id};
</delete>
<update id="update">
update books set
bookName = #{bookName},
bookCounts = #{bookCounts},
detail = #{detail}
where bookID = #{bookId};
</update>
<select id="selectById" resultType="com.jtl.library.pojo.Book">
select * from books where bookID = #{bookId};
</select>
<select id="selectByName" resultType="com.jtl.library.pojo.Book">
select * from books
where bookName like "%"#{bookName}"%"
</select>
<select id="selectAll" resultType="com.jtl.library.pojo.Book">
select * from books;
</select>
</mapper>
3.编写service层的接口和实现类
接口:
package com.jtl.library.service;
import com.jtl.library.pojo.Book;
import java.util.List;
/**
* @author jtl
* java学习用
*/
public interface BookService {
int addBook(Book book);
int deleteBookById(int id);
int updateBook(Book book);
Book queryBookById(int id);
List<Book> queryBookByName(String name);
List<Book> queryAllBook();
}
实现类:
package com.jtl.library.service.impl;
import com.jtl.library.mapper.BookMapper;
import com.jtl.library.pojo.Book;
import com.jtl.library.service.BookService;
import java.util.List;
/**
* @description:
*/
public class BookServiceImpl implements BookService {
private BookMapper bookMapper;
@Override
public int addBook(Book book) {
return bookMapper.insert(book);
}
@Override
public int deleteBookById(int id) {
return bookMapper.deleteById(id);
}
@Override
public int updateBook(Book book) {
return bookMapper.update(book);
}
@Override
public Book queryBookById(int id) {
return bookMapper.selectById(id);
}
@Override
public List<Book> queryBookByName(String name) {
return bookMapper.selectByName(name);
}
@Override
public List<Book> queryAllBook() {
return bookMapper.selectAll();
}
}
4.Spring层
首先是Spring整合Mybatis:
这里遇到一个问题,就是spring配置文件模板突然找不到了,试着刷新了一下依赖,发现又可以了,包括之前写Mapper文件时没有提示的问题也解决了,所以这些配置文件找不到或者没关联基本上是依赖的问题,尝试用maven重新构建一下即可:
先编写连接数据库的配置文件jdbc.properties.xml:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild
jdbc.username=root
jdbc.password=jtl
编写spring整合mybatis的配置文件spring-mybatis.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:jdbc.properties"/>
<!--2.配置数据库连接池(druid)-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.配置SqlSessionFactory对象
需要配置数据库连接池
配置mybatis核心配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--4.配置扫描Mapper接口的包,,动态实现Mapper接口注入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描Mapper接口包 -->
<property name="basePackage" value="com.jtl.library.mapper"/>
</bean>
</beans>
然后是Spring整合service层
<?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: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/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
">
<!--扫描service相关的bean-->
<context:component-scan base-package="com.jtl.library.service"/>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!--开启事物注解驱动器,这个配置告诉spring容器我们将使用注解去控制事物-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
这里注意,要让两个配置文件有关系才行,下面是一种配置方法,还有一种就是用import直接导入
最后,把两个配置文件合并成一个:
<?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-service.xml"/>
<import resource="spring-mybatis.xml"/>
</beans>
5.SpringMVC层
先配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">
<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>
<!--encodingFilter,过滤器解决中文乱码问题-->
<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>
</web-app>
'/'表示该项目的所有请求路径;'/*'表示只能有一级子路径,它匹配'/a.jsp'但是不匹配'/jsp/a.jsp'。
spring-mvc.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: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
https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解驱动 -->
<mvc:annotation-driven/>
<!-- 2.静态资源默认servlet配置-->
<mvc:default-servlet-handler/>
<!--3.配置视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.jtl.library.controller"/>
</beans>
最终整合:
<?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="spring-service.xml"/>
<import resource="spring-mybatis.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
三.开始写程序
写程序的过程中又遇到几个配置上的问题:
第一个是tomcat启动的时候报错:
27-Nov-2023 19:05:27.463 严重 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal 一个或多个筛选器启动失败。完整的详细信息将在相应的容器日志文件中找到
27-Nov-2023 19:05:27.463 严重 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal 由于之前的错误,Context[/ssm01]启动失败
解决办法是手动把jar包导进去:
第二个是启动后报了个空指针异常:
java.lang.NullPointerException: Cannot invoke "com.jtl.library.mapper.BookMapper.selectAll()" because "this.bookMapper" is null
原因很简单,没有注入属性,把service实现类中的属性注入就行了:
···@Autowired
private BookMapper bookMapper;
第三是web的小蓝点突然消失,然后index.jsp找不到了:
解决办法:
把这个web resource改成你当前项目的web目录即可
第四是关于数据库信息的配置,看这篇即可,注意你用的版本就好了