Spring MVC 深度剖析与实战应用,与spirngboot和tomcat之间奥秘

大家好:我是狂飙程序员,今日给大家分享spring mvc相关内容,看来这篇文章对这一块知识复习和深入有一定帮助,本文通过容易理解的方式给大家分享。

一、Spring MVC 概述

1.1 Spring MVC是什么?

Spring MVC 是 Spring 框架的一个模块(提升:spirng框架有哪些核心模块呢?),它是基于 Java 实现的一个轻量级 Web 框架,遵循 MVC(Model-View-Controller,模型 - 视图 - 控制器)设计模式(分层思想出现)。MVC 模式将一个应用程序分为三个核心部分:模型(Model)、视图(View)和控制器(Controller),它们各自处理不同的职责,从而实现代码的解耦和可维护性,这里主要弄清楚有哪几层,明白分层思想出现。

  • 模型(Model):负责封装数据和业务逻辑。例如,在一个电商系统中,商品信息就是一个模型,它包含商品的名称、价格、描述等属性,同时可能还包含一些与商品相关的业务逻辑,如计算商品的折扣价格,通俗易懂一点就是对应项目中的实体嘛。
  • 视图(View):负责将模型中的数据呈现给用户。常见的视图技术有 JSP、Thymeleaf 等。以电商系统为例,商品列表页面就是一个视图,它将商品模型中的数据以列表的形式展示给用户,其实就是指的页面,前端这一块,比如html,jsp,vue等等。
  • 控制器(Controller):负责接收用户的请求,调用模型处理业务逻辑,并选择合适的视图将结果展示给用户。在电商系统中,当用户点击 “查看商品列表” 按钮时,控制器会接收这个请求,调用商品模型获取商品列表数据,然后选择商品列表视图将数据展示给用户,控制层就是我们项目中的Controller ,也就是入口,Controller 在项目中会根据业务模块分为若干个Controller,比如:
@Api(tags = "小程序")
@RestController
@RequestMapping("/xxx")
public class MiniProgramController {
}

@Api(tags = "商品")
@RestController
@RequestMapping("/xxx")
public class MiniProgramController {
}
...........
我们是不是已经弄清楚了mvc三层分别是什么了?然后有分层的思想了?我们继续...

1.2 为什么出现 Spring MVC

我们要弄清楚为什么出现spring MVC,肯定要弄清楚为什么对吧?在 Spring MVC 出现之前,Java Web 开发主要使用 Servlet 和 JSP 技术。虽然 Servlet 和 JSP 可以实现 Web 应用的开发,但它们存在一些问题,但是很多程序员没有使用过JSP吧,很多都是后面直接使用springboot的吧,没有经历过这个过程。使用 Servlet 和 JSP 技术存在以下几个问题:

  • 代码耦合度高:Servlet 和 JSP 通常会混合处理业务逻辑和视图展示,导致代码难以维护和扩展。例如,一个 Servlet 可能既处理用户登录的业务逻辑,又负责将登录结果展示给用户,当业务需求发生变化时,修改代码会变得非常困难,我记得我以前写JSP代码的时候把连接数据库的代码,业务代码都会写入到不同的JSP页面中,大家知道这样的问题了吧,因为那时还没spring mvc出现。
  • 开发效率低:使用 Servlet 和 JSP 开发 Web 应用需要编写大量的样板代码,如处理请求参数、转发请求等,这会增加开发人员的工作量,降低开发效率。
  • 缺乏统一的开发规范:不同的开发人员可能采用不同的方式来实现 Web 应用,导致代码风格不一致,不利于团队协作和项目管理,其实问题还不止这几项,大家想想还有什么问题?

Spring MVC 的出现解决了上述问题,它提供了一种更加优雅、高效的方式来开发 Java Web 应用。通过遵循 MVC 设计模式,Spring MVC 实现了代码的解耦,提高了代码的可维护性和可扩展性;同时,它还提供了丰富的注解和工具,减少了开发人员编写样板代码的工作量,提高了开发效率。

1.3 历史背景

