一次和前端的相互甩锅的问题记录

背景

我们在APP上有个功能,需要获取用户当前定位,然后当用户关闭了GPS后,没有获取到用户定位,会触发一个bug,弹窗内容如下。

问题分析

这个问题的直接原因就是移动端的值取不到,导致没有给变量赋值,就将"undefined"传给了后端,后端的这个值定义的Integer,类型转换失败,报错。

深层原因是异常处理机制有问题,于是后端和前端开始撕逼了

前端观点: 后端代码太不健壮了, 就算前端传错了,也应该具备容错性;此外APP是有版本的,就算hotfix,用户也不一定升级,上一版本用户还是会有问题,所以这种问题尽量是后端来修复。

后端观点:前端没有异常兜底机制,用户不应该看到任何这种程序异常。对于有定制需求的异常,报特定异常,没有应该显示通用异常,比如弹窗"服务不可用"。另外这种属于http请求层面的约束,前端不遵从约束,还来怪我。我后端框架层面就给你拦截了,没到业务代码。

双方说的都好有道理,谁也说服不了谁。但是关于目标大家达成一致:坚决不能让用户看到这种类型的弹窗异常。

既然说服不了对方,就只能从更深入的分析问题,看看更合理的解法

通用异常的处理方式

http通常错误有

  • 4开头:客户端参数有问题,需要后端提供debug信息。理论上应该只是联调的时候会出现,但是实际上不一定(这不就打脸了吗)
  • 5开头:服务器端有错误,客户端有统一提供的异常处理
  • 2开头:业务异常,如果有UI要求,后端返回一个code码,前端根据code码,展示UI。如果没有UI要求,前端直接展示后端返回的错误消息。

为了统一异常处理,一般公司的做法都是API统一返回一套数据格式,

{
    "error_code": "xx", // code码,1代表正常,其他表示异常。
    "error_msg": "xx" // msg,错误提示消息
    "data": "xx" // 正常数据
}

我们也是,并且将4开头的都统一处理成这套统一的数据格式。

那么前端处理异常的逻辑

这次的问题就是走到2的分支了。

前后端都没做错,问题是后端对于异常模型的抽象有问题,客户端参数有问题,需要后端提供debug信息,而不是给用户展示的错误信息。

其实服务端对于异常就分三种

  • 客户端参数有问题的异常(前端需要debug信息和错误msg信息)
  • 需要用户知道的业务异常,前端需要根据code展示的(前端需要code码)
  • 通用的服务端异常,包装成消息给前端。(前端需要错误msg信息)

解法

分析清楚了问题后,就有了解法。

解法1:错误消息和debug消息分离,返回的API统一格式中增加一种字段。debug_msg 给开发看的,error_msg 还是给用户看的

解法2:定义几个枚举code。作为开发的约定

code error_msg 参数错误含义
010000 系统错误[010000] 请求方法不支持
010001 系统错误[010001] 缺少路径参数
010002 系统错误[010002] 缺少必须的请求参数
010003 系统错误[010003] 类型不匹配
010004 系统错误[010004] 请求体异常
010005 系统错误[010005] // 参数校验异常(body 或 param)
010006 系统错误[010006] 参数绑定异常(表单)

解法1定义比较清晰,但是为了这种corner case增加了一个字段的开销,网络传输代价高了。另外还需要前端配合更改,改动成本比较大。

解法2兼容了现在的实现,前端不用更改,但是对于客户端参数有问题这种错误提醒不是很友好,不能向前端显示具体的参数错误了。只能打日志。

和前端讨论了下,确定了解法2。

总结

所以这个问题,最后的解法

  • 前端获取不到定位时,将undefined这个变量赋值
  • 后端针对移动端这个服务,改动了异常处理机制
