Spring boot 相关
纠错
首先,bootstrap.yml作为配置文件,是在springcloud中实现的,而不是springboot!
sb根本就不会加载bootstrap.yml!
百度的答案都是sb中这两者区别,错到德玛西亚去了。
- 认识bootstrap.yml
在springcloud中,使用bootstrap首先加载一些配置,这部分是高优先级不会被后续覆盖的。
通常是用做加载配置中心配置。不要在这里配置其他属性,会出现很诡异的事。(我测了,配置0000,得出0)所以就乖乖的按照springcloud的建议来。最后,bootstrap.yml作为配置文件,是springcloud中的定义
Spring Cloud Open Fegin
FEIGN是走HTTP的,即使利用接口特性做成类RPC的方式,但也还是走HTTP的。但是就我使用感受,速度还行,比想象中要快。rpc固然速度比http快,但是你要考虑的稳定性、数据传输的可靠性、熔断保护,以及更方便的链路监控和追踪,这时候HTTP的优势就体现了。
Spring cloud的http从以下几个方面可以优化
- 换成okhttp3。
- 应用中不要做异步传输,防止异步等待,如果遇到异步场景,一定要利用好消息队列和缓存。
- 如果http1.1,有些场景利用keep-alive,减少连接损耗。
- 可以考虑尝试HTTP/2
Springboot2.x
- Spring boot 2.x 无法使用
servlet: context-path, 采用的是spring.webflux.base-path: - @ConditionalOnProperty 注解介绍
1 |
|
Springboot data redis 和data-elasticsearch中的netty冲突
使用场景
spring-data-elasticsearch和spring-boot-data-redis都是使用的netty作为通信框架, 如果在加载时优先加载redis 链接的bean, 那么后续es创建时会导致启动失败, 异常日志Caused by: java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]- 具体原因在elasticsearch项目的这个类中有实现, 原因是又针对netty的处理器配置设置了一次参数,导致nettyRutime时检测到重复赋值…
1 | package org.elasticsearch.transport.netty4; |
解决方案
- github的issus
- 将es配置优先加载
- 启动类中添加覆盖配置
1 | public static void main(String[] args) { |
- 启动时添加启动参数也可以覆盖配置
-Des.set.netty.runtime.available.processors=false
总结
如果集成了其他使用netty的相关框架在spring boot配置类中加载, 都会导致和
elasticserach配置冲突造成启动失败, 例如:spring-boot-starter-actuator中的elasticsearch健康检查配置
spring-boot中的@Order注解
- 通过@Order注解来注入集合时,指定顺序的场景, 首先我们定义两个Bean实现同一个接口,并添加上@Order注解
1 | public interface IBean { |
- 然后在一个测试bean中,注入IBean的列表,我们需要测试这个列表中的Bean的顺序是否和我们定义的@Order规则一致
1 |
|
- 根据我们的预期, anoBeanList集合中,anoBean2应该在前面
1 | ano order bean 1 |
- 只能决定使用顺序不能指定初始化加载顺序.
spring-boot 依赖外部jar的使用
依赖配置
1 | <dependency> |
打包配置
1 | <build> |
spring interceptor使用注意项
如不是特殊情况需要在拦截器interceptor中获取body的, 建议替换成filter实现或者一定要声明filter搭配interceptor进行request包装类来将body向下传递, 原因是在执行优先级
filter > interceptor > controller中的body内容是inputStream形式向下传递的, 如果在interceptor中取出了body内容, 会导致filter传递完的inputStream无法继续向下传递, 而controller无法获取到参数, 产生stream is closed异常
Spring boot validator 校验 和 独立配置返回消息内容整合
spring boot validator是由hibernate-validator实现的, hibernate-validator 使用的是 JSR-303 的默认ValidationMessages.properties包, 所以需要手动设置加载自定义springboot message 文件
官方解释: 指定用于解析验证消息的自定义
Spring MessageSource,而不是依赖 JSR-303 的默认ValidationMessages.properties包,在类路径中。 这可能指的是 Spring 上下文的共享messageSource
加载自定义消息配置文件
1 | /** |
问题:
LocalValidatorFactoryBean设置自定义的messageSource不生效, 是由于项目中有配置继承了WebMvcConfigurationSupport类, 导致Validator实例会被该配置中的OptionalValidatorFactoryBean类创建的LocalValidatorFactoryBean覆盖掉丢失messageSource
解决: 修改当前配置继承的WebMvcConfigurationSupport类替换成实现WebMvcConfigurer即可,这样会加载自定义重写的springmvc配置, spring mvc会判断是否加载了Validator直接使用
聚合工程多模块message文件的处理
- 重写spring-boot的
MessageSourceAutoConfiguration中的MessageSource不使用ResourceBundleMessageSource而使用ReloadableResourceBundleMessageSource
1 |
|
- 不重写配置, 直接在yaml设置多个文件
1 | spring: |
声明校验错误提示信息配置
- 设置引用变量
1 | # message.properties |
- 在实体类中属性上使用相关注解
1 |
|
- 还可以使用
MessageSource进行动态添加占位符参数, 调整返回的校验消息内容
1 | # message.properties |
异常处理方法
- 全局拦截, 在Controller声明的方法
1 |
|
- 如果是在方法层级校验, 需要设置自定义的校验器, 否则无法返回
mesages.properties的错误消息
1 | /** |
- 接口中使用注解方式
1 |
|
Springboot使用 @RequestPart
场景
使用可以需要将文件和对象分参数一起提交, 请求content-type类型是multipart/form-data传递
例子
- 前端参数封装example (by vue)
1 | const studentVo = { } |
- 后端接口example
1 |
|
总结
如果后端参数定义的是对象, 前端一定需要转换成blob类型, 否则会提示
org.springframework.web.HttpMediaTypeNotSupportedException: application/octet-stream....
spring boot 内置tomcat设置
1 |
|
Ali QL Express 工具使用
- 初始化
- 转换表达式
- 执行
Java Timer vs ExecutorService?
Q: I have code where I schedule a task usingjava.util.Timer. I was looking around and sawExecutorServicecan do the same. So this question here, have you usedTimerandExecutorServiceto schedule tasks, what is the benefit of one using over another?
Also wanted to check if anyone had used theTimerclass and ran into any issues which theExecutorServicesolved for them.
A:
According toJava Concurrency in Practice:
Timercan be sensitive to changes in the system clock,ScheduledThreadPoolExecutorisn’t.Timerhas only one execution thread, so long-running task can delay other tasks.ScheduledThreadPoolExecutorcan be configured with any number of threads. Furthermore, you have full control over created threads, if you want (by providingThreadFactory).- Runtime exceptions thrown in
TimerTaskkill that one thread, thus makingTimerdead :-( … i.e. scheduled tasks will not run anymore.ScheduledThreadExecutornot only catches runtime exceptions, but it lets you handle them if you want (by overridingafterExecutemethod fromThreadPoolExecutor). Task which threw exception will be canceled, but other tasks will continue to run.
If you can useScheduledThreadExecutorinstead ofTimer, do so.
One more thing… whileScheduledThreadExecutorisn’t available in Java 1.4 library, there is aBackport of JSR 166 (java.util.concurrent) to Java 1.2, 1.3, 1.4, which has theScheduledThreadExecutorclass.
Mapstruct 插件
- idea 安装mapstruct support 插件, 写expression好用
- 不同类型使用代码表达式转换,
@Mapping注解可以设置某个属性映射关系,expression表达式则是实现的源代码, 也可以使用@Mapper注解中导入的实现类的方法名 - 如果表达式中含有导入的外部包, 则使用
@Mapper(import={Arrays.class}类似引入即可
1 |
|
- 结合
lombok插件, 实体类中涉及到继承父类属性, 并且都使用了@SuperBuilder, 自动生成的convert实现类不会出现问题 - 如果手动设置
@Mapping,且转换类在使用父类属性时, 需要设置@Mapper(builder = @org.mapstruct.Builder(disableBuilder = true), 否则自动生成convert实现类方法中会直接编译成了父类导致报错
1 |
|
springboot启动脚本加载优先级
- 没有指定配置文件的情况下当前jar包目录同级有配置文件或者有config文件夹, 优先加载外部的,会覆盖内部classes下的.
1 | 启动指定外部配置文件 |
hutool excel工具
读取excel过慢, 注意不同操作系统环境有内存泄露风险, 推荐使用easyexcel
Es 相关
ES 跨集群搜索设置
- elasticsearch.yml 相关配置
1 | http.host: 0.0.0.0 |
- kibana.yml 设置
1 | server.host: "0.0.0.0" |
- 设置远程集群搜索
1 | PUT _cluster/settings |
组合查询
- example : and condition1 or ( condition 2 and condition 3)
1 | POST _search |
Vue 相关
优化
- vue-cli4 工程
vue.config.js设置
1 | chainWebpack: config => { |
使用docker 安装使用 onlyoffice
安装
- 如果开启使用
example页面功能, 需要需要配置/etc/onlyoffice/documentserver-example/default.json文件中的 example 的地址,配置为 docker 网卡地址
访问
- onlyoffice 是使用 jwt 签名进行验证用户的真实性以及请求来源的真实性
- 在 7.2 版本后默认启用了 jwt认证 功能, 启动服务会生成相应的签名密钥, 签名的secret密钥可以在
/etc/onlyoffice/documentserver/local.json中找到, 调用onlyoffice 页面时一定需要携带 token内容, 完整的参数如下 e.g
1 | { |
- 请求原理: 后端生成配置信息以及使用 onlyOffice提供的secret 密钥将配置信息进行jwt签名, 生成 token一并返回, 页面携带 token 以及文件地址访问 onlyoffice 服务, 借助 onlyoffice 的 api 打开编辑或预览文件
问题
- 在官方提供的后端spring 例子中, 创建文件无法打开页面问题, 在 chrome 中, 不安全的网站(非 https)内容默认是阻止重定向的, 在 chrome输入
chrome://settings/content中找到相应网站设置不安全内容设置为允许 - 打开文件提示文件下载失败: 最主要的问题是documentServer无法访问应用服务后端提供的文件地址, 检查页面返回的editorConfig对象中的url地址ip是否允许documentServer访问
springboot 批量获取redis key超时问题
Scan命令是一种比Keys命令更加高效、安全的遍历Redis key的方式,可以减少因为大量 key 集中在一起而导致的阻塞和性能问题。
1 | // 实例化 RedisTemplate (按实际场景使用template) |
首先实例化 RedisTemplate,并设置了它的连接工厂和属性。然后构造了一个 ScanOptions,用于指定 Scan 的参数,包括需要匹配的 key 前缀和每次返回的 key 数量等。接着通过 RedisTemplate 的 executeWithStickyConnection 方法执行 RedisCallback,获取一个 ScanCursor。最后遍历 ScanCursor 并对每个 key 进行操作。
需要注意的是,Scan 命令的返回结果是一个游标,需要通过循环遍历来获取所有的 key。同时,如果在循环遍历过程中有新的 key 被添加到 Redis 中,也有可能被遗漏。因此,在遍历过程中需要保证数据的一致性和可靠性。
Maven wrapper 代理地址
1 | distributionUrl=https://mirrors.huaweicloud.com/repository/maven/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip |