这是我参与更文挑战的第12天,活动详情查看: 更文挑战
spring boot2.x中的新特性我们也能够显而易见,增加了spring Framwork5结合netty作为启动容器增加了异步非阻塞的机制,支持http2.x,redis底层框架性能上也得到和很大的提升当然springboot2.x在框架上升级了不止这些。在从boot1.x升级到boot2.x中,难免会遇到各种各样的问题.在这里我总结了大部分伙伴在升级boot框架经常会遇到的一些常规问题以及困惑。希望能够帮助到更多同类似问题的伙伴
升级的必要性
首先升级boot2.x建议我们还是先阅读下这篇文章 Spring Boot 2.0迁移指南 在升级前我们需要先注意以下几点:
- 迁移到Spring Boot 2将升级许多依赖项,需要在升级之前首先确定兼容版本。
- 自定义配置相关的变更.比如configuration等
- Spring Boot 2.0需要Java 8或更高版本。不再支持Java 6和7。框架底层基础整合了Spring Framework 5.0。
- 按照spring官方的提示,我们建议分阶段升级,而不要一次升级到最新的GA:首先升级到2.0,然后再升级2.1。
- 默认情况下,Spring Boot现在默认使用CGLIB代理,包括对AOP的支持。如果您需要基于接口的代理,则需要将设置spring.aop.proxy-target-class为false。
- 启动boot jar命令,如果我们通过java -jar在启动命令后面紧跟外部配置文件,那么外部配置文件的参数需要做变更在boot 1.x中为 spring.config.location 在boot2.x中则变为 spring.config.additional-location。
- 在web容器接口调用方面,不在提供RestTemplate,而是直接变为RestTemplateBuilder
等等,以上新特性都在boot2.0迁移指南中,建议各位伙伴在框架升级之前多参考下,可以帮助到我们很多。
2.x与1.x redis集成区别
2.x版本中,默认是使用lettuce;1.x版本的时候,默认使用的就是Jedis;关于两个的区别:
1. Jedis和Lettuce都是Redis Client
2. Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的。
3. 如果想要在多线程环境下使用 Jedis,需要使用连接池。
ConfigurationProperties中prefix配置前缀驼峰命名的问题
如以下我们的yml中的配置是这样的层级
activityImage:
onScreenTime: 7
复制代码
Spring Boot 2.0不支持驼峰式嵌套。它将引发InvalidConfigurationPropertyNameException:配置属性名称’********’无效。
代码中需要修改:
@ConfigurationProperties(prefix = "activity-image")
复制代码
feign.optionals.OptionalDecoder
feign.optionals.OptionalDecoder信息缺失,在boot2.x中取消了 spring-cloud-openfeign-core, 而feign.optionals.OptionalDecoder信息在feign-java8包中,我们需要引入 spring-cloud-starter-feign组件包,因为在此组件包中包含了feign-java8包相关信息.
No qualifying bean of type ‘org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
可见在boot1.x服务中我们直接通过@Autowired注入ThreadPoolTaskScheduler定时任务无法进行直接使用。但是通过程序我们还是能够直接将ThreadPoolTaskScheduler进行new出来。那么具体实现的方案也就好办了,我们需要自定义下TaskScheduler即可,例子:
@Configuration
public class SchedulerConfig extends WebMvcConfigurerAdapter{
@Bean
public TaskScheduler scheduledTaskExecutor() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("scheduled-thread-");
return scheduler;
}
}
复制代码
升级之后,jpa中的某些方法类型变更了怎么办?比如findone、findAll等
- findone方法
从源码中我们可以看到,findone的方法输入参数不在为我们提供之前的String类型的参数类型了,返回的类型也变为了jdk1.8的Optional类型,那我们可以怎么办呢?在这里我举两个有效的解决方法,大家可以参考以下方式来进行解决即可:
方式一 可以直接使用Example类型为我们提供的方法传入对象实例即可
Student stu=new Student();
stu.setId("12345");
Student student = studentRepository.findOne(Example.of(stu)).orElse(null);
方式二 Spring Data Jpa 支持定义在Repository接口中的方法名来定义查询,方法名是根据实体类的属性来确定的。
studentRepository.findById(id).orElse(null)
复制代码
以上为两种解决之前findone的jpa的方式,但是相对来说,我比较更喜欢第二种方式,可以直接通过方法名也就是对象的属性名称来进行精确查询,这个功能确实非常棒。
- findAll方法
关于findAll方法,对于我个人感觉来说总得和依赖低版本没太大区别。findAll方法取消了之前接收list参数的方式,直接变为了无参的,但是从源码中我们可以可以看到了,我们可以通过findAllById的方法进行传递list并且传递一堆id进行查询。所以我们也可以直接通过findAllById方法直接替换之前findAll传递参数的方式。另外如果我们实在是想使用原来的findAll的方式进行查询,我们可以使用jpa sql的方式也能够解决问题,比如如下案例:
@Query("SELECT t FROM Student t WHERE id IN (:ids)")
List<Student> findAll(@Param("Ids") List<String> Ids);
复制代码
以上就是我做的兼容的方式,总之升级框架之后,jpa算是比较改动稍微大一点的,如果我们正好使用了JpaRepository提供的基础的几个常用的方法的话,得需要改动业务代码才能够进行兼容。