其实这篇笔记在云笔记里记载好久了,忽然看到,分享出来帮自己复习也希望能帮到需要的人(ΦωΦ)
springboot优点:
1.快速构建项目
2.对主流开发框架的无配置集成
3.项目可独立运行,无需外部依赖Servlet容器
4.提供运行时的应用监控
5.极大的提高了开发、部署效率
6.与云计算的天然集成
启动类@SpringbootApplication 是一个组合注解,主要的注解组成有@EnableAutoConfiguration、@Configuration、@ComponentScan:
@EnableAutoConfiguration:让springboot根据类路径下的jar包依赖进行自动配置
例如,添加了spring-boot-starter-web依赖,会自动添加tomcat和spring mvc 的依赖,那么springboot就会对tomcat和springmvc进行自动配置
Sptingboot会自动扫描@SpringbootApplication所在类的同级包以及下级包里的bean(若为JPA项目还可以扫描到@Entity的实体类)。建议将入口放在groupId+arctifactId的组合包名下
@Configuration:一般用来初始化配置类使用,通过@Configuration注解标注的类会在项目初始化的时候加载,也可理解为用spring的时候xml里面的标签
@ComponentScan告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。
一、配置篇
1.配置文件:application.properties或者application.yml 在目录src/main/resources/下
2.配置读取:
如果spring启动时没有读取配置文件,需在pom.xml文件里加:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
① Environment 读取
注意:Environment 不仅仅是从配置文件中获取,还要其他的一些配置信息来源(比如本机配置)
② @Value 读取
③ 对象映射方式
自定义配置文件需用@PropertySource(“classpath:xxx.properties”)去读取,除yml文件
3.多环境选择
4.配置文件的优先级:
①外置,在相对于应用程序运行目录的 /config 子目录中
②外置,在应用程序运行的目录中
③内置,放在config包下(即 src/main/resources/config)目录下
④内置,放在classpath根目录下(即默认的 src/main/resources/目录下)
上面的优先级是从高到低来的,即外置的改与内置的;config下面的高于根目录下的
(即应用外的配置文件优先于应用内,config目录下的优先于根目录下的)
bootstrap.yml(bootstrap.properties)先加载
application.yml(application.properties)后加载
bootstrap.yml 用于应用程序上下文的引导阶段。
bootstrap.yml 由父Spring ApplicationContext加载。
父ApplicationContext 被加载到使用 application.yml 的之前
(是不是有点绕口,其实很好记)更改环境选择的方式:
①命令行参数
注意:命令行参数传入时,请注意写法形同 --key=value
②外置配置文件方式4.加载自定义配置文件
指定根目录下配置文件名
5.配置内引用
①random随机数
②配置引用
使用 ${xxx} 来表示引用配置 xxx的值
6.配置动态刷新
借助springcloud中ContextRefresher类
再使用**@RefreshScope**注解
使用refresh()方法即可刷新
7.配置变更监听
利用springboot的事件通知机制,配置config变更的监听
二、日志篇
日志级别:trace<debug<info<warn<error<fatal
info 一般处理业务逻辑的时候使用,就跟 system.err打印一样,用于说明此处是干什么的。slf4j使用的时候是可以动态的传参的,使用占位符 {} 。后边一次加参数,会挨个对应进去。
debug: 一般放于程序的某个关键点的地方,用于打印一个变量值或者一个方法返回的信息之类的信息
error: 用户程序报错,必须解决的时候使用此级别打印日志。
warn:警告,不会影响程序的运行,但是值得注意
fatal: 重大错误
1.debug日志支持
默认是不输出debug日志的,如果需要,则需要在配置文件中添加 debug=true 属性;同样可以设置trace=true,就可以看应用输出的trace日志
2.log levels
3.输出格式
logging.pattern.cnotallow=%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
效果如下:
4.输出文件
5.logback配置
①appender标签
a.class属性选择输出的地方
b.输出格式:
如:%d [%t] %-5level %logger{36}.%M(%file:%line) - %msg%n
%m输出的信息,
%p日志级别,
%t线程名,
%d日期,
%c类的全名,
%i索引【从数字0开始递增】
%M方法名
%lines输出日志的行数
%F/%file源码文件名
c.日志归档:
②logger标签
三、bean篇
1.自定义bean的加载条件:
通过@Conditional注解配合Condition接口,来决定给一个bean是否创建和注册到Spring容器中,从而实现有选择的加载bean
满足条件则加载bean
也可加在类上
使用注解不需自己实现Condition接口
@ConditionalOnBean注解属性:
value:bean类型
type:bean类型
annotation:要求bean上拥有指定的注解
name:bean名称
@ConditionalOnProperty
prefix:配置前缀
havingValue:要求配置存在,且包含某个值
name:配置名
matchIfMissing:即便没有配置,也依然创建(true时)2.多实例选择
存在@Primary注解时:
@Resource注解指定name时,根据name来查找对应的bean
@Autowired注解,全部都用@Primary标识的注解
@Primary注解要求唯一(一个接口的子类中,只能有一个实现上有这个注解)
不存在@Primary注解时:
@Resource注解指定name时,根据name来查找对应的bean
@Autowired注解时,根据属性名去查对应的Bean,如果查不到则抛异常;如果查到,那即是它了
3.同名bean的两种解决方式:
①指定其中一个bean的名称
②排除掉其中一个同名bean的自动加载四、AOP篇
1.基本概念:
① advice
before: 在方法执行之前被调用
after: 在方法执行之后调用
after returning: 方法执行成功之后
after throwing: 方法抛出异常之后
around: 环绕,自己在内部决定方法的执行时机,因此可以在之前之后做一些业务逻辑
② joint point
连接点,比如方法调用,方法执行,字段设置/获取、异常处理执行、类初始化、甚至是 for 循环中的某个点
但 Spring AOP 目前仅支持方法执行 (method execution),PointCut就是那个被拦截的方法
③ pointcut
切点,用来描述满足什么规则的方法会被拦截
④ aspect
切面是切点和通知的结合。通知和切点共同定义了关于切面的全部内容,它是什么时候,在何时和何处完成功能
⑤ introduction
引入允许我们向现有的类添加新的方法或者属性
⑥ weaving
生成一个代理类,在调用被拦截的方法时,实际上执行的是代理类,这个代理类内部执行切面逻辑
一个方法执行时,只要满足条件,多个相同或不同类型的advice都可以拦截
2.基本使用:
3.注解拦截方式
相同类型可都拦截
4.嵌套拦截
① 如果有切面的方法被没切面的方法调用,那他将不被拦截
②调用本类中,满足被拦截的方法,也不会走切面逻辑;调用其他类中的满足切面拦截的方法,会走切面逻辑
③如果调用的方法上加了拦截的注解,则内部调用的方法全被正常拦截
小结:
a.执行的目标方法,如果调用了本类中一个满足切面规则的方法A时,在执行方法A的过程中,不会触发切面逻辑
b.执行的目标方法,如果调用其他类中一个满足切面规则的方法B时,在执行方法B的过程中,将会触发切面逻辑
5.AOP拦截方法的作用域
内部调用不走切面逻辑,所有private修饰符不可用
public, protected, default 作用域的方法都可以被拦截
6.AOP优先级
①同一切面,不同类型ddvice优先级
② 同一切面,同一类型切面
如定义了三个@Before切面,输出顺序是根据方法名决定
Order注解尝试
测试结果并未改变优先级
③不同切面,相同类型的advice
A切面中的advice会优先B切面中同类型的advice
可以通过 Order 注解来解决不同切面的优先级问题,依然是值越小,优先级越高
④不同切面,不同advice顺序
优先级高的切面中的advice执行顺序会呈现包围优先级低的advice的情况
五、JdbcTemplate篇
两种sql传参方式:
一个是写完整的sql语句,问题是存在注入的风险
其次是使用占位符(?), 实际的值通过参数方式传入
1.查询:
单条查询:
①queryForMap 返回一条记录,返回的结果塞入Map<String, Object>, key为固定的String对应查询的列名;value为实际值
②queryForObject 同样返回一条数据,与上面的区别在于可以借助RowMapper来实现返回结果转换为对应的POJO
或
注意:上面的查询,必须有一条记录返回,如果查不到,则抛异常
批量查询:
queryForList :一次查询>=0条数据,返回类型为 List<Map<String, Object>>
queryForRowSet:返回SqlRowSet对象,需要遍历获取所有的结果
query:
①提供三种结果处理方式:
a.不返回结果的回调姿势
b.对结果批量处理的方式 ResultSetExtractor
c.对结果单个迭代处理方式 RowMapper
②可以返回>=0条数据
③如果需要对查询的连接参数进行设置,使用PreparedStatementCreator来创建PreparedStatement方式处理2.新增:
update(sql)
update(sql, param1, param2…)
update(sql, new PreparedStatementCreator(){})
update(new PreparedStatementSetter(){})
update(new PreparedStatementCreator(){}, new GeneratedKeyHolder())
插入并返回主键:
六、Feign篇
关于springCloud的有关整理还没做好,所以先把feign的放这:
启动类加@EnableFeignClients
Feign的源码实现的过程如下:
1.首先通过@EnableFeignCleints注解开启FeignCleint
2.根据Feign的规则实现接口,并加@FeignCleint注解
3.程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的类,并将这些信息注入到ioc容器中。
4.当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate
5.RequesTemplate在生成Request
6.Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
7.最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
有个坑点:feign调用接口传递LocalDateTime值时会自动转化为上午下午的时间,无法解析(放在对象中传递无此问题)