# leo-springboot **Repository Path**: wangss3/leo-springboot ## Basic Information - **Project Name**: leo-springboot - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-17 - **Last Updated**: 2021-11-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # springboot项目脚手架 [![star](https://gitee.com/wangss3/leo-springboot/badge/star.svg?theme=dark)](https://gitee.com/wangss3/leo-springboot) [![fork](https://gitee.com/wangss3/leo-springboot/badge/fork.svg?theme=dark)](https://gitee.com/wangss3/leo-springboot) >本专栏是作者leo使用```SpringBoot```、```Mysql```等技术栈和偏向于DDD领域驱动设计方式,搭建的springboot模板项目。如果本项目能为您提供帮助,请给予支持(关注、点赞、分享)! > **作者:** leo,Java Developer,[:leo: CSDN 李白与孟浩然](https://blog.csdn.net/wang521qian/) **如何支持:** - 点击右上角Star :star: 给予关注 - 赏个鸡腿🍗 赞赏码 --- 雨后天晴写下、年华,
巫山云景彩霞、如画。
心似平远走**码**、飞驾,
整装年少风华、正恰。
搭建基础脚手架,方便后续快速开发,框架中主要集成springboot、常用jar、封装的工具类 ## 一、工程源码 **源码地址**: - [https://gitee.com/wangss3/leo-springboot](https://gitee.com/wangss3/leo-springboot) ## 二、项目架构 **目录结构**: - src/main/java 项目的源代码所在的目录 - src/main/resources 项目的资源文件所在的目录 - 其他目录结构见名知意 **引入功能**: - springboot 2.3.3 - commons-lang3 常用工具类、commons-io io操作工具类 - druid 数据库连接池 - spring-boot-starter-log4j2 日志组件 ## 三、引入组件 **log4j2日志组件引入**: springboot默认是使用logback来进行日志记录,本项目使用log4j2来记录日志,为避免冲突,需要在pom中排除logback。 ``` org.springframework.boot spring-boot-starter spring-boot-starter-logging org.springframework.boot ``` 也要注意其他jar中是否有引入。 引入log4j2依赖: ``` org.springframework.boot spring-boot-starter-log4j2 ``` 在src/main/resources/添加配置文件log4j2.xml,项目启动时log4j2会自动到这个目录加载。 也可以在application.properties中配置路径:```logging.config=classpath:log4j2.xml``` 使用案例: - @Slf4j - private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(***.class); --- 异步日志的配置方式: - 引入disruptor并发包 ``` com.lmax disruptor 3.4.2 ``` - 增加log4j2.component.properties配置文件,启用异步属性 - 在application.properties文件中指定使用的日志文件为:log4j2-async.xml ```logging.config=classpath:log4j2-async.xml``` - 使用```log.info("是否为异步日志:{}", AsyncLoggerContextSelector.isSelected());``` 语句判断是否开启异步日志 --- **springboot-javafx-support组件引入**: ``` de.roskenet springboot-javafx-support ${springboot-javafx-support.version} ``` 使用方法: ``` @SpringBootApplication @Slf4j public class LeoSpringbootJavafxApplication extends AbstractJavaFxApplicationSupport { public static void main(String[] args) { // DemoStageView视图类,CustomSplash启动动画类 launch(LeoSpringbootJavafxApplication.class, DemoStageView.class, new CustomSplash(), args); } @Override public void start(Stage stage) throws Exception { super.start(stage); } } ``` **druid连接池引入**: 本项目采用阿里的druid连接池进行数据库连接管理,引入jar如下:其中需要注意的是剔除springboot默认连接池HikariCP ``` org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.3 HikariCP com.zaxxer com.alibaba druid-spring-boot-starter 1.1.23 mysql mysql-connector-java 5.1.46 com.oracle ojdbc6 6.0 ``` druid配置数据库和参数设置: ``` # Spring Boot的数据源配置的默认类型是org.apache.tomcat.jdbc.pool.Datasource #配置druid连接池 #mysql数据源 spring.datasource.druid.mysql.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.mysql.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.druid.mysql.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 spring.datasource.druid.mysql.username=root spring.datasource.druid.mysql.password=root #oracle数据源 spring.datasource.druid.oracle.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.oracle.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.druid.oracle.url=jdbc:oracle:thin:@localhost:1521:ORCL spring.datasource.druid.oracle.username=test spring.datasource.druid.oracle.password=test # 连接池配置 spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 # 连接等待超时时间 spring.datasource.druid.max-wait=30000 # 配置检测可以关闭的空闲连接间隔时间 spring.datasource.druid.time-between-eviction-runs-millis=60000 # 配置连接在池中的最小生存时间 spring.datasource.druid.min-evictable-idle-time-millis=300000 #用来检测连接是否有效的sql 必须是一个查询语句 #mysql中为 select 'x' #oracle中为 select 1 from dual spring.datasource.druid.validation-query=select 'x' spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false #当数据库抛出不可恢复的异常时,抛弃该连接 spring.datasource.druid.exception-sorter=true # 打开PSCache,并且指定每个连接上PSCache的大小 #是否缓存preparedStatement,mysql5.5+建议开启 spring.datasource.druid.pool-prepared-statements=true spring.datasource.druid.max-open-prepared-statements=20 spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20 # 配置监控统计拦截的filters, 去掉后监控界面sql无法统计, 'wall'用于防火墙 spring.datasource.druid.filters=stat,wall #通过connectProperties属性来打开mergeSql功能;慢SQL记录 spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500 #合并多个DruidDataSource的监控数据 spring.datasource.druid.use-global-data-source-stat=true # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔 #spring.datasource.druid.aop-patterns=com.leo.servie.* # WebStatFilter配置 #spring.datasource.druid.web-stat-filter.enabled=true # 添加过滤规则 #spring.datasource.druid.web-stat-filter.url-pattern=/* # 忽略过滤的格式 #spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* # StatViewServlet配置 #spring.datasource.druid.stat-view-servlet.enabled=true # 访问路径为/druid时,跳转到StatViewServlet #spring.datasource.druid.stat-view-servlet.url-pattern=/druid/* # 是否能够重置数据 #spring.datasource.druid.stat-view-servlet.reset-enable=false # 需要账号密码才能访问控制台 #spring.datasource.druid.stat-view-servlet.login-username=druid #spring.datasource.druid.stat-view-servlet.login-password=druid123 # IP白名单 #spring.datasource.druid.stat-view-servlet.allow=127.0.0.1 # IP黑名单(共同存在时,deny优先于allow) # spring.datasource.druid.stat-view-servlet.deny=192.168.1.218 # 配置StatFilter spring.datasource.druid.filter.stat.log-slow-sql=true ``` 在启动类中排除druid自动加载的bean,否则项目启动会报错:```@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})`` 增加配置类,加载创建数据库连接,可参考:com.leo.base.db.config.DynamicDataSourceConfig.java 高版本druid需要配置@Configuration文件才能打开监控界面,例如:com/leo/base/config/DruidConfig.java 将spring监控也加入到druid中,例如:com/leo/base/config/SpringMonitoringConfig.java mysql-connector-java:8.0.21 和 mysql-connector-java:5.xx.xx 不同: - 驱动变为:com.mysql.cj.jdbc.Driver - 需要关闭:useSSL=false - 需要指定:serverTimezone=GMT%2B8 **集成redis功能**: 项目中数据的使用遵循28定律,大部分时间只有20%的数据被使用到,所以我们应该将热点数据进行缓存,以减轻数据库压力,redis功能jar引入: ``` org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 ``` 增加配置文件:application-redis.properties ``` spring.redis.host=127.0.0.1 spring.redis.port=6379 #Redis 索引(0~15,默认为 0) spring.redis.database=0 #Redis 密码,如果没有就默认不配置此参数 spring.redis.password= #Redis 连接的超时时间 spring.redis.timeout=30s #连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle=5 #连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle=10 #连接池最大连接数(使用负值表示没有限制) spring.redis.lettuce.pool.max-active=20 #连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.lettuce.pool.max-wait=1ms spring.redis.lettuce.shutdown-timeout=100ms #缓存失效时间(毫秒) spring.cache.redis.time-to-live=10000 ``` 正常来说,引入jar,配置完参数以后,就可以通过RedisTemplate和StringRedisTemplate两个类直接使用。但是为了方便使用,我们配置一个类RedisConfig, 重新生成一个RedisTemplate的bean,改写key和value的序列化方式。为了方便对redis进行操作,我们还要实现一个RedisUtil工具类,用来操作redis。 使用redis作为缓存,在启动类中加上@EnableCaching注解,就会开启缓存,springboot会自动生成一个RedisCacheManager,但是我们需要对RedisCacheManager进行 一些更改,所以会在配置类RedisConfig中进行重写,更方便使用。 针对缓存,我们主要介绍几个注解的使用: - @CacheConfig 这个注解在类上使用,用来描述该类中所有方法使用的缓存名称,当然也可以不使用该注解,直接在具体的缓存注解上配置名称 - @Cacheable 这个注解一般加在查询方法上,表示将一个方法的返回值缓存起来,默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值。这个方法的查询情况为: 如果先从缓存获取数据,如果有数据直接返回,没有数据在查询数据库。 ![Spring Cache中提供了root对象](src/main/resources/static/md/root.png) - @CachePut 这个注解一般加在更新方法上,当数据库中的数据更新后,缓存中的数据也要跟着更新,使用该注解,可以将方法的返回值自动更新到已经存在的key上。还可以加条件:```@CachePut(key = "#sno", condition = "#result != null")``` - @CacheEvict 这个注解一般加在删除方法上,当数据库中的数据删除后,相关的缓存数据也要自动清除,该注解在使用的时候也可以配置按照某种条件删除(condition属性)或者或者配置清除所有缓存(allEntries属性) - @Caching 组合注解 待补充。。。 异常处理,缓存雪崩等问题,不在整理。 **集成邮件发送功能**: 项目日常使用中,会需要使用到发送邮件进行通知,系统集成邮件功能引入jar: ``` org.springframework.boot spring-boot-starter-mail org.springframework.boot spring-boot-starter-freemarker ``` 因为涉及到文件上传,所以需要引入jar commons-fileupload 作为实现类: ``` commons-fileupload commons-fileupload 1.4 ``` - 首先配置文件上传实现类,指定上传文件得属性设置,请参考文件applicationContext-file.xml和文件application-file.properties - 其次配置mail属性,参考文件application-mail.properties ``` # 163 # 邮箱主机 spring.mail.host=smtp.163.com spring.mail.port=465 # 发送者的邮箱 spring.mail.username=18616345762@163.com # 邮箱秘钥 spring.mail.password=wangss123 # 开启qq邮箱的安全认证 spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true # 模板邮件路径 spring.mail.template=/mail/template.html ``` - 指定邮件模板templates/mail/templates.html,并进行配置 邮件发送demo请参考:com/leo/controller/MailTestController.java 存在bug:异步发送带附件得邮件时,因为springboot机制,在controller执行完成以后就会将缓存 得上传文件删除,所以导致异步线程执行得时候,找不到附件,从而发送失败。 ---- 已修复 ## 四、功能概述 **自路由功能**: 根据业务不同,数据体量不同,目前市面上多使用多数据源: - 主从分离 - 既有oracle数据库也有mysql数据库 - 多数据源 等情况,所以自己实现了动态路由功能,在包com.leo.base.db下实现,其中包含五个注解,如有需要可以自行修改增加: - @DynamicDataSource 动态路由,指定数据源,适用于增删改查,使用方式在方法上增加注解,并指定数据源:```@DynamicDataSource(value = "mysql")``` - @GlobalDataSource 全局路由,适用于全局表,用于查询,例如一些字典表等,使用方式在方法上增加注解,并指定表名:```@GlobalDataSource(tableName = "globalStudent")```,任取一个数据源进行指定 - @RandomDataSource 随机路由,用来搞笑的,适用于增删改查,使用方式:```@RandomDataSource(tableName = "randomStudent")``` - @ShardingDataSource 分片路由,根据表名获取分片字段,根据分片字段获取分片值,进行hash计算,得出要存入的数据源,适用于增删改查,使用方式:```@ShardingDataSource(tableName = "shardingStudent")``` - @UnionDataSource 广播路由(聚合路由),根据配置获取所有的数据源进行查询,如果返回结果是对象,则取第一个值,如果返回结果是集合,则进行合并返回,只用于查询```@UnionDataSource(tableName = "unionStudent")``` - @ReadWriteSeparationDataSource 读写分离路由,不在细讲,适用于增删改查,如果不需要复杂版的可以简化 结合配置文件,示例如下:applicationContext-routers.xml ``` ``` 分片路由算法说明:length总和为1024,count为分几片,每片占1024的多少比例,dataSourceKey要和count总和保持一致, ``` ``` **处理指定请求后缀**:(如果没有需要,则可以移除) 请参考文件:```com/leo/base/config/CustomWebMvcConfigurer.java``` **springboot的事件监听机制**: 涉及事件回调机制的几个类: - ApplicationContextInitializer - SpringApplicationRunListener - CommandLineRunner 常用 - ApplicationRunner 常用 ![springboot事件回调](src/main/resources/static/md/springboot事件回调.png) 案例位置:com/leo/base/initialize/* **springboot集成eventbus事件监听**: - 自定义注解 @EventBusListener - 启动完成以后,获取使用@EventBusListener注解的类,并注册到监听中 - 当事件触发以后,通知各个监听者 这里有一点需要注意:EventBus有同步和AsyncEventBus异步之分,异步时传入的线程池要注意,也可以使用@EnableAsync和@Async注解 使同步事件变成异步。推荐使用注解的方式 ## 五、项目演示 ## 六、专栏学习(自愿支持) ## 七、与我联系 ## 八、参与贡献 1. 如果您对本项目有任何建议或发现文中内容有误的,欢迎提交 issues 进行指正。 2. 对于文中我没有涉及到知识点,欢迎提交 PR。