自动装配原理
Yaml
yaml是一种文件格式,在java企业级开发中常用于参数配置
- server: port: 8080 # :中间有空格作为分隔符 不然不识别 address: 127.0.0.1 #对象 person: name: zhangsan age: 20 #对象的行内写法 person2: {name: zhangsan,age :18} #数组 address: beijing shanghai #数组的行内写法 address2: [beijing,shanghai] #纯量 msg1: 'hello \n world' #不会识别转义字符 会原样输出 msg2: "hello \n world" #会识别转义字符
yaml读取启动参数
在我们实际开发中,都是多个代码协作开发,每个人都会在本地跑自己的项目,连接本地虚拟机的环境,例如redis、mongo配置,这样会导致我们频繁的修改配置文件,故启动java的时候填写动态参数指定要变化的数据,这样更高效的完成开发,节省不必要的修改,下面演示一下idea环境如何配置启动参数,注意一定要在参数前加-D
yaml怎么写?
java程序读yaml参数
在springboot的基础设施中,有一个模块是读取基础配置文件,这样通过解耦合的方式给注册的组件赋值,那么我们会有一个疑问,像redis、mysql、mogno这些配置是怎么赋值给注册的组件(bean)上的呢?需要注意的是,必须注册(component注解)的组件才会被赋值
springboot的做法是这样的
我们这里就尝试使用@Value 注解来赋值,这是最简单的方式适合简单的数据
异常
所有异常都在throwable子类下,java中异常分两种error和exception
error
error是错误当出现这个异常jvm会立即停止,例如OOM,StackOverFlow,系统崩溃,这类错误通常不可解决
exception
exception有分为编译时异常和运行时异常,编译时异常需要程序员主动去捕获或者抛出异常(但需要方法上声明throws Exception),运行时异常不需要特殊处理,甚至可以直接抛出(不需要在方法上声明throws),通常由JVM抛出该异常(例如除数为0,空指针异常),这些异常需要程序员手动去捕获,以防止程序遇到异常而终止,确保程序在捕获异常后还能继续向下运行。
如何实现
- import org.springframework.http.HttpStatus; /** 全局自定义异常类 */ @Data public class GlobalException extends RuntimeException { private HttpStatus httpStatus; private String errorMsg; }
为什么未主动处理异常程序并没有终止
配置好springboot全局异常类,程序未对异常进行处理(抛出异常或者捕获异常),程序依旧会继续执行,而且会把异常信息返回到前台页面。是因为全局异常类帮我们拦截(aop切面)并处理了这些异常,并且将异常信息响应给前端页面。
当然了,拦截的只是controller层,最后如果程序运行正确响应信息给页面,否则响应异常信息统一封装响应到页面,提升代码可读性和可维护性,动态代理将在控制层试图去捕获异常,这样dao、service层就不会出现频繁捕获异常,直接向上层去throw就行。
接口防刷
实际场景中为了避免某个API被恶意刷,可以通过一些手段对接口进行限额,多少秒之内请求的次数,当达到上线的时候就给页面提示错误的信息。
解决方案:拦截器+redis,springboot拦截器对所有请求做前置处理,获取当前ip的请求次数进行处理。
这种方案在执行业务逻辑之前进行拦截处理了,可以降低服务器和数据库压力,但有一个问题是请求还是放行到了java层面,更好的优化是在网关层进行拦截,通过某些算法限制ip某一时间段的访问限制。
定时任务
应用场景
生成报表、更新缓存数据、数据持久化、数据刷新等
实现
springboot的定时任务可以轻松解决以上的需求
实现原理
知道了怎么用,我们简单聊一下原理?
springboot在启动的时候,会扫描类上EnableScheduling注解,如果存在说明开启了定时任务注解,接着就会扫描带有Scheduled注解的方法,完成初始化操作,当触发条件满足是任务调度器就会在线程池中找一个空闲的线程去执行当前任务,执行完成后线程将返回线程池中等待下一次调度。
线程池满了怎么办?
ThreadPoolExecutor有4种拒绝策略
AbortPolicy | 新任务会直接被终止并抛出异常 |
CallRunsPolicy | 新任务将由调用者本身的线程去执行 |
DiscardPolicy | 新任务将直接丢弃不会有任何提示 |
DiscardOldPolicy | 丢弃最早的线程(即使还在执行中)同时尝试运行新任务 |
我们可根据任务的延时性选择合适的拒绝策略,如果对实时性要求不高可以选用丢弃策略,等待下次定时任务执行,如果对实时性要求高且不希望当前任务丢失就可以选择调用者执行策略,但可能会导致调用方执行延迟
日志
Springboot2.5以上版本默认自带logback日志系统 即只需要导入lombok