Redian新闻
>
一个注解干翻所有Controller

一个注解干翻所有Controller

公众号新闻

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
来源:geekhalo

1. 概览

日常开发中,最繁琐的便是编写 Controller。很多公司都制定了规范:Controller 不能存在任何的业务逻辑,主要完成参数解析和结果转换。

不过查看项目源码,你会发现 Controller 中存在了大量不该存在的逻辑,对此,你有什么好的方法?依赖 Code Review?从我角度,我觉得 Controller 根本就不需要存在。

1.1. 背景

之前对 CommandService 和 QueryService 进行封装,通过定义接口的方式快速搭建应用服务,大大提升了开发效率和代码质量,在有了应用服务之后,便是在其基础之上编写 Controller,把能力暴露出去。这是一个非常繁琐且没有技术含量的重复工作。而对于枯燥的重复工作,我的策略一直都是“交由框架完成”。

1.2. 目标

简单的说,我们的目标便是不写Controller,但还要保留 Controller 的效果。

  1. 不需要编写 Controller 代码,将 CommandService 和 QueryService 直接暴露为 Web 接口;
  2. 完成与 Swagger 框架的集成,动态生成 api doc,方便前端接入;

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

2. 快速入门

2.1. 环境准备

首先,在 pom 中增加 lego-starter,具体如下:

<dependency>  
    <groupId>com.geekhalo.lego</groupId>  
    <artifactId>lego-starter</artifactId>  
    <version>0.1.11-rest-SNAPSHOT</version>  
</dependency>  

其次,增加 swagger 相关依赖,具体如下:

<dependency>  
    <groupId>io.springfox</groupId>  
    <artifactId>springfox-boot-starter</artifactId>  
    <version>3.0.0</version>  
</dependency>  
<dependency>  
    <groupId>io.springfox</groupId>  
    <artifactId>springfox-data-rest</artifactId>  
    <version>3.0.0</version>  
</dependency>  

最后,新建 SpringFoxConfiguration,启用 Swagger 具体如下:

@Configuration  
@EnableSwagger2  
public class SpringFoxConfiguration {  
}  

2.2. 初识统一控制器

打开浏览器,输入 http://127.0.0.1:8080/swagger-ui/ 打开 swagger 界面,会发现新增两个 Controller:

command-dispatcher-controller 是对 CommanderService 的Web暴露,主要用于执行写入和更新等业务操作,两个接入点包括:

  1. RequestBody 接入。以 json 作为入参,适用于复杂的参数结构;
  2. RequestParam 接入。以 param 作为参数,适用于简单场景;

query-dispatcher-controller 是对 QueryService 的Web暴露,主要用于执行业务的查询操作,同样支持 RequestBody 和  RequestParam 两种接入方式。与 command-dispatcher-controller 唯一区别是提供了对 Get 方法支持。

但在展开方法后,有点让人绝望。

serviceName 和 method 两个参数从哪获取?nativeRequest 和 nativeResponse 又是什么东西?这两个接口怎么使用?

看不明白也正常,因为我们不会直接使用这两个处理器。

2.3.  Command 控制器

2.3.1. 启用 Command 控制器

OrderCommandService 接口上增加 @AutoRegisterWebController 注解,将其对外暴露为 Web 端口。

@CommandServiceDefinition(  
        domainClass = Order.class,  
        idClass 
= Long.class,  
        repositoryClass 
= OrderRepository.class)  
@AutoRegisterWebController(name 
"order")  
public interface OrderCommandService{  
    void cancel(Long orderId);  
  
    Long create(CreateOrderCommand command);  
  
    void paySuccess(PaySuccessCommand command);  
}  
2.3.2. 使用 Order Command 控制器

输入 http://127.0.0.1:8080/swagger-ui/ 访问 swagger 界面,发现新增一组 Controller。

OrderCommandService 服务中的所有方法全部出现在 Controller 中。

首先,展开 CommandByBody 中的 create 方法,可见:

然后,展开 CommandByParam 中的 create 方法,具体如下:

整体结构和手写 Controller 基本一致,所暴露的功能也全部相同。

2.4. Query 控制器

2.4.1. 启用 Query 控制器

OrderQueryService 接口上增加 @AutoRegisterWebController 注解,将其对外暴露为 Web 端口。

@QueryServiceDefinition(domainClass = Order.class,  
        repositoryClass 
= OrderQueryRepository.class)  
@Validated  
@AutoRegisterWebController(name 
"order")  
public interface OrderQueryService {  
    OrderDetail getById(@Valid @NotNull(message = "订单号不能为null") Long id);  
  
    Page<OrderDetail> pageByUserId(@Valid @NotNull(message = "查询参数不能为 null") PageByUserId query);  
  
    List<OrderDetail> getByUserId(@Valid @NotNull(message = "查询参数不能为 null") GetByUserId getByUserId);  
  
