SpringMVC框架详解

一、SpringMVC 概述

SpringMVC 是一个基于 Servlet 的轻量级 Web 框架,在 Java Web 开发中起着至关重要的作用。它主要解决了视图(View)与控制器(Controller)之间的交互问题,为开发者提供了一种高效、灵活的方式来构建 Web 应用程序。

SpringMVC 并不关心数据模型(Model)的具体实现,这使得开发者可以根据项目需求自由选择合适的数据存储和处理方式。MVC 设计模式将应用程序分为三个主要部分:模型、视图和控制器。在 SpringMVC 中,视图负责展示数据给用户,控制器接收用户请求并处理业务逻辑,然后将结果返回给视图进行展示。

SpringMVC 框架具有高度可配置性,包含多种视图技术,如 JSP、Velocity、Thymeleaf 等。这意味着开发者可以根据项目需求选择最适合的视图技术,而不会受到框架的限制。例如,在一些项目中,可能需要使用 JSP 来展示动态页面;而在另一些项目中,Thymeleaf 可能更适合,因为它提供了更好的模板分离和可维护性。

SpringMVC 的核心组件包括 DispatcherServlet、HandlerMapping、Controller、ModelAndView 和 ViewResolver。DispatcherServlet 是前端控制器,负责接收所有请求并将其分发给相应的控制器。HandlerMapping 用于配置请求路径与控制器的对应关系,确保请求能够被正确地路由到相应的处理方法。Controller 是具体处理请求的组件,它接收请求参数,执行业务逻辑,并返回 ModelAndView 对象。ModelAndView 包含了模型数据和视图名称,ViewResolver 根据视图名称解析出具体的视图对象,最终将模型数据填充到视图中并返回给用户。

总之,SpringMVC 作为一个轻量级的 Web 框架,通过解决 VC 之间的交互问题,为开发者提供了一种高效、灵活的方式来构建 Web 应用程序。其高度可配置性和丰富的核心组件使得开发者能够根据项目需求进行定制化开发,提高开发效率和代码质量。

二、SpringMVC 核心组件

(一)前端控制器 DispatcherServlet

DispatcherServlet 作为 SpringMVC 的前端控制器,起着至关重要的中转站作用。它接收所有的用户请求,相当于 MVC 模式中的控制器(C),是整个流程控制的中心。DispatcherServlet 与 Spring IoC 容器无缝集成,能够获得 Spring 的所有好处,同时减少了其他组件之间的耦合度。

DispatcherServlet 主要负责以下职责:

  1. 文件上传解析:如果请求类型是 multipart,将通过 MultipartResolver 进行文件上传解析。
  1. 请求映射:通过 HandlerMapping,将请求映射到处理器(返回一个 HandlerExecutionChain,它包括一个处理器、多个 HandlerInterceptor 拦截器)。
  1. 处理器适配:通过 HandlerAdapter 支持多种类型的处理器(HandlerExecutionChain 中的处理器)。
  1. 视图解析:通过 ViewResolver 解析逻辑视图名到具体视图实现。
  1. 本地化解析。
  1. 渲染具体的视图等。
  1. 异常处理:如果执行过程中遇到异常将交给 HandlerExceptionResolver 来解析。

(二)处理器映射器 HandlerMapping

HandlerMapping 负责配置请求路径与 Controller 的对应关系。在 SpringMVC 中会有很多请求,每个请求都需要一个 Handler 处理,而 HandlerMapping 的作用就是根据当前 request 找到对应的 Handler 和 Interceptor,然后封装成一个 HandlerExecutionChain 对象返回。

HandlerMapping 接口中定义了一个关键方法 getHandler(HttpServletRequest request),该方法的返回值就是 HandlerExecutionChain。HandlerMapping 的继承关系主要分为两大类:AbstractHandlerMethodMapping 和 AbstractUrlHandlerMapping。AbstractHandlerMethodMapping 体系下的都是根据方法名进行匹配的,而 AbstractUrlHandlerMapping 体系下的都是根据 URL 路径进行匹配的。

(三)控制器 Controller

Controller 作为具体处理请求的组件,在 SpringMVC 中起着核心作用。它接收请求参数,执行业务逻辑,并返回 ModelAndView 对象。控制器通常使用注解或 XML 配置方式将请求映射到处理方法上。

