Spring MVC
Spring MVC 之初体验
环境搭建
在 IDEA 中新建一个 web 项目,用 Maven 管理项目的话,在 pom.xml 中加入 Spring MVC 和 Servlet 依赖即可。
1 | <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> |
Spring MVC 简单配置
- 在 web.xml 中配置 Servlet
- 创建 Spring MVC 的 xml 配置文件
- 创建 Controller 和 View
1、web.xml
1 | <!-- Spring MVC配置 --> |
2、spring-servlet.xml
1 | "1.0" encoding="UTF-8" xml version= |
3、Controller
1 | package controller; |
@RequestMapping 可以写在方法上,也可以写在类上,上面代码方法上的 RequestMapping 都含有 /test
, 那么我们就可以将其抽出直接写在类上,那么方法里面就不需要写 /test
了。
如下即可:
1 |
|
上面的代码方法的参数中可以看到有一个 @RequestParam
注解,其实还有 @PathVariable
。这两个的区别是啥呢?
@PathVariable
标记在方法的参数上,利用它标记的参数可以利用请求路径传值。- @RequestParam是指请求url地址映射中必须含有的参数(除非属性 required=false, 默认为 true)
看如下例子:
1 | "/user/{userId}") // 请求url地址映射 ( |
上面例子中如果浏览器请求的是 /user/1
的时候,就表示此时的用户 id 为 1,此时就会先从 session 中查找是否有 “user” 属性,如果有的话,就代表用户此时处于登录的状态,如果没有的话,就会让用户返回到登录页面,这种机制在各种网站经常会使用的,然后根据这个 id = 1 ,去查找用户的信息,然后把查找的 “user” 放在 model 中,然后返回用户详情页面,最后在页面中用 $!{user.name}
获取用户的名字,同样的方式可以获取用户的其他信息,把所有的用户详情信息展示出来。
创建 Spring MVC 之器
Spring MVC 核心 Servlet 架构图如下:
Java 中常用的 Servlet 我在另外一篇文章写的很清楚了,有兴趣的请看:通过源码详解 Servlet ,这里我就不再解释了。
这里主要讲 Spring 中的 HttpServletBean、FrameworkServlet、DispatcherServlet 这三个类的创建过程。
通过上面的图,可以看到这三个类直接实现三个接口:EnvironmentCapable、EnvironmentAware、ApplicationContextAware。下面我们直接看下这三个接口的内部是怎样写的。
EnvironmentCapable.java
1 | public interface EnvironmentCapable { |
EnvironmentAware.java
1 | public interface EnvironmentAware extends Aware { |
ApplicationContextAware.java
1 | public interface ApplicationContextAware extends Aware { |
怎么使用这个这个接口呢?
参考文章:org.springframework.context.ApplicationContextAware使用理解
HttpServletBean
这里就直接看其中最重要的 init() 方法的代码了:
1 | /** |
FrameworkServlet
其中重要方法如下:里面也就两句关键代码,日志代码我直接删掉了
1 | protected final void initServletBean() throws ServletException { |
再来看看上面代码中调用的 initWebApplicationContext() 方法
1 | protected WebApplicationContext initWebApplicationContext() { |
initWebApplicationContext 方法做了三件事:
- 获取 Spring 的根容器 rootContext
- 设置 webApplicationContext 并根据情况调用 onRefresh 方法
- 将 webApplicationContext 设置到 ServletContext 中
这里在讲讲上面代码中的 wac == null 的几种情况:
1)、当 WebApplicationContext 已经存在 ServletContext 中时,通过配置在 servlet 中的 ContextAttribute 参数获取,调用的是 findWebApplicationContext() 方法
1 | protected WebApplicationContext findWebApplicationContext() { |
2)、如果 WebApplicationContext 还没有创建,调用的是 createWebApplicationContext 方法
1 | protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) { |
里面还有 doXXX() 方法,大家感兴趣的可以去看看。
DispatcherServlet
DispatcherServlet 继承自 FrameworkServlet,onRefresh 方法是 DispatcherServlet 的入口方法,在 initStrategies 方法中调用了 9 个初始化的方法。
这里分析其中一个初始化方法:initLocaleResolver() 方法
1 | private void initLocaleResolver(ApplicationContext context) { |
查看默认策略代码:
1 | protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) { |
其他几个方法大概也类似,我就不再写了。
小结
主要讲了 Spring MVC 自身创建过程,分析了 Spring MVC 中 Servlet 的三个层次:HttpServletBean、FrameworkServlet 和 DispatcherServlet。HttpServletBean 继承自 Java 的 HttpServlet,其作用是将配置的参数设置到相应的属性上;FrameworkServlet 初始化了 WebApplicationContext;DispatcherServlet 初始化了自身的 9 个组件。
Spring MVC 之用
分析 Spring MVC 是怎么处理请求的。首先分析 HttpServletBean、FrameworkServlet 和 DispatcherServlet 这三个 Servlet 的处理过程,最后分析 doDispatcher 的结构。
HttpServletBean
参与了创建工作,并没有涉及请求的处理。
FrameworkServlet
在类中的 service() 、doGet()、doPost()、doPut()、doDelete()、doOptions()、doTrace() 这些方法中可以看到都调用了一个共同的方法 processRequest() ,它是类在处理请求中最核心的方法。
1 | protected final void processRequest(HttpServletRequest request, HttpServletResponse response) |
DispatcherServlet
上一章中其实还没把该类讲清楚,在这个类中,里面的智行处理的入口方法应该是 doService 方法,方法里面调用了 doDispatch 进行具体的处理,在调用 doDispatch 方法之前 doService 做了一些事情:首先判断是不是 include 请求,如果是则对 request 的 Attribute 做个快照备份,等 doDispatcher 处理完之后(如果不是异步调用且未完成)进行还原 ,在做完快照后又对 request 设置了一些属性。
1 | protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { |
doDispatch() 方法:
1 | protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { |
Handler,HandlerMapping,HandlerAdapter 三个区别:
- Handler:处理器,对应 MVC 的 C层,也就是 Controller 层,具体表现形式有很多种,可以是类,方法,它的类型是 Object,只要可以处理实际请求就可以是 Handler。
- HandlerMapping:用来查找 Handler 的。
- HandlerAdapter :Handler 适配器,
另外 View 和 ViewResolver 的原理与 Handler 和 HandlerMapping 的原理类似。
小结
本章分析了 Spring MVC 的请求处理的过程。