源码免费下载SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统
Posted .29.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码免费下载SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统相关的知识,希望对你有一定的参考价值。
个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~
个人主页:.29.的博客
学习社区:进去逛一逛~
SpringBoot-SSMP整合案例
一、实现方案
案例实现方案分析:
-
实体类开发 —— 使用Lombok快速制作实体类
-
Dao开发 —— 整合MyBatisPlus,制作数据层测试类
-
Service开发 —— 整合MyBatisPlus进行增量开发,制作业务层测试类
-
Controller开发 —— 基于Restful开发,使用PostMan测试接口功能
-
Controller开发 —— 前后端开发协议制作
-
页面开发 —— 基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
-
- 列表、新增、修改、删除、分页、查询
-
项目异常处理
-
按条件查询 —— 页面功能调整、Controller修正功能、Service修正功能
二、案例实现
1.快速搭建springboot工程
1.快速搭建
:
2.勾选需要的起步依赖
:
2. 实体类快速开发(Lombok)
Lombok
:一个Java类库,提供了一组注解,简化了POJO实体类开发
pom.xml导入lombok依赖
:
- lombok版本由SpringBoot提供,故无需额外指定
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
快速利用lombok开发实体类
:
@Data注解
:自动创建实体类属性的Getter、Setter方法
import lombok.Data;
/**
* @author .29.
* @create 2023-03-27 20:58
*/
@Data
public class Book
private int id;
private String type;
private String name;
private String description;
3.数据层开发
手动导入springboot未提供勾选的起步依赖
:
<!--手动添加MyBatisPlus的起步依赖-->
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--手动添加Druid数据库连接池的起步依赖-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
</dependencies>
springboot配置文件
:
将配置文件修改为yml
格式后,配置相关数据源信息
# 配置端口号
server:
port: 8080
# 配置dataSource(数据源)
spring:
datasource:
druid:
username: root
password: abc123
url: jdbc:mysql://localhost:3306/springboot?useSSL=false&useUnicode=true&CharacterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置MyBatisPlus
# table-prefix:配置表格前缀,避免无法找到表格的问题
# id-type: 配置id类型,设置为auto以配合数据库表格的自增列,若不设置,在新增时不指定自增列会报错
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
# 开启MyBatisPlus日志功能(注意:配置在mybatis-plus:的下一级)
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Mapper接口
import com.haojin.springboot.springbootssmp.domain.Book;
import org.apache.ibatis.annotations.Mapper;
/**
* @author .29.
* @create 2023-03-27 21:11
*/
@Mapper
public interface BookMapper extends BaseMapper<Book>
//只需要让Mapper接口继承BaseMapper<>,以实体类类型作为泛型,就能直接使用MyBatisPlus提供好的CRUD方法
MyBatisPlus提供的相关方法参考:
MyBatisPlus——分页功能
:
-
分页操作需要设置分页对象
IPage
-
IPage
对象中封装了分页操作的所有数据: -
- 数据(Records)
- 当前页码值(Current)
- 每页数据总量(Size)
- 最大页码值(Pages)
- 数据总量(Total)
-
@Test
public void testSelectPage()
//实现分页功能的测试
IPage page = new Page(1, 5);
bookMapper.selectPage(page,null);
//测试 获取IPage对象中封装的数据:
System.out.println(page.getCurrent());//当前页码
System.out.println(page.getSize()); //每页数据总量
System.out.println(page.getPages()); //最大页码值
System.out.println(page.getTotal()); //数据总量
System.out.println(page.getRecords());//数据
只是上述调用MyBatisPlus中提供的分页功能相关的方法还无法真正实现分页功能,MyBatisPlu是通过拦截器来实现分页的,所以需要配置拦截器。
- 分页操作时在MyBatisPlus的常规操作基础上增强得到的,内部时动态地拼写SQL语句,因此需要增强对应地功能,使用MyBatisPlus拦截器实现:
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author .29.
* @create 2023-03-27 22:36
*/
//拦截器配置类
@Configuration
public class MPConfig
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor()
//创建MP拦截器的容器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
//往容器中添加需要的拦截器,这里是实现分页功能的拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
配置了拦截器,上文测试的分页相关功能就能顺利实现啦~
MyBatisPlus——条件查询功能
:
- 可以使用
QueryWrapper
对象封装查询条件实现条件查询功能,这里推荐使用LambdaQueryWrapper
对象——所有查询操作封装成方法调用。
@Test
public void testGetByCondition()
//设置分页规则(第一页,每页五条)
IPage page = new Page(1, 5);
//将需要查询的类型作为泛型,LambdaQueryWrapper封装了所有查询操作,可直接调用相关方法
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
//like方法封装条件进行查询
lqw.like(Book::getName,"Spring");
//查询结果分页
bookMapper.selectPage(page,lqw);
4.业务层开发
注意
:
- Service接口名称定义为业务名称,与数据层接口名称进行区分
- 制作测试类测试Service功能是否有效
- 可使用通用接口
IService<T>
快速开发Service - 可使用通用实现类
ServiceImpl<M,T>
快速开发ServiceImpl - 可以在通用接口也基础上做功能重载或功能追加
- 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
①普通方式开发
业务层接口
:
import com.haojin.springboot.springbootssmp.domain.Book;
import java.util.List;
/**
* @author .29.
* @create 2023-03-28 19:41
*/
//业务层接口
public interface BookService
//增
Boolean save(Book book);
//改
Boolean update(Book book);
//删
Boolean delete(Integer id);
//查
Book getById(Integer id);
List<Book> getAll();
//分页
IPage getPage(int currPage,int pageSize);
接口实现类
:
import com.haojin.springboot.springbootssmp.domain.Book;
import com.haojin.springboot.springbootssmp.mapper.BookMapper;
import com.haojin.springboot.springbootssmp.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author .29.
* @create 2023-03-28 19:46
*/
//业务层接口实现类
@Service
public class BookServiceImpl implements BookService
@Autowired
private BookMapper bookMapper;
//业务层方法 与 数据层方法名 尽量不相同
//新增
@Override
public Boolean save(Book book)
return bookMapper.insert(book) > 0;
//修改
@Override
public Boolean update(Book book)
return bookMapper.updateById(book) > 0;
//删除
@Override
public Boolean delete(Integer id)
return bookMapper.deleteById(id) > 0;
//根据id查询
@Override
public Book getById(Integer id)
return bookMapper.selectById(id);
//查询所有
@Override
public List<Book> getAll()
return bookMapper.selectList(null);
//分页
@Override
public IPage getPage(int currPage, int pageSize)
IPage page = new Page(currPage, pageSize);
bookMapper.selectPage(page,null);
return page;
创建测试类,测试业务层功能是否能正常运行
:
import com.haojin.springboot.springbootssmp.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author .29.
* @create 2023-03-28 19:56
*/
@SpringBootTest
public class testServiceImpl
@Autowired
private BookService bookService;
@Test
public void testSave()
Book book = new Book();
book.setType("计算机理论");
book.setName("数据结构与算法");
book.setDescription("小白的算法入门推荐书籍");
System.out.println(bookService.save(book));
@Test
public void testUpdate()
Book book = new Book();
book.setId(8);
book.setType("测试更新 类型");
book.setName("测试更新 书名");
book.setDescription("测试更新 简介");
System.out.println(bookService.update(book));
@Test
public void testDelete()
System.out.println(bookService.delete(8));
@Test
public void testGetById()
System.out.println(bookService.getById(1));
@Test
public void testGetAll()
System.out.println(bookService.getAll());
@Test
public void testGetPage()
IPage page = bookService.getPage(1, 5);
System.out.println(page.getCurrent());//当前页码
System.out.println(page.getSize()); //每页数据总量
System.out.println(page.getPages()); //最大页码值
System.out.println(page.getTotal()); //数据总量
System.out.println(page.getRecords());//数据
②快速方式开发
基于MyBatisPlus快速构建业务层接口
:
- 这里一个接口,继承IService,操作类型作为泛型,就完成了上文繁琐的业务层实现操作
import com.baomidou.mybatisplus.extension.service.IService;
import com.haojin.springboot.springbootssmp.domain.Book;
/**
* @author .29.
* @create 2023-03-28 20:25
*/
//业务层快速开发(基于MyBatisPlus构建)
public interface IBookService extends IService<Book>
//已经提供了大量通用方法
//不通用的业务层方法继续在这里定义开发即可
//分页
IPage<Book> getPage(int currPage,int pageSize);
//条件查询分页
IPage<Book> getPage(int currPage,int pageSize,Book book);
MyBatisPlus提供的通用方法
:
基于MyBatisPlus快速构建接口实现类
:
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haojin.springboot.springbootssmp.domain.Book;
import com.haojin.springboot.springbootssmp.mapper.BookMapper;
import com.haojin.springboot.springbootssmp.service.IBookService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author .29.
* @create 2023-03-28 20:34
*/
@Service
//基于MyBatisPlus快速构建业务层接口实现类
public class MPBookServiceImpl extends ServiceImpl<BookMapper, Book> implements IBookService
@Autowired
BookMapper bookMapper;
//自己定义的
//分页
@Override
public IPage<Book> getPage(int currPage, int pageSize)
IPage page = new Page(currPage, pageSize);
bookMapper.selectPage(page,null);
return page;
//条件查询分页
@Override
public IPage<Book> getPage(int currPage, int pageSize,Book book)
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
lqw.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
lqw.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
IPage page =
文章目录
-
1.引言
在 Spring Boot项目之中,我们引入 Spring Security依赖,什么也没做,启动项目 Spring Security 就会生效,访问请求就进行了拦截。
Spring Boot 对于 Spring Security 提供了自动化配置方案,可以使用更少的配置来使用 Spring Security。
那么这个过滤器链是怎么加载和实现拦截的呢?
2.Spring Security过滤器链加载
1.2.注册名为 springSecurityFilterChain的过滤器
当 Spring Boot 项目启动后,SecurityFilterAutoConfiguration
类会加载 DelegatingFilterProxyRegistrationBean
注册过滤器,名字为 springSecurityFilterChain
。
注意:springSecurityFilterChain名字是固定写死的。
DelegatingFilterProxyRegistrationBean
注册成功后,该过滤器就被加载了到了注册器中。然后调用getFilter()方法生成 DelegatingFilterProxy
代理对象并注册到 IOC
中 。
2、查看 DelegatingFilterProxy类
我们访问项目,就会进入 DelegatingFilterProxy
类的 doFilter
方法。
DelegatingFilterProxy类本质也是一个 Filter,其间接实现了 Filter接口,但是在 doFilter中其实调用的从 Spring 容器中获取到的代理 Filter的实现类。
返回的 FilterChainProxy
对象。
由此可知,DelegatingFilterProxy
类通过 springSecurityFilterChain
这个名称,得到了一个 FilterChainProxy
过滤器,最终执行的是这个过滤器的 doFilter
方法。
验证 springSecurityFilterChain名词不能修改
查看 initDelegate方法。
3.查看 FilterChainProxy类
FilterChainProxy
类本质也是一个 Filter,所以查看 doFilter
方法。留意该类里面的属性。
public class FilterChainProxy extends GenericFilterBean
private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
private static final String FILTER_APPLIED =
FilterChainProxy.class.getName().concat(".APPLIED");
// 过滤器链
private List<SecurityFilterChain> filterChains;
private FilterChainProxy.FilterChainValidator filterChainValidator;
private HttpFirewall firewall;
3.1 查看 doFilterInternal方法。
惊不惊喜?15个过滤器都在这里了!
3.2 查看 getFilters方法。
原来这些过滤器都被封装进 SecurityFilterChain对象中。
4 查看 SecurityFilterChain接口
SecurityFilterChain
类是个接口,实现类也只有一个 DefaultSecurityFilterChain
类。
DefaultSecurityFilterChain
类的构造方法,初始化了 List filters,是通过传参放进去的。
过滤器链参数是什么时候传入的?
5 查看 SpringBootWebSecurityConfiguration类
创建 Spring Security
过滤器链是交给 Spring boot
自动配置,由 SpringBootWebSecurityConfiguration
类创建注入。
查看 WebSecurityConfigurerAdapter
类。
然后会注入 HttpSecurity对象,HttpSecurity可以理解为 Spring Security 的 http核心配置,存放 Spring Security 中的过滤器链、请求匹配路径等相关认证授权的重要方法。
然后开始创建 Spring Security 过滤器链了,是交给 Spring Boot自动配置,一共有 15个过滤器。
使用 OrderedFilter进行代理,并设置了order属性。
添加完成后,将这些过滤器再封装为 DefaultSecurityFilterChain对象。
最后通过 WebSecurityConfiguration配置加载 springSecurityFilterChain,WebSecurityConfiguration中维护了securityFilterChains属性,会存放过滤器链中所有的过滤器。
总结:
Spring boot 通过 DelegatingFilterProxyRegistrationBean
注册过滤器,名字为 springSecurityFilterChain
,并生成 DelegatingFilterProxy
代理对象并注册到 IoC中。最终真正调用 FilterChainProxy
过滤器的 doFilter
获取到 Spring Security 过滤器链
。
Spring Security的过滤器链在底层是封装在 SecurityFilterChain接口中的。
以上是关于源码免费下载SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot整合ElasticSearch和Mysql 附案例源码