例如,使用 @Controller 注解告诉 Spring 这是一个控制器类,@RequestMapping 注解告诉 Spring 将请求映射到处理方法上。Controller 负责调用相应的服务层方法来处理请求,并将结果添加到 ModelAndView 对象中,然后返回的视图名称设置为特定的值。

(四)ModelAndView

ModelAndView 由数据与视图名称组成,是 Controller 处理完请求后的结果。它主要有以下几个作用:

  1. 设置转向地址:可以指定要访问的视图层的 URL 地址。
  1. 存储数据:将底层获取的数据进行存储(或者封装)。
  1. 传递数据给 View:最后将数据传递给视图进行展示。

ModelAndView 有多种使用方法,例如可以先创建 ModelAndView 对象,再通过它的方法去设置数据与转发的视图名;也可以通过带有参数的构造方法直接返回数据与转发的视图名;还可以设置重定向。

(五)视图解析器 ViewResolver

视图解析器 ViewResolver 可根据视图名称确定需要使用的视图组件。它负责将逻辑视图名称解析为实际的视图实现。在 SpringMVC 中,可以使用 InternalResourceViewResolver 或其他自定义的视图解析器来解析视图。

例如,配置一个 InternalResourceViewResolver 作为视图解析器,并将前缀设置为特定路径,后缀设置为特定扩展名。这样,当 Controller 返回一个 ModelAndView 对象时,ViewResolver 就可以根据视图名称解析出具体的视图对象,最终将模型数据填充到视图中并返回给用户。

三、SpringMVC 第一个程序

(一)创建项目及 UserController 类

创建 SpringMVC 项目通常可以使用 Maven 或 Gradle 等构建工具。首先创建一个 Maven 项目,并在 pom.xml 文件中引入 SpringMVC 相关的依赖包。例如,<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.1</version></dependency>。

接着,在项目中创建一个名为 UserController 的类,用于实现用户与程序的互联互通。在这个类中,可以使用@Controller注解来标识这是一个控制器类,然后使用@RequestMapping注解在方法上定义请求的映射路径。例如:


@Controller

public class UserController {

@RequestMapping(value = "/hello")

public String helloWorld() {

return "hello world";
  }

}

这样,当用户在浏览器中访问/hello路径时,SpringMVC 就会调用这个方法,并返回 "hello world" 字符串。

(二)@RequestMapping 注解

@RequestMapping注解在 SpringMVC 中起着注册接口路由映射的重要作用。它可以用于类或方法上。用于类上时,表示类中的所有响应请求的方法都以该地址作为父路径。例如:

@RequestMapping(value = "/user/findByModal", method = {RequestMethod.POST})
public Result list(@RequestBody(required =false) User user) {
    return userService.list(user);
}

在这个例子中,当用户访问/user/findByModal路径时,会调用list方法。

@RequestMapping注解有多个常用属性,如 value 属性(指定请求的实际地址)、path 属性(和 value 属性作用相同,用于映射)、name 属性(相当于方法的注释,使方法更易理解)。例如:@RequestMapping(value = "/toUser", name = "获取用户信息")。

(三)@ResponseBody 注解

@ResponseBody注解在 SpringMVC 中用于处理方法返回字符或对象时的情况。当方法上有@ResponseBody注解时,Spring 会自动选择一个合适的HttpMessageConverter,将返回值转换为对应的格式(如 JSON、XML 等),并写入 HTTP 响应体中。

例如,当方法返回一个对象时,@ResponseBody会将这个对象转换为 JSON 格式并写入响应体。如果返回的是一个字符串,也会直接写入响应体。

使用时机如下:

  • 返回的数据不是 HTML 标签的页面,而是其他某种格式的数据时(如 JSON、XML 等)使用。
  • 在 GET、POST、PUT 等请求方式下,根据 request header 的 Content-Type 值来判断是否需要使用@ResponseBody。例如,当 Content-Type 为 application/json 或 application/xml 等格式时,通常需要使用@ResponseBody来处理返回值。

(四)GET 和 POST 请求的写法

在 SpringMVC 中,GET 和 POST 请求有不同的写法。

对于 GET 请求,可以使用@GetMapping注解或在@RequestMapping注解中设置 method 属性为 RequestMethod.GET。例如:

@RequestMapping(value = "/detail", method = {RequestMethod.GET})
    public Result detail(@RequestParam(value = "id", required = false) Long id) {
        //根据id查询详情
        if (null == id){
            return ResultGenerator.genSuccessResult(new User());
        }else {
            User user = userService.findById(id);
            if (null == user){
                return ResultGenerator.genSuccessResult(new User());
            }else {
                //返回查询的单个详情
                return ResultGenerator.genSuccessResult(user);
            }
        }
    }

