大家好:我是狂飙程序员,今日给大家分享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
中配置 HandlerMapping
、ViewResolver
等:
<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
找到HelloController
的hello
方法进行处理,该方法返回视图名称hello
和模型数据message
,ViewResolver
会将视图名称解析为hello.jsp
,最后DispatcherServlet
会将模型数据渲染到hello.jsp
并返回给客户端,是不是很清楚了,对你有帮助吗,还是要总结一下他们的调用流程:
Spring MVC 核心组件调用流程关系
Spring MVC 是基于 Java 实现的一个经典的 Web 开发框架,其核心组件 DispatcherServlet
、HandlerMapping
、Controller
、ModelAndView
、ViewResolver
之间的调用流程如下:
客户端请求到达 DispatcherServlet
DispatcherServlet
是 Spring MVC 的核心前端控制器,负责接收所有客户端的 HTTP 请求。当客户端(如浏览器)发送一个请求到 Web 应用时,该请求首先会被DispatcherServlet
拦截。- DispatcherServlet 借助 HandlerMapping 查找处理器
HandlerMapping
的作用是根据请求的 URL 等信息,将请求映射到具体的处理器(通常是Controller
中的某个方法)。DispatcherServlet
会调用HandlerMapping
来确定处理该请求的合适处理器。- DispatcherServlet 调用处理器(Controller)
- 找到对应的处理器后,
DispatcherServlet
会将请求转发给相应的Controller
。Controller
是处理业务逻辑的组件,它会接收请求参数,调用业务服务进行处理,并返回处理结果。
- 找到对应的处理器后,
- 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;