当前位置: 首页 > article >正文

springboot中动态api如何设置

1.不需要编写controller 等mvc层,通过接口动态生成api。

这个问题,其实很好解决,以前编写接口,是要写controller,需要有

@RestController
@RequestMapping("/test1")
public class xxxController{
@ApiOperation("测试预览")
    @PostMapping("/test2")
    public Object test(String name) throws Exception {
}
}

在这个总开关类里面dispacherServlet这个类里面是需要解析的,
从doDispatch方法开始解析(只贴需要的代码)

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine handler for the current request.
				//1.这个方法就是执行了寻找对应的类实例和方法名
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
				// 找不到会报错,就是常见的404,没有找到xxx/xxx方法映射,
					noHandlerFound(processedRequest, response);
					return;
				}
}

然后ctrl点进去
mappedHandler = getHandler(processedRequest);
这个方法
来到:

@Nullable
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
		// 从这里便利找
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

HandlerMapping 它就长这样子
在这里插入图片描述
其中绿色的这个就是我们写的什么controller啥的地址啦还有对应得方法,在里面。

2.重点

从上图看 这个红色 就是我们要写的一个了,因为为什么呢,你要动态的,绿色代码里你都没写。是springboot你写了controller代码它自动扫描到的,所以你得自己配一个进去。这样子就能够实现动态解析了。

3.基于以上简单的介绍,那就可以开始了,说白了就是模范写一个进去,让springboot能够识别。他原生自带的不行,咱就给它

RequstMappingHandlerMapping 就是模仿这个类写一个。

先看这个类长啥样:

public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
		implements MatchableHandlerMapping, EmbeddedValueResolverAware {
		
}
继承还挺多,完了我们也写一个,主要实现这个方法即可lookupHandlerMethod(),这个就是怎么找对应地址和方法的逻辑
@Component
public class CustomHandlerMapping extends RequestMappingInfoHandlerMapping
        implements MatchableHandlerMapping, Ordered {
    @Autowired
    private List<HandlerMethodArgumentResolver> argumentResolvers; // 注入Spring Boot自带的参数解析器

    @Override
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        // 根据请求路径动态返回对应的处理器方法
        if (lookupPath.startsWith("/test")) {
            Object handler = getApplicationContext().getBean(CustomHandler.class);
            return new HandlerMethod(handler, "handleTestRequest", HttpServletRequest.class, HttpServletResponse.class);
        }
        return null;
    }
    @Override
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = super.getHandlerExecutionChain(handler, request);
//        System.out.println(super.getAdaptedInterceptors());
//        chain.addInterceptor(new ApiInterceptor()); // 注册自定义拦截器
        List<HandlerInterceptor> interceptors = new ArrayList<>();
        return chain;
    }


    @Override
    protected boolean isHandler(Class<?> beanType) {
        return false;
    }

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        return null;
    }


    @Override
    public RequestMatchResult match(HttpServletRequest request, String pattern) {
        System.out.println(request);
        System.out.println(pattern);
        return null;
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }
}

还有一个具体的业务逻辑
@Component
@Slf4j
public class CustomHandler {

    public void handleTestRequest(HttpServletRequest request, HttpServletResponse response) {
        // 在这里编写处理特定请求的逻辑
        // 例如,可以根据请求参数、请求头等信息进行动态处理
        try {
            log.info("方法:"+request.getMethod());
            log.info("参数:"+request.getParameterMap().values());
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            // 跨域设置
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", "Authorization");//这里很重要,要不然js header不能跨域携带  Authorization属性
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
            response.getWriter().write(JSON.toJSONString(ResultBody.ok().data("你好")));
        } catch (IOException e) {
            // 处理异常
        }
    }
}

以上就是一个动态api的逻辑了,喜欢的可以走一下源码完善。在数据可视化这个方面这个用的还是蛮多。


http://www.kler.cn/news/135192.html

相关文章:

  • redission源码解读
  • HIS系统源码,云HIS源码,二级医院信息管理系统源码,预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站、护士工作站
  • Golang Context 的使用指南
  • String字符串性能优化的几种方案
  • QT专栏1 -Qt安装教程
  • 21、ila
  • Sentinel入门
  • 基于STC12C5A60S2系列1T 8051单片的模数芯片ADC0809实现模数转换应用
  • 2、LeetCode之两数相加
  • 为什么我们在Springmvc拦截器的时候要加判断 handler instanceof HandlerMethod
  • Google Chrome 任意文件读取 (CVE-2023-4357)漏洞
  • Transformer中WordPiece/BPE等不同编码方式详解以及优缺点
  • uvm环境获取系统时间的方法和使用案例
  • Python爬虫批量下载图片
  • Kafka快速入门
  • 利用OpenCV做个熊猫表情包 二
  • 单链表相关面试题--2.反转一个单链表
  • 深入理解MongoDB的CRUD操作
  • 五分钟,Docker安装kafka 3.5,kafka-map图形化管理工具
  • Golang中读写CSV文件的全面指南
  • 和鲸科技创始人范向伟受邀出席“凌云出海,来中东吧”2023华为云上海路演活动
  • NX二次开发UF_CAM_ask_cutter_db_object 函数介绍
  • CDN加速在社会发展中的挑战与机遇
  • 【Machine Learning in R - Next Generation • mlr3】
  • PDF/X、PDF/A、PDF/E:有什么区别,为什么有这么多格式?
  • 树莓派4b编译FFmpeg支持硬件编解码
  • 极智嘉(Geek+)官宣重磅合作伙伴,再度赋能仓储自动化解决方案落地
  • 查询数据库DQL
  • 不爱的人在一起会幸福吗
  • 网络安全(大厂面试真题集)