SpringMVC框架学习一:SpringMVC 处理请求流程

SpringMVC概述

Spring MVC 为展现层提供的基于MVC设计理念的优秀框架,是目前最主流的MVC框架之一,它包括许多优点:

1. 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无需实现任何接口

2. 支持 REST 风格的 URL 请求 

2. 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性

先简单描述Spring MVC处理请求的过程

  与大多数基于 Java 的 Web 框架一样,Spring MVC 所有请求都会通过一个前端控制器 DispatcherServlet,它的任务是将请求发送给 Spring MVC 控制器。控制器是一个用于处理请求的组件。在典型的应用程序中可能会有多个控制器,DispatcherServlet 需要知道请求发送给哪个控制器。所以 DispatcherServlet 会查询一个或多个处理器映射来确定请求的下一站在哪。处理器映射会根据请求所携带的URL信息来进行决策。

  一旦选择了合适的控制器, DispatcherServlet 会将请求发送给选中的控制器。到达控制器,请求会卸下其负载(用户提交的信息)并耐心等待控制器处理这些信息(实际上,设计良好的控制器本身只处理很少甚至不处理工作,而是将业务逻辑委托给一个或多个服务对象)。

  控制器在完成逻辑处理后,通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息称为模型(model)。不过仅仅给用户返回原始信息是不够的,这些信息还需要以用户友好的方式进行格式化,一般是HTML。所以信息需要发送一个视图(view),通常会是JSP页面。

  控制器所做的最后一件事是将模型数据打包,并标出用于渲染输出的视图名称。它接下来会连同模型和视图名称发送回 DispatcherServlet。

  这样控制器就不会与特定的视图相耦合,传递给 DispatcherServlet 的视图名称并不直接表示某个特定的 JSP。实际上,它甚至并不能确定视图是JSP。相反,它仅仅传递了一个逻辑名,这个名字将会用来查找用来产生正真结果的视图。DispatcherServlet 将会使用视图解析器来将逻辑视图名匹配为一个特定的视图实现,它可能是也可能不是JSP。

  最后,DispatcherServlet 交付模型数据,请求任务就完成了。视图使用模型数据渲染输出,并且通过这个输出将响应对象传递给客户端。

整体架构如图

 

我们结合图与Spring MVC中的类再来描述一下请求整个过程

① 整个过程始于客户端发送一个HTTP 请求,Web应用服务器收到这个请求,如果匹配 DispatcherServlet 的请求映射路径(在web.xml中指定),Web容器将该请求转交给DispatcherServlet处理。

② DispatcherServlet 接收到这个请求之后,将根据请求信息(包括URL、HTTP方法、请求报文头、请求参数。Cookies等)及 HandlerMapping 的配置找到处理请求的处理器(Handler)。可将 HandlerMapping 看成路由控制器,将 Handler看成目标主机。值得注意的是:Spring MVC 中并没有定义一个 Handler接口,实际上任何一个Object都可以成为请求处理器。

③ 当DispatcherServlet 根据 HandlerMapping 得到对应当前请求的Handler之后,通过HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用Handler。HandlerAdapter 是 Spring MVC 框架级接口,顾名思义,HandlerAdapter 是一个适配器,它用统一的接口对各种 Handler 方法进行调用。

④ 处理器完成业务逻辑的处理后将返回一个 ModelAndView 给 DispatcherServlet,ModelAndView 包含了视图逻辑名和模型数据信息

⑤ ModelAndView 中包含的是"逻辑视图名"而非真正的视图对象,DispatcherServlet 借由 ViewResolver 完成逻辑视图名到真实视图对象的解析工作

⑥ 当得到真实的视图对象 View 之后,DispatcherServlet 就使用这个 View 对象对 ModelAndView 中的模型数据进行视图渲染。

⑦ 最终客户端得到的响应消息可能是一个普通的HTML页面,也可能是一个XML页面或JSON串,甚至是一张图片或一个PDF文档等不同的媒体形式。

