那天被同事甩过来一段报错截图,冷不丁就被问到springmvc是什么,脑子一下子空了,明明之前敲过相关代码,却没法顺顺当当说出一句完整的话。屏幕上堆着红色的异常堆栈,页面跳转一直不对,请求发出去之后像石沉大海,连数据走到哪一层都追踪不到,只能点开项目里的配置文件,一行一行慢慢捋。

最开始的想法很简单,以为它就是个单纯写接口的工具,把地址和方法绑在一起就能接收前端传过来的参数。照着网上贴出来的片段往配置里复制,改了包扫描路径,加了注解,启动项目的时候看着日志里没有抛出异常,还以为已经搞定了。点页面发起请求,结果直接返回404,刷新多少次都一样,抓包工具里能看到请求已经发出去,后端却完全没有进入对应方法的打印日志。

卡在这耗了挺久。

来回切换xml文件和java类,一会怀疑视图解析器的前缀后缀写错,一会又纠结注解有没有导错包,甚至把已经写好的控制器类删掉重写一遍,每改一次就重启一次服务,等待启动的间隙里,反复在心里琢磨springmvc是什么,不想只记住别人复述出来的定义,想顺着这次请求流转的过程自己感受它到底在项目里承担哪一部分工作。同组的人路过扫了一眼,只提了一句分发的问题,没再多说,也没有直接把修好的代码发过来。

后来才反应过来,之前只盯着接口接收参数这一小块,忽略了请求从抵达容器开始,还要经过好几个环节。DispatcherServlet最先接住请求,再根据地址去找对应的映射,匹配到写了注解的方法之后,把前端传的参数封装好传进去,方法执行结束拿到返回值,再交给视图或者转换成json给到前端。那天没有配置好处理器映射器和适配器,请求进来之后找不到匹配的处理方法,才一直报找不到资源的提示,不是代码逻辑写错,是中间流转的环节断掉了。

调整配置之后重新启动,再次发起请求,控制台终于打印出我写在方法第一行的日志,参数也成功打印出来,那一刻没有那种豁然开朗的通透感,反倒觉得有点茫然,原来我之前理解的范围窄得离谱。它不是一个独立运行的框架,依托在spring之上,把web请求相关的一堆零散操作收拢起来,不用自己手写原生servlet去反复处理request和response对象,不用每次都写重复的转发、编码处理代码。

试过把返回值改成字符串交给视图解析器跳转页面,也试过加上注解直接返回json数据,两种写法都跑通之后,能隐约感受到它提供的选择挺多,但也没有形成固定的认知。同一个项目里,有人习惯用xml做集中配置,有人偏爱全注解开发,两种方式我都简单试了下,注解写起来省事不少,配置文件会清爽很多,只是出问题的时候,查找对应的配置位置会稍微费点功夫,不同人的习惯不一样,也没有哪一种是唯一可行的方式。

中途还踩过参数绑定的坑,前端传过来的日期字符串,一直没法自动转成后端的日期类型,页面一直报类型转换失败。当时搜了一些片段,试着加自定义转换器,调试的时候断点一步步往下走,看着参数绑定这一步卡住,折腾很久才勉强调通,现在回想起来,那一段只是springmvc里很小的一块能力,可放在当时,足够耗掉大半个晚上。

这些都只是我那次调试里碰到的情况,只代表我自己的感受,别的人上手的时候,卡住的地方大概率完全不一样,有人可能一开始就在拦截器这块绕很久,也有人很早就接触全局异常处理,体会和我不会相同。我到最后也没能整理出一段干净利落的话,一句话讲清springmvc是什么,脑子里留存下来的,大多是这次调错时看到的请求链路,还有一堆零零散散的配置细节。

关掉ide的时候已经挺晚,没有整理笔记,也没有把知识点归档。只是记住了请求进来之后,不是直接进到我们写的业务方法里,中间还有一套固定的流程在运转。