1. 新建spring-boot项目,pom依赖文件如下:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>wei</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>wei</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.3</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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<!-- lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<!-- aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. yml配置:
server:
port: 6789
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test_zsw
username: zsw
password: 123456
driver-class-name: com.mysql.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.test.wei.biz.*.entity
3. 启动类(加上mapperScan)
package com.zsw.six;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.test.wei.biz.*.mapper")
@SpringBootApplication
public class SixApplication {
public static void main(String[] args) {
SpringApplication.run(SixApplication.class, args);
}
}
mybatis配置类
package com.test.wei.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {
/***
* plus 的性能优化
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
// SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
//performanceInterceptor.setMaxTime(1000);
// SQL是否格式化 默认false
performanceInterceptor.setFormat(false);
return performanceInterceptor;
}
/**
* mybatis-plus 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
page.setDialectType("mysql");
return page;
}
}
4. 代码自动生成类:
package com.zsw.six.generator;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
/**
* 代码生成器
*/
public class MyGenerator {
public static void main(String[] args) {
String[] tables = new String[] { "t_vehicle_insurance" };
String[] tablePrefix = new String[] { "t_" };
String mapperDir = "/src/main/resources/mapper/insurance/";
String pack = "com.zsw.wei.biz.insurance";
executeCode(pack, tables, tablePrefix, mapperDir);
}
private static void executeCode(String pack, String[] tables, String[] tablePrefix, String mapperDir) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
// 是否覆盖已有文件
globalConfig.setFileOverride(true);
// 生成文件的输出目录
String projectPath = System.getProperty("user.dir");
globalConfig.setOutputDir(projectPath + "/src/main/java");
// globalConfig.setOutputDir("C:\\workspaceTest\\generatorTest");
// 设置service名称,自动生成的带有I
globalConfig.setServiceName("%sService");
// 开发人员
globalConfig.setAuthor("zhangshiwei");
// 是否打开输出目录
globalConfig.setOpen(true);
// 开启 BaseResultMap
globalConfig.setBaseResultMap(true);
// 指定生成的主键的ID类型
globalConfig.setIdType(IdType.AUTO);
// 时间类型对应策略: 只使用 java.util.date 代替
// gc.setDateType(DateType.ONLY_DATE);
mpg.setGlobalConfig(globalConfig);
// 数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
// 从视图获取
//dsc.setSchemaName("V_LAW_CAMERA");
dataSourceConfig
.setUrl("jdbc:mysql://127.0.0.1:3306/test");
dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
dataSourceConfig.setUsername("test");
dataSourceConfig.setPassword("test");
mpg.setDataSource(dataSourceConfig);
// 包配置
PackageConfig pc = new PackageConfig();
// 父包名.如果为空,将下面子包名必须写全部,否则就只需写子包名
pc.setParent(pack);
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
if (StringUtils.isEmpty(pc.getModuleName())) {
return projectPath + mapperDir + tableInfo.getXmlName() + ".xml";
} else {
return projectPath + mapperDir + pc.getModuleName() + "/" + tableInfo.getXmlName() + ".xml";
}
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
// 数据库表映射到实体的命名策略: 下划线转驼峰命名
strategy.setNaming(NamingStrategy.underline_to_camel);
// 数据库表字段映射到实体的命名策略: 下划线转驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// 【实体】是否为lombok模型(默认 false)
strategy.setEntityLombokModel(true);
// 需要包含的表名,允许正则表达式(与exclude二选一配置)
strategy.setInclude(tables);
// 驼峰转连字符
strategy.setControllerMappingHyphenStyle(true);
// 表前缀
strategy.setTablePrefix(tablePrefix);
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
5. 生成的代码:
![]() |
|
|
|
|
|
![]() |
|
注意:未配置mybatis相关二级缓存,先把cache这行删除!
6. 测试:
package com.zsw.six.order;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zsw.six.biz.order.entity.Order;
import com.zsw.six.biz.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
/**
* 订单测试类
*
* @author zhangshiwei
* @since 2019年7月2日 下午2:13:42
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTest {
@Autowired
private OrderService orderService;
@Test
public void findListTest() {
EntityWrapper<Order> orderEntityWrapper = new EntityWrapper<>();
List<Order> orderList = orderService.selectList(orderEntityWrapper);
log.info("无条件查询订单信息orderList:{}", orderList.size());
}
}
7. 测试结果:
![]() |
8. mybatis-plus生成的代码,有baseMapper,可以直接使用其中的很多方法;
之前整合老是报错:完全是因为引入的jar包有误!!!找了好久,一个个对比才发现的,算是个大坑了!
二.打印日志的配置
1.在application.yml中
# 日志配置
logging:
config: classpath:logback.xml
2.新增日志配置文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- %m输出的信息, %p日志级别, %t线程名, %d日期, %c类的全名, %i索引 -->
<!-- appender是configuration的子节点,是负责写日志的组件 -->
<!-- ConsoleAppender把日志输出到控制台 -->
<!-- <property name="CONSOLE_LOG_PATTERN" -->
<!-- value="%date{yyyy-MM-dd HH:mm:ss} | %highlight(%-5level) | %boldYellow(%thread) | %boldGreen(%logger) | %msg%n"/> -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--<pattern>${CONSOLE_LOG_PATTERN}</pattern> -->
<!--<pattern>%date{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) (%file:%line\)- %m%n</pattern>-->
<!--<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{360} - %msg%n</pattern>-->
<pattern>%d [%thread] %highlight(%-5level) [%c] [%F:%L] [trace=%X{traceId}] - %msg%n</pattern>
<!-- 控制台也要使用utf-8,不要使用gbk -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 1.先按日期存日志,日期变了,将前一天的日志文件名重命名为xxx%日期%索引,新的日志仍然是sys.log -->
<!-- 2.如果日期没有变化,但是当前日志文件的大小超过1kb时,对当前日志进行分割 重名名 -->
<appender name="syslog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>mylog/sys.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:log/sys.2017-12-05.0.log -->
<fileNamePattern>mylog/sys.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
<maxHistory>30</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->
<maxFileSize>10240KB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- pattern节点,用来设置日志的输入格式 -->
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<!-- 记录日志的编码 -->
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>
<!-- 控制台日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.appley为根包,也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="com.test.wei" level="DEBUG">
<appender-ref ref="syslog"/>
</logger>
</configuration>
三.整合线程池druid
1.application.yml数据库连接配置修改
spring:
datasource:
# 线程池配置
druid:
url: jdbc:mysql://127.0.0.1:3306/test_zsw
username: zsw
password: 123456
driver-class-name: com.mysql.jdbc.Driver
# druid管理界面
# http://localhost:6789/druid/login.html
# 用户名密码是在DruidConfiguration配置中的loginUsername和loginPassword
# 初始化线程数量大小,最小,最大
initialSize: 5
minIdle: 5
maxActive: 20
# 配置获取连接等待超时时间,单位是毫秒
maxWait: 60000
# 配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 用来检测连接是否有效的sql,要求是一个查询语句
# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
validationQuery: SELECT 1 FROM DUAL
# 建议配置为true,不影响性能,并且保证安全性。
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle;在mysql下建议关闭。
poolPreparedStatements: false
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
maxPoolPreparedStatementPerConnectionSize: 0
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
filters: stat,wall,logback
# Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
# Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔
aop-patterns: com.test.wei.biz.*
# 合并执行的相同sql,避免因为参数不同而统计多条sql语句
# 用来配置SQL慢的标准,执行时间超过slowSqlMillis的就是慢
connection-properties:
druid.stat.mergeSql: true
druid.stat.slowSqlMillis: 5000
2.线程池相关配置
package com.test.wei.config;
import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class DruidConfiguration {
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
log.info("配置数据源druidDataSource:{}", druidDataSource);
return druidDataSource;
}
/**
* 注册一个StatViewServlet
*/
@Bean
public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() {
log.info("init Druid Servlet Configuration");
// org.springframework.boot.context.embedded.ServletRegistrationBean提供类的进行注册.
ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>(
new StatViewServlet(), "/druid/*");
// 添加初始化参数:initParams
// 白名单:
servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
// IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to
// view this page.
servletRegistrationBean.addInitParameter("deny", "192.168.1.73");
// 登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername", "zhangshiwei");
servletRegistrationBean.addInitParameter("loginPassword", "123456");
// 是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
/**
* 注册一个:filterRegistrationBean ------ 配置监控服务器
*/
@Bean
public FilterRegistrationBean<WebStatFilter> druidStatFilter() {
FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(
new WebStatFilter());
// 添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
// 添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
3.测试线程池druid监控
![]() |
四.springboot整合cache二级缓存:
1.springboot默认已经开启了二级缓存,不需要再手动开启,但是要加jar包:
<!-- 开启二级缓存 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
2.实体类实现Serializable接口,mybatis-plus的model已完成;
3.mapper中开启二级缓存: 在xml中加<cache/> 或 mapper.java文件上加注解@CacheNamespace
4.测试:
第一次访问:
![]() |
第二次访问:
![]() |
5.二级缓存的应用场景:
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
一般情况,不要开启二级缓存!
局限性太大!
比如一个mapper.xml中的查询sql,关联了多个表! 其中一个表的数据被修改了,又没到刷新时间,就无法获取到最新的数据!!!
使用二级缓存,慎之又慎!!!