阿男的小窝

View the Project on GitHub

分析笔记(二):RESTEASY-828 Issue with injected ServletContext in Resteasy/SpringMVC setup

尝试自己注入httpServletResteasyContext

ResteasyContext的设计:

ResteasyContextresteasy当中的使用位置:

在对resteasy-spring模块的分析完成之后,发现没有地方通过ResteasyContext保存servletContext

写一个MyServletRequestListener

它实现了javax.servlet.ServletRequestListener接口:

使用「debug」模式启动服务:

在「IntelliJ」里面加载项目,分析启动过程,第一次启动的时候,会触发ResteasyDeploymentImplstart()方法:

这个逻辑定义在resteasy-spring提供的springmvc-resteasy.xml里面:

ResteasyDeploymentImpl初始化完成后,接着初始化依赖ResteasyDeploymentImplSpringBeanProcessor

上面是初始化过程。总结一下,springmvc-resteasy.xml里面定义的几个「bean」如下:

此外,注意到DispatcherRegistryProviderFactory。最后,SpringBeanProcess在初始化过程使用ResteasyDeploymentImpl(是ResteasyDeployment的接口实现)。

下面是SpringBeanProcessor的初始化过程截图:

查看上面断点停下来时候的「stacktrace」,看到几个beans对应的实际instances:

如上面截图所示,分别是:

综合上面的分析,相关的classes组成如下:

接下来继续分析服务的启动过程:SpringBeanProcessor和相关的beans初始化完成后,就要处理用户的请求,此时走的是ResteasyHandlerAdapterhandle()方法:

上面这个handle()方法,是用户每次请求都要执行的,是处理请求的入口。

继续往下执行,注意因为这是第一次启动,虽然MyServletRequestListener工作了,但是注入servletContext失败:

初步分析,是因为第一次访问的时候,springmvc-resteasy.xml的加载是「lazily initialized」的,所以里面的ResteasyDeploymentImpl和其它组件都是会在「第一次启动」执行,而后续访问都是直接走,所以应该在MyServletRequestListener的执行次序方面有一些冲突。

后续可以通过多次访问来验证这点:

可以看到后续的访问都不再报错了。而且只走ResteasyHandlerAdapterhandle()方法:

以上是对问题的分析记录,有了上面的基础,后续的工作是给出解决方案。