Quarkus的Spring扩展快速改造Spring项目
前言
博主上个礼拜,已经实现了quarkus的native image应用的上线,经过两天的监控下来,一切运行指标良好,就是内存升到了100M了,这个后续继续跟进观察。今天聊点老的spring应用改造成quarkus的问题。一个新的框架是否可以顺利的在一个公司落地,除了本身优秀的设计和优异的性能外,框架的生态和上手的难度以及对现有框架的兼容性都是非常重要的考量因素,在quarkus之前,使用最广泛的web框架就是spring webmvc框架了,数据访问层用的多的也是spring data jpa等。quarkus充分考虑了这种spring用户的需求,官方出品了多个针对spring环境的迁移扩展包,有了这些spring扩展,可以非常轻松的从spring应用迁移到quarkus平台上来。
spring-webmvc扩展
添加扩展依赖
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-web</artifactId> </dependency>
兼容以下spring的注解用法
@RestController @RequestMapping("/test") public class TestController { @GetMapping("/hello") public String hello(@RequestParam("name") String name){ return "hello" + name; } @PostMapping("/hello") public String hello1(@RequestBody Hello hello){ return "hello" + hello.getName(); } @GetMapping("/{name}") public String hello2(@PathVariable(name = "name") String name) { return "hello" + name; } class Hello{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
以上示例了最基本的restfull接口用法,quarkus的spring-web扩展常用的spring注解基本都支持了,但是使用时要注意,有些用法可能稍微有点不兼容,比如GET请求参数映射,纯spring环境下,可以不用@RequestParam注解绑定,但是quarkus环境下就必须使用@RequestParam注解绑定入参,还有spring下的MultipartFile不支持,涉及到表单文件上传的场景必须要改成JAX-RS的标准模式才行,这块会单独来写。
spring-datajpa扩展
添加扩展依赖
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-data-jpa</artifactId> </dependency>
兼容以下spring-data-jpa的用法
public interface MovieRepository extends CrudRepository<Movie, Long> { Movie findFirstByOrderByDurationDesc(); @Query("select m from Movie m where m.rating = ?1") Iterator<Movie> findByRating(String rating); @Query("from Movie where title = ?1") Movie findByTitle(String title); @Query("select m from Movie m where m.duration > :duration and m.rating = :rating") List<Movie> withRatingAndDurationLargerThan(@Param("duration") int duration, @Param("rating") String rating); @Query("from Movie where title like concat('%', ?1, '%')") List<Object[]> someFieldsWithTitleLike(String title, Sort sort); @Modifying @Query("delete from Movie where rating = :rating") void deleteByRating(@Param("rating") String rating); @Modifying @Query("delete from Movie where title like concat('%', ?1, '%')") Long deleteByTitleLike(String title); @Modifying @Query("update Movie m set m.rating = :newName where m.rating = :oldName") int changeRatingToNewName(@Param("newName") String newName, @Param("oldName") String oldName); @Modifying @Query("update Movie set rating = null where title =?1") void setRatingToNullForTitle(String title); @Query("from Movie order by length(title)") Slice<Movie> orderByTitleLength(Pageable pageable); }
如下的接口定义都支持
org.springframework.data.repository.Repository
org.springframework.data.repository.CrudRepository
org.springframework.data.repository.PagingAndSortingRepository
org.springframework.data.jpa.repository.JpaRepository
Hibernate ORM使用物理命名策略和隐式命名策略来映射属性名称。如果您希望使用Spring Boot的默认命名策略,spring-data-jpa扩展包也提供了支持,只需要设置以下属性:
quarkus.hibernate-orm.physical-naming-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
博主之前没了解到spring扩展之前,也遇到了相同的问题,最后只能从spring将命名策略拷贝到本工程里。不得不说quarkus想的还是蛮周到的
spring-Di扩展
添加扩展依赖
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-di</artifactId> </dependency>
兼容以下IOC用法
@Configuration public class TestConfig { @Autowired private AccountRepository repository; @Value("${acc}") private String acc; @Bean AccountService accountService() { return new AccountService(repository); } }
以上示例了最基础的用法,声明一个服务的@service、@Compoment等都支持,下面是支持的spring注解和JAX-RS的注解对照表
spring-boot-properties扩展
添加扩展依赖
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-boot-properties</artifactId> </dependency>
支持以下spring配置方式
@ConfigurationProperties("greeting") public class GreetingProperties { public String text; }
结语
quarkus的这些spring扩展,看上去就和spring一样,其实底层实现完全不一样,quarkus并没有引入spring的bean、context等容器上下文,这些扩展仅仅是作为注解元数据信息使用而已。以上列举了四种常见的spring使用扩展支持,quarkus支持的扩展还有Spring-Scheduled、Spring-Cache、Spring-Security、Spring Cloud Config Server,这里就不一一列举了,可以点击链接查看官方的文档。随着quarkus社区的迭代,spring扩展兼容支持会越来愈好越来越多,不过那个时候也有可能spring boot也追赶上了GraalVm,无论怎样,对于我们开发者而言,多个选择总是好的。