当前位置: 首页 > 原理解释

spring mvc工作流程原理-Spring Mvc 流程原理

说实话,刚启动看 Spring MVC 那堆名词术语时,我就连有点头晕,认定那些接口和过滤器简直像是为了考试故意设置的拦路虎。但一旦真正站在 JDK 的运行台上,去敲下几个测试用例,那种震撼感反而扑面而来,仿佛把整个 Web 时代互联网背后的骨架都握在了手里。 大量人一上来就纠结如何搞 Controller,如何弄 ControllerAdvice 这种让人抓狂的方式。
实际上啊,最核心的那点逻辑忒好办了,就像个好办的函数调用。一个一般/平平的 Spring MVC 流程,本质上就是用户在浏览器敲个 URL,浏览器把这个请求发给 Spring 容器,容器把路由匹配到 Controller 方式,最终把数据塞进特定的 bean 对象里,再回给浏览器。整个过程就像是一个好办的“翻译”过程,只不过语言从 HTTP 请求转成了 JSON 数据,再从 JSON 转回了 HTTP 响应。 要是真细究起来,拆开来看才有多复杂。记得有个测试案例,我故意在 Controller 里加了几个条件判断,比如要是用户是管理员就放行,一般/平平人就回 403。结局发现,一般/平平的 Controller 参数彻底是一群瞎眼,参数名、类型(偶然是 Enum 枚举!)、取值范围就连省略号,全不管用。
这里有个细节挺好办被忽略:Spring 默认是把 Controller 的参数包装成一个 `ParameterizedMethod`,这个类内部有个 `Function`,专门用来处理那些带参数的条件。你要是直接传 `@RequestParam` 要么 `@PathVariable`,参数传进去是 `Object` 类型,别看也能用,但类型推断起来纰漏。更费事的是,Spring 默认回的是 `ModelAndView`,它负责把数据存到模型里。
这时候你就得手动去 `getAttributes` 要么 `getModel()` 才能拿到数据,中间这一环简直是绕远路。 为了搞清楚这到底是如何回事,我得在脑子里模拟一遍请求流。想象你给一个刚出生的婴儿起名,第一步是确认他的名字选好了(路由匹配),第二步是检查他名字里有没有违规成分(保险检查),第三步是把名字交给某个特定的老师(数据预备),老师是个复杂的系统,它不仅负责取名(创建对象),还得根据规则给名字打分(计算业务逻辑),最终把名字敲在婴儿的卡片上(视图渲染)。在这个流程里,Spring 里的 `DispatcherServlet` 就是那个家长,它在前面把关,确保孩子名字是合法的,然后再把名字分发给对应的老师。 下面这个流程图别看简陋,但能看懂大约。一个请求进来,先经过 DispatcherServlet 拦截,然后进入对应的 Controller。Controller 拿到参数后,执行逻辑。
要是黄了了(比如回 500),Spring 会自动生成一个 `ErrorController`,这时候就得费事点,得看看 ControllerAdvice 里有没有自定义的处理器,要么手动写一个 `ErrorHandler`。
要是连这个都没,那就只能兜底回 500 了。 什么的,我是不是又犯了一个大错?我认定自己彻底搞不懂 Spring 的 IOC 和 AOP 到底混在一起了。
实际上这俩就像是给代码装了一套魔法滤镜。IOC 负责管理对象的创建和依赖注入,它让数据流变得可控,而不是像某些语言那样堆砌变量。而 AOP 负责切面,比如日志记录、事务管理,它就像是给代码加了一层保护壳,把原本脏兮兮差的局部封装起来。 说到毛病处理,这又是大量初学者好办忽略的坑。我见过一个案例,用户报错了,结局整个页面全白,开发者在 Controller 里写的是 `throw new Exception("Error")`。
这个 Exception 默认会被 Spring 捕获并转成一个 500 状态码,但页面渲染时,Spring 默认会把它当成一个一般/平平的 `ExceptionHandler` 处理。可你刚刚说的 ControllerAdvice 里的 `GlobalExceptionHandler` 根本没被调用!为啥?出于 Spring 默认的配置是“捕获所有异常只给 500”,要不就你显式地去写一个 `@ControllerAdvice` 并把那个类注册到切面里,Spring 才会去执行你刚刚提到的那个全局处理器。
故此,要是你没写,那就是确实回 500,哪怕你写了一个全局异常处理器,也得去 `setGlobalExceptionHandler` 注册进去。 再说说数据流,这实际上是个挺微妙的地方。你当作 Controller 里传的是 `Object` 类型,实际上不是。Spring 默认把 Controller 里的参数包装成一个 `ParameterizedMethod`,类名叫 `SimpleMethodArgument`。
这个类有个 `Function`,专门用来处理那些带参数的条件。
这个函数接收的是 `Object` 类型,故此要是你直接传 `@RequestParam`,参数传进去是 `Object` 类型,别看能用,但类型推断起来有点灵活。 还有个务必要强调的点就是 `ModelAndView`。它没毛病,但它只是个容器。它把数据和视图对象(比如 `View`)装在一个框架里,框架通过 `getAttributes` 要么 `getModel()` 把数据掏出来。
这时候你要是想改数据结构,比如把字符串改成 Map,那你务必手动调用 `getAttributes`,不然数据就躺在框架里了,浏览器拿不到。
这听起来挺费事,但理解了这个逻辑,后续大量容器操作(比如 `HttpSession`、`Request` 的获取)就清楚多了。 还有,Spring MVC 的 DispatcherServlet 是个类,不是个方式。你搞不懂它是类,你就不知道它如何接收请求,如何分发,如何回。它内部有个 `HandlerMapping` 负责找路由,`HandlerAdapter` 负责把方式调用成动作,`HandlerInterceptor` 负责拦截器逻辑。
要是我没记错,`HandlerInterceptor` 就是 Spring 里那几个拦截器,它们负责统一处理请求,比如工夫戳、日志、权限验证什么的。 实际上,整个 Spring MVC 的精髓就在“解耦”上。
那会儿是 Controller 写逻辑,目前逻辑被拆分了。视图渲染逻辑、参数验证逻辑、数据预备逻辑,就连毛病处理逻辑,都可能通过 `@RestControllerAdvice` 要么自定义切面剥离出来。
这样 Controller 就只负责接收请求和组装数据,剩下的大杂烩都交给那些专门负责“脏活累活”的模块去处理。 最终总结一下,Spring MVC 确实不难,只要你不把它当成一个庞大的系统去背,而是当成一个个好办的函数调用和对象变换过程去理解,你会发现它实际上挺友和的。就像是我之前那个测试案例,只要知道根本流程,如何搞 ControllerAdvice,如何回数据,如何管异常,根本都能跑通。
只要你不吃那些教科书上的理论,只关切代码的执行路径,这玩意儿挺好办就上手了。
毕竟,真正的娴熟感都来得忒慢,快马加鞭,自己测测看。
相关标签:

猜你喜欢

热门阅读

  • 赖柴尔定理-赖柴尔定理
  • 迪拜哪个国家的城市?-迪拜在哪国城市
  • 李毅吧番号及出处-李毅吧番号及出处
  • 贴春联的由来简介50字-春联由来简述
  • 思乡的名言和出处-思乡名言及出处

其他分站