程序启动自动注册外部接口

1.业务背景

        针对公司提供的对外接口,需要在系统内部进行管理。需要对内对外接口实现分离。

2.想法

        1、针对对外接口本质就是接口文档,就无需提供增删改,仅供查询即可,数据存放数据库,请求头和请求体都是json字符串,另外就是请求类型 请求携带参数的方式。

        2、提供增删改查功能,由前端凭借json,后端单表的crud

        3、由于是系统内部接口,所以可以在程序启动或者某个点拦截代理获取的这些信息,存放到数据库

        所以我就傻不拉几针对以第一三种方式开始我的码农生活。

 3.实现

        1.可以使用拦截和代理两种方式,我个人认为开机启动一次,设置拦截有点多余。所以我想法是在代理对象注册为容器的调用初始化方法这个点。

        2.自定义注解

/**
 * 外部接口自启动
 *
 *
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autorun {
}

         3. 使用注解

@Autorun
@RestController
@RequestMapping("/system/foreign")
public class SysForeignUnstructTransferTaskController extends BaseController {}

        4.定义说明注解

                考虑到每个属性需要有说明,就像swagger定义了一个注解,逻辑就是通过类获取类的方法再去校验每个类上的注解和参数,通过参数有可以获取属性的上面注解的说明

        

@Retention(RetentionPolicy.RUNTIME)
public @interface ApiExplain {

    /**
     * 说明
     * @return
     */
    String explain() default "";

    /**
     * 分组
     * @return
     */
    GroupType[] group() default {GroupType.ADD, GroupType.EDIT, GroupType.REMOVE, GroupType.SELECT};

    enum GroupType {
        ADD,
        EDIT,
        REMOVE,
        SELECT
    }
}

        5.设置切面逻辑

@Aspect
@Component
public class AutorunAspect {



    @Value("${server.port}")
    private String port;
    @Value("${server.host:localhost}")
    private String host;

    /**
     * 存放方法需要的参数
     */
    private static Map<String, String> param = new HashMap<>();
    static {
        param.put("/system/foreign/add/unstruct/transfer/task", "value" );
        param.put("/system/foreign/edit/unstruct/transfer/task", "value2");
        param.put("/system/foreign/remove/unstruct/transfer/task/2", "value2");
        param.put("/system/foreign/get/unstruct/transfer/task/2", "value2");
        param.put("/system/foreign/get/unstruct/transfer/task/list", "value2");
        param.put("/system/foreign/copy/unstruct/transfer/task/2", "value2");
        param.put("/system/foreign/switch/unstruct/transfer/task/2", "value2");
        param.put("/system/foreign/export/unstruct/transfer/task/2", "value2");
    }

    @Before("@within(com.trinity.common.annotation.Autorun)")
    public void before(JoinPoint joinPoint) {
        StringBuffer prefix = new StringBuffer(String.format("http://%s:%s", host, port));
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method[] methods = targetClass.getDeclaredMethods();
        if (targetClass.isAnnotationPresent(RequestMapping.class)){
            prefix.append(targetClass.getAnnotation(RequestMapping.class).value()[0]);
        }

        for (Method method : methods) {
            ApiManag apiManag = new ApiManag();
            StringBuffer url = new StringBuffer(prefix);
            apiManag.setVisibleScope(1L);
            // 获取api的名字
            if (method.isAnnotationPresent(ApiOperation.class)) {
                ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
                apiManag.setApiName(apiOperation.value());
            }else {
                apiManag.setApiName(method.getName());
            }

            if (method.isAnnotationPresent(GetMapping.class)) {
                GetMapping getMapping = method.getAnnotation(GetMapping.class);
                url.append(getMapping.value()[0]);
                apiManag.setRequestMethod(1L);
            }
            if (method.isAnnotationPresent(DeleteMapping.class)) {
                DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
                url.append(deleteMapping.value()[0]);
                apiManag.setRequestMethod(4L);
            }
            if (method.isAnnotationPresent(PostMapping.class)) {
                PostMapping postMapping = method.getAnnotation(PostMapping.class);
                url.append(postMapping.value()[0]);
                apiManag.setRequestMethod(2L);
            }
            if (method.isAnnotationPresent(PutMapping.class)) {
                PutMapping putMapping = method.getAnnotation(PutMapping.class);
                url.append(putMapping.value()[0]);
                apiManag.setRequestMethod(3L);
            }
            ApiExplain explain = getExplain(method);
            apiManag.setRequestUrl(url.toString());
            apiManag.setDescribe(explain == null ? "" : explain.explain());
        }

    }

    /**
     * 获取属性说明
     * @param method
     * @return
     */
    private ApiExplain getExplain(Method method){
        // 获取方法的参数类型
        Class<?>[] paramTypes = method.getParameterTypes();
        // 遍历参数类型数组
        for (int i = 0; i < paramTypes.length; i++) {
            // 获取类的所有字段(包括私有、保护、公共字段)
            Field[] fields = paramTypes[i].getDeclaredFields();
            // 遍历字段数组
            for (Field field : fields) {
                // 打印字段名和类型
                // 检查字段上是否存在指定的注解
                if (field.isAnnotationPresent(ApiExplain.class)) {
                    // 获取字段上的注解
                    return field.getAnnotation(ApiExplain.class);
                }
            }
        }
        return null;
    }



}

          6.失败

                写到这,准备发送请求才发现这个行不通或者还得修改表的数据结构。因为要获取接口返回值,如果是写入操作务必对产生脏数据,所以还是单表crud 简单轻松。

     4.总结

       写的代码越多发现自己错的越多,但是辛苦绞尽脑汁的写的代码头大,想法都是出奇的奇怪。删了删了重写

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值