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

Java 有没有什么好办法做 Map 参数校验?

  •  2
     
  •   Freeego · 2020-03-04 16:07:52 +08:00 · 5020 次点击
    这是一个创建于 1730 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对象入参的话可以用 Validation,那如果是 Map 呢?只能自己写一套校验类吗,有没有什么黑科技可以用?
    29 条回复    2020-03-06 10:38:28 +08:00
    chendy
        1
    chendy  
       2020-03-04 16:43:23 +08:00
    换成对象入参
    用 Map 一时爽,维护 xxx
    Uyuhz
        2
    Uyuhz  
       2020-03-04 16:55:14 +08:00
    用 Map 后面是真难受 还是老老实实对象吧
    Freeego
        3
    Freeego  
    OP
       2020-03-04 17:00:05 +08:00
    @chendy
    @Uyuhz 问题是不是所有入参都能映射到 Bean 上面…总有些太灵活的用对象不太合适
    optional
        4
    optional  
       2020-03-04 17:01:40 +08:00
    用 json-schema 校验。
    18258226728
        5
    18258226728  
       2020-03-04 17:43:47 +08:00
    赞同 1 楼,用 Map 就是给自己找不自在...对象灵活就继承,继承不行就泛型,反正不用 Map 当参数
    godoway
        6
    godoway  
       2020-03-04 18:16:20 +08:00 via Android
    问一下 map 转对象( jackson 序列化之类)再校验,这思路是否可行
    avk458
        7
    avk458  
       2020-03-04 18:20:12 +08:00
    能用 map 的为什么不用 bean ?懒得生成*O 吗
    guyeu
        8
    guyeu  
       2020-03-04 19:00:36 +08:00
    说用 bean 的各位大佬,有个场景看怎么用 bean:

    一个接口需要适配若干种 sdk,每种 sdk 需要的参数都不一致(基本没什么共同点),接口参数就是 sdk 需要的参数,具体用哪种 sdk 由配置决定。

    这个入参怎么用 bean 呢?
    lurenw
        9
    lurenw  
       2020-03-04 19:05:47 +08:00
    @guyeu 除非是历史原因, 不然为啥一个接口要适配若干种 sdk 呢, 专事专干. 你即便用 map 适配了, 底层也是各种 case 判断
    neptuno
        10
    neptuno  
       2020-03-04 19:06:12 +08:00
    @guyeu 参数不一样的话,接口内部处理逻辑一样吗,如果也不一样的话,可以写成多个接口吧
    Freeego
        11
    Freeego  
    OP
       2020-03-04 19:09:00 +08:00
    @18258226728
    @avk458
    @guyeu 我的想法是这样,如果能用对象当然就用对象(所谓的能用指的是传入的参数在语义上确实符合对象的特性,比如一个用户一篇文章之类)。但是有的时候我确实找不到一种合适的方法创建它,就比如 @guyeu 说的。还有比如一个接口会对数据库中多个表进行更新操作的,比如接口中需要调用外部 sdk 进行装配的,这种不是直接参数入库的方法就比较难用对象表示参数,用了也很牵强,最后搞得到处都是 Bean。所以我觉得合适的用对象做参数,复杂的灵活的用 map,只要做好文档其实也可以,个人想法。
    daveze
        12
    daveze  
       2020-03-04 19:09:07 +08:00 via iPhone
    @guyeu 不要搞一个大而全的接口…在源头接口路径上就分开不好么,为啥要走到最后才分开。
    Cbdy
        13
    Cbdy  
       2020-03-04 19:27:48 +08:00 via Android
    可以尝试拓展一下我的这个库
    https://github.com/cbdyzj/joi
    Freeego
        14
    Freeego  
    OP
       2020-03-04 19:51:12 +08:00
    @optional
    @Cbdy
    谢谢,我看一下
    yanyueio
        15
    yanyueio  
       2020-03-04 20:22:36 +08:00 via Android
    正规路子就是 bean,即所谓的*O。就算要兼容各种 sdk,搞得 bean 满天飞,但没办法这是问题规模导致的。如果约定真的大于配置的话,那就和几家 sdk 的领导,管事儿的提前打好招呼,可惜,这不现实。然,如果你换一种思路考虑,真的都是简单聪明思路搞事情,那估计这个行业好多人会被迫转岗或者直接下岗。扯远了。具体看贵单位团队 leader 怎么说了。
    chendy
        16
    chendy  
       2020-03-04 20:35:15 +08:00
    @guyeu 你说这种不是接口…是入口…
    szuwl
        17
    szuwl  
       2020-03-05 00:01:17 +08:00
    强类型语言为什么要用 map 呢,直接使用 bean 就好,你现在图省事用了 map,后续要修改的时候会花费你几倍的时间并且会有更大程度的出错概率,而且 bean 做参数检验就简单多了
    Jooooooooo
        18
    Jooooooooo  
       2020-03-05 00:24:10 +08:00
    答案是不要用 map

    缺点太多, 不一一列举了
    guyeu
        19
    guyeu  
       2020-03-05 00:25:14 +08:00
    @yanyueio #15
    @daveze #12
    @Freeego #11
    @neptuno #10
    @lurenw #9

    一个接口的原因是希望这部分逻辑对客户端隐藏,客户端也只需要把自己本地的 sdk 传给它的数据传到服务器就行。采用哪种 sdk 是由环境决定的,基本上在构建期间就会把这个配置同步到前后端。
    fniy
        20
    fniy  
       2020-03-05 00:41:55 +08:00 via iPhone
    我包装了一下 map,然后提供 getString 之类的取值方式,抛出“key 不能为空,key 格式不正确”等的 ApiException。这样在 controller 里,取值很简洁。

    如果某值可以为空,就调取 optString (“key”,“默认值”)。注意,一个是 get,一个是 opt。
    neptuno
        21
    neptuno  
       2020-03-05 09:28:23 +08:00 via iPhone
    @guyeu 可以有多个入口,处理好参数之后,统一进入你们的逻辑方法,但如果是历史遗留原因,是不太好改
    wallace1z
        22
    wallace1z  
       2020-03-05 12:50:43 +08:00
    wallace1z
        23
    wallace1z  
       2020-03-05 12:52:28 +08:00
    不过如果可能还是希望不要用 Map,里面是什么,有什么,都不会很清楚,后期麻烦
    Freeego
        24
    Freeego  
    OP
       2020-03-05 13:46:40 +08:00
    @wallace1z
    @Jooooooooo
    @szuwl
    请教一下,有的时候参数只有两三个,而且映射不到一张数据库表里去,这个时候也是为此建一个 Bean 吗?
    wallace1z
        25
    wallace1z  
       2020-03-05 15:32:39 +08:00   ❤️ 1
    @Freeego 以 Spring MVC 为例,我个人而言,一般参数两三个的 Get 请求可以直接接收把,然后手动验证下参数合法性;当然了,如果这些参数多次出现,且验证流程一样那么就通过一个实体类然后通过 Valid 验证了。但是比如像请求是`application/json`这种就还是需要实体类的否则如果使用 Map 接收,那么如果你是前后通吃且这个项目不需要外人可以,但是如果不是怎么确保其他人对于这些能够字段能够清楚,难道让他去完全一清二白的摸源代码?
    这篇文章可以看下,https://xwjie.github.io/rule/controller.html#controller%E8%A7%84%E8%8C%83
    不说了,认真工作
    18258226728
        26
    18258226728  
       2020-03-05 17:54:15 +08:00
    @Freeego 还是推荐用 bean,类似 @guyeu 说的这种情况,一个接口调用若干 SDK,如果不把这些 sdk 的参数抽象出来为啥还要做接口?如果没有共同点我觉得都不是同一种接口,放在一起也不合适。
    用 Map 不如用泛型,接口无非就是通用的头和校验加密解密之类的,然后数据体就是泛型,按照不同场景定义 bean
    wc951
        27
    wc951  
       2020-03-05 19:19:19 +08:00
    jsr303 好像有分组校验吧,各种 sdk 也可以用一个对象啊
    guyeu
        28
    guyeu  
       2020-03-05 21:07:51 +08:00
    @18258226728 #26 根据参数类型划分接口么。。。我们的思路是根据功能划分接口。
    18258226728
        29
    18258226728  
       2020-03-06 10:38:28 +08:00
    @guyeu 不是哈,当然是根据功能,但是这功能一致的接口,参数确完全没用相同点,这个比较奇怪
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3094 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 14:43 · PVG 22:43 · LAX 06:43 · JFK 09:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.