写在前面:
这篇文章只是我对SpringMVC的理解,细节会理解的不到位,后面会慢慢修改。
MVC原理
MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核⼼思想是通过将业务逻辑、数据、显示分离来组织代码。
1、模型代表应用程序的数据和业务逻辑。它负责处理数据的读取、存储、验证和处理,以及执行应用程序的核心业务逻辑(不仅仅是对数据的存储和查询,还包含业务逻辑代码)
2、视图是用户界面的表示,负责展示数据给用户,并接收用户的输入。
3、控制器是模型和视图之间的协调者,负责处理用户的输入、更新模型的数据以及更新视图的显示
SpringMVC的作用:
SpringMVC就是在接到URL请求的时候,根据请求将其映射到对应的处理方法上面去。在方法处理结束后,根据返回的值,返回正确的页面。
具体步骤
1.1 Spring容器收集到所有的Controller,Service这些创建Bean的实体对象
1.2 将对应的Service对象注入到Controller里面
1.3 根据URL映射到具体的处理方法上
1.4 根据返回的结果,找到对应的页面
各个模块在其中的作用
- 客户端(浏览器)发送请求, DispatcherServlet 拦截请求。
- DispatcherServlet 根据请求信息调⽤ HandlerMapping 。
- HandlerMapping 根据uri 去匹配查找能处理的 Handler (也就是我们平常说的 Controller 控制器) ,并会将请求涉及到的拦截器和Handler ⼀起封装。
- DispatcherServlet 调⽤ HandlerAdapter 适配执⾏ Handler 。
- Handler 完成对⽤户请求的处理后,会返回⼀个 ModelAndView 对象给DispatcherServlet
- ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。 Model 是返回的数据对象, View 是个逻辑上的 View
- ViewResolver 会根据逻辑 View 查找实际的 View 。
- DispaterServlet 把返回的 Model 传给 View (视图渲染)
- 把 View 返回给请求者(浏览器)
详细解析:
2.1 Spring是如何拿到所有的Controller对象的?
<context:component-scan base-package="com.xja.web.controller"/>
(1)这个配置会表明Spring需要去这个包下面扫描的的类,并根据注解在Spring容器中创建Bean对象。
(2)如何扫描?他会根据根空间(类路径)按照这个路径找到那个位置,依次判断所有的文件是否是一个类文件,并且通过反射创建类对象。
(3)查看这个类的头部是否有对应的注解,比如@Controller,或者@Component,并且会根据@RequestMapping注解,创建一个Map里面的Key是RequestMapping里面的值,这也是为什么RequestMapping里面的值不可以相同的原因,因为Map中的Key不能相同。
2.2 是如何实现注入的?
(1) 首先拿到Controller这个类的所有的类属性Filed,看那个属性头上有@AutoWired注解
(2) 使用filed.set(obj1,ob2j)这个方法,将obj1的filed这个属性的值改为obj2。这样这个就注入成功
2.3 实现方法映射集
(1)获得类的方法Method[],类对象.getDeclaredMethods()
(2)判断方法头上是否有RequestMapping注解,根据注解生成方法映射集Map,key存储的是RequestMapping里面的值,Value里面则是Method对象。
2.4 MVC是如何得到每一个请求的?
在web.xml文件中配置了一个Dispatcher分发器的Servlet,并且设置这个Servlet会拦截所有的请求。
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
所以如何映射就是这个DispatcherServlet处理的。
2.4 如何将URL映射到具体方法?
将URL拆分,然后先找到Controller类的映射,在去找到Method的映射,然后执行这个方法。
Method.invoke(obj1,obj2)。
2.5 将返回值定位到具体的页面?
SpringMVC将返回的值通过配置的ViewsResolver,重新拼接链接,定位到页面的位置。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
可以看到这视图解析器具有前缀和后缀,将放会的字符拼接到一起。重新渲染,放回给客户端。