问题布景

最近计划发动一个前后端分离的项目.创立spring boot工程.创立vue工程.不在这儿细说.这儿简略说一个状况码封装的问题.

web项目运用http协议.首先会想到http默许的状况码,例如200、301、401、500等.详细信息不在这儿阐明,网上许多白皮书.这儿说一下状况码界说的一些优化实践.

实践开发过程中事务代码一般会自界说一套包含事务意义的状况码.这样就会呈现两套状况码,一套是http默许的.一套是事务自界说的.这两套状况码在实践项目中如何运用呢?假如两套状况码语义上没有任何交集,那没问题,各用各的.依据事务布景取对应的状况码就能够了.所以理想状况是期望在界说事务状况码的时分避开http默许状况码的语义,http默许状况码能够满足的语义就运用http默许的.
可是实践操作中总会遇到一些特别状况或许看起来难以区分的状况.

举一个比如:企业信息查询接口,当查询用户没有所要查询企业的检查权限.这个时分后端可能设置http默许状况码401.假如前端关于没有查询权限简略弹窗提示,感觉运用401没什么问题.可是假如事务需求杂乱一些,用户没有查询权限分几种类型,不同的类型前端需求进行不同的触发动作.例如,用户不属于查询企业,前端提示用户不在查询企业内部,展现一个申请加入企业的跳转链接.假如用户在企业内部可是被公司法人约束访问,提示用户联络法人展现法人手机号.这个时分为了让前端有不一样的处理,只是运用401不够了.需求界说两个事务状况码401001标识不在企业内部,401002被法人禁止查询.有了事务状况码就会遇到一个问题,http默许的401还需求么?因为这个时分前端的判别逻辑可能是依据401+401001或许直接依据401001判别.我倾向于前端经过401001判别即可.这样401状况码存在与否就无所谓了.依照这个思路咱们能够制定一种比较极端的计划:便是一切的后端事务处理的恳求回来的http默许状况码都是200.一切的事务恳求都增加一个事务状况码阐明对应的事务语义.
基于上面的总结,说一个详细封装完成的计划.

后端服务完成计划(这儿只是运用spring boot项目作为阐明):

关于后端服务来说http默许的状况码只会用到200.一切事务语义都自界说一套状况码.这样很简略想到封装回来结构的时分两层结构,一层是http默许的status一致设置成200.回来的数据结构增加code变量用来标识事务语义的状况码.最简略的完成计划便是controller层封装ResponseEntity.status=HttpStatus.OK.数据目标运用调用事务方法的回来值判别.一般便是service层的回来目标封装之后写入.详细完成检查spring web的ResponseEntity.这儿不细说.

这样计划为了controller层完成简略,可能要求service屏蔽一切反常,只能经过回来值来进行处理.当然要求service层屏蔽一切反常也简略,经过封装service的切面阻拦一切反常.既然切面能够阻拦一切反常,那放到service或许servcie的调用层(例如manage层).无论哪一层都能够.可是往往实践问题要更加杂乱,例如依据反常的事务处理.假如咱们所在各层增加切面阻拦反常,可能因为反常被错误阻拦导致事务无法触发.或许其他的反常处理被错误屏蔽.解决这个问题的简略计划便是反常阻拦之后进行本层反常处理,处理之后再次抛出.一切不要反常处理的层都不做反常阻拦.便是切面里边和事务代码里边的try-catche处理之后都将反常继续抛出.一切的抛出反常都依据当前的事务语义设置状况码.一个计划便是自界说反常抛出结构.一切抛出的反常都有状况码.这个能够依据实践状况来处理了.

有的时分依据反常类型判别没必要增加状况码.例如咱们设计一个CanNotFindCompanyException(message).也能够设计一个通用的BusinessCompanyException(CanNotFindCompanyCode,message).我个人比较倾向于设计一个通用的.层与层之间的反常处理判别经过code.不是经过反常类型.当然了有些大的分类最好经过反常类型.例如需求事务回滚的反常和不需求事务回滚的反常.这个就看阻拦反常的处理计划了.这个详细问题详细分析一下.可是我个人觉得反常类型尽量少,尽量运用code.这样咱们做反常阻拦处理的时分反常阻拦分类比较简略.尤其是controller层一致反常阻拦.既然这儿提到了controller层一致反常阻拦就简略说一下.controller层反常阻拦一个简略完成计划是经过ControllerAdvice完成反常阻拦.例如ExceptionHandler注解判别.反常类型少,这儿处理的方法就少,而且大多数状况都是透传给前端,详细依据状况码的动作由前端决定.当然也能够经过过滤器和阻拦器完成,直接封装回来目标.我不倾向于在过滤器或许阻拦里边封装状况码.状况码一般和事务相关,阻拦器和过滤器一般是和事务无关.过滤器和阻拦里边处理反常的简略计划便是直接抛出.这儿说一个比较特别的比如.权限验证过滤器.验证用户是否登录系一致般在过滤器里边完成.假如恳求没有权限标识(例如token)直接抛出反常.过滤器反常直接抛给servelet容器.相当于回来前端500.所以过滤器抛出反常的时分需求谨慎,抛出反常之后前端是否有合适的处理计划.大多数状况下过滤器抛出的反常前端都是直接展现message信息,不会有其他处理.本文意图是说状况的封装,这儿说的许多反常处理的方法.因为一般状况反常处理睬涉及到状况码的设计.有些反常不需求状况码,有些需求.所以说的有点多了.

总结一下服务端状况码的处理:

默许http的状况码(status)运用200.事务界说一套自己语义相关的状况码.状况码的传递计划是:正确的状况码经过回来值方法传递.错误的状况码经过反常抛出的方法.尽量削减反常的类型,尽量经过一致的反常带着状况码的方法抛出.各层切面尽量不要屏蔽或许修改反常类型或许状况码,最好直接抛出.controller层经过advice一致处理反常.过滤器和阻拦器能够直接抛出servletException.没必要封装回来值反常.

前端服务完成计划(这儿运用axios方法阐明)

关于前端服务来说http恳求经过axios调用恳求.因为一切的事务反常回来的http status都是200,详细状况码在事务数据里边.我倾向于一切的http默许状况码的处理逻辑都放到axios阻拦器里边.阻拦器关于一切status是200的回来值直接将事务数据回来给调用接口.在详细封装各个事务调用接口里边解析出事务状况码code.进行详细事务处理.这儿有一个问题,各个事务接口关于状况码的处理可能有重复的.也可能有事务接口特有的.这样咱们能够封装一致事务状况码处理接口,一致接口里边无法处理的直接回来,再由各个事务接口单独处理.这样前端关于状况码的处理可能分为两层,三类型.两层是axios阻拦器处理的http默许状况码和事务处理的事务状况码.三类型是http默许状况码类型、事务通用状况码类型和接口特有状况码类型.