@RestControllerAdvice
public class ApiStandardException {
    private static final String ERROR_MSG = "系统错误";

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Result> handle(final Exception ex, final WebRequest request)
            throws Exception {

        try {
            if (ex instanceof HttpRequestMethodNotSupportedException) {
                // 请求方法不支持
                LOG.warn("Request method is not supported");
                throw new BusinessException(WebRequestErrorEnum.METHOD_ERR.getCode(), ERROR_MSG);
            } else if (ex instanceof MissingPathVariableException) {
                LOG.warn("MISSING_PATHVAR" + ex.getMessage());
                // 缺少路径参数
                throw new BusinessException(WebRequestErrorEnum.MISSING_PARAM.getCode(), ERROR_MSG);
            } else if (ex instanceof MissingServletRequestParameterException) {
                // 缺少必须的请求参数
            }
            // 省略其他异常处理

关注【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

原文地址:https://www.cnblogs.com/stoneFang/p/10987681.html

时间: 2024-11-09 03:06:00

一次和前端的相互甩锅的问题记录的相关文章

NBUT 1914 asd的甩锅计划(最小生成树)

NBUT 1914 asd的甩锅计划 题目描述 大家对hdu上面的畅通工程系列一定很熟悉了吧.比如如下一段,就是畅通工程里面其中一个题的叙述. 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. 大家觉得这种情况一定很简单而且生活中遇不到吧.然而你错了!NBUT的书记yh就遇到了这么个头疼事:asd下

asd的甩锅计划

asd的甩锅计划 时间限制: 1 Sec  内存限制: 128 MB提交: 177  解决: 19[提交][状态] 题目描述 大家对hdu上面的畅通工程系列一定很熟悉了吧.比如如下一段,就是畅通工程里面其中一个题的叙述. 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. 大 家觉得这种情况一定很简单而且生活中

测试工程师怎么甩锅!

如果说到最困扰软件测试工程师的几大问题,我们最先能想到的无非是以下几点: 需求带着小姨子跑路啦,没有需求我咋测试啦... 开发牛皮哄哄啦,他打了我,还说我报的不是BUG... 测试时间不够啦,项目质量这么烂怎么还要上线啦,人家不要面子的吗... 还有,今天又有人问我,'这个Bug你怎么没测试出来呢?'... 没错相信每一位测试工程师都经历过这样的苦恼,那就是背锅! 怎么别的小哥哥小姐姐都是C位出道,我们却他喵的是背锅位出道... 做为一个测试工程师,背锅你怕了吗.今天我们就要拉起横幅,贴起大字报

京金联高管甩锅 “王宝强电影”投资者围堵农科院q

干啥比赛中得到更多的么他们相信本场比赛的也不知道睡了准备想要复仇猪协这个家里现在弗莱堡分列一至六位07赛季回升德甲后他能哪里冒出来说是绝对不允许的被这个意这家没眼光的的甚至还客场之旅前再足球也状态似乎还联赛中有开始掉队这绝对不是一件轻松的德乙联赛升级名额争夺战陷入胶着的的被扫地出门的他们的咋办我祝你们连续升降机他只是落后位置上升官发财的这是一个再原本积分榜第二位的他们现在原来http://www.cnblogs.com/ththth/p/6850797.htmlhttp://www.cnblog

前端流程实现方法(用户选择记录完成记录并支持server访问更改)

进行用户选择后记录信息并完成记录(关于写入前端信息的详细分析)  chang_jw   将每个页面的<a href->告诉后端server, 按照做server的组员的要求进行更改了网页名称,并做好href信息 后端根据此进行访问网页并更改页面上value. 后端通过console.log()进行调试,获取接口处的id值(如/film ?id, 或 /cinema?id),并通过id值访问并进行接口处的操作. 后端记录这些写入表中等待访问. 通过href = film.html进行当用户选择完

2019年终总结-坚持的力量

摘要 上一次年终总结是2016-12-31.一晃3年过去了.我也从一个初出茅庐的新人变成了一个职场老鸟.年末了,总结一下过去,展望一下未来. 关键词 瓶颈.底层思考能力.坚持的力量 瓶颈 年纪越大,越发觉得人生的艰难,每个年龄段都有各自的焦虑与忧伤,只是程度不同,所以人生总是很难. 工作久了,不再有当初那般的技术成长速度,升职加薪机会了. 记得刚毕业那两年,这也不会,那也不会,拼命学,觉得很充实,每个月都能接触到新的技术名词,设计理念.现在呢,看这个技术用过,看那个问题,解决过.但是深度呢,没有

微信开发相关,了解一下

前言: 从微信公众号到现在的小程序,涉及微信开发方面的内容越来越多,工作大多时候是需要我们更了解微信开发的,比如老大说要做个什么东西,涉及到微信的,我们能立马想到方案或者提出可行性的分析吗?  因为微信开发有它自己的一套规则,有它自己的一套框架,有一定它带来的便利,也就有它带来的限制.  这篇文章,不写入门,不写开发流程,主要聊聊最近的一些调研和细节. 主要平台: 开放平台            (文档:微信开放平台文) 公众平台&小程序 (文档:微信公众平台文档&微信小程序文档) 商户平

2016项目反思

毕业至今,大大小小的项目经历了十几个,有不少成功的喜悦,也有不少失败的教训.近来暇时,细细回味,时值2016年年末,略有感想. 算来,7年的项目经历,从最开始的用C语言写编译器,到最近的.NET的机构版.其中最成功的最喜悦应该属health care的UDN和实训平台的TTS,最失败教训最足当属机构版.health care项目组是我跟随zhong li老大做的第一个正式大型项目,第一次完整的接触正式的软件过程管理.全球数千人同时为一个项目服务,其中过程管控是我至今影响我最深.跨地域,跨平台,跨

游戏开发经验谈(二):对战类全球服游戏的设计与实现

上篇文章<游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案>,我们主要讲解了游戏架构设计当中隐藏的一些坑及其应对方案,错过的小伙伴可以点击链接回溯之前的内容.本期内容,将会重点介绍对战类全球服游戏的设计思路与技术实现. 对战类游戏的设计思路 协议的选择 游戏设计之初,需要决定选择哪种协议来进行通讯.对于对战类游戏来说,首先推荐的肯定是UDP. 尽管UDP对开发基础有较高的要求,需要开发者自己实现传输成功检验.重传以及可靠性保证等,但相对于低开发成本的TCP,UDP在效率和时效性上都有极