V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
DXDE443
V2EX  ›  Java

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

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

    以上情况都是 @RequestMapping,你要不用 @ModelAttribute
    DXDE443
        29
    DXDE443  
    OP
       Mar 27, 2018 via Android
    @domty 试了下并没有发现有什么用额,但如果配合 requestparam(required=false)这个 example 就永远为 null 了,穿什么都不好使
    DXDE443
        30
    DXDE443  
    OP
       Mar 27, 2018 via Android
    我 requestparam 注解确实用错了,但 requestbody 那前台就要穿 json 了吧,这改动稍微有点大
    seaswalker
        31
    seaswalker  
       Mar 27, 2018
    我觉着可以尝试自定义 HandlerMethodArgumentResolver,比如继承 RequestResponseBodyMethodProcessor
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5747 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 106ms · UTC 06:59 · PVG 14:59 · LAX 23:59 · JFK 02:59
    ♥ Do have faith in what you're doing.