1. springboot介绍
2.搭建springboot环境
2.1 使用maven项目
在pox.xml文件中加入parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
</parent>
在pom.xml文件中加入依赖web
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
创建Controller
@RestController
public class IndexController {
@GetMapping("/index")
public String index(){
return "helleo springboot1";
}
}
创建启动服务器的主类
@SpringBootApplication
public class AppServer {
public static void main(String[] args) {
SpringApplication.run(AppServer.class,args);
}
}
2.2 使用Spring initlalizr 官网
创建module,选择spring initlalizr创建,通过https://start.spring.io创建。
2.3 使用Spring initlalizr阿里云
2.4 访问https://start.spring.io
下载一个压缩包,解压后通过idea打开,就是一个springboot 工程。
3. springboot parent和starter
所有springboot项目要继承的项目
在其中, 依赖了一个spring-boot-dependencies,在里面规范了使用的各第三方依赖的版本号。
4.启动类
主启动类的位置
5.springboot 支持的三种服务器
内置tomcat默认的处理器
jetty: 更轻量级的容器
pom.xml文件中配置 的
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--取消tomcat服务器-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--加入jetty服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
undertow:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--取消tomcat服务器-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--加入undertow服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
6. springboot配置文件
创建springboot工程时会自动创建一个application.properties文件。
还可以支持application.yml 和application.yaml格式的文件。
主要应用的是application.yml格式的文件。
如果没有出自动提示,解决方式如下:
7. 以jar包的方式运行
1.打包的处理
可以 mvn package
也可以使用idea中maven生命周期package,双击
打包成功,在工程的target目录下找到jar包。进入target目录,运行java -jar 文件名.jar
8.springboot整合swagger3
步骤1:加入依赖
<!--引入swagger3 的依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
步骤2:编写swagger的配置类
package com.liqun.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* @ProjectName: springboot
* @Package: com.liqun.config
* @ClassName: Swagger3Config
* @Description: java类作用描述
* @Author: 滨海之君
* @CreateDate: 2023/5/29 23:00
*/
@Configuration
public class Swagger3Config {
@Bean
public Docket apiConfig(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
//设置通过什么方式定位到需要生成文档的接口
//定位了方法上的ApiOperation
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("springboot-swagger项目")
.description("项目描述信息")
.contact(new Contact("滨海之君","http://www.xx.com","binhaizhijun@163.com"))
.version("1.0")
.build();
}
}
步骤3:
要在application.yml文件中配置,避免程序报错:
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
或
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
步骤4:
在主启动类上添加@EnableOpenApi
注解 ,如果是swagger2,使用@EnableSwagger2
步骤5:
在Controller类上添加 注解:@Api(tags = {"对当前类的说明"})
步骤6:
在Controller方法上添加注解:@ApiOperation(value = "对方法的说明和用途")
步骤7:
在Controller方法上,为方法的参数说明:
@GetMapping("/{id}")
@ApiOperation("按给定id来查询学生信息")
@ApiImplicitParams(
@ApiImplicitParam(name = "id",value = "学生id",required = true,
paramType = "path",
dataType = "Integer",dataTypeClass=Integer.class)
)
public Object selectById(@PathVariable int id){
return new Student(id,"王某","男",23);
}
步骤8:
在Controller方法参数中,加入说明
@DeleteMapping("/{id}")
@ApiOperation("按给定的id来删除学生信息")
public Object deleteById(@ApiParam(name = "id",value = "学生id") @PathVariable int id){
return "success";
}
步骤9:
在实体类上加入参数说明:
@ApiModel(value = "学生对象",description = "学生对象,用来对应数据库表student")
public class Student {
@ApiModelProperty(value = "学生id",required = true,example = "1001")
private int id ;
@ApiModelProperty(value = "学生姓名",required = true,example = "张三")
private String name;
@ApiModelProperty(value = "学生性别",required = true,example = "男")
private String gender;
@ApiModelProperty(value = "学生年龄",required = false,example = "12")
private int age;
}
步骤10:测试swagger
访问地址:http://localhost:8080/swagger-ui/index.html
知识点
restful风格
学生管理
/student 查询 get
/student 新增 post
/student 更新 put
/student/1 删除 delete
/student/1 根据id查询 get
9. 设置springboot自动重启
9.1 springboot启动banner修改
在yml文件中配置:
spring:
banner:
location: banner.txt
resourses根路径下存放 banner.txt
。
9.2 设置自动重启
步骤1:
在pom.xml文件中加入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
步骤2:
勾选idea中的
步骤3:
按住ctrl+shift+alt+/
弹出菜单,选择Registry
勾选
步骤4:
- 重新启动服务器
- 修改源文件
- 切换到浏览器,查看效果
- 再切换会idea,看控制台,已经自动重启
9.3 自动重启设置原理
Springboot提供的重启技术,通过两个类的加载器来完成。ClassLoader
不会更改的类(来自第三方的jar包)被夹在到BaseClassLoader中,
会更改的类被夹在到RestartClassLoader
9.4 排除自动重启资源
有一些资源,在更改是不一定需要触发自动重启。比如thymeleaf,
配置排除的目录
spring:
devtools:
restart:
exclude: static/**,public/**,templates/**
10. springboot配置文件位置
springboot启动是会自动查找和加载application.properties
和application.yml
或者application.yaml
。
从一下位置
fileL./config/
file:./
classpath:/config/
classpath:./
优先级从上到下。
如果文件没那个不是默认名,需要通过 --spring.config.name=文件名(不要写扩展名)
进行设置
或者(文件已经生成jar)
java -jar 包名.jar --spring.config.name=文件名(不要写扩展名)
11. yaml文件
11.1 yaml文件的语法
- yaml以数据为中心,比properties和xml更适合做配置文件
- 和properties文件相比,更简洁。
- 和xml文件相比,少了结构化代码,数据更直接。
- 以空格的缩进程度来控制层级关系。
- 大小写敏感。
- 支持字面值、对象、数组数据结构,也支持复合结构。
- 数据和前缀属性中间要有空格。
- 字符串可以不加引号,如果需要处理特殊字符,需要使用双引号。
- 使用集合、数组的时候,需要使用“-”,后面有空格。
11.2 测试基本数据类型
name: 张三
age: 12
money: 123.45
birth: 1990/01/12
11.3 将yml封装到实体类中
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
yaml
com:
liqun:
model:
user:
name: 张三
age: 23
gender: 男
money: 234.45
birth: 1990/01/12
实体类:
@Data
@Component
@ConfigurationProperties(prefix = "com.liqun.model.user")
public class User {
private String name;
private int age;
private String gender;
private double money;
private Date birth;
}
Controller中引入实体类:
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private User user;
@GetMapping("/userObj")
public User user(){
return user;
}
}
11.4 将数据封装到Environment对象
通过Environment对象的getProperties方法,获取yml文件中的数据
com:
liqun:
model:
user:
name: 张三
age: 23
gender: 男
money: 234.45
birth: 2023/01/12
projectName: springboot
@Resource
private Environment env;
@GetMapping("env")
public Object ev(){
System.out.println(env.getProperty("projectName")); //springboot
System.out.println(env.getProperty("com.liqun.model.user.name")); //张三
return "sucess";
}
11.5.1 List类型
likes:
- 打球
- 游泳
- 游戏
11.5.2 Set类型
set: [xxx,yyy,zzz]
11.5.3 Map类型
map:
k1: v1
k2: v2
map1: {k1: v1,k2: v2,k3: v3}
11.5.4 集合封装对象类型
stuList:
- {name: 张三,age: 22}
- {name: 李四,age: 30}
stuList2:
- name: 王五
age: 33
- name: 高小红
age: 32
11.5.5 @ConfigurationProperties注解
查看自动配置,
redis的配置
@ConfigurationProperties(prefix = "spring.redis")
11.6 yaml 松弛绑定
springboot使用一些宽松的规则将Environment属性绑定到@ConfigurationProperties bean。因此Environment属性名和bean属性名称之间不需要完全匹配。例如: context-path绑定到contextPath, 大写的PORT 绑定到小写的port
对于userName属性,下面四种方式,都可以绑定
com:
liqun:
model:
user:
# user-name: 张三
# userName: 高小红
# user_name: 牟心智
USER_NAME: 王五
属性 | 用法 |
---|---|
user-name | 烤肉串风格,推荐用于 .properties和.yml文件 |
userName | 标准的驼峰式语法 |
user_name | 下划线表示法,也是在.properties和.yml文件使用的另一种格式 |
USER_NAME | 大写格式,在使用系统环境变量时推荐使用 |
11.7 多环境配置
spring profiles允许用户根据配置文件(dev,test,prod)来注册bean。因此,当应用程序开发运行时,只有某些bean可以加载。
而生产环境中,某些其他bean可以加载。
命名规范:application-{profiles}.yml 例如:application-dev.yml
案例: 在开发环境中,使用8080端口,在生产环境中,使用8081端口
分别开发两个不同的yml文件:
开发环境中的文件: application-dev.yml
方法1:
server:
port: 8080
生产环境中的文件: application-prod.yml
server:
port: 8081
全局配置文件中,指定哪个是被激活的:
spring:
profiles:
active: dev
方法2:
在启动时通过参数指定,优先级大于yml配置文件
通过启动参数:-Dspring.profiles.active=prod
指定。
方法3:
将项目使用maven打成jar报,在终端运行命令行:
java -jar --spring.profiles.active=prod
指定。
11.8 使用@Profile
案例:现有一个接口,来实现支付处理,一个实现类,来模拟是使用支付宝支付,一个实现类来模拟使用微信支付,支付的方式跟着开发环境的不同,选择不同的处理方式。
启动不同的换进,会调用不同的接口。
11.9 yaml文件使用el配置
11.10 随机值的引用
12. springboot整个junit
在pom.xml文件中放入junit相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
测试类
要写在test>java下面
@SpringBootTest(classes = AppServer.class) //括号里指明引导类的位置
@SpringBootTest
public class AppTest {
@Resource
private UserService service;
@Test
void contextLoads() {
List<User> list = service.list();
list.forEach(System.out::println);
}
}
心得:
1.工程中的包一定不要从其他工程复制,太坑了。
2.test 下面的包结构 一定要和main 下面的一致,不一致的话,下面提到的尽管指定了引导类的位置,虽然也能启动,但是测试类在独立的IOC容器, 使用不了Service等组件注入。
3.测试类@SpringBootTest(classes = AppServer.class) 尽量带上括号里面的,这样指定程序的主启动类,这样无论测试类放在那个包下,也不会出问题了。
13. springboot整合mybatis
pom.xml文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot2</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot_mybatis2</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入swagger3 的依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置application.yml文件:
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher # 解决swagger3报错的
# 配置数据库连接相关属性
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
启动类,自动扫描Mapper
@SpringBootApplication
@MapperScan(basePackages = "com.liqun.mapper") //启动类扫描Mapper
public class SpringBootMybatisApp {
public static void main(String[] args) {
SpringApplication.run(SpringBootMybatisApp.class,args);
}
}
在启动类上添加@MapperScan(basePackages = "com.liqun.mapper")
, 就不用再每个mapper接口上添加@mapper
注解了;如果不加这个@MapperScan
, 则需要每个mapper接口都需要添加@mapper
,有时候,很容易遗忘的。
当然,也可以配置不同包路径下的扫描,例如:
@MapperScan(basePackages = {"com.liqun.mapper","com.liqun.abc"})
不要用@ComponentScan(basePackages = {"com.liqun.mapper","com.liqun.abc","com.liqun.*"})
这种写法来代替@MapperScan(basePackages = {"com.liqun.mapper","com.liqun.abc"})
, 因为@ComponentScan
只会根据指定的扫描范围来扫描容器中包含@Controller 、@Service、@Mapper等组件。如果mapper接口中没有添加@Mapper
,那就老老实实的使用@MapperScan(basePackages = {"com.liqun.mapper","com.liqun.abc"})
.
配置mybatis日志打印
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
分页处理:
pom.xml文件中添加分页插件
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
分页处理代码:
@ApiOperation("分页显示学生信息")
@GetMapping("/{start}/{size}")
public Object listByPage(@PathVariable Integer start,@PathVariable Integer size){
PageHelper.startPage(start,size);
// service.selectByPage(start,size);
List<Student> list = service.selectList();
PageInfo<Student> pageInfo = new PageInfo<>(list);
return pageInfo;
}
日志打印:
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper.xml文件的位置配置:
如果mapper.xml文件和mapper.java接口是同一个路径,不需要配置。
如果mapper.xml文件和mapper.java接口不在同一个路径,需要做如下配置
mybatis:
mapper-locations: classpath:mapper/*.xml
如果使用xml配置文件,指定类的别名:
mybatis:
type-aliases-package: com.liqun.entity # 设置别名
14. mybatis-plus
官网:https://baomidou.com
14.1 整合mybatis
14.1.1 创建一个mybatis项目
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis_1</artifactId>
<!-- <properties>
<maven.complier.source>8</maven.complier.source>
<maven.complier.target>8</maven.complier.target>
</properties>-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
mybaits配置文件:
<?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>
<properties resource="db.properties"></properties> <!--引入数据库配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入我们自己编写的每一个接口的实现文件-->
<mappers>
<mapper resource="com/liqun/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
数据库配置文件:db.properites
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456
编写测试类:
public class TestMybatis {
@Test
public void test() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(Resources.getResourceAsReader("SqlMapConfig.xml"));
SqlSession sqlSession = factory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> list = mapper.selectList();
list.forEach(System.out::println);
sqlSession.close();
}
}
14.1.2 编写日志文件
log4j.rootLogger = debug,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
配置文件学习:
### 设置###
log4j.rootLogger = DEBUG,stdout,D,E,datasource
#%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},SSS为毫秒数(也可以写为SS,只不过SSS如果不足三位会补0),输出类似:2011-10-18 22:10:28,021
#%r: 输出自应用启动到输出该日志耗费的毫秒数
#%t: 输出产生日志的线程名称
#%l: 输出日志事件的位置,相当于%c.%M(%F:L)的组合,包括类全名、方法、文件名以及在代码中行数。例如:cn.xm.test.PlainTest.main(PlanTest.java:12)
#%c: 输出日志信息所属的类目,通常就是所在类的全名。可写为%c{num},表示取完整类名的层数,从后向前取,比如%c{2}取 "cn.qlq.exam"类为"qlq.exam"。
#%M: 输出产生日志信息的方法名%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中
#%%: 输出一个"%"字符
#%F: 输出日志消息产生时所在的文件名称
#%L: 输出代码中的行号
#%m: 输出代码中指定的消息,产生的日志具体信息
#%n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
#下面是配置将日志信息插入数据库,
#配置输出目标为数据库(假如要将日志在控制台输出,配置为log4j.appender. stdout =org.apache.log4j.ConsoleAppender;
# 将日志写入文件,配置为log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
#这样的配置在许多地方都要有,需要可查有关资料),当然你也可以自己扩展org.apache.log4j.jdbc.JDBCAppender这个类,
# 只需要在这里配置就可以了例如我们配置我自己扩展的MyJDBCAppender,配置为#log4j.appender.db=com.name.commons.MyJDBCAppender
log4j.appender.datasource=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.datasource.layout=org.apache.log4j.PatternLayout
log4j.appender.datasource.driver=com.mysql.cj.jdbc.Driver
#定义什么级别的错误将写入到数据库中
log4j.appender.datasource.Threshold = DEBUG
log4j.appender.datasource.BufferSize=1
#设置缓存大小,就是当有1条日志信息是才忘数据库插一次,我设置的数据库名和表名均为user
log4j.appender.datasource.URL=jdbc\:mysql\://localhost\:3306/logDB?characterEncoding\=UTF8&zeroDateTimeBehavior\=convertToNull&serverTimezone=UTC
log4j.appender.datasource.user=root
log4j.appender.datasource.password=123456
log4j.appender.datasource.sql=insert into logmsg (class,method,create_time,log_level,log_line,msg) values ('%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%l','%m')
14.1.3 加入mybatis-plus
pom.xml文件修改
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis_1</artifactId>
<!-- <properties>
<maven.complier.source>8</maven.complier.source>
<maven.complier.target>8</maven.complier.target>
</properties>-->
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<!--<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.0-alpha7</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
修改Mapper.java文件,继承BaseMapper<实体类》
public interface StudentMapper extends BaseMapper<Student> {
// List<Student> selectList();
}
修改测试类,将SqlSessionFactoryBuilder对象创建MybatisSqlSessionFactoryBuilder类的对象。
@Test
public void test() throws IOException {
SqlSessionFactoryBuilder builder = new MybatisSqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(Resources.getResourceAsReader("SqlMapConfig.xml"));
SqlSession sqlSession = factory.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student(100, "高淑红", 32, "女");
int insert = mapper.insert(student);
sqlSession.commit();
System.out.println(insert);
List<Student> list = mapper.selectList(null);
list.forEach(System.out::println);
sqlSession.close();
}
14.2 mybatis整合spring
**步骤1 :**在pom.xml文件中添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis_spring</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.0-alpha7</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
步骤2: 配置log4j.properties 和db.properties
log4j.rootLogger = debug,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456
步骤3: 编写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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
">
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<--驱动类的名字不需要配置,会根据url自动改的去加载,会知道使用的是哪种数据库-->
</bean>
<!--配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置mapper的扫描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.liqun.mapper"/>
</bean>
</beans>
步骤4: 编写实体类
@Data
public class Student {
private Integer id;
private String StudentName;
private String gender;
private Integer age;
}
步骤5: 编写mapper接口
public interface StudentMapper extends BaseMapper<Student> {
}
步骤6: 编写测试程序:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSprintMP {
@Resource
private StudentMapper mapper;
@Test
public void testList(){
List<Student> students = mapper.selectList(null);
students.forEach(System.out::println);
}
}
14.3 mybatis-plus整合springboot
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- <parent>
<artifactId>springboot2</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot_mybatisplus</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
实体类
@Data
public class Student {
private Integer id;
private String studentName;
private Integer age;
private String gender;
}
mapper接口
public interface StudentMapper extends BaseMapper<Student> {
}
启动类
@SpringBootApplication
@MapperScan(basePackages = {"com.liqun.mapper"})
public class MPServer {
public static void main(String[] args) {
SpringApplication.run(MPServer.class,args);
}
}
测试类
@SpringBootTest(classes = MPServer.class )
public class MPtest {
@Resource
private StudentMapper mapper;
@Test
public void testMapper(){
List<Student> students = mapper.selectList(null);
students.forEach(System.out::println);
}
}
14.4 详解BaseMapper
insert
deleteById
deleteById
deleteByMap
delete
deleteBatchIds
updateById
update
selectById
selectBatchIds
selectByMap
selectOne
exists
selectCount
selectList
selectMaps
selectObjs
selectPage
selectMapsPage
14.4.1 插入数据
配置了mybatis-plus的日志打印
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
新增的操作:
创建一个实体类对象
使用@TableId(type=IdType.AUTO)
指定主键的生成策略
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true) //链式
@TableName("student")
public class Student {
@TableId(type = IdType.AUTO)
private Integer id;
private String studentName;
private Integer age;
private String gender;
}
调用Mapper的insert方法,执行保存。
14.4.2 @TableField注解
用法:
1.处理对象的属性和表字段名不匹配。
2.对象的属性在表中不存在。
3.隐藏对象属性在表中的查询。
public class Student {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value = "name") //荡子算名和属性名不匹配时配置
private String studentName;
@TableField(select = false) //这个字段查询不返回值
private Integer age;
@TableField(exist = false) //表明这个字段在数据库表中不存在
private String gender;
}
14.4.3 删除处理
14.4.3.1 按指定id删除
@Test
void deleTest(){
Student student = new Student();
student.setId(100000);
int i = mapper.deleteById(student);
System.out.println("i==="+i);
}
14.4.3.2 按给定的Map条件删除
@Test
void deleteTest(){
HashMap<String, Object> map = new HashMap<>();
map.put("student_name","木木");
int i = mapper.deleteByMap(map);
System.out.println("i==="+i);
}
14.4.3.3 批量删除给定id数据
@Test
void deleBacthIds(){
List<Integer> ids = Arrays.asList(100,1001);
int i = mapper.deleteBatchIds(ids);
System.out.println("i==="+i);
}
14.4.3.4 逻辑删除处理
在application.yml文件中做配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
修改数据库表结构,增加一个字段deleted
,默认值是0;
在3.0.0版本之前,需要加入@TableLogic
注解
@TableLogic
private Integer deleted;
14.4.3.5 使用条件构造器删除
@Test
void deleteWQ2(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.eq("gender","男")
.like("student_name","顾");
mapper.delete(wrapper);
}
@Test
void deleteQW(){
Student student = new Student();
student.setStudentName("高小红").setGender("男");
QueryWrapper<Student> wrapper = new QueryWrapper<>(student);
mapper.delete(wrapper);
}
//使用Lambda方式
@Test
void delete2(){
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
wrapper.like(Student::getStudentName,"高")
.eq(Student::getAge,32);
mapper.delete(wrapper);
}
//判定booleann类型的值,必须满女足给定的条件
@Test
void delete3(){
Student student = new Student();
student.setStudentName("高").setGender("nv");
QueryWrapper<Student> wrapper = new QueryWrapper<>();
// wrapper.eq(!StringUtils.isNullOrEmpty(student.getGender()),"gender",student.getGender())
// .like(!StringUtils.isNullOrEmpty(student.getStudentName()),"student_name",student.getStudentName());
LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.like(!StringUtils.isNullOrEmpty(student.getStudentName()),Student::getStudentName,student.getStudentName());
wrapper.eq("gender","男")
.like("student_name","高");
mapper.delete(lambdaQueryWrapper);
}
14.4.4 修改处理
@Test
void updateById(){
Student student = new Student();
student.setAge(30).setGender("女").setId(4);
mapper.updateById(student);
}
@Test
void update1(){
Student student = new Student();
// student.setGender("女").setAge(35);
student.setAge(32).setGender("女");
UpdateWrapper<Student> wrapper = new UpdateWrapper<>();
wrapper.likeRight("student_name","高");
mapper.update(student,wrapper);
}
@Test
void update2(){
UpdateWrapper<Student> wrapper = new UpdateWrapper<>();
wrapper.set("gender","女").set("age","31")
.likeRight("student_name","高");
// mapper.update(new Student(),wrapper); //new Student() 可以写成null
mapper.update(null,wrapper);
}
@Test
void update3(){
LambdaUpdateWrapper<Student> wrapper = new LambdaUpdateWrapper<>();
wrapper.set(Student::getGender,"女").set(Student::getAge,"25")
.likeRight(Student::getStudentName,"顾");
// mapper.update(new Student(),wrapper); //new Student() 可以写成null
mapper.update(null,wrapper);
}
14.4.5 查询处理
@Test
//主键查询
void selectById(){
Student student = mapper.selectById(4);
System.out.println(student);
}
@Test
void selectByIds(){
List<Student> students = mapper.selectBatchIds(Arrays.asList(4, 5));
students.forEach(System.out::println);
}
@Test
void selectByMap(){
Map<String,Object> map = new HashMap<>();
map.put("student_name","牟心智");
List<Student> students = mapper.selectByMap(map);
students.forEach(System.out::println);
}
@Test
void selectOne(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.eq("student_name","牟心智");
Student student = mapper.selectOne(wrapper); //查询多条会报错
System.out.println(student);
}
@Test
void exists(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.eq("student_name","高小红");
boolean exists = mapper.exists(wrapper);
System.out.println(exists);
}
@Test
void count(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高");
Long aLong = mapper.selectCount(wrapper);
System.out.println(aLong);
}
@Test
//查询结果以map封装
void selectMaps(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高");
List<Map<String, Object>> list = mapper.selectMaps(wrapper);
list.forEach(e->{
e.forEach((k,v)->{
System.out.println(k+"\t"+v);
});
});
}
@Test
//只返回第一个字段的值
void selectObjs(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高");
List<Object> objects = mapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}
@Test
void selectList(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高");
List<Student> students = mapper.selectList(wrapper);
students.forEach(System.out::println);
}
@Test
void selectList2(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
// wrapper.like("student_name","高")
// .or()
// .eq("gender","女");
List<Student> students = mapper.selectList( null);
students.forEach(System.out::println);
}
@Test
void selectList3(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高")
.or()
.eq("gender","女");
List<Student> students = mapper.selectList( wrapper);
students.forEach(System.out::println);
}
@Test
void selectList4(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高").eq("gender","女")
.or()
.eq("gender","女");
List<Student> students = mapper.selectList( wrapper);
students.forEach(System.out::println);
}
@Test
//姓高 and (age=女or age>30)
void selectList5(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("student_name","高")
.and(i->i.eq("gender","女").or()
.gt("age",30));
List<Student> students = mapper.selectList( wrapper);
students.forEach(System.out::println);
}
@Test
//排序
void selectListOrderBy(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("age").orderByAsc("id");
List<Student> students = mapper.selectList(wrapper);
students.forEach(System.out::println);
}
@Test
//实现子查询
void selectSub(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.inSql("teacher_id","select id from teacher where teacher_name ='王老师'");
List<Student> students = mapper.selectList(wrapper);
students.forEach(System.out::println);
}
14.4.6 分页处理
创建一个分页插件的配置类
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
@Test
void selectPage(){
Page<Student> page = new Page<>(1,2);
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.likeRight("student_name","高");
mapper.selectPage(page,wrapper);
System.out.println(page);
List<Student> records = page.getRecords(); // 查询的数据
long total = page.getTotal(); //总记录数
long pages = page.getPages(); //总页数
long current = page.getCurrent(); //当前页
long size = page.getSize(); // 每页显示 ?条数据
boolean b = page.hasPrevious(); //是否有上一页
boolean b1 = page.hasNext(); //是否有下一页
}
@Test
void selectMapsPage(){
Page<Map<String,Object>> page = new Page<>(1,2);
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.likeRight("student_name","高");
mapper.selectMapsPage(page,wrapper);
System.out.println(page);
List<Map<String,Object>> records = page.getRecords(); // 查询的数据
long total = page.getTotal(); //总记录数
long pages = page.getPages(); //总页数
long current = page.getCurrent(); //当前页
long size = page.getSize(); // 每页显示 ?条数据
boolean b = page.hasPrevious(); //是否有上一页
boolean b1 = page.hasNext(); //是否有下一页
records.forEach(System.out::println);
records.forEach(map->map.forEach((k,v)-> System.out.println(k+"\t"+v)));
}
14.4.7 自动义查询语句处理
要在yml.xml文件中配置mapper.xml文件路径和别名
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
type-aliases-package: com.liqun.entity
编写mapper接口和xml
测试:
14.5 主键生成策略
五中策略
- auto:数据库id自增
- assign_id:通过雪花算法,生成id(number或string)
- assign_uuid:使用UUID,主键string类型 32位长字符串(包含数字和字母)
- nput:用户输入ID
- none:没有指定主键的类型(注解里使用,跟随全局。全局里使用,相当于input)
在yaml配置文件中配置全局主键生成策略
mybatis-plus:
configuration:
db-config:
id-type: auto
14.6 自动填充功能
实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
接口的实现类:
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 在插入时完成自动天车工功能
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
this.strictInsertFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
}
@Override
public void updateFill(MetaObject metaObject) {
// 在更新时完成自动天车工功能
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
}
}
将数据库表中加入两个字段
create_time datetime类型
update_time datetime类型
在实体类中加入两个属性,并加入fill规则
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
插入数据库表时,createTime和updateTime会自动插入数据,
更新数据库表时,updateTime会自动更新处理。
14.7 通用枚举
使用场景
- 用户性别 男 女 未知
- 商品状态 入库 出库
- 用户状态 激活 未激活
修改数据库表,加入status字段,类型是int
在yml文件中添加枚举扫描
mybatis-plus:
# 支持统配符 * 或者 ; 分割
typeEnumsPackage: com.baomidou.springboot.entity.enums
创建枚举
方式一: 实现Enum接口,重写getValue方法
public enum StatusEnum implements IEnum<Integer> {
IN(0,"入库"),
OUT(1,"出库");
StatusEnum(Integer stutusValue, String statusDesc) {
this.stutusValue = stutusValue;
this.statusDesc = statusDesc;
}
// @EnumValue
private final Integer stutusValue;
private final String statusDesc;
@Override
public String toString() {
return this.statusDesc;
}
@Override
public Integer getValue() {
return this.stutusValue;
}
}
方式二:在枚举类型的值上加入@EnmuValue
public enum StatusEnum {
IN(0,"入库"),
OUT(1,"出库");
StatusEnum(Integer stutusValue, String statusDesc) {
this.stutusValue = stutusValue;
this.statusDesc = statusDesc;
}
@EnumValue
private final Integer stutusValue;
private final String statusDesc;
@Override
public String toString() {
return this.statusDesc;
}
}
在Goods实体类对象上,加入属性,是枚举类型的
@Data
public class Goods {
// @TableId(type= IdType.AUTO)
// @TableId(type = IdType.ASSIGN_ID)
@TableId(type = IdType.ASSIGN_UUID)
private String id;
private String name;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
//创建枚举类型
private StatusEnum status;
}
14.8 Service的接口和实现类
新增一个service接口,击沉gIService接口
public interface StudentService extends IService<Student> {
}
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
新增一个service实现类,继承ServiceImpl,实现自定义的service接口
14.9 多数据源
步骤1:导入依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
步骤2:配置yml文件:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
dynamic:
primary: master
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
slave_1:
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
步骤4:在Service时尚加入@DS(“数据源名称”)
@Service
@DS("master")
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
@Service
@DS("slave_1")
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
}
@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解。
14.10 乐观锁插件
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version 不对,就更新失败
配置乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
创建数据库表,增加version
字段
实体类添加@Version
注解
@Data
public class Bank {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private Integer money;
@Version
private Integer version;
}
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
14.11 ActiveRecord操作
ActiveRecord(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
ActiveRecord一直广受动态语言(PHP、Ruby等)的喜爱,而java作为准静态语言,对应ActiveRecord往往只能感叹其优雅,所以MP也在AR道路上进行了一定的探索。
支持ActiveRecord模式:
- 支持ActiveRecord形式调用,实体类只需继承Model类即可进行强大的CRUD操作。
- 需要项目中已注入对应实体的BaseMapper。
继承实体类Model:
@Data
@Accessors(chain = true) //支持链式编程
public class Emp extends Model<Emp> {
private Integer id;
private String name;
private String addr;
}
使用测试:
@Test
void testAR(){
Emp emp = new Emp();
emp.setName("李四").setAddr("天津");
boolean insert = emp.insert();
System.out.println(insert);
}
这里有个问题:多数据源的情况下,这个怎么选择不同的数据源呢?
14.12 代码生成器
步骤1:在pom.xml文件中加入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot2</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot_mybatisplus_generator</artifactId>
<properties>
<java.verson>8</java.verson>
</properties>
<dependencies>
<!--模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
yaml 文件:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
mvc:
pathmatch:
matching-strategy: ant_path_matcher # 解决swagger3报错的
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted
测试生成器:
@Test
void Generator(){
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8", "root", "123456")
.globalConfig(builder -> {
builder.author("滨海之君") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(".\\src\\main\\java"); // 指定输出目录
})
// .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
// int typeCode = metaInfo.getJdbcType().TYPE_CODE;
// if (typeCode == Types.SMALLINT) {
// // 自定义类型转换
// return DbColumnType.INTEGER;
// }
// return typeRegistry.getColumnType(metaInfo);
//
// }))
.packageConfig(builder -> {
builder.parent("com.liqun") // 设置父包名
.moduleName("generator"); // 设置父包模块名
// .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_emp") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
统一返回结果对象:
public interface ResultCode {
Integer SUCCESS = 20000;
Integer ERROR = 20001;
}
@Data
@Accessors(chain = true)
public class Result {
private Boolean isSuccess;
private Integer code;
private String message;
private Map<String,Object> data;
public static Result success(){
return new Result().setIsSuccess(true)
.setCode(ResultCode.SUCCESS)
.setMessage("操作成功")
.setData(new HashMap<>());
}
public static Result error(){
return new Result().setIsSuccess(false)
.setCode(ResultCode.ERROR)
.setMessage("操作失败")
.setData(new HashMap<>());
}
public Result setData(HashMap<String,Object> data){
this.data = data;
return this;
}
public Result setData(String key,Object value){
this.data.put(key,value);
return this;
}
}
对于mapper.xml文件的使用
在yml文件中配置mapper.xml的位置和别名个
mybatis-plus:
mapper-locations: mapper/**/*.xml
type-aliases-package: com.liqun.generator.entity
在生成器中,设置mapper.xml文件生成的位置
14.13 使用MybatisX插件
功能1: 在Mapper.java 和Mapper.xml 之间切换。
功能2: 生成代码
步骤1:配置idea的数据库链接
步骤2:
功能3:
生成新增
生成删除
生成查询
生成修改
15. thymeleaf模板引擎
配置pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot2</artifactId>
<groupId>com.liqun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot_thymeleaf</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置yml文件
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
thymeleaf:
cache: false # (默认是打开的)。 开发环境下,关闭缓存,生产环境下,打开缓存
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted
创建模板:
File>Settings>Editor>file and Code Templates ,
选择File对话框,点击加号,
新建 名称 thymeleaf ,扩展名为html
thymeleaf 中${} 报红处理
解决方式1:
<!--/*@thymesVar id="title" type=""*/-->
解决方式2:
在<!DOCTYPE html>
下面加入
<!--suppress ALL-->
16. 上传处理
网页:
Controller:
yml配置文件
savePath: c:/uploadtest
spring:
servlet:
multipart:
max-file-size: 104857600
17. springboot整合redis操作
在yml文件中配置:
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
username: root
password: 123456
redis:
port: 6379
host: localhost
mybatis-plus:
type-aliases-package: com.liqun.entity
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Controller中,使用RedisTemplate
@RestController
public class RedisController {
@Resource
private RedisTemplate redisTemplate;
private StringRedisTemplate stringRedisTemplate; //这个可以解决乱码
@GetMapping("/{key}")
public Object get(@PathVariable String key){
Object o = stringRedisTemplate.opsForValue().get(key);
return o;
}
@PostMapping("/{key}/{value}")
public Object set(@PathVariable String key,@PathVariable String value){
stringRedisTemplate.opsForValue().set(key,value);
return "ok";
}
}
修改RedisTemplate序列化实现类:
@Configuration
public class RedisConfig {
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return redisTemplate;
}
}
模拟缓存操作:
@RestController
@RequestMapping("/member")
public class MenberController {
@Resource
private MemberService memberService;
@Resource
private RedisTemplate redisTemplate;
@GetMapping("/{id}")
public Object getById(@PathVariable int id){
String key = "member:"+id;
//从缓存中查询数据
Object member = redisTemplate.opsForValue().get(key);
if(member==null){
//从数据库中查询
System.out.println("查询数据库");
Member m = memberService.getById(id);
//将查询结果仿佛缓存
redisTemplate.opsForValue().set(key,m);
return m;
}else {
System.out.println("查询缓存数据成功");
return member;
}
}
}
可以设置redis客户端实现:
spring:
redis:
client-type: lettuce