    Long countByUser(@Valid @NotNull(message = "查询参数不能为 null") CountByUserId countByUserId);  
  
    List<OrderDetail> getPaidByUserId(Long id);  
}  
2.3.2. 使用 Order Query 控制器

输入 http://127.0.0.1:8080/swagger-ui/ 访问 swagger 界面,发现新增一组 Controller。

OrderQueryService 服务中的所有方法全部出现在 Controller。

首先,展开 QueryByBody 中的 pageByUserId 方法,可见:

然后,展开 QueryByParam 中的 pageByUserId 方法,具体如下:

入参与返回值结构非常清晰,整体结构和手写 Controller 基本一致,所暴露的功能也全部相同。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

3. 设计&扩展

整个设计分为两部分:

  1. 提供统一的Controller,作为所有请求的转发器;
  2. 提供插件与 Swagger 进行集成,提供完整的 api doc;

3.1. 统一 Controller

提供 QueryDispatcherController 作为所有查询请求的入口,核心架构如下:

初始化流程如下:

  1. Spring 对所有的 QueryService 进行实例化;
  2. 完成实例化的 QueryService Bean 自动注册到 QueryServicesRegistry
  3. QueryMethodRegistryQueryServicesRegistry 中获取服务实例,对 QueryMethod 进行解析,并完成注册;

执行流程如下:

  1. 客户端向服务器发起请求;
  2. 服务器将请求 路由到 QueryDispatcherController 的相关方法;
  3. QueryDispatcherController 根据 serviceName 和 methodName 从 QueryMethodRegistry 中获取 QueryMethod,执行业务方法,最后返回最终结果;

3.2. 与 Swagger 集成

提供 QueryServicesProvider 与 Swagger 进行集成,提供完整的 api doc,整体设计如下:

QueryServiceProviderQueryDispatcherController 一致,同样依赖于 QueryMethodRegistry 中的 QueryMethod 信息。

核心流程如下:

  1. QueryServicesProviderQueryMethodRegistry 中获取 QueryMethod 信息;
  2. 解析 QueryMethod 信息生成 RequestHander,并注册到 Swagger ;
  3. 用户请求 Swagger 时,将 RequestHander 转化为 api doc进行返回;

4. 项目信息

  • 项目仓库地址:https://gitee.com/litao851025/lego
  • 项目文档地址:https://gitee.com/litao851025/lego/wikis/support/web


欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
广告科技公司TTD推出媒体购买平台;Gusto Collective收购Mercury Integrated(广告狂人日报)注意! 加国多个食品正在被召回,有Costco这款网红产品加《全民免费医保》如何开始的Wellesley College 麻州韦尔斯利女子学院 你赞同录取跨性别男子吗?地主可能遇到的问题 十八,再谈租给section 8Tipping Livestreamers ‘Out of Control’: China State Broadcaster港大和微软提出Uni-ControlNet:可控制扩散模型再添一员!Hierarchy of Controls开源了!UniControl:可控视觉生成的统一扩散模型【糗事,笑话】男女第一次的约会一个注解实现 WebSocket 集群方案,这样玩才爽!室温超导是否真在美国实现了?精选SDE岗位 | Moloco、Torc Robotics、Interactive Brokers等公司发布新岗位!【惠宜美高】惠宜学子补录 Fountain Valley School 和 Virginia Episcopal School!完美世界TA谈Stable Diffusion插件,ControlNet、Segment Anything用GPT-4实现可控文本图像生成,UC伯克利&微软提出新框架Control-GPT科学与艺术并进!走进加拿大私校之玛丽大学圣名学校 Holy Name of Mary College School怎么开始学佛(十四)学佛不是要得奥运冠军,而是体育锻炼Can Rural Vloggers Make China’s Countryside Cool?恭喜Boston College学员斩获BlackRock (US) 2023暑期实习Offer恭喜Boston College学员斩获BlackRock (US)暑期实习Offer一文解读|Java编译期注解处理器AbstractProcessor五个步骤,助你优雅的写好 Controller 层代码![歪解] self control澳洲Coles纸袋遭吐槽!众多网友抱怨:一次就破!Coles这样回应…今日实习|Point 72 Entry-level Quantitative Researcher 火热招聘中!University Dean Sacked After Sharing Lewd Image With Colleagues以一己之力干翻所有同行!Chemist Warehouse“统治”市场,门店数量超过300家,缺遭同行唾弃国际青少年创新创业大赛! International Youth Innovation&Entrepreneur ContestBrokerage Apps Allowing Overseas Trading Pulled From App StoresCalls for Female-Only Sleeper Train Compartments Heat Up柏林工大也有自己的Döner店了!适配Diffusers框架的全套教程来了!从T2I-Adapter到大热ControlNet不卖了,跟他们打!他干翻所有外资,雪洗民族产业之耻ControlNet仅靠一张照片完成“旧房改造” | GitHub热榜第一
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。