【Springboot系列】Springboot接管所有Controller,magic-api源码阅读

news2024/11/26 15:47:50

系列文章地址:Spring Boot学习大纲,可以留言自己想了解的技术点

最近在项目中使用了一个第三方的包 magic-api,节省了很多的时间,整体来说就是只用写sql就好了,不用写service,controller那些,全部统一处理了。

具体的使用大家可以搜索下,网上到处都是,建议去官网看。

为了使用这个包,必须得大概了解下是怎么回事,要不然用的不踏实,这里面最重要的其实是脚本执行引擎的重定义,这部分我还没有深究,

这篇文章主要关注的是如何接管所有的controller。

1、magic-api的使用流程

magic-api 在启动之后会有一个网页界面,在界面中配置开放的接口和执行的脚本

这些接口会存到数据库或者文件中,在程序运行的过程中会加载所有的接口到内存中,等待调用

2、controller主要流程

在正常的请求过程中,都知道使用注解@Controller加上RequestMapping就可以将一个方法作为接口开放出来,可以看到下面的流程

DispatchServlet做为分发器,从handlerMapping类中查找对应的Method 方法,然后注入请求对象,进行调用,

magic-api 这里接管所有的controller必然要在handlerMapping中做点手脚

3、magic-api的处理方式

1.通过magic-api-spring-boot-starter的spring.factories可以看到启动类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.ssssssss.magicapi.spring.boot.starter.MagicAPIAutoConfiguration

/**
 * magic-api自动配置类
 */