在这个例子中,当用户访问/user/detail?id=1时,会调用这个方法,并根据传入的 id 参数获取用户信息并返回。

对于 POST 请求,可以使用@PostMapping注解或在@RequestMapping注解中设置 method 属性为 RequestMethod.POST。例如:

@RequestMapping(value = "/add", method = {RequestMethod.POST})
public Result add(@RequestBody User user) {
    return userService.add(user);
}

在这个例子中,当用户提交一个表单到/users/add路径时,会调用这个方法,并根据传入的用户对象创建一个新用户。

四、SpringMVC 获取参数

(一)传递单个参数

在 SpringMVC 中,传递单个参数可以直接在方法中定义参数名,与前端传递的参数名保持一致即可接收参数。例如,@RequestMapping("/m1")public String m1(String name){return "接收到的参数 name:" + name;},当请求的 URL 为127.0.0.1:8080/param/m1?name=zhangsan时,方法中的参数name就会被赋值为zhangsan。需要注意的是,使用基本类型来接收参数时,参数必须传(除boolean类型),否则会报 500 错误;类型不匹配时,会报 400 错误。

(二)传递对象

Spring MVC 可以自动实现参数对象的赋值。例如,可以创建实体类,实体类中的字段和表单字段name名一样,将其作为参数则可以自动赋值。比如创建一个Person对象,当前端传递的参数名与Person对象的属性名一致时,框架会自动将参数值赋给Person对象的对应属性。例如,@RequestMapping("/m4")public String m4(Person person){return "接收到的参数 person:" + person.toString();},当请求的 URL 为http://127.0.0.1:8080/param/m4?id=123&name=zhangsan&age=18时,框架会自动将参数值赋给Person对象的id、name和age属性。

(三)表单参数传递及传递多个参数

表单参数传递可以通过在控制器方法中指定和表单字段名一样的参数名便可以直接获取传递的参数值。例如,@RequestMapping("/login")public String login(String username, String password){return "用户名: " + username + " | 密码: " + password;},当表单提交时,框架会自动将表单中的参数值赋给方法中的参数。

传递多个非对象参数时,同样可以在方法中直接定义多个参数名,与前端传递的参数名保持一致即可接收参数。例如,@RequestMapping("/m2")public String m2(String name, Integer age){return "接收到的参数 name:" + name + ",age:" + age;},当请求的 URL 为http://127.0.0.1:8080/param/m2?name=zhangsan&age=18时,方法中的参数name和age就会被分别赋值为zhangsan和18。

(四)后端参数重命名

在某些特殊情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个time给后端,而后端又是用createtime字段来接收的,这样就会出现参数接收不到的情况。如果出现这种情况,我们就可以使用@RequestParam来重命名前后端的参数值。例如,@RequestMapping("/login")public String login(@RequestParam(value = "time", required = false) String createtime){return "时间:" + createtime;},设置了@RequestParam,那么前端就必须要传递time这个参数,如果不传递就会报错。查看@RequestParam源码,设置成false后,那么前端不传递这个参数也不会报错了。

(五)设置参数非必传

通过设置@RequestParam中的required属性可以实现参数非必传。当required属性设置为false时,该参数可传可不传,不传的话默认为null。例如,@RequestMapping("/value")@ResponseBodypublic String getParam(@RequestParam(value = "username", required = false) String name){return "注册成功: " + name;},没有传递参数时,默认为null,没有发生异常,访问成功。

(六)接收 JSON 对象

当我们前端传递 JSON 对象时,后端在使用接收普通对象的方式是接收不了的。要接收 JSON 对象,需要使用注解@RequestBody标注一下。例如,在 pom.xml 中引入 JSON 相关依赖<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.9</version></dependency>,然后在控制器方法中使用@RequestBody注解接收 JSON 对象。例如,@RequestMapping("/reg")public String reg(@RequestBody UserInfo userInfo){return "用户信息:" + userInfo;}。

(七)获取 URL 中参数

获取 URL 中参数要使用注解@PathVariable。例如,@Controller@ResponseBody@RequestMapping("/user")public class UserController {@RequestMapping("/hero/{id}/{name}")public String getHeroInfo(@PathVariable String id, @PathVariable String name){return "ID:" + id + " | Name: " + name;}},当请求的 URL 为/user/hero/123/zhangsan时,方法中的参数id和name就会被分别赋值为123和zhangsan。