大概了解一下背景,只是了解就行,Spring 框架最初由 Rod Johnson 在 2003 年发布,它的目标是为 Java 企业级应用提供一个轻量级的开发框架。随着 Spring 框架的不断发展,为了满足 Web 开发的需求,Spring 团队在 Spring 框架中引入了 Spring MVC 模块。

Spring MVC 借鉴了许多其他 Web 框架的优秀设计思想,如 Struts、WebWork 等。它在设计上更加注重灵活性和可扩展性,同时提供了与 Spring 框架其他模块的无缝集成,使得开发人员可以更加方便地构建企业级 Web 应用。这里重点提到了几个关键词:模块,灵活性,可扩展性,无缝集成,这些是不是我们应该关注的和提升自己的关键词?在我们的项目中是不是真正做到了?

二、Spring MVC 核心知识点

2.1 核心组件

Spring MVC 的核心组件包括 DispatcherServlet、HandlerMapping、Controller、ModelAndView、ViewResolver 等,下面分别介绍这些组件的作用:

2.1.1 DispatcherServlet

DispatcherServlet 是 Spring MVC 的核心控制器,它负责接收所有的 HTTP 请求,并将请求分发给相应的处理器进行处理。可以将 DispatcherServlet 看作是一个交通枢纽,所有的请求都要经过它,然后由它将请求引导到合适的目的地。那大家思考一下DispatcherServlet是不是我们的总指挥部一样?所以的请求都要经过这里,由它分发,那这里是不是可以去看看源码了?

2.1.2 HandlerMapping

HandlerMapping 负责根据请求的 URL 找到对应的处理器(Controller)。它就像一个地图,根据请求的地址(URL)找到对应的目的地(Controller)。Spring MVC 提供了多种 HandlerMapping 实现,如 BeanNameUrlHandlerMapping、RequestMappingHandlerMapping 等。

2.1.3 Controller

Controller 是处理请求的核心组件,它负责处理业务逻辑,并返回处理结果。在 Spring MVC 中,Controller 通常是一个普通的 Java 类,通过注解(如 @Controller、@RequestMapping)来标识。例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
public class HelloController {
    // 使用 @RequestMapping 注解将该方法映射到 /hello 路径
    @RequestMapping("/hello")
    // 使用 @ResponseBody 注解将方法的返回值直接作为响应体返回
    @ResponseBody
    public String hello() {
        return "Hello, Spring MVC!";
    }
}

2.1.4 ModelAndView

ModelAndView 是一个包含模型数据和视图信息的对象,它用于将模型数据传递给视图,并指定要使用的视图。例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
public class UserController {
    // 使用 @RequestMapping 注解将该方法映射到 /user 路径
    @RequestMapping("/user")
    public ModelAndView getUser() {
        // 创建一个 ModelAndView 对象
        ModelAndView modelAndView = new ModelAndView();
        // 向模型中添加数据
        modelAndView.addObject("username", "John");
        // 设置要使用的视图名称
        modelAndView.setViewName("user");
        return modelAndView;
    }
}

2.1.5 ViewResolver

ViewResolver 负责根据视图名称找到对应的视图对象。它就像一个翻译器,将视图名称翻译成实际的视图对象。Spring MVC 提供了多种 ViewResolver 实现,如 InternalResourceViewResolver、ThymeleafViewResolver 等。

写到这里我在思考一个问题:DispatcherServlet、HandlerMapping、Controller、ModelAndView、ViewResolver 他们之间有什么关系呢?我们清楚了吗?

代码示例

以下是一个简单的 Spring MVC 示例,展示了上述组件的使用:

配置 DispatcherServlet

在 web.xml 中配置 DispatcherServlet

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

配置 Spring MVC

在 spring-mvc.xml 中配置 HandlerMappingViewResolver 等:

<mvc:annotation-driven />
<context:component-scan base-package="com.example.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
</bean>

创建 Controller

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, Spring MVC!");
        return "hello";
    }
}

创建视图

在 /WEB-INF/views/ 目录下创建 hello.jsp

