springboot升级引发的问题
springboot升级引发的问题
最近springboot发布了新的版本,我的应用已经很久没有升级了,打算找个时间升级一下.
直接升级springboot2.5.6,发现很多@deprecate的类在使用.还好,系统顺利启动.
后面看到springboot更新了@EnableWebMvc注解,而且WebMvcConfigurerAdapter已经过时,不建议使用.
我的应用本身使用velocity的view,配置比较复杂,所以用xml进行载入.xml中的mvc前缀和@EnableWebMvc功能上有重复,那就去掉@EnableWebMvc的注解,也顺利.
于是,我天真的得出结论,2.5.6的springboot对于应用可以直接使用......
过了2天,我又换回springboot1.5.18版本,突然发现不能登录了.....
简单调试下来,发现登录的controller中,死活不能得到前端输入的用户名和密码.我第一反应就是升级引起的问题,我赶紧回退版本,发现使用之前的配置一切都好.
然后慢慢的尝试,最后发现是@EnableWebMvc注解引起的.在springboot1.5.18版本,如果不使用@EnableWebMvc注解,就会报错,controller中获取不到参数.如果使用@EnableWebMvc注解,就可以顺利运行.
这就奇怪了,整体看@@EnableWebMvc是不可能了,那么多载入.....怎么着手????
我的controller的编写特别简单,没有使用任何注解
@RequestMapping("login")
public String login(ModelMap model , LoginModel loginModel , HttpServletRequest request , HttpServletResponse response)这种注入方式,还是使用springMVC中请求中获取参数,这个机制不应该修改的呀,而且就和@EnableWebMvc注解有关.
我把断点打在controller内部,然后看执行线程栈,一个一个慢慢往上找,找到了InvocableHandlerMethod->ServletInvocableHandlerMethod,再往上就看到我熟悉的RequestMappingHandlerAdapter了,就是springMVC那套啊,再慢慢看参数,发现方法的参数注入有问题.
再找,InvocableHandlerMethod.getMethodArgumentValues(),发现参数是在argumentResolvers中进行解析的,springboot在启动的时候,一共注入了27个参数解析器

最终解析controller参数的解析器为new ServletModelAttributeMethodProcessor(true)
再仔细看,这个resolver又调用到WebDataBinder,再bindMultipart中,使用WebUtil.getParametersStartingWith()从request.getParameterNames()进行参数获取的.
没问题啊,为啥没获取到???
最终发现,spring在使用request.getParameterNames()的时候,获取的是空,那就是另外一个问题了.
因为request的流只能读取一次,而项目中往往需要对各种request进行拦截和调用,所以,我的代码里面对request的流做了缓存,这个做缓存的是一个filter,springboot在启动的时候,如果使用了@EnableWebMvc注解,启动的时候,filter的顺序是这样的

如果没有使用@EnableWebMvc注解,filter的加载顺序是这样的

而中间的hiddenHttpMethodFilter的源码是这个样子的

就是中间的request.getParameter()方法的调用,会让整个request流无法加载,从而导致我后面加载的filter在读取request的时候,无法读取到数据.
顺便看了下hiddenHttpMethodFilter的执行顺序是-1000-,很高的优先级.
写在最后
问题的解决也是一行代码就搞定了,设置下filter的优先级就完事了.本来有很多话说,过了2天再写博客的时候,就剩娘希匹了.....
spring的版本变迁,导致spring的版本碎片非常严重,再加上springboot,哎,springboot2.4已经过维护期了.....
