V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Joker123456789
V2EX  ›  Java

分享一下声明式 API 的写法

  •  
  •   Joker123456789 · 2020-12-16 12:02:56 +08:00 · 4538 次点击
    这是一个创建于 1430 天前的主题,其中的信息可能已经有所发展或是发生改变。

    通常一个 Controller 是以 class 的形式创建的,需要在里面注入 Service,写方法体,调用 Service 的方法,来完成数据交互。

    而声明式 API 是将 class 变成一个 interface,节省了一些代码量,从而提高开发效率,同时因为这只是一个抽象方法,重新编写的成本极低,所以当不需要的时候 可以直接无脑删,不用担心后面又需要了咋办。

    演示效果如下

    假设现在有一个 Service,bean 名称为 aService,现在需要通过 Controller 来调用 aService 里面的 selectList 方法

    @MarsApi(refBean="aService")
    public interface TestApi {
    
    	返回类型 selectList(TestDTO testDTO);
    }
    

    当我们请求这个接口的时候,他会自动调用 aService 里面的 selectList 方法,并将返回值转成 json 返回。

    如果我想在这个 API 里面 调用 bService 里的方法咋办?

    @MarsApi(refBean="aService")
    public interface TestApi {
    
    	// 这个注解可以覆盖类上面的 refBean
    	@MarsReference(beanName = "bService")
    	返回类型 selectList(TestDTO testDTO);
    }
    

    我不想把 API 里的方法名称 写的跟 Service 一样咋办?

    @MarsApi(refBean="aService")
    public interface TestApi {
    
    	@MarsReference(refName = "要调用的 service 的方法名")
    	返回类型 selectList(TestDTO testDTO);
    }
    

    我可以不调用方法,只返回 Service 里面的一个属性值吗?

    @MarsApi(refBean="aService")
    public interface TestApi {
    
    	@MarsReference(refName = "要调用的属性名", refType = RefType.PROPERTY)
    	返回类型 selectList(TestDTO testDTO);
    }
    

    想对参数做校验咋办,这都没方法体了,难道写在 Service ?

    在接参对象的属性上添加 @MarsDataCheck 注解接口

    // 不可为空,且长度在 2-3 位
    @MarsDataCheck(notNull = true,maxLength = 3L,minLength = 2L, msg = "id 不可为空且长度必须在 2-3 位之间")
    private Integer id;
    
    // 正则校验
    @MarsDataCheck(reg = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$",msg = "密码不可以为空且必须是 6-12 位数字字母组合")
    private String password;
    

    不同的接口对参数的校验需求不一样,这种校验方式在遇到两个接口用同一个接参对象时会不会就 GG 了

    不会,加一个 apis 属性即可搞定

    public class ExpVO {
    
        /* 
         * expGetRequest 和 expPostRequest 两个接口都不允许 name 为空
         * 只需要在 apis 属性里配置这两个接口即可,但是由于他们都是 exp 开头的
         * 所以用通配符即可
         */
        @MarsDataCheck(notNull = true, msg = "名称不可以为空", apis={"exp*"})
        private String name;
    
        /* 
         * saveRequest 和 expPostRequest 两个接口都不允许 address 为空
         * 只需要在 apis 属性里配置这两个接口即可
         */
        @MarsDataCheck(notNull = true, msg = "地址不可以为空", apis={"expPostRequest","saveRequest"})
        private String address;
    
    }
    

    想要给 API 加 try-catch,让它在异常的时候,还可以正常返回 json 咋办?

    这个不用使用者关心了,因为这个框架是纯粹面向前后端分离的,所以无论出现什么情况,前端都可以收到 json, 假如出异常了,那么前端会收到这样一个 json

    {error_code:500, error_info:"异常提示"}
    

    我还是有点顾虑,不敢尝试这种写法

    没关系,我们兼容常规的 Controller 写法

    @MarsApi
    public class DemoController {
    
    	@MarsWrite("userInfoServiceImpl")
    	private UserInfoService userInfoService;
    
    	public String demo(UserInfoDTO userInfoDTO, HttpMarsRequest request){
    		return "";
    	}
    }
    

    有点意思,我想再多了解一点

    官网地址:http://mars-framework.com/

    第 1 条附言  ·  2020-12-16 15:12:59 +08:00
    有些人啊,就很奇怪,我分享下我的作品 碍你什么事了吗? 不喜欢就退出不就好了? 我分享个作品 就活该被你们骂还是怎么着?

    这些人真是脑子有问题,赶紧去医院看看吧。
    43 条回复    2020-12-17 13:22:11 +08:00
    lwq84510
        1
    lwq84510  
       2020-12-16 12:44:01 +08:00 via iPhone   ❤️ 1
    @Livid 这历史发帖算变相推广了吧
    SorcererXW
        2
    SorcererXW  
       2020-12-16 12:50:43 +08:00
    你需要 GraphQL
    Joker123456789
        3
    Joker123456789  
    OP
       2020-12-16 12:57:15 +08:00
    @SorcererXW 跟我这个完全不搭噶, 拿其他项目压我,也要压在点上啊。 弄个完全不搭噶的 干嘛。
    Joker123456789
        4
    Joker123456789  
    OP
       2020-12-16 13:08:11 +08:00
    @lwq84510

    你能找到 跟这一模一样的历史帖子,我直播吃屎。

    还有,这里都是程序员,我推的也是一个正儿八经的开源项目,开源,开源。 所以你有什么无法接受的?

    不喜欢不用不就好了。
    Kirsk
        5
    Kirsk  
       2020-12-16 13:54:01 +08:00 via Android
    没有用过你项目的 这什么奇葩写法 调用顺序是什么 用过 spring 的 哦 我去找声明 bean 注入的地方 做框架是要解耦 不解耦要他干嘛 你这个侵入程度很明显 只适合自己内部用 比 autowired 更费心力
    eric96
        6
    eric96  
       2020-12-16 14:28:10 +08:00   ❤️ 1
    你们怎么会有这么多奇怪的想法
    efaun
        7
    efaun  
       2020-12-16 14:29:53 +08:00   ❤️ 1
    @Joker123456789 #4 开源不是挡箭牌,只要帖子里有外部链接且利益相关的,一律算推广
    disk
        8
    disk  
       2020-12-16 14:31:17 +08:00
    如果接口和服务是绑定的,用这个注解可以省些代码量。解耦的话完全就不合适这种。
    Joker123456789
        9
    Joker123456789  
    OP
       2020-12-16 14:44:02 +08:00
    @efaun

    是算推广啊,不然我分享出来干嘛? 推上 github,静静等待,一切看缘分不是更好。

    而且谁写东西不是为了利益的? 我还真不信有这种人, 不为推广,不为让更多人看到,那么放自己网盘加密不是更好。

    我之所以声明是正儿八经的开源项目,不是为了当挡箭牌,只是为了明确调性,技术社区发技术帖子,我个人认为完全没问题, 我之所以有罪 就是因为这个项目是我做的,如果不是我做的,估计就没人说啥了。
    jaylee4869
        10
    jaylee4869  
       2020-12-16 14:46:14 +08:00
    Java 开发者使用声明式 API 无非就是注解。
    https://lawrenceli.me/blog/declarative-programming
    Joker123456789
        11
    Joker123456789  
    OP
       2020-12-16 14:46:16 +08:00
    @Kirsk controller 调用 service 要什么顺序? 不就是调用 service 里的一个方法就好了吗?

    你后面几句 我一句都没听懂,可否详细说明一下?
    Joker123456789
        12
    Joker123456789  
    OP
       2020-12-16 14:48:24 +08:00
    @jaylee4869

    针对你的回帖,我想说一句 [AOP 无非就是动态代理,IOC 无非就是反射赋值]

    然后,你给我的连接里面的声明式 API 应该仅仅只是跟我的说法重名了,但不是同一种东西。
    efaun
        13
    efaun  
       2020-12-16 14:49:34 +08:00   ❤️ 2
    @Joker123456789 #9 “你之所以有罪 就是因为”你的贴子应该发在了 java 节点而不是推广节点,懂?
    Joker123456789
        14
    Joker123456789  
    OP
       2020-12-16 14:52:15 +08:00
    @efaun 如果不是我做的呢?? 你还会说这句话吗? 如果我介绍的是 spring 里的 某个技术点呢?

    还有,这整篇文章都是在正儿八经的介绍这个结束点啊,你看到什么推广的字眼了没? 不就因为这个项目是我做的,你们很排斥嘛。
    zhuangzhuang1988
        15
    zhuangzhuang1988  
       2020-12-16 14:54:52 +08:00
    不喜欢写一堆注解来做 dependency-injection
    还是 asp.net 来得好,
    https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0
    efaun
        16
    efaun  
       2020-12-16 14:57:08 +08:00   ❤️ 2
    @Joker123456789 #14 看不懂人话?我第一句就说了“只要帖子里有外部链接且利益相关的,一律算推广”,第二句也说了“你的贴子应该发在了 java 节点而不是推广节点”,全篇跟是不是你做的有关系吗?你算什么东西?不是你做的几个 star 怎样,是你做的几万个 star 又怎样?推广就应该发在推广节点,你自己的回复也承认了这是推广,现在又翻脸不认?什么玩意
    brezp
        17
    brezp  
       2020-12-16 15:00:00 +08:00
    点进去看了下, 野心很大啊, 想自己再造一个 spring?
    Joker123456789
        18
    Joker123456789  
    OP
       2020-12-16 15:02:57 +08:00
    @efaun 那你又算什么东西? 轮得到你指指点点?? 我发个技术文章关你屁事啊? 不喜欢就滚蛋,我求你用还是怎么着?

    你说我该发到推广节点,不就是因为 [这是我做的吗?] 除此之外还有什么原因吗?? 你从我的文章里一五一十指出问题来,去指啊。

    如果我的文章是 [分享一下 AOP 的写法] 你还会跟我说这些屁话吗?

    连你自己为什么要骂我的原因 自己心里都没数吗??

    是你莫名其妙的出来一顿乱喷,还好意思对我发火,什么玩意。
    efaun
        19
    efaun  
       2020-12-16 15:09:48 +08:00
    @Joker123456789 #18 两次好言好语回复不看,非要被喷才舒服,看来你现在还是不知道自己的项目为什么不被 V2EX 的人看好,哎,可怜、可悲、可叹,希望其他开源项目没事🙏
    Joker123456789
        20
    Joker123456789  
    OP
       2020-12-16 15:14:34 +08:00
    @efaun 好言好语??? 哈哈哈 XSWL, 知道自己理亏了 就开始扯别的了? 还希望别的没事,别的项目 一样被你们这种人喷。 在这装什么无辜呢
    11ssss
        21
    11ssss  
       2020-12-16 15:17:47 +08:00
    ‘我之所以声明是正儿八经的开源项目’ 路过,GitHub 开源协议不加一下吗?
    Joker123456789
        22
    Joker123456789  
    OP
       2020-12-16 15:19:03 +08:00
    @11ssss 你应该没认真看,或者你的网卡了 没加载出来
    efaun
        23
    efaun  
       2020-12-16 15:21:42 +08:00   ❤️ 2
    @Joker123456789 #20 哎,可怜人,其他项目都会遵守规则发推广节点,只有你,我说了三次你还不知道错在哪里

    呜呼哀哉!
    11ssss
        24
    11ssss  
       2020-12-16 15:22:40 +08:00
    @Joker123456789 看错了 当我没说
    Joker123456789
        25
    Joker123456789  
    OP
       2020-12-16 15:25:00 +08:00
    @efaun 那你又知道自己错在哪了吗? 呜呼哀哉你 MB 啊。真当自己是上帝啊,我做什么轮得到你指指点点? 赶紧滚吧,有意见就举报一波,让管理员来删帖,比跟我 BB,看你来气。
    shuige
        26
    shuige  
       2020-12-16 15:43:49 +08:00
    楼下吃瓜
    rocbomb
        27
    rocbomb  
       2020-12-16 15:47:31 +08:00
    这个。。。ASP.NET Core MVC 是不是有点像
    liuhuansir
        28
    liuhuansir  
       2020-12-16 15:47:42 +08:00
    吃瓜,看看最后怎么处理这个帖子,劝 LZ 还是别爆粗口,注意下素质
    qwertyzzz
        29
    qwertyzzz  
       2020-12-16 16:22:39 +08:00
    吃瓜 我觉得这还好吧 没那么多推广味 发哪我也不那么在意 不看 x 了得了 没必要当个圣母指指点点
    Joker123456789
        30
    Joker123456789  
    OP
       2020-12-16 16:23:14 +08:00
    @liuhuansir 谢谢提醒,但是没办法,直性子被喷了忍不住要反击。
    shenlanAZ
        31
    shenlanAZ  
       2020-12-16 16:23:35 +08:00
    相当于把 controller 层砍掉了,如果 controller 需要根据参数来调用不同的 service 乃至不同的方法 这样就很难实现了。

    另外 refBean 为什么要 Bean 名称,既然已经确认类型了 为什么不用 IxxService.class ?我为什么还要手动拼出来 bean 名称 还是说你框架可以帮我自动取到 bean 名称。

    另外一点 在异常的时候返回 我比较关心你那个 error_code 为 500 的时候 http status 是不是 500,error_code 是否可以定制,如果不可定制 那和 http status 重复的意义在哪里?
    Kirsk
        32
    Kirsk  
       2020-12-16 17:28:39 +08:00 via Android
    @Joker123456789 如果你认为使用你的东西要仔细阅读文档 而不是像多数人使用 spring 时一些约定俗成的写法 那 ok 如果不是我怎么知道你封装的注解有什么操作 而且你这个设计等于在 spring 上再自己封装一层 你能给使用者带来更高效的开发吗 如果我不用你框架了 是不是全部爆红? 影响到整体项目没? 打个比方 我从 orm1 框架换 orm2 他影响的范围是数据存取部分 如果 orm12 都遵守一样的范式协议影响更小 你说你能直接删 你的返回单个参数涉及业务逻辑没? 参数校验规则涉及没 你见过哪个框架是这么设计的 我把框架删了要不要补大量的逻辑?
    mmrx
        33
    mmrx  
       2020-12-16 18:42:18 +08:00
    spring boot 小白,我想问这个 interface 的写法兼容 Swagger 么,支持注解方式的跨域配置么
    如果不支持,只能用你说的兼容常规 Controller 写法,那这个框架还有什么意义呢
    Joker123456789
        34
    Joker123456789  
    OP
       2020-12-16 19:53:48 +08:00 via iPhone
    @mmrx swagger 是 自动生成文档的,不是硬需求,支不支持看后面规划。 跨域问题,这个肯定是支持的,不然我敢纯粹面向前后端分离吗
    Joker123456789
        35
    Joker123456789  
    OP
       2020-12-16 19:55:18 +08:00 via iPhone
    @shenlanAZ 根据返回的数据,判断是否成功 并不难吧, 为什么必须要 http status 告诉你, 我不太理解。
    Joker123456789
        36
    Joker123456789  
    OP
       2020-12-16 19:57:24 +08:00 via iPhone
    @Kirsk 这跟 spring 一点关系都没, 而且我确实不是按照约定俗成的规则写的。

    不会出现报红,因为这不是渐进式框架, 使用者要么从创建项目开始就用,要么永远不用。
    Joker123456789
        37
    Joker123456789  
    OP
       2020-12-16 20:00:32 +08:00 via iPhone
    @shenlanAZ 而且 现在流行的做法 不都是 catch 里返回 json 吗,或者用异常监听, 就是为了避免 500 啊
    Joker123456789
        38
    Joker123456789  
    OP
       2020-12-16 20:03:08 +08:00 via iPhone
    @Kirsk 最后,我说的删 不是指删框架, 你可能没看懂, 又或者是我没写明白
    xuanbg
        39
    xuanbg  
       2020-12-16 20:19:29 +08:00
    我今天下午 40 多个接口居然一气呵成写完鸟……,中间还玩了几把游戏,这效率还要什么自行车
    mmrx
        40
    mmrx  
       2020-12-17 10:04:10 +08:00
    @Joker123456789 Swagger 目前我接触到的基本上都是用的,输出 API 文档目前应该就是硬需求了吧..
    另外这些基础的注解配置我专门看了一下你官网的文档,貌似都么有提及,都是在讲一些新的,不一样的点。个人感觉没有兼容说明对于大多数人都是比较劝退的,因为没多少人原因当小白鼠
    mmrx
        41
    mmrx  
       2020-12-17 10:04:44 +08:00
    @mmrx 原因->愿意
    alienx717
        42
    alienx717  
       2020-12-17 10:55:20 +08:00
    有想法
    Joker123456789
        43
    Joker123456789  
    OP
       2020-12-17 13:22:11 +08:00 via iPhone
    @mmrx 另外的注解配置是指啥? 我不是很明白,可否细说一下。

    然后关于 swagger 这个,支持当然是最好的,可以避免手工写文档嘛, 但不支持嘛 也不是很要命, 主要看使用者的想法吧。 不过我后面会考虑的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1913 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:34 · PVG 00:34 · LAX 08:34 · JFK 11:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.