<!DOCTYPE html>
<html>
<head>
    <title>Hello Spring MVC</title>
</head>
<body>
    <h1>${message}</h1>
</body>
</html>

通过以上配置和代码,当客户端访问/hello时,DispatcherServlet会接收请求,通过HandlerMapping找到HelloControllerhello方法进行处理,该方法返回视图名称hello和模型数据messageViewResolver会将视图名称解析为hello.jsp,最后DispatcherServlet会将模型数据渲染到hello.jsp并返回给客户端,是不是很清楚了,对你有帮助吗,还是要总结一下他们的调用流程:

Spring MVC 核心组件调用流程关系

Spring MVC 是基于 Java 实现的一个经典的 Web 开发框架,其核心组件 DispatcherServletHandlerMappingControllerModelAndViewViewResolver 之间的调用流程如下:

客户端请求到达 DispatcherServlet

  • DispatcherServlet 是 Spring MVC 的核心前端控制器,负责接收所有客户端的 HTTP 请求。当客户端(如浏览器)发送一个请求到 Web 应用时,该请求首先会被 DispatcherServlet 拦截。
  • DispatcherServlet 借助 HandlerMapping 查找处理器
  • HandlerMapping 的作用是根据请求的 URL 等信息,将请求映射到具体的处理器(通常是 Controller 中的某个方法)。DispatcherServlet 会调用 HandlerMapping 来确定处理该请求的合适处理器。
  • DispatcherServlet 调用处理器(Controller)
    • 找到对应的处理器后,DispatcherServlet 会将请求转发给相应的 ControllerController 是处理业务逻辑的组件,它会接收请求参数,调用业务服务进行处理,并返回处理结果。
  • Controller 返回 ModelAndView
    • Controller 处理完请求后,会返回一个 ModelAndView 对象。ModelAndView 包含了模型数据(Model)和视图名称(View)。模型数据用于传递给视图进行渲染,视图名称指定了要使用的视图。
  • DispatcherServlet 借助 ViewResolver 解析视图
    • ViewResolver 的作用是根据 ModelAndView 中的视图名称,解析出具体的视图对象。DispatcherServlet 会调用 ViewResolver 来完成视图解析工作。
  • DispatcherServlet 使用解析后的视图渲染模型数据
    • 视图解析完成后,DispatcherServlet 会使用解析得到的视图对象,将 ModelAndView 中的模型数据渲染到视图中,并将渲染后的结果返回给客户端,写到这里我们是不是已经弄清楚了他们直接的关系了?那我们继续研究研究........

2.2 注解

Spring MVC 提供了丰富的注解,用于简化开发过程,下面介绍一些常用的注解:

2.2.1 @Controller

@Controller 注解用于将一个类标识为控制器。例如:

import org.springframework.stereotype.Controller;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
public class ProductController {
    // 控制器方法
}

2.2.2 @RequestMapping

@RequestMapping 注解用于将请求映射到控制器的方法上。它可以用于类和方法上,用于指定请求的 URL 路径。例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
// 将该类下的所有方法映射到 /product 路径下
@RequestMapping("/product")
public class ProductController {
    // 将该方法映射到 /product/list 路径
    @RequestMapping("/list")
    @ResponseBody
    public String getProductList() {
        return "Product List";
    }
}

2.2.3 @RequestParam

@RequestParam 注解用于获取请求参数。例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
@RequestMapping("/user")
public class UserController {
    // 将该方法映射到 /user/login 路径
    @RequestMapping("/login")
    @ResponseBody
    public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
        if ("admin".equals(username) && "123456".equals(password)) {
            return "Login Success";
        } else {
            return "Login Failed";
        }
    }
}

2.2.4 @PathVariable

@PathVariable 注解用于获取 URL 路径中的变量。例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

// 使用 @Controller 注解将该类标识为一个控制器
@Controller
@RequestMapping("/product")
public class ProductController {
    // 将该方法映射到 /product/{id} 路径
    @RequestMapping("/{id}")
    @ResponseBody
    public String getProductById(@PathVariable("id") int id) {
        return "Product ID: " + id;
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值