(八)上传文件

在 SpringMVC 中上传文件可以使用注解@RequestPart。例如,@RequestMapping("/upimg")public boolean upImg(Integer uid, @RequestPart("img") MultipartFile file){boolean result = false;try {file.transferTo(new File("D:/IDEA/img.png"));result = true;} catch (IOException e){log.error("上传图片失败: " + e.getMessage());}return result;}。

文件上传有一些注意事项:

  1. 保存文件的目录问题:不同平台的配置文件设置不同,比如在开发环境和生产环境中需要将上传的文件保存到不同的目录。可以通过配置文件来设置不同环境下的文件保存路径,如application-dev.yml(开发环境配置文件)和application-prod.yml(生产环境配置),并在application.yml中设置配置文件的运行平台。
  1. 生成图片名称问题:为了解决文件覆盖问题,可以使用 UUID(通用唯一标识)来生成不重复的文件名。UUID 是由当前电脑网卡的 mac + 时间戳 + 随机数组成的,使用 UUID 可以保证文件名字不会重复。

五、SpringMVC 返回数据

(一)返回静态页面

在 SpringMVC 中,可以使用不同的方式返回静态页面。例如,使用@Controller注解配合return "index.html"的方式可以返回静态页面。不过需要注意的是,当使用@RestController注解时,会将返回的路径视为字符串数据而非 HTML 页面进行返回。如以下代码示例:

@RequestMapping("/return")

@RestController

public class ReturnController {

@RequestMapping("/index")

public String returnIndex() {

return "/index.html";

}

}

此时页面不能正常返回静态页面,而是将index.html作为字符串返回。而如果使用@Controller注解,就可以成功将index.html解析为 HTML 页面进行返回。

(二)返回 JSON 对象

在 SpringMVC 中,返回 JSON 对象通常有两种主要方式。

  1. 使用@ResponseBody注解:该注解的作用是把方法返回结果转成 JSON 或 XML 格式并进行返回。不管要返回什么类型的数据,是 String 还是一个对象,只要是需要请求后想直接返回 JSON 或 XML 类型的数据,都可以使用这个注解。一般@ResponseBody注解会将 map、JavaBean 对象自动转成{"":"","":""}这种 JSON 的对象表示形式,会将 list 转成[a,b,c]这种 JSON 的数组表示形式,而 String 类型的数据则会直接原样输出。例如:
public Result list(User user) {
        //调用PageHelper公共方法实现分页
        PageHelper.startPage(user.getPage() == null ? 0 : user.getPage(), user.getLimit() == null ? 10 : user.getLimit());
        //查询没有逻辑删除
        user.setIsDelete(false);
        //分页查询
        List<User> list = userMapper.list(user);
        PageInfo pageInfo = new PageInfo(list);
        //返回分页后的结果集
        return ResultGenerator.genSuccessResult(pageInfo);
    }
  1. 使用 response 对象返回:这种方式就是自己进行数据格式转换,使用 response 对象进行返回。首先设置 response 的内容类型为application/json,然后通过response.getWriter().write(resultString)的方式返回 JSON 数据。

(三)请求转发或请求重定向

  1. 请求转发:在 SpringMVC 中,可以使用forward:/路径的方式进行请求转发。转发是服务器行为,只需一次跳转,用户看不到 URL 地址上的变化。转发能够获取 request 作用域中的数据,因为它只发出了一次请求。例如:
@RequestMapping("/handle0")

public String handle0() {

System.out.println("handle0 运行");

  return "forward:/hello";

}
  1. 请求重定向:可以使用redirect:/路径的方式进行请求重定向。重定向是浏览器端的行为,需要进行二次跳转,用户能看到 URL 地址上的变化。重定向无法获取 request 中的数据,因为它发出了二次请求,每一次请求对应着一次新的 request。例如:
@RequestMapping("/handle2")

public String handle2() {

System.out.println("handle2 运行");

  return "redirect:/hello.jsp";

}

请求转发和重定向在实际应用中有不同的场景,需要根据具体需求进行选择。例如,如果需要在服务器内部进行页面跳转且希望保留 request 作用域中的数据,可以选择请求转发;如果需要让用户看到 URL 地址的变化或者访问不同服务器中的数据,可以选择请求重定向。

