问题表现:在配置和依赖都正确的情况下,无法通过配置的用户名密码登录Druid的监控页面
检查配置发现 配置的用户名和密码和请求中参数是一致的🤔
Debug发现 ResourceServlet 是Druid的登录实现, 且调试发现usernameParam是null,但是前端请求是看到有参数的。
开始查看当前线程栈上游都经过了哪些过滤器和拦截器,找到第一个接收前端请求的地方看是否接收到参数,然后发现getParamter()是有值的. 这个时候放开了断点,想再试一次看是哪层丢了值,结果发现页面登录成功了。
仔细调试 org.apache.catalina.connector.Request 类后发现了问题的原因
首先是getParameter方法看起来是读 get,实际上还做了惰性的解析写操作,所以这也是为什么代码规范中推荐get命名的方法不要藏有副作用的逻辑,只能是读。
其次解析逻辑中如果符合usingInputStream || usingReader 就会退出不会走后续的解析参数逻辑。
因为有监控所有请求日志的需求,所以有个Filter负责复制Request内容,此处会触发一次读Request的Body流,然后导致了这次的问题。由于我在第一个Filter执行前就在Debug中执行了 getParameter 方法,也就触发了parseParameters方法执行,所以Druid的Service就能获取到参数了。
所以最后解决方案就是在复制Request的Body 去构造 BodyReaderWrapper 前,先调用一次request.getParameter 方法 🤣