SpringMVC
是基于Java的Web应用程序开发框架,它是Spring Framework的一部分。它提供了一种基于模型-视图-控制器(Model-View-Controller,MVC)架构的方式来开发灵活、可扩展的Web应用程序。
SpringMVC框架通过将请求的处理流程划分为三个核心组件来实现MVC架构:
SpringMVC框架通过DispatcherServlet
作为前端控制器(Front Controller),协调和管理整个请求处理过程。当客户端发送请求时,DispatcherServlet会根据配置信息将请求委派给相应的处理器(Controller),并将结果发送给适当的视图进行渲染。
SpringMVC提供了许多功能和特性,如请求映射、数据绑定、表单处理、数据验证、文件上传、国际化、拦截器、异常处理等。它还支持使用注解和XML配置来进行灵活的开发和配置。
总而言之,SpringMVC是一个用于开发Web应用程序的轻量级、灵活且功能丰富的框架,它通过MVC架构模式提供了一种优雅的方式来构建现代化的Web应用程序。
MVC 是⼀种思想,而 Spring MVC 是对 MVC 思想的具体实现。SpringMVC是Spring Framework中用于构建Web应用程序的MVC框架,它实现了MVC设计模式的思想,并提供了一套机制来实现模型、视图和控制器之间的解耦和交互。
现在绝大部分的 Java 项目都是基于 Spring(或 Spring Boot)的,而 Spring 的核心就是 Spring MVC。也就是说 Spring MVC 是 Spring 框架的核心模块,而 Spring Boot 是 Spring 的脚手架.Spring MVC 是⼀切项目的基础,Spring、Spring Boot 项目基本都是基于 Spring MVC 的。
学习SpringMVC只需要掌握以下三个功能:
Spring MVC 项目创建和 Spring Boot 创建项目相同(Spring MVC 使用Spring Boot 的方式创建),在创建的时候选择 Spring Web 就相当于创建了 Spring MVC 的项目。
接下来创建一个UserController类:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@RequestMapping("/sayhi")
public String sayHi(){
return "hi SpringMVC!";
}
}
启动项目,在网页中访问http://localhost:8080/sayhi
,结果如下:
代码中各注解的含义:
@RestController
: 相当于@Controller
+@ResponseBody
;@Controller
在Spring框架启动时加载.@ResponseBody
表示返回非页面数据.@RequestMapping
: @RequestMapping 是 Spring Web 应⽤程序中最常被用到的注解之⼀,它是⽤来注册接口的路由映射的。
路由映射:所谓的路由映射指的是,当用户访问⼀个 url(地址) 时,将用户的请求对应到程序中某个的某个方法的过程就叫路由映射。
@RequestMapping
的使用:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/Test")//一级路径
@Controller
@ResponseBody
public class TestRequestMapping {
@RequestMapping("/testReqMap")//二级路径
public String doTestMapping(){
return "doTestMapping!";
}
}
@RequestMapping
既可以修饰类也可以修饰方法.当修饰类和方法时,访问的地址是类+方法.
打开PostMan
,当发送GET
请求时:
执行成功!
当发生POST
请求时:
执行成功.
我们可以看到,默认情况下使用注解 @RequestMapping
可以接收 GET
或 POST
请求.
GET
请求的三种写法:
(1)@RequestMapping("/index")
(2)@RequestMapping(value = "/index",method = RequestMethod.GET)
(3)@GetMapping("/index")
POST
请求的三种写法;
(1)@RequestMapping(value = "/index",method = RequestMethod.POST)
(2)@PostMapping("/index")
在 Spring MVC 中可以直接用方法中的参数来实现传参,比如以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Simple Web Page</title>
</head>
<body>
<h1>Welcome to My Simple Web Page</h1>
<p>This is a paragraph of text.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</body>
</html>
将Test.html
文件放置到resources
->static
目录下:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/GetParam")
public class GetParameter {
@RequestMapping("/m1")
public Object method1(String name){
System.out.println("参数 name: "+name);
return "/Test.html";
}
}
在网页中访问:http://localhost:8080/GetParam/m1?name=flower
.可以看到html
写的简易网页:
同时我们在url中赋值name=flower
同时我们可以在控制台中看到:
首先创建一个Student
类:
package com.example.demo.controller;
import lombok.Data;
@Data//组合注解相当于@Getter + @Setter + @ToString
// +@EqualsAndHashCode +@RequiredArgsConstructor +@NoArgsConstructor
public class Student {
private String name;
private int age;
private int id;
}
再运行一下代码:
@RequestMapping("/m2")
public Object method_2(Student s1){
System.out.println("对象中的 name:"+s1.getName());
System.out.println("对象中的 age:"+s1.getAge());
System.out.println("对象中的 id: "+s1.getId());
return "/Test.html";
}
打开网页访问http://localhost:8080/GetParam/m2
,运行结果如下:
同时控制台的信息打印如下:
如果我们在url中加入参数:http://localhost:8080/GetParam/m2?name=huang&age=18&id=1
同时控制台打印信息如下:
如果url为:http://localhost:8080/GetParam/m2?name=huang&id=18&age=1
注意此时参数的顺序变化对控制台打印的信息是没有影响的.当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后端获取参数的结果.
@RequestMapping("/m3")
public Object method_3(String name, String pwd) {
System.out.println("name 参数:" + name);
System.out.println("pwd 参数:" + pwd);
return "/Test.html";
}
使用Postman访问http://localhost:8080/GetParam/m3?name=huang&age=18
访问成功.同时控制台打印信息为:
某些特殊的情况下,前端传递的参数key 和我们后端接收的key可以不一致,比如前端传递了一个time
给后端,而后端又是用createtime
字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用@RequestParam
来重命名前后端的参数值。
@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {
System.out.println("时间:" + createtime);
return "/Test.html";
}
我们可以从控制台看到打印的信息正确,也就是说拿到了time.
但是在Postman
中出现了400
的情况:
查看原码可以看到,@RequestParam
中的required
默认为true
.
required
:必须的意思,默认值为true,因此不传递此参数就会报400的错误。
我们可以修改参数实现非必传参数设置.
修改代码为:
@RequestMapping("/m4")
public Object method_4(@RequestParam(value = "time",required = false) String createtime) {
System.out.println("时间:" + createtime);
return "/Test.html";
}
使用@RequestBody注解可以简化接收JSON数据的过程,提高开发效率,保障安全性,并且支持复杂对象和可扩展性。它是一种常用的处理JSON数据的方式,在前后端分离的开发模式中广泛使用。
后端代码为:
@RequestMapping(value = "/m5", method = RequestMethod.POST)
public Object method_5(@RequestBody Student s1) {
System.out.println("Student:" + s1);
return "redirect:/Test.html";
}
注意此处要使用redirect
.但是在使用JSON格式的POST请求接收对象返回时,通常不会使用重定向。因为重定向主要用于将客户端导航到另一个URL,而在处理POST请求时,我们通常期望在同一个URL下进行数据传递和处理。
控制台中信息打印为:
后端代码:
@PostMapping("/m6/{name}/{password}")
public Object method_6(@PathVariable String name, @PathVariable String password) {
System.out.println("name:" + name);
System.out.println("password:" + password);
return "redirect:/Test.html";
}
使用Postman访问:http://localhost:8080/GetParam/m6/huang/12345
:
注意这种方式通常用于网页搜索时在前面显示的情况.
后端代码:
@RequestMapping("/m7")
public Object upload(@RequestPart("myimg6") MultipartFile file) {
String fileName = UUID.randomUUID() + // 文件名
file.getOriginalFilename().substring( // 文件后缀
file.getOriginalFilename().lastIndexOf("."));
File saveFile = new File("E:\\JavaEE\\upload\\" + fileName);
try {
file.transferTo(saveFile);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
此处使用了UUID
.
UUID (Universally Unique Identifier) 是一种标识符,用于唯一地标识信息、实体或资源。它是一个128位长的数字,在计算机系统中广泛使用。UUID 通常表示为32位十六进制数,由连字符分隔为五组,形如:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,其中每组为8位、4位、4位、4位和12位十六进制数字。
打开Postman
,设置文件myimg6
为longmao.jpg
,发送GET
请求:
打开upload文件可以看到:
注: 文件大小有要求, 那么可以通过Spring官方文档查询默认值, 进而在配置文件中修改默认大小. Common Application Properties
获取 Request
和 Response
对象
后端代码:
@RequestMapping("/param10")
@ResponseBody
public String param10(HttpServletResponse response, HttpServletRequest request) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
return name + " 你好.";
}
@CookieValue获取cookie: 后端代码:
@RequestMapping("/cookie")
@ResponseBody
public String cookie(@CookieValue(value = "bite",required = false) String bite) {
return "cookie:" + bite;
}
访问网页:http://localhost:8080/GetParam/cookie
,设置cookie
@SessionAttribute获取Session: 后端代码:
// 存储 session
@RequestMapping("/setsess")
@ResponseBody
public void setSess(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute(SESSION_KEY, "zhangsan");
}
// 获取 session
@RequestMapping("/getsess")
@ResponseBody
public Object getSession(@SessionAttribute(SESSION_KEY) String name) {
return "session -> " + name;
}
执行:http://localhost:8080/GetParam/setsess
后再执行http://localhost:8080/GetParam/getsess
可以看到:
@RequestHeader获取 Header: 后端代码:
@ResponseBody
@RequestMapping("/gethd")
public Object getHeader(@RequestHeader("Host") String host) {
return "header -> " + host;
}
在代码中执行http://localhost:8080/GetParam/gethd
:
前面我们已经提及到了关于返回静态页面,此处做简单介绍即可:
在resources.static
中创建前端页面Test.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Simple Web Page</title>
</head>
<body>
<h1>Welcome to My Simple Web Page</h1>
<p>This is a paragraph of text.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</body>
</html>
后端代码:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/Test")
public class TestController {
@RequestMapping("/test")
public Object getTest() {
return "/Test.html";
}
}
在浏览器中访问:http://localhost:8080/Test/test
注意代码中的返回路径:
当return
中加了/
之后就代表是从根路径去找Test.html
的.
当不加/
的时候, 它是在/test
底下去找Test.html
的, 即在当前目录底下去找Test.html
的. 显然在上面的URL并找不到, 因为Test.html
是放在根路径下的.
后端代码:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OwnerController {
@RequestMapping("/m7")
public String method_1(){
return "<h1>hi, h1.</h1>";
}
}
通过Fiddler抓包可以看到,返回的是text/html
:
后端代码:
@RequestMapping("/m2")
public HashMap<String, String> method_2(){
HashMap<String, String> map = new HashMap<>();
map.put("C", "C Value");
map.put("Java", "Java Value");
map.put("MySQL", "MySQL Value");
return map;
}
运行可以得到:
通过Fiddler抓包可以看到,返回的是JSON对象
:
// TestController下, 类注解@RequestMapping("/Test")
// 请求转发
@ResponseBody
@RequestMapping("/fw")
public String fw(){
return "forward:/index.html";
}
// 请求重定向
@ResponseBody
@RequestMapping("/rd")
public String rd(){
return "redirect:/index.html";
}
请求转发和请求重定向的直观区别:
请求转发: 当输入localhost:8080/Test/fw
后, URL不变.
请求重定向: 当输入localhost:8080/Test/rd
后, URL变为localhost:8080/Test.html
请求转发(Forward)和请求重定向(Redirect)是在Web应用程序中用于处理请求的两种不同的方式。
请求转发(Forward):
请求重定向(Redirect):
区别:
热部署(Hot Deployment)是指在系统运行过程中,无需停机或重新启动,即可更新和部署软件或应用程序的新版本或修改。 热部署则提供了一种更加灵活和高效的方式来部署软件。通过热部署,新的代码、配置文件或资源可以在系统运行时被动态加载,而无需重启整个应用程序。这样可以减少系统停机时间,避免用户的中断,提高系统的可用性和稳定性。 热部署技术通常与现代的应用程序框架和容器化技术结合使用,如Java中的热代码替换(Hot Code Replacement)和Spring Boot的热部署功能。通过热部署,开发人员可以快速地进行代码调试、功能添加或修复,并且不会对正在运行的系统产生较大的影响。
pom.xml
中引入依赖: <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
Settings
中勾选Settings->Advanced Settings
中选择:
热部署启动成功: