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

请教一下,你们写接口的时候如果传入参数不合法,返回的结果是直接提示参数非法还是报错?

  •  
  •   InHello · 157 天前 · 5608 次点击
    这是一个创建于 157 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如有一个查询车辆详情的接口,参数定义的是车牌号,但是我做接口测试可能会传入纯数字、英文、null 等等这些正常参数外的其他字符。 我司返回来的结果直接报 java 错误,在我的理解中如果参数非法,返回的接口应该是提示用户"参数非法"而不是直接报一个 java 错误,不知道对不对。

    54 条回复    2022-12-29 16:00:14 +08:00
    nekoneko
        1
    nekoneko  
       157 天前
    对, 让后端统一处理一下返回信息
    JYii
        2
    JYii  
       157 天前   ❤️ 1
    当然是捕捉参数异常丢出去,你同事那直接就是懒得处理
    liprais
        3
    liprais  
       157 天前
    直接报 java 错误是抛异常?
    抛异常说明有问题,用户不应该看到你内部的异常
    cai88112
        4
    cai88112  
       157 天前
    你是对的
    InDom
        5
    InDom  
       157 天前
    报错误一般就是真的没在入口做检测, 后面莫名其妙在某个地方没按预期运行崩了.
    不过入口参数检查的时候,如果不符合预期也可以使用报错的方式反馈.

    但是这两种还是可以分出来的 如果 每次都完全不同的错误就属于前者, 如果每次错误提示都很相似, 大概率是第二个了.
    k9982874
        6
    k9982874  
       157 天前
    直接爆堆栈就过分了,让后端加 validation
    InHello
        7
    InHello  
    OP
       157 天前
    @liprais 抛异常的
    wolfie
        8
    wolfie  
       157 天前
    序列化错误怎么算?
    int32 类型,传 abc 。
    yatoooon
        9
    yatoooon  
       157 天前
    后端统一处理
    wong2
        10
    wong2  
       157 天前
    400 而非 500
    InDom
        11
    InDom  
       157 天前
    但是 如果是后者 属于 预期内的错误, 是可以以可以预期的方式提供错误信息(比如按照接口规范返回与前端沟通过的特定格式的数据)

    而非直接给了一个前端不曾预料的返回内容, 所以,不管怎样,如果出现了这个不可预期的返回,就是后端的锅.
    InHello
        12
    InHello  
    OP
       157 天前
    @wong2 code 直接报 500 ,message 报异常
    dd991
        13
    dd991  
       157 天前
    后端提示什么,直接展示出来就好,老板会让他改的
    unco020511
        14
    unco020511  
       157 天前
    后端有框架可以很方便的校验参数有效性
    AirBai2
        15
    AirBai2  
       157 天前
    http 状态码 400 ,外加 message
    wangritian
        16
    wangritian  
       157 天前
    你是指报异常吗?确实不对,应该报业务或框架层级的错误
    bthulu
        17
    bthulu  
       157 天前
    我一般是报 200, 数据返回默认值
    lucays
        18
    lucays  
       157 天前
    总之报 500 肯定是有问题
    200 还是 4xx 看公司内部规范。。。
    wu00
        19
    wu00  
       157 天前
    参数错误,后端 validation+默认提示(给开发人员看的),前端自己也要做前端的 validation ,用户提示信息是前端自己定
    业务错误,http 状态码 4xx ,给 errorType 和 message(给开发人员看的),前端根据 errorType 做页面逻辑和错误提示
    服务端异常,http 状态码 500 ,前端给友好页面 /提示(稍后再试)
    buchikoma
        20
    buchikoma  
       157 天前
    这种需要前后端定一下异常类型和异常提示,后端根据异常类型抛错误信息和 code ,前端根据 code 对错误信息进行包装抛给用户
    xuanbg
        21
    xuanbg  
       157 天前
    直接抛异常那就是懒。嗯嗯,虽然我有时候也这样。
    spring 是可以在实体类的字段上通过注解来对参数进行校验的。如果不是实体类,那也可以自己写校验逻辑。然后抛参数非法的异常出去就好了。

    虽然,这样做意义其实也不是很大。但作为一个有追求的程序员,优雅是必须的。
    Felldeadbird
        22
    Felldeadbird  
       157 天前
    按理来说应该提示非法参数。 估计后端没做处理,当非法提交后涉及到异常报错了,触发了 java 错误。

    前端的做法应该是根据 code 或者 status 返回结果 执行对应的提示页或错误页。
    hhjswf
        23
    hhjswf  
       157 天前
    说明没有做全局异常处理。
    zypy333
        24
    zypy333  
       157 天前
    我想起来我的奇葩同事,写个传入楼层返回该楼层门禁点位 list ,然后他硬是写了个如果查不到数据手动抛个异常,但是实际上有的楼层确实是没有门禁报警器的,然后他还不愿意改,最后是前台想办法单独处理,遇到那个楼层,直接不请求后台
    zypy333
        25
    zypy333  
       157 天前
    他应该不上 v 站

    ```java
    public TableDataInfo list(@PathVariable String floor) throws Exception {
    EntrancePoint entrancePoint=new EntrancePoint();
    List<PublicEquipment> listOfep=new ArrayList<>();
    List<EntrancePoint> list=null;
    if(floor.isEmpty()){
    throw new Exception("Please enter the number of floors");
    }else {
    entrancePoint.setFloor(floor);
    list = entrancePointService.selectEntrancePointList(entrancePoint);
    if(list.isEmpty()){
    throw new Exception("The set or list cannot be empty!");
    }else{
    for (EntrancePoint entrancePoints:list) {
    PublicEquipment pe =new PublicEquipment();
    pe.setDeviceName(entrancePoints.getName());
    pe.setIp(entrancePoints.getEntranceHost());
    pe.setModelName(entrancePoints.getModelName());
    pe.setState(entrancePoints.getEntranceStatus().equals("0")?"开启":"关闭");
    pe.setDoorNum(entrancePoints.getVariable());
    listOfep.add(pe);
    }
    }
    }
    return getDataTable(listOfep);
    }
    ```
    kop1989smurf
        26
    kop1989smurf  
       157 天前
    不能任凭异常抛出。

    1 、异常需要全局处理,要有对应的类型编号、唯一编号、日志记录。
    2 、未处理的异常会增大 web 容器的开销。
    3 、不利于其他产品进行统一的错误提示。
    InHello
        27
    InHello  
    OP
       157 天前
    @Felldeadbird 对的 就是这样的,但是前端也没有做任何异常处理
    InHello
        28
    InHello  
    OP
       157 天前
    @zypy333 就是这种
    InHello
        29
    InHello  
    OP
       157 天前
    @kop1989smurf 我感觉我司他们就没有做任何处理
    YouTing
        30
    YouTing  
       157 天前
    前后端都没有写校验,也没有抛出异常。前端至少要对 500 等未知错误进行提示,因为不知道什么时候就出奇奇怪怪的的问题,有提示用户就知道这一步不能干,后端的参数校验是必写的
    zoharSoul
        31
    zoharSoul  
       157 天前
    如果用户正常操作不会碰见的 case, 那什么文案无所谓的
    Macolor21
        32
    Macolor21  
       157 天前
    spring validation 这么难学吗?
    chioplkijhman
        33
    chioplkijhman  
       157 天前
    422 Unprocessable Entity
    libook
        34
    libook  
       157 天前
    直接包 Java 错误是不是意味着根本没做错误处理?

    具体还是得形成标准,而标准不唯一。主要的目的还是利于联调以及前端进行错误展示,比如对所有的情况划分业务状态码。
    ThreeK
        35
    ThreeK  
       156 天前
    Validation 加 Exception Handling 。自己代码直接参数异常抛出去,项目统一拦截返回,每块代码都各司其职。
    msg7086
        36
    msg7086  
       156 天前
    抛异常可以但是最顶层要接住异常然后返回正确的 JSON/XML 主体啊。
    zsj1029
        37
    zsj1029  
       156 天前
    @zypy333 我也会这样写,这个习惯个人来看挺好的,但是全局必须有个 catch 拦截,转可读格式数据给前端,我说的是接口的情况。如果是 sdk 调用,调用方处理异常也是可以接受的
    devswork
        38
    devswork  
       156 天前
    @NotBlank("车牌不能为空值")
    @Pattern(regexp = "正则",message = "车牌格式不合法")
    @Length(min = 7,max = 7,message="车牌必须为 7 位")
    private String number;
    devswork
        39
    devswork  
       156 天前
    @devswork 我们每个接口都得定义入参 VO ,以及出参 VO ,然后每个 VO 上的每个参数都要加 validation 判断 null 、判断空字符串、判断长度等,必要时候加正则校验,然后写一个统一异常处理器,处理 BindException 、MethodArgumentNotValidException 、ConstraintViolationException ,如果异常是属于业务上定义的,自己封装一个 Exception 和定义一个返回码,用来表示数据不符合业务规定。
    FawkesV
        40
    FawkesV  
       156 天前
    @devswork #38 正规做法就这样, 对入参进行校验就好
    Seayon
        41
    Seayon  
       156 天前
    基于 Spring 和 Hibernate Validation 的全局参数统一校验,Spring Boot 参数校验
    https://blog.csdn.net/Seayonzhao/article/details/118419116
    nanjingwuyanzu
        42
    nanjingwuyanzu  
       156 天前 via iPhone
    后端这也太懒了吧
    aru
        43
    aru  
       156 天前
    @devswork 我就说一句,新能源车牌是 8 位
    netabare
        44
    netabare  
       156 天前 via Android
    感觉应该区分「输入 /输出数据不合法」和「程序内部状态错误」吧。

    在我的理解里,一个程序应该是只对特定的输入有效,产生期待中的输出,对于这以外的其他输入,应该直接拒绝运行,避免产生意想不到的结果。

    在后端里面,这个逻辑应该可以等价于……一个大的事件循环在监听外部的请求,首先检测请求的有效性,对于有效的请求,开始执行这个程序(启动线程、调用服务之类的),
    netabare
        45
    netabare  
       156 天前 via Android
    如果请求内容无效,直接返回错误报告。

    然后…在后端程序里面,毕竟无法保证程序状态永远正确,所以需要用异常来检查和保证程序尽量正确运行。

    唔,我倒是没怎么写过后端,但是我对程序的理解是这样。感觉重要的还是如何保证请求的内容健康有效这一个环节,当然可用的工具也很多就是了。

    至于随地抛异常,我是反对的,因为异常意味着程序状态发生了不正常的情况,即使可以在上层捕获,这种用法给人的感觉就像用异常处理 NPE 一样(
    dengji85
        46
    dengji85  
       156 天前
    我就不做后端校验的,只做前端校验,因为时间不够,能用就行
    wupher
        47
    wupher  
       156 天前
    你的理解没错。

    后端永远不应依赖于前端校验。正则表达式校验一下车牌号,如果不会写,还可以询问 ChatGpt 。

    像这样写代码,能用。但一旦到了运营环境中,出现故障想要溯源,日志中到处都是异常栈,会很难追溯。
    shm7
        48
    shm7  
       156 天前
    抛出特定类型的参数非法错误,外部错误处理机制返回 参数非法提示信息。
    daliusu
        49
    daliusu  
       156 天前
    肯定也不能直接抛出内部错误
    可以约定抛出一个 400 错误,携带一个 errorMsg:"xxxx",然后再带个参数来描述需不需要前端弹出提示,比如 talkError:true ,这样前端在接口响应层直接拦截就可以自己写错误提示样式,具体错误信息后端返回,框架一般都自带这种功能
    devswork
        50
    devswork  
       156 天前
    @aru 只是 validation 用法举个例子,不要在意细节
    zypy333
        51
    zypy333  
       155 天前
    @zsj1029 我不理解这种写法居然还能有人赞同,数据库查不到结果就返回空就行了,抛个错是几个意思
    hellojukay
        52
    hellojukay  
       155 天前
    直接返回 4xx , 但是不要直接提示 "xxx 参数不合法“,对于系统入侵者来说,这样的提示是一个指示牌,告诉他们怎么入侵系统。
    ma836323493
        53
    ma836323493  
       155 天前
    前端都不做校验我后端做什么校验
    SACKJJKLL
        54
    SACKJJKLL  
       154 天前
    参数后端校验,后端写个 wrapper 抛出或者直接 java 抛异常
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4718 人在线   最高记录 5634   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 09:08 · PVG 17:08 · LAX 02:08 · JFK 05:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.