下面我们通过实现一个 HelloWorld 程序来展示请求流程

创建工程步骤分为:

1. 加入jar包

2. 在web.xml中配置 DispatcherServlet

3. 加入 Spring MVC 的配置文件

4. 编写处理请求的处理器,并标识为处理器

5. 编写视图

web.xml 配置 DispatcherServlet:DispatcherServlet默认加载路径为 /WEB-INF/<servletName-servlet>.xml 的 Spring配置文件,启动 WEB 层的 Spring 容器。也可以通过contextConfigLocation 初始化参数自定义配置文件的位置和名称。

 1     <!-- 默认路径下的 Spring 配置文件,名字及路径为/springmvc-test/WebContent/WEB-INF/springDispatcherServlet-servlet.xml -->
 2     <servlet>
 3         <servlet-name>springDispatcherServlet</servlet-name>
 4         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        
 5      <load-on-startup>1</load-on-startup>
 6     </servlet>
 7 
 8     <servlet-mapping>
 9         <servlet-name>springDispatcherServlet</servlet-name>
10         <url-pattern>/</url-pattern>
11     </servlet-mapping>
 1     <!-- 自定义的spring 配置文件可以放置在类路径src下,名字在属性中指定为springmvc.xml -->
 2     <servlet>
 3         <servlet-name>springDispatcherServlet</servlet-name>
 4         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 5         <init-param>
 6             <param-name>contextConfigLocation</param-name>
 7             <param-value>classpath:springmvc.xml</param-value>
 8         </init-param>
 9     
10         <load-on-startup>1</load-on-startup>
11     </servlet>
12 
13     <servlet-mapping>
14         <servlet-name>springDispatcherServlet</servlet-name>
15         <url-pattern>/</url-pattern>
16     </servlet-mapping>

创建 Spring MVC 配置文件

1     <!-- 配置自动扫描的包 -->
2     <context:component-scan base-package="com.bupt.springmvc"/>
3 
4     <!-- 配置视图解析器:将视图逻辑全路径名解析为/WEB-INF/views/<viewsName>.jsp (需在/WEB-INF下新建一个名为views(自定义)的文件夹) -->
5     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
6         <property name="prefix" value="/WEB-INF/views/"/>
7         <property name="suffix" value=".jsp"/>
8     </bean>

创建请求处理器类

 1 package com.bupt.springmvc.handler;
 2 
 3 import org.springframework.stereotype.Controller;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 
 6 //@Controll注解将一个POJO转化为处理请求的控制器
 7 @Controller
 8 public class HelloWorld 
 9 {
10     private static final String SUCCESS = "success";
11     
12     /**
13      * 1. 使用 @RequestMapping 注解来映射请求的URL
14      * 2. 返回值会通过视图解析器解析为实际的物理视图,对于InternalResourceViewResolver视图解析器
15      * 通过 prefix + returnValue + suffix 这种方法来得到实际物理视图,再执行转发操作,如本例中会转发到 /WEB-INF/views/success.jsp
16      * 
17      */
18     @RequestMapping("/helloworld")
19     public String hello()
20     {
21         System.out.println("hello world");
22         return SUCCESS;
23     }
24 }

编写转发页面 success.jsp 

 1 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 2     pageEncoding="ISO-8859-1"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <title>Insert title here</title>
 7 </head>
 8 <body>
 9     <h4>Success Page</h4>
10 </body>
11 </html>

编写请求页面 index.jsp

 1 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 2     pageEncoding="ISO-8859-1"%>
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 4 <html>
 5 <head>
 6 <title>Insert title here</title>
 7 </head>
 8 <body>
 9     <a href="helloworld">Hello World</a>
10 </body>
11 </html>

启动服务器访问 index.jsp 页面,点击超链接,可以看到页面跳转至 success.jsp页面,同时控制台打印 hello world。

原文地址:https://www.cnblogs.com/2015110615L/p/5613617.html