问题描述
操作介绍:请求某个接口A,在该接口中通过POST请求另一个接口B
现象描述:由于请求接口B时URL地址错误,在接口A中没有捕获异常,出现异常之后。对此处的断点放行之后,会跳转到我的登录拦截器,登录拦截器里面校验的时候检测到用户未登录(实际在进行前面的一系列操作时用户是已经登录的)。
问题跟踪
通过断点调试,简要画出程序的跳转流程:
说明:
①②处说明 由于在HTTP中解析的时候出现 URISyntaxException异常,会抛出IllegalArgumentException异常,而IllegalArgumentException异常是RuntimeException的子类,所以在②处会判断到是属于RuntimeException的实例,故抛出异常,HTTP捕获到URISyntaxException异常后抛出IllegalArgumentException异常的代码如下:
③ 在②处检测到是RuntimeException实例后抛出异常,代码如下:
④ 在③处抛出异常之后,程序会进入到请求关闭的阶段,代码如下:
⑤ 在④处只是关闭请求,并没有对异常进行处理,所以在doDispatcher中会捕获到异常,如下代码(1)处。然后会将这个异常抛出,执行到如下代码(2)处,在代码(2)处发生异常,在代码(3)处捕获到异常,最后执行到finally,注意看代码(4),当程序执行到代码(4)时,此时条件里面的multipartRequestParsed值为false,但是继续单步调试的时候,程序是可以进入到代码块的,这里还没有弄明白是什么原因造成的:
⑥ doDispatch中的代码执行完后,程序进入到doService里面,代码如下,注意看红色标记的地方,出现了上述⑤处一样的问题,attributesSnapshot是为null的,但是if条件是attributesSnapshot不为null的时候才能进入,这里也同样在if条件不为true的时候进入了代码块,也就是在这里,HttpServletRequest的所有属性被置空了。
问题原因说明
看完上述程序流程后,再来说一下文章标题提到的问题是如何造成的吧。
在接口A中访问接口B时,执行上述流程,最终导致HttpServletRequest的关键属性如Cookie被置空,由于在访问接口B的时候出现了异常,spring会将请求重定向到/error。在我们的程序设计中,所有的接口访问都是要经过登录拦截器的,所以在请求/error接口的时候会再次进入到登录拦截器里面,由于在过程⑥中,请求的Cookie已经被置空(注意,这里是在服务端置空了Cookie),所以在服务端检测到用户是出于未登录状态。
但是在调试过程中又发现另一个问题,/error接口不一定会被请求,原因在于由于调试时间暂停的时间较长,会导致在请求接口B的时候迟迟得不到响应,导致接口B请求超时,所以在操作中会发现,有时候我们重新刷新前端页面的时候,用户还是处于登录状态,这也就是为什么我在前面说要注意是在服务端置空了Cookie,因为在此刷新页面的时候是从客户端发出请求的,客户端的Cookie没有被置空,所以重新刷新页面后用户还是登录状态。
遗留问题
调试过程中,if条件不为true,为什么也能进入到代码块里面?