springboot中动态api如何设置

参考: https://blog.csdn.net/lmchhh/article/details/128634606
https://www.jb51.net/article/272297.htm
https://www.cnblogs.com/tuxiaoer/p/17100570.html

一、有两种方法

第一种直接改底层如下:

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) {
            // 处理异常
        }
    }
}

接下来介绍第二种

  • 也就是在springboot中集成,直接使用里面的自带的requestMappingHandlemaping,也就是得写一个,就一个controller,但是这个要适配所有的api
  • 当然啦 这个要规定一个前缀,但是后面就随便了,话不多说直接上代码
 @GetMapping("/test/**")
    public ResultBody test(HttpServletRequest request){
        String path1 = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        System.out.println(path1);
        return  ResultBody.ok();
    }
  • 这样子,以test开头的都被匹配到了。

注意!!!提醒一下

  • 以上配合数据库存取的
    • 匹配地址
    • 还有取数规则
  • 那么这个就是动态api了,其中有黑名单拦截 是否需要token等认证啥的,都是一些业务上的了

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值