持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
1、背景
公司有个产品在客户现场定制化开发,客户看到我们产品用的还是老版本的spring,为了统一版本,立马提出要升级版本到spring5的诉求,领导安排我帮出个方案,下面是曲折的过程。
2、步骤
2.1、将spring当前版本相关jar包升级至5.0.2RELEASE版本
- Spring-beans
- Spring-context
- Spring-jms
- Spring-web
- Spring-orm
- Spring-jdbc
- Spring-core
- Spring-webmvc
- Spring-expression
2.2、Spring完成升级之后启动服务发现
java.lang.NoClassDefFoundError: javax/validation/ParameterNameProvider异常,经排查需要升级hibernate-validator依赖。将hibernate-validator升级至当前最新的稳定版本hibernate-validator.6.2.0.Final
2.3、升级完成之后启动发现异常
提示spring-servlet.xml中配置项org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter已经过期,经查阅文档要改为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter即可。
2.4、服务正常启动,但是调用接口出错
出现Input is required错误,跟踪错误信息发现之前使用的防止注入攻击的XssFilter会使用spring提供的htmlUtils来对request相关信息进行转义,而spring5对此工具类进行了改造升级。解决方法是不使用spring5提供的工具类,自己在XssHttpServletRequestWrapper.java中实现htmlEscape方法,同时需要增加HtmlCharacterEntityReferences.java类。
2.5、服务能正常启动,但是调用接口一律出现403问题
经跟踪调用路径,发现最终跳转至了404页面,但是当前access-control-tongyi.xml文件中并未对404页面进行放行,所以报了403没有权限的错误。将404页面加至放行列表中<mvc:exclude-mapping path="/404.html"/>
2.6、此时调用接口又出现404问题
分析springmvc调用流程,经调试源码,发现spring4和spring5的handlerMapping已不同,之前的RequestMappingHandlerMapping是第一个,优先级更高,而spring5的BeanNameUrlHandlerMapping是第一个,而RequestMappingHandlerMapping排在最后一个,此时接口请求已经匹配不到对应的方法,而是匹配到了配置了<mvc:resources location="/" mapping="/**" />的SimpleUrlHandlerMapping,即将/loginAdmin/getAppId 的接口请求当作了静态资源去处理,当然会找不到此资源,所以出现404问题。
Spring4:
Spring5:
解决方案是修改spring-servlet.xml中对静态资源放行的策略,去掉<mvc:resources location="/" mapping="/" />,增加按文件类型进行放行<mvc:resources location="/" mapping="/." />、<mvc:resources location="/admin/" mapping="/admin//." />、<mvc:resources location="/agent/" mapping="/agent//." />、<mvc:resources location="/manager/" mapping="/manager//." />
3、总结
这次升级过程还是比较曲折的,期间有些报错确实误导了我,比如途中出现的403和404错误,这些报错只是表现形式,其实真的的原因还是仔细思考探究。