六、SpringMVC 特点与优势

(一)清晰的角色划分

SpringMVC 具有清晰的角色划分,包括前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器(Validator)、命令对象(Command)、表单对象(Form Object)等。前端控制器负责接收所有请求并进行分发;HandlerMapping 根据请求找到对应的处理器;HandlerAdapter 执行处理器;ViewResolver 解析视图;Controller 处理具体业务逻辑;Validator 进行数据验证等。每个角色都有明确的职责,使得开发过程更加清晰和高效。

(二)分工明确且扩展灵活

SpringMVC 的各个组件分工明确,各司其职。这种明确的分工使得开发人员能够更加专注于自己负责的部分,提高开发效率。同时,SpringMVC 的扩展点相当灵活,可以很容易地进行扩展。虽然在实际开发中可能并不需要频繁扩展,但这种灵活性为应对复杂业务需求提供了保障。例如,可以根据实际情况定制自己的视图解析器、处理器映射器等。

(三)可直接使用业务对象

由于命令对象就是一个 POJO(Plain Old Java Object),无需继承框架特定 API,可以使用命令对象直接作为业务对象。这一优点使得开发更加简洁,减少了代码的冗余。开发人员可以直接使用现有的业务对象进行开发,而不需要为了适应框架进行额外的封装或继承,提高了代码的可维护性和可复用性。

(四)与 Spring 其他框架无缝集成

SpringMVC 与 Spring 其他框架无缝集成,这是其他 Web 框架所不具备的优势。可以方便地与 Spring 的 IOC(Inverse of Control,控制反转)容器、AOP(Aspect-Oriented Programming,面向切面编程)等功能结合使用。例如,可以利用 Spring 的 IOC 容器管理业务对象的生命周期,通过 AOP 实现日志记录、事务管理等功能。这种无缝集成使得开发人员能够更加高效地构建企业级应用。

(五)可适配及可定制性

SpringMVC 可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。这意味着开发人员可以根据实际需求选择合适的处理器类,提高了框架的灵活性。同时,HandlerMapping、ViewResolver 等组件能够非常简单地定制。可以根据项目需求定制请求的映射规则、视图的解析方式等,满足不同项目的个性化需求。

(六)功能强大的数据验证等机制

SpringMVC 具有功能强大的数据验证、格式化、绑定机制。可以对用户输入的数据进行严格的验证,确保数据的合法性和准确性。同时,能够对数据进行格式化,使得数据在不同的表现形式之间进行转换更加方便。例如,可以将用户输入的日期字符串自动转换为 Java 中的 Date 对象。这种强大的数据处理机制提高了应用的稳定性和可靠性。

(七)易于单元测试

利用 Spring 提供的 Mock 对象能够非常简单地进行 Web 层单元测试。在单元测试中,可以使用 Mock 对象模拟真实的请求和响应,对控制器进行测试。这种方式不依赖于真实的服务器环境,测试速度快,并且能够很好地保存和循环使用测试用例。例如,可以使用 MockMvc 进行控制器的单元测试,通过设置请求参数、模拟执行控制器方法,并验证返回结果,确保控制器的功能正确。

(八)本地化及主题切换支持

SpringMVC 对本地化、主题的解析提供了支持,使我们更容易进行国际化和主题的切换。可以根据不同的地区和用户需求,展示不同语言和风格的界面。这对于面向全球用户的应用非常重要,能够提高用户体验和应用的适应性。例如,可以通过配置不同的资源文件实现多语言支持,根据用户的选择切换不同的主题风格。

(九)强大的 JSP 标签库

SpringMVC 拥有强大的 JSP 标签库,使 JSP 编写更容易。JSP 标签库提供了丰富的功能,如数据绑定、主题支持等。开发人员可以使用这些标签库简化 JSP 页面的开发,提高开发效率。同时,标签库的使用使得页面代码更加简洁、易读,便于维护。例如,可以使用标签库快速实现数据的展示和表单的生成。

七、SpringMVC 工作原理

(一)MVC 模型与 SpringMVC 关系

MVC 即 Model-View-Controller,是一种软件设计模式。其中,Model 负责封装数据及对数据的操作,不依赖视图和控制器,只负责提供数据;View 负责从 Model 中拉取数据并展示,没有具体的程序逻辑;Controller 用于控制程序的流程,将 Model 中的数据展示到 View 中。

