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

请教大佬们一个关于 springmvc 的一个简单问题

  •  1
     
  •   DXDE443 · 2018-03-26 11:58:16 +08:00 · 4779 次点击
    这是一个创建于 2439 天前的主题,其中的信息可能已经有所发展或是发生改变。
    @GetMapping("test")
    public void Test(Job example){
        System.out.println(example);
    }

    对于这样一个 controller,我想要接受 example 这样一个可选实体参数,我希望前台传这个参数时,我可以正常接收到这个参数,前台不穿这个参数时,我希望这个参数为 null,但 springmvc 的逻辑是,不管前台是否穿了参数,都会 new 一个对象传进来,这样我就不好判断前台是否穿了这个参数,我尝试了@RequestParam(required = false)@RequestParam(defaultValue = "null"),均以失败告终,目前临时解决办法是重写了 eqauls 方法

    if(example.equals(new Job())){
        example = null;
    }
    判断传进来的实体是否和新 new 出来的空实体 eqauls,从而判断有没有参数,但我感觉这样很 low,请教一下各位大佬有没有更优雅的解决办法
    31 条回复    2018-03-27 14:00:23 +08:00
    sorra
        1
    sorra  
       2018-03-26 14:12:01 +08:00
    可以直接调用 request 做判断,检查一下 request body 之类的
    yang2yang
        2
    yang2yang  
       2018-03-26 14:19:56 +08:00
    目的是判断前台是否传递了这个参数,既然对象一定会 new 出来,那么是不是可以判断 example 对象里面的其他字段是否为 null,进一步来判断有没有传递这个 example 这个参数
    li24361
        3
    li24361  
       2018-03-26 14:24:08 +08:00
    不要判断对象,判断你需要的字段即可
    LucasLee92
        4
    LucasLee92  
       2018-03-26 14:38:21 +08:00
    可以用 aop 拦截,用 Objects.equals 做判断,然后判断与 new 的一致,把输出结果变为 null
    LucasLee92
        5
    LucasLee92  
       2018-03-26 14:39:27 +08:00
    可以考虑加自定义注解和 aop 的方式来定制实现你需要的功能
    seancheer
        6
    seancheer  
       2018-03-26 14:52:21 +08:00
    判断 job 里面的字段就可以了。。不行的话自行自定 interceptor,手动将 url 映射到 controller,然后就可以实现你想要的功能了。
    mosliu
        7
    mosliu  
       2018-03-26 14:54:52 +08:00
    我一般采用字段判断,
    好比:Long 类型的 id,判断 id==null 就好。
    DXDE443
        8
    DXDE443  
    OP
       2018-03-26 15:22:11 +08:00
    谢大佬们回答,感觉 spring 这块设计的不太好啊,我觉得我这个需求应该很正常吧,没传参留 null,竟然挺复杂。。。实体字段比较多而且都是可选参数,特别是部分字段是基本类型(int 什么的)有默认值,通过实体判断代码不少也不太靠谱,分析 request+aop/拦截器应该是可以,但这又得造轮子了。。。想了半天感觉干脆拆成两个 controller 一个带参数一个不带参数还简单点(逃
    pmispig
        9
    pmispig  
       2018-03-26 18:36:19 +08:00
    直接对参数对象进行判断就行了,比如传一个 map 进来,你看下 map 是不是空,是空的话肯定是没传,何必固执一定要空指针...
    azygote
        10
    azygote  
       2018-03-26 19:14:56 +08:00 via iPhone
    你这里 Job 对象类似一个容器,这个对象的每个字段对应你 get 请求的键值对,这个设计很合理,因为你 get 请求传参数肯定一个参数一个参数中间加&来传的,不存在直接传一个对象过来。
    lastpass
        11
    lastpass  
       2018-03-26 19:17:33 +08:00 via Android
    没有猜错的话(没有仔细研究过 springmvc 源码),
    springmvc 也是通过反射泛型来给你进行注入的。。
    你要你这个 example 为 null。
    那在反射的时候就直接 gg 了。
    而且没记错的话 struct2 也是这样的吧。
    DXDE443
        12
    DXDE443  
    OP
       2018-03-26 20:26:54 +08:00 via Android
    @lastpass 但这里如果是 Integer 或 String 它就会很聪明的留 null,特别是我加上了 @RequestParam(required=false)后,这个 example 更迷了,无论传什么字段都为 null,但穿 example=123 就会装配到第一个字段,虽然感觉应该是个 bug 但也说明了实现应该是可能的
    zhouyou457
        13
    zhouyou457  
       2018-03-26 21:17:01 +08:00 via iPhone
    requestmapping 了解一下
    yianing
        14
    yianing  
       2018-03-26 21:46:37 +08:00
    @zhouyou457 #13 getmapping 好像就是 requestmapping,只不过方式指明了 get
    watzds
        15
    watzds  
       2018-03-27 00:37:25 +08:00 via Android
    为什么要判断 null 呢,实在需要 Test 里再加一个 bool 参数也行啊
    yanjinbin
        16
    yanjinbin  
       2018-03-27 02:09:07 +08:00 via iPhone
    没听懂,你的接口设计有问题,spring mvc 会扫描注解,装备。有
    mgcnrx11
        17
    mgcnrx11  
       2018-03-27 07:10:50 +08:00 via iPhone
    @DXDE443 字段部分不用基本类型,用包装类型。阿里的手册也是这样建议
    jorneyr
        18
    jorneyr  
       2018-03-27 08:44:00 +08:00
    这个一般用 @Valid 来验证前端是否传递了某些指定的参数
    liuzuo
        19
    liuzuo  
       2018-03-27 09:23:08 +08:00
    @RequestBody 吧?为啥是 @RequestParam
    domty
        20
    domty  
       2018-03-27 09:36:52 +08:00
    ModelAttrinbute 注解?
    Infernalzero
        21
    Infernalzero  
       2018-03-27 09:38:43 +08:00   ❤️ 1
    你这种情况就应该用 POST,用 GET 的场景这个对象是通过 BeanUtils.instantiateClass 创建的,所以一定会有,如果你写到 body 里就是通过 messageConverter 来转了,这样只要设置 @RequestBody(required = false)就可以了
    lululau
        22
    lululau  
       2018-03-27 09:48:31 +08:00
    自己配置 ArgumentResolver 吧
    paragon
        23
    paragon  
       2018-03-27 09:54:44 +08:00
    @domty 看了这么多 终于有正确答案了~
    lastpass
        24
    lastpass  
       2018-03-27 10:37:12 +08:00 via Android
    回复 @DXDE443 (以下均为瞎猜)你看 integer 和 string 都是可以直接赋值的呀。不需要进行反射。反射的时候你需要存在这个对象,然后找到这个对象的方法,set 值吧。所以并不是 Integer 或 String 它就会很聪明的留 null。
    LucasLee92
        25
    LucasLee92  
       2018-03-27 10:43:02 +08:00
    @Infernalzero
    大佬,想系统学习 spring,看哪本书比较好,还是说得去看源码吗?
    johnj
        26
    johnj  
       2018-03-27 10:50:35 +08:00   ❤️ 1
    @LucasLee92 官方文档不错
    DXDE443
        27
    DXDE443  
    OP
       2018-03-27 11:52:44 +08:00 via Android
    @mgcnrx11 我的实体类是用 idea 的 jpa 工具生成的,这个工具 not null 的字段都会被映射成基本类型,我个人没找到哪里有设置不生成基本类型,一个一个改就太麻烦了
    vjnjc
        28
    vjnjc  
       2018-03-27 12:04:05 +08:00
    #24 楼说得对,string 和 Integer 无法反射赋值,所以是 null。
    一般的 object 都是先构造,再把每个参数反射注入。
    你的情况就是构造好了后没有参数可以注入,程序结束。

    以上情况都是 @RequestMapping,你要不用 @ModelAttribute
    DXDE443
        29
    DXDE443  
    OP
       2018-03-27 12:11:01 +08:00 via Android
    @domty 试了下并没有发现有什么用额,但如果配合 requestparam(required=false)这个 example 就永远为 null 了,穿什么都不好使
    DXDE443
        30
    DXDE443  
    OP
       2018-03-27 12:18:26 +08:00 via Android
    我 requestparam 注解确实用错了,但 requestbody 那前台就要穿 json 了吧,这改动稍微有点大
    seaswalker
        31
    seaswalker  
       2018-03-27 14:00:23 +08:00
    我觉着可以尝试自定义 HandlerMethodArgumentResolver,比如继承 RequestResponseBodyMethodProcessor
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1995 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 102ms · UTC 16:20 · PVG 00:20 · LAX 08:20 · JFK 11:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.