Spring MVC(Model-View-Controller)是一种用于构建基于Java的Web应用程序的框架。它是Spring Framework的一部分,是一个经典的MVC设计模式的实现,旨在帮助开发人员更轻松地构建可维护和可扩展的Web应用程序。
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分:
Model(模型): 模型代表应用程序的数据和业务逻辑。它负责管理数据的状态和处理数据操作。通常,模型对象是用于封装和表示应用程序数据的Java类。
View(视图): 视图负责显示模型的数据给用户。它们负责将数据以用户友好的方式呈现出来,通常是通过HTML模板或其他前端技术来实现的。
Controller(控制器): 控制器处理用户的请求并协调模型和视图之间的交互。它接收用户输入,然后根据输入决定如何更新模型数据,并选择适当的视图来显示结果。
Spring MVC的工作流程如下:
用户发起一个HTTP请求,该请求被Spring的前端控制器(DispatcherServlet)拦截。
前端控制器将请求路由到相应的控制器处理程序,该处理程序执行请求的逻辑。
控制器处理程序可能会调用适当的服务或业务逻辑,以获取或处理数据。
处理程序处理完逻辑后,将数据存储在模型对象中,并选择一个适当的视图。
视图负责将模型中的数据呈现为最终的HTML响应。
前端控制器将最终的HTML响应发送回用户。
Spring MVC提供了许多功能,例如请求映射、数据绑定、验证、国际化、文件上传等,使开发人员能够更轻松地构建和管理Web应用程序。它还支持各种视图技术,包括JSP、Thymeleaf、FreeMarker等,以及RESTful Web服务的开发。
MVC(Model-View-Controller)是一种软件设计模式,用于将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller),以实现分离关注点、模块化和可维护的应用程序架构。MVC 模式的目标是将数据、用户界面和控制流程分开,使应用程序更易于理解、开发和维护。
Spring MVC 是 Spring Framework 的一部分,它是基于 MVC 设计模式的一个 Web 框架。Spring MVC 所做的就是在 Web 开发环境中实现了 MVC 模式,以帮助开发人员构建灵活、可扩展的 Web 应用程序。
因此,Spring MVC 是基于 MVC 模式的一种实现,它在 Web 开发中提供了一套现成的架构、组件和工具,使开发人员能够更方便地构建符合 MVC 设计原则的 Web 应用程序。它封装了大量的底层细节,提供了请求处理、数据绑定、视图解析、验证、异常处理等功能,使开发者能够专注于业务逻辑的实现而不必过多关注底层的 Web 技术细节。
总结起来,MVC 是一种通用的设计模式,用于组织应用程序架构,而 Spring MVC 是 Spring Framework 在 Web 开发中对 MVC 模式的具体实现。通过 Spring MVC,开发人员可以更轻松地构建符合 MVC 设计原则的 Web 应用程序,并且可以利用 Spring 框架的众多特性来提高应用程序的可维护性、可测试性和扩展性。
学习 Spring MVC 我们只需要掌握以下 3 个功能:
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC
Spring MVC 项⽬创建和 Spring Boot 创建项⽬相同(Spring MVC 使⽤ Spring Boot 的⽅式创建),在创建的时候第三方框架依赖选择 Spring Web 就相当于创建了 Spring MVC 的项⽬。
在 Spring MVC 中使用@RequestMapping
来实现 URL 路由映射,也就是浏览器连接程序的作用。我们在spring boot的创建与使用中,最后的项目demo实际上就是一个springmvc的项目。
package com.fyd.springmvcdemo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller // 控制器,在spring启动的时候加载并注册
@ResponseBody // 当前类返回的是非静态页面
@RequestMapping("/web") // 使用/web 能访问到当前类
public class WebController {
// 使用/web/hello 能访问到当前方法
@RequestMapping("/hello")
public Object sayHello() {
return "Hello, Spring MVC!";
}
}
- @RestController = @Controller + @ResponseBody,表示一个HTTP控制器,返回的是非静态页面的数据
- @RequestMapping 默认是返回静态页面,如果我们是要返回一个html,就不需要加@ResponseBody注解
@Controller
@RequestMapping("/web")
public class WebController {
@RequestMapping("/hello2")
public Object sayHello2() {
return "/index.html";
}
}
@RequestMapping
是 Spring MVC 中一个重要的注解,用于将请求映射到控制器的处理方法上。它可以应用在类级别或方法级别,用于定义请求路径、HTTP 方法、请求参数等信息,以指定控制器方法如何处理不同类型的请求。
在方法级别,@RequestMapping
可以用于处理特定请求路径的请求。以下是一些常用的属性和用法:
@RequestMapping(value = "/home")
public String homePage() {
// ...
}
@RequestMapping
对所有 HTTP 方法都适用。你可以使用枚举类型 RequestMethod
来指定具体的方法。@RequestMapping(value = "/submit", method = RequestMethod.POST)
public String submitForm() {
// ...
}
@RequestMapping(value = “/submit”, method = RequestMethod.POST) 可以用更具体的注解替换:@PostMapping(/submit)
@RequestMapping
注解允许你根据路径、HTTP 方法、请求参数、请求头等条件来映射控制器的处理方法。它为控制器提供了灵活的映射选项,使你可以根据不同的请求类型和条件来执行相应的业务逻辑。同时,@RequestMapping
也可以应用在类级别,用于定义控制器的根路径,从而进一步组织请求映射。随着 Spring MVC 版本的升级,@RequestMapping
还演变为多个更具体的注解,如 @GetMapping
、@PostMapping
等,用于更清晰地表达不同 HTTP 方法的映射关系。
@RequestMapping("/getOneParam")
public Object getOneParam(HttpServletRequest request) {
return "Hello, " + request.getParameter("name");
}
在SpringMVC中默认内置隐藏了两个参数,一个是Request(HttpServletRequest)、一个是Response(HttpServletResponse)对象,所以如果想要使用这两个参数,只需要在方法中申明即可获取到。
@RequestMapping("/getOneParam2")
public Object getOneParam2(String name) {
return "Hello, " + name;
}
当传的参数是一个整形的时候,有两种方式:用int和Integer
@RequestMapping("/getIntParam")
public Object getIntParam(int id) {
return "你的id是:" + id;
}
当前端没有传id过来的时候是会直接报错
当我们换成Integer时,并不会报错而是null
为了减少报错和没必要的日志信息,我们推荐使用Integer获取整型参数
/**
* 获取多个参数
* @param name
* @param id
*/
@RequestMapping("/getMultiParam")
public Object getMultiParam(String name, Integer id) {
return "Hello, " + name + ",你的id是:" + id;
}
SpringMVC中,当传递多个参数的时候,传递参数的顺序是不影响程序执行的,获取参数的结果之和和参数的名称有关,和顺序无关。
/**
* 获取对象
* @param user
*/
@RequestMapping("/getObject")
public Object getObject(User user) {
return user.toString();
}
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private Integer age;
private String sex;
}
在前端该怎么传参数就怎么传,主要是后端封装成对象了,当没传的就是null值。当要扩充参数时,直接在要操作的类里加就好了,不用修改controller类。
获取少量参数
/**
* 获取登录信息
*/
@RequestMapping("/login")
public String login(String name,String password) {
if (name.equals("fyd") && password.equals("123456")) {
return "登录成功
";
} else {
return "登录失败
";
}
}
<h1>登录h1>
<form action="web/login" method="post">
<div>
<label for="name">用户名:label>
<input type="text" id="name" name="name" placeholder="请输入用户名">
<label for="password">密码:label>
<input type="password" id="password" name="password" placeholder="请输入密码">
<input type="submit" value="登录">
div>
form>
/**
* 获取注册信息(多个参数)
*/
@RequestMapping("/register")
public String register(User user) {
return user.toString();
}
<div>
<h1>注册h1>
<form action="web/register" method="post">
<div>
<div>
<label for="name">用户名:label>
<input type="text" id="name" name="name" placeholder="请输入用户名">
div>
<div>
<label for="password">密码:label>
<input type="password" id="password" name="password" placeholder="请输入密码">
div>
<div>
<label for="email">邮箱:label>
<input type="email" id="email" name="email" placeholder="请输入邮箱">
div>
<div>
<label for="phone">手机号:label>
<input type="text" id="phone" name="phone" placeholder="请输入手机号">
div>
<div>
<label for="address">地址:label>
<input type="text" id="address" name="address" placeholder="请输入地址">
div>
<div>
<input type="submit" value="注册">
div>
div>
form>
div>
/**
* ajax请求登录
*/
@RequestMapping("/loginAjax")
public HashMap<String, Object> loginAjax(String name, String password) {
HashMap<String, Object> result = new HashMap<>();
if (name.equals("fyd") && password.equals("123456")) {
result.put("code", 200);
result.put("msg", "登录成功");
} else {
result.put("code", 500);
result.put("msg", "登录失败");
}
return result;
}
导入jQuery后,在前面的登录页面里加入下面代码请求后端接口
<script>
function onsub(){
// 请求后端的接口使用 ajax
jQuery.ajax({
url:"login2",
type:"POST",
data:{"name":jQuery("#name").val(),"password":jQuery("#password").val()},
success:function(result){
alert(result);
console.dir(result);
}
});
}
script>
/**
* 获取用户传的json数据
*/
@RequestMapping("/getJson")
public HashMap<String, Object> getJson(@RequestBody User user) {
HashMap<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("msg", "获取成功");
result.put("data", user);
return result;
}
上传文件
/**
* 上传文件,返回上传的路径
*/
@RequestMapping("/upload")
public String upload(String name, @RequestPart("file") MultipartFile file) throws IOException {
// 获取文件名
String fileName = file.getOriginalFilename();
// 获取文件后缀
String suffixName = fileName.substring(fileName.lastIndexOf("."));
// 重新生成文件名
fileName = UUID.randomUUID() + suffixName;
// 获取项目路径
String filePath = ClassUtils.getDefaultClassLoader().getResource("").getPath() + "static/upload/";
// 创建文件路径
File dest = new File(filePath + fileName);
// 判断文件是否已经存在
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
// 上传文件
file.transferTo(dest);
return filePath + " 上传成功";
}
/**
* 获取cookie
*/
@RequestMapping("/getCookie")
public String getCookie(@CookieValue("fyd") String cookie) {
return "cookie: " + cookie;
}
/**
* 设置session
*/
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request) {
request.getSession().setAttribute("username", "fyd");
return "session: 设置成功";
}
/**
* 获取session
*/
@RequestMapping("/getSession")
public String getSession(@SessionAttribute(value = "username",required = false) String username) {
return "session: " + username;
}