@Configuration
@ConditionalOnClass({RequestMappingHandlerMapping.class})
@EnableConfigurationProperties(MagicAPIProperties.class)
@Import({MagicJsonAutoConfiguration.class, ApplicationUriPrinter.class, MagicModuleConfiguration.class, MagicDynamicRegistryConfiguration.class})
@EnableWebSocket
@AutoConfigureAfter(MagicPluginConfiguration.class)
public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketConfigurer {

2.可以看到导入了几个配置类到容器中,其他的没怎么关注,直接在MagicDynamicRegistryConfiguration中查找

@Configuration
@AutoConfigureAfter(MagicModuleConfiguration.class)
public class MagicDynamicRegistryConfiguration {
   @Autowired
   @Lazy
   private RequestMappingHandlerMapping requestMappingHandlerMapping;

可以看到这里注入了RequestMappingHandlerMapping,想必一定是在这里进行的骚操作,继续往下看

3.ApiInfoMagicResourceStorage 是配置的接口,在这里做的注入

@Bean
@ConditionalOnMissingBean
public RequestMagicDynamicRegistry magicRequestMagicDynamicRegistry(ApiInfoMagicResourceStorage apiInfoMagicResourceStorage) throws NoSuchMethodException {
   return new RequestMagicDynamicRegistry(apiInfoMagicResourceStorage, Mapping.create(requestMappingHandlerMapping, properties.getWeb()), properties.isAllowOverride(), properties.getPrefix());
}

4.下面具体的就不做深入展开了,等下会讲原理

最后会讲所有的请求全部映射到RequestHandler里的invoke方法

**
 * 测试入口、实际请求入口
 *
 * @param request       HttpServletRequest
 * @param response      HttpServletResponse
 * @param pathVariables 路径变量
 * @param parameters    表单参数&URL参数
 * @return 返回请求结果
 * @throws Throwable 处理失败抛出的异常
 */
@ResponseBody
@Valid(requireLogin = false)
public Object invoke(HttpServletRequest request, HttpServletResponse response,
                @PathVariable(required = false) Map<String, Object> pathVariables,
                @RequestHeader(required = false) Map<String, Object> defaultHeaders,
                @RequestParam(required = false) Map<String, Object> parameters) throws Throwable {

4、自己实现,接管所有的controller到RequestHandler

4.1 创建springboot项目

idea一键next,没有难度,创建一个空的springboot web项目就好

4.2 创建一个controller的处理类,这里没有加controller的注解

这里直接拷贝了magic-api的RequestHandler,去除了业务逻辑

/**
 * 请求入口处理
 */
@Component
public class RequestHandler {

   /**
    * 测试入口、实际请求入口
    *
    * @param request       HttpServletRequest
    * @param response      HttpServletResponse
    * @param pathVariables 路径变量
    * @param parameters    表单参数&URL参数
    * @return 返回请求结果
    * @throws Throwable 处理失败抛出的异常
    */
   @ResponseBody
   public Object invoke(HttpServletRequest request, HttpServletResponse response,
                   @PathVariable(required = false) Map<String, Object> pathVariables,
                   @RequestHeader(required = false) Map<String, Object> defaultHeaders,
                   @RequestParam(required = false) Map<String, Object> parameters) throws Throwable {
      return "香菜";
   }
}

4.3 注册处理类到requestMapping

@Configuration
public class MappingConfig {
    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, RequestHandler handler) throws NoSuchMethodException {
        RequestMappingInfo info = RequestMappingInfo.paths("/caraway").methods(RequestMethod.GET).build();
        //    注意这里的方法签名,要和RequestHandler保持一致
        Method method =  RequestHandler.class.getDeclaredMethod("invoke", HttpServletRequest.class, HttpServletResponse.class, Map.class, Map.class, Map.class);
        mapping.registerMapping(info, handler, method);
    }
}

4.4 测试

输入地址:http://localhost:16002/caraway

端口记得改成你本地的端口,因为多开了几个服务,这里的端口是16002

如果看到下面的界面,证明我们注入成功了

4.5 开发遇到的问题

上面代码写完,本以为没有问题,但是在使用的时候一直报错

搜索了下:问题就是源自springboot 2.6.0后的新特性,目前版本的解决方案是在springboot的配置文件中,以下配置,修改默认映射策略:

spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER

或者降低版本,如使用2.5.4版本

5、总结

magic-api 减少了很多繁琐的接口,开发速度很快。

requestMapping的动态导入controller,可以将业务接管

magic-api的脚本引擎还没研究,


推荐书

2020年9月“中国好书”、斩获第十六届文津奖图书奖的科普力作——《公式之美》火热畅销中,不管你是文科生还是理科生,它值得所有人了解与翻阅!

万物速朽,唯有公式永恒!本书通过人类最美的23个公式,用人文解析数学之美,重塑人类理性堤坝,抵挡盲信洪流,聚集日益退却的独立思考者,打破快餐式的碎片刷屏时间……用趣味解读发现科学之美,用公式智慧重构思考体系!

电商链接

京东:https://item.jd.com/12717209.html

当当:http://product.dangdang.com/29121842.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/400994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink从入门到精通系列(二)

3、Flink 部署 Flink 是一个非常灵活的处理框架&#xff0c;它支持多种不同的部署场景&#xff0c;还可以和不同的资源管 理平台方便地集成。 3.1、快速启动一个 Flink 集群 3.1.1、环境配置 Flink 是一个分布式的流处理框架&#xff0c;所以实际应用一般都需要搭建集群环境…

IO与NIO区别

一、概念 NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。 二、NIO和IO的主要区别 下表总结了Java I…

GM8773C 是一款 1:2 DSI 桥接芯片,可实现 4 路进 8 路出转换器功能、视频分离器功能。

GM8773C 是一款 1&#xff1a;2 DSI 桥接芯片&#xff0c;可实现 4 路进 8 路出转换器功能、视频分离器功能。芯片内集成了一个 4 路单一链路的 MIPI DSI 接收器和 8 路双链路 MIPI DSI 发送器。 接 收 器 每 路 可 以 支 持 到 2.0Gbps/lane &#xff0c; 可 以 最 高 支 持 到…

平面设计软件Corel CDR2023又开始放大招啦,CorelDRAW Graphics Suite 2023有哪些新增功能?

CorelDRAW 2023中文版即将于2023年3月14日&#xff0c;在苏州举行线上直播的2023新品发布会&#xff0c;本次发布会主题为“设计新生力&#xff0c;矢量新未来”。 发布会邀请思杰马克丁公司领导、Corel 中国区总经理分享思杰与 Corel 的合作模式及在 CorelDRAW 产品上推动历程…

JavaEE简单示例——Bean管理

简单介绍&#xff1a; 在这一章节我们会比较详细的介绍我们在之前的测试类中以及Bean管理XML配置文件中所使用到的类和方法&#xff0c;以及XML中配置的属性所代表的详细含义。以及之前我们反复提到但是一直没有详细的讲解的一个东西&#xff1a;容器。我们可以大致的有一个概…

react+antdpro+ts实现企业级项目四:注册页面实现及useEmotionCss的介绍

创建文件路径并注册register路由 在pages/User下创建Register文件夹并创建index.tsx文件 然后在config/routes创建register注册路由。注册完后&#xff0c;当在登陆页面点击注册按钮时就可以跳转到此注册页面而不会报404了。 export default [{path: /user,layout: false,rou…

PaddleOCR关键信息抽取(KIE)的训练(SER训练和RE训练)错误汇总

1.SER训练报错: SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception 1.1.问题描述 在执行训练任务的时候报错 单卡训练 python3 tools/train.py -c train_data/my_data/ser_vi_layoutxlm_xfund_zh.yml错误信息如下&#xff1a; T…

初识C++需要了解的一些东西(1)

目录&#x1f947;命名空间&#x1f3c5;存在原因&#x1f3f5;命名空间定义&#x1f3a7;命名空间的3种使用方式&#x1f3c6;C输入和输出&#x1f31d;缺省参数&#x1f31c;缺省参数概念⭐️缺省参数分类☀️函数重载&#x1f525;引用&#x1f31a;引用概念&#x1f313;引…

LeetCode 热题 C++ 581. 最短无序连续子数组 617. 合并二叉树

581. 最短无序连续子数组 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组&#xff0c;并输出它的长度。 示例 1&#xff1a; 输入&am…

记录--Vue自定义指令实现加载中效果v-load(不使用Vue.extend)

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 网站效果演示&#xff1a;ashuai.work:8888/#/myLoad GitHub仓库地址代码&#xff1a;github.com/shuirongshu… 加载中思路分析 实现加载中效果&#xff0c;一般有两种方式: 第一种是&#xff1a;搞一…

双馈风力发电机-900V直流混合储能并网系统MATLAB仿真

MATLAB2016b主体模型&#xff1a;双馈感应风机模块、采用真实风速数据。混合储能模块、逆变器模块、转子过电流保护模块、整流器控制模块、逆变器控制模块。直流母线电压&#xff1a;有功、无功输出&#xff08;此处忘记乘负一信号输出&#xff09;&#xff0c;所以是负的。蓄电…

鉴源论坛 · 观模丨模型检查综述

作者 | 李建文 华东师范大学软件工程学院博导 版块 | 鉴源论坛 观模 01 模型检查的历史 模型检查是一种起源于20世纪70年代末的形式化验证技术。该技术最初由Edmund M. Clarke、E. Allen Emerson和Joseph Sifakis提出&#xff0c;他们因在模型检查领域的贡献而获得了2007年的…

无监督循环一致生成式对抗网络:PAN-Sharpening

Unsupervised Cycle-Consistent Generative Adversarial Networks for Pan Sharpening &#xff08;基于无监督循环一致生成式对抗网络的全色锐化&#xff09; 基于深度学习的全色锐化近年来受到了广泛的关注。现有方法大多属于监督学习框架&#xff0c;即对多光谱&#xff0…

【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置git环境和项目创建

【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置git环境和项目创建项目的逐步细分配置git环境创建项目后端前后端不分离写法-url访问路径解析资源安装vuevue文件后端解析数据发送到前端页面解析出来项目的逐步细分 匹配界面&#xff1a;需要用微服务实况直播&#xff1…

Lesson 9.1 集成学习的三大关键领域、Bagging 方法的基本思想和 RandomForestRegressor 的实现

文章目录一、 集成学习的三大关键领域二、Bagging 方法的基本思想三、RandomForestRegressor 的实现在开始学习之前&#xff0c;先导入我们需要的库&#xff0c;并查看库的版本。 import numpy as np import pandas as pd import sklearn import matplotlib as mlp import sea…

Flink学习-单词统计WordCount

WordCount&#xff08;流处理&#xff09;通过socket数据源&#xff0c;去请求一个socket服务&#xff08;9999&#xff09;,得到数据流然后统计数据流中出现的单词及其个数1.创建一个编程入口&#xff0c;生成环境StreamExecutionEnvironment streamEnv StreamExecutionEnvir…

嵌入式Linux驱动开发(二)LED驱动

1. Linux下LED驱动原理 与裸机区别在于&#xff0c;编写驱动要符合linux驱动框架规范。裸机直接对寄存器物理地址进行读写&#xff0c;linux下需要经过MMU。 1.1 地址映射相关概念 1&#xff09;MMU&#xff08;Memory Manage Unit - 内存管理单元&#xff09;&#xff1a; …

新星计划·第四季·Python赛道报名入口 -〖你就是下一个新星〗

↓↓↓报名方式&#xff1a;&#xff08;下滑到本页面底部&#xff09;重要提醒&#xff1a;这里是新星计划第四季Python赛道报名入口&#xff0c;一经报名&#xff0c;不可更换。报名入口点击此处跳转 一、新星计划 新星计划是一个以发掘潜力新人、培养优质博主为目标的创作…

css3动画属性

边框弧度 border-radius:value // 四角 border-radius:value value // 左上右下 右上左下 border-radius:value value value value // 左上 右上 右下 左下 text-shadow:value value value color; // 水平 垂直 模糊度 颜色 线性渐变&#xff1a;background-image:linear-…

oracle的时间戳获取不含中文内容的方式

背景&#xff1a; 在做oracle的数据库同步时发现&#xff0c;创建的行级触发器获取表的时间戳数据时含有中文&#xff0c;导致入库时转义乱码&#xff0c;条件匹配失败。 调试过程&#xff1a; 写了一个declare脚本测试&#xff1a; declare --类型定义 cursor c_job IS sele…