SpringMVC 是基于 MVC 模式的一种轻量级 Web 框架。SpringMVC 对 MVC 模式的具体实现如下:模型部分通常由一个或多个 JavaBean 对象组成,用于存储数据和业务逻辑,可以直接对数据库进行访问;视图部分可以是一个或多个 JSP 页面,向控制器提交数据并为模型提供数据显示,JSP 页面主要使用 HTML 标记和 JavaBean 标记来显示数据;控制器部分由一个或多个 Servlet 对象组成,根据视图提交的请求进行控制,即将请求转发给业务逻辑的 JavaBean,并将处理结果存放到实体模型 JavaBean 中,输出给视图显示。

(二)SpringMVC 五大核心组件关系

SpringMVC 的五大核心组件包括 DispatcherServlet、HandlerMapping、HandlerAdapter、ViewResolver 和 View。它们之间的协作关系紧密,共同完成了从用户请求到响应结果的整个过程。

DispatcherServlet 作为前端控制器,是整个请求处理的入口,负责分发请求。它接收用户请求后,依据 HandlerMapping 的配置,查找对应的控制器。HandlerMapping 负责根据请求找到对应的控制器,并将请求和对应的控制器封装成 HandlerExecutionChain 返回给 DispatcherServlet。

DispatcherServlet 接着调用 HandlerAdapter 去执行处理器。HandlerAdapter 本质上是一个适配器,可以根据要求找到对应的 Handler 来运行。由于 Handler 涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发 Handler。

Handler 执行完后给 HandlerAdapter 返回 ModelAndView。ModelAndView 由数据与视图名称组成,包含了处理结果。DispatcherServlet 再将 ModelAndView 传给 ViewResolver 进行视图解析。

ViewResolver 本质上也是一种映射关系,可以将视图名称映射到真正的视图地址。它向 DispatcherServlet 返回真正的 View。最后,DispatcherServlet 对视图进行渲染,并向用户响应结果。

View 是一个接口,实现类支持不同的 View 类型(如 jsp、freemarker、pdf 等)。本质上就是将 Handler 处理器中返回的 Model 数据嵌入到视图解析器解析后得到的页面中,向客户端做出响应。

(三)工作流程详解

SpringMVC 的工作流程可以分为以下几个主要步骤:

  1. 用户发起请求到前端控制器(DispatcherServlet)。用户通过浏览器向服务器发送一个 HTTP 请求,这个请求会先到达前端控制器 DispatcherServlet。
  1. 前端控制器请求处理器映射器(HandlerMapping)去查找处理器(Handler)。DispatcherServlet 接收到请求后,会调用 HandlerMapping。HandlerMapping 通过 xml 配置或者注解进行查找,找到对应的 Handler 和 Interceptor,然后封装成一个 HandlerExecutionChain 对象返回给 DispatcherServlet。
  1. 找到以后处理器映射器(HandlerMapping)向前端控制器返回执行链(HandlerExecutionChain)。HandlerExecutionChain 包括一个处理器和多个 HandlerInterceptor 拦截器。
  1. 前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)。DispatcherServlet 根据 HandlerExecutionChain 中的处理器,选择一个合适的 HandlerAdapter,创建其实例对象,并调用其 handle 方法去执行处理器。
  1. 处理器适配器去执行 Handler。HandlerAdapter 运用 Java 的反射机制执行 Handler 的具体方法,获取 ModelAndView 对象。
  1. Handler 执行完给处理器适配器返回 ModelAndView。Handler 处理完请求后,将处理结果封装成 ModelAndView 对象返回给 HandlerAdapter。
  1. 处理器适配器向前端控制器返回 ModelAndView。HandlerAdapter 将 ModelAndView 对象返回给 DispatcherServlet。
  1. 前端控制器请求视图解析器(ViewResolver)去进行视图解析。DispatcherServlet 将 ModelAndView 对象中的视图名称传给 ViewResolver,让其解析出真正的视图地址。
  1. 视图解析器向前端控制器返回 View。ViewResolver 根据视图名称映射到真正的视图地址,并将其封装成 View 对象返回给 DispatcherServlet。
  1. 前端控制器对视图进行渲染。DispatcherServlet 将 ModelAndView 中的模型数据填充到 View 对象中,进行视图渲染。
  1. 前端控制器向用户响应结果。渲染完成后,DispatcherServlet 将最终的视图结果返回给用户的浏览器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机毕设定制辅导-无忧学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值