Spring_______SpringMVC的基本流程

Author Avatar
GGB 8月 08, 2018

总述

说到SpringMVC可以先看下面这张图:


PWa7vV.md.jpg


从这张图我们可以很清晰地看到SpringMVC作为Spring内嵌的MVC模块其整体的工作流程:

  1. 用户向服务器发送请求,请求被Spring 的前端控制器DispatcherServlet截获。
  2. DispatherServlet对请求URL(统一资源定位符)进行解析,得到URI(请求资源标志符),然后根据该uri,调用HandlerMapping获得该Handler配置的所有相关的对象。
  3. DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。
  4. 提取请求中的模型数据,开始执行Handler(Controller)。期间Spring会自动帮你做一些工作:
  • 消息转换
  • 数据转换
  • 数据格式化
  • 数据验证
  1. Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图名和模型
  2. 根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet.
  3. ViewResolver结合Model和View来渲染视图
  4. 将视图结果返回客户端

为了更清晰直观的描述其在程序中所发挥的作用,我觉得我们可以结合springMVC的配置文件说起:

第一部分 web.xml

作为一个JavaWeb项目,无论使用什么框架,其本质还是得归根到JSP,Servlet上来,而其根本的配置信息就是由web.xml所配置的。作为SpringMVC中的控制转发器DispatcherServlet其本质也是个负责拦截请求并转发的Servlet,所以使用SpringMVC的第一步便是在web.xml配置好DispatherServlet.看下面的代码(省略头文件):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
!-- 配置DispathcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载配置文件路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

如上便配置好了DispatherServlet,当然其中还有对springMVC本身的配置文件,以及之后spring与DAO层,service层的spring配置文件的路径说明也必须要添加到之中去。

第二部分 springmvc-config.xml

这个文件配置的便是对springmvc的整体相关配置文件了,在 SpringInAction 一书中,作者推荐了采用java代码的方式对SpringMVC进行配置。

但就目前所流行的开发模式中,依然是采用.xml配置文件使配置与逻辑业务分离,我个人也更喜欢.xml的配置方式,但是在有些情况下,需要对不同地方按不同逻辑进行选择配置时,这时Java配置才展现出它的优点。

如下展示的是一个简单但可用的springmvc配置文件(文件名可以任取,只要在web.xml中配置好),通过对其的解读,我们可见窥见一个完整的springmvc运作(头文件已省略):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- 配置SpringMVC -->
<!-- 1:开启SpringMVC注解模式 -->
<!-- 简化配置:
(1)自动注册DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter
xml,json默认支持读写 -->
<mvc:annotation-driven/>

<!-- 2:静态资源默认servlet配置
1)加入对静态资源的处理:js,gif,png
2) 允许使用"/"做整体映射
-->
<mvc:default-servlet-handler/>

<!-- 3:配置jsp 显示ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

<!-- 4.spring可以自动扫描base-package下面的包或子包的java文件,当扫描到spring相关的类时,可自动注册 -->
<context:component-scan base-package="controller"/>
  1. mvc:annotation-driven/

这条语句会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean,这是SpringMVC为@COntrollers分发请求所必需的,并提供数据绑定支持,读写XML的支持(JAXB)和读写JSON的支持(默认Jackson)等功能。

大部分情况我们使用默认的配置即可,但如果想要修改一些默认,如利用非Jackson处理json数据时,就需要在mvc:annotation-driven标签中进行修改。

  1. mvc:default-servlet-handler/

该语句使用默认的Servlet来响应静态文件,因为在web.xml中使用了DispatcherServlet截获所有请求url,所以在请求引入静态文件,例如js的引用语句

1
<script type="text/javascript" src="js/ggb.js"/>

DispatherServlet会将”/“看成请求路径而报错。所以需要加上该语句进行配置。

  1. ViewResolver的配置

通过该项配置,当我们通过controller返回一个视图名时,会自动加上前缀prefix和后缀suffix,这样可以简化我们的代码编写。

  1. <context:component-scan base-package=”controller”/>

通过该语句,我们可以扫描到controller包下我们所写的controller组件,进而进行映射控制


把每一个组件配置完成后,我们便可以开始使用springmvc进行业务逻辑控制,下面列举一个小例子:

1
2
3
4
5
6
7
8
@Controller
public class HelloWorldContoller{
@RequestMapping("/helloworld")
public String helloWorld(Model model){
model.addAttribute("message","HelloWorld!");
return "hello";
}
}

这里便完成了一个极其简单的控制器实例了,首先我们通过@Contoller注解告诉spring这是一个控制器组件,之后的@RequestMapping(“/helloworld”)则声明以下方法用于处理url中的xxxx/helloworld请求,而计算机能识别此路径的前提,当然也是因为我们在web.xml中所声明的对’/‘的映射,以及springmvc.config中开启扫描后的结果。

请求处理方法中可以带多种参数,而最重要的便是Model和ModelAndView参数了,在MVC框架中,控制器执行业务逻辑后产生模型数据(Model),而视图(View)则用于渲染模型数据。

在上例中,我们想model中加入了参数”HelloWorld!”,当其返回”hello”时,便会被自动解析为 ‘/WEB-INF/jsp/hello.jsp’ 这也是我们所配置的ViewResolver的功劳。这样,当我们在hello.jsp页面中通过EL表达式便可取到messge的值”HelloWorld!”输出到页面上了。

此时再回顾我们开篇所给出的SpringMVC的流程图,通过这个么一个简单的例子,便实现了从拦截请求,控制器处理,数据模型建立,视图解析这一个整个MVC的过程!

当然,要实现更加复杂的程序功能,还有很多SpringMVC注解如:

  • @PathVariable 对请求的参数进行映射
  • @CookieValue 处理请求中的Cookie值
  • @RequestBody 自动将json数据参数传化为对应Pojo
  • @Response 自动将结果pojo转化为json格式
  • 等等

想了解更为详细的配置方法和注解使用,可以去阅读官方文档,或者查看其他网络资源。

本文为GGB学习过程中的笔记总结,欢迎各位的指正和交流。