Spring Web MVC 是基于 Servlet API构建的原始 Web 框架,从一开始就包含在Spring框架中。它的正式名称“SpringWebMVC”来自其源模块的名称(Spring-webmvc),但它通常被称为"SpringMVC". Spring Web MVC 是⼀个 Web 框架.

MVC 角色 | 类比餐厅里的谁? | 负责干啥? |
|---|---|---|
View(视图) | 「菜单 + 餐桌」 | 给用户看的 “界面”(菜单让你点菜、餐桌让你放盘子) |
Controller(控制器) | 「服务员」 | 接收用户需求,安排后厨做菜、给你上菜 |
Model(模型) | 「后厨 + 食材」 | 处理具体业务(切菜、炒菜),操作数据(食材) |
浏览器(用户) | 「你(顾客)」 | 发起请求(点菜、催菜) |
① 你(浏览器)发起请求 → 喊 “服务员!我要点菜!”
② 服务员(Controller)接需求 → “好的,我去安排后厨做!”
③ 后厨(Model)做菜 → “宫保鸡丁做好啦!”
④ 服务员(Controller)选 “上菜方式” → “用啥盘子装?端哪张桌?”
⑤ 你(浏览器)看到菜 → “开吃!”
假设做一个 “用户登录” 功能,对应 MVC 流程:
login.html),有用户名、密码输入框 → 对应 “菜单”。
LoginController.java,接收用户提交的账号密码 → 对应 “服务员”。
UserService.java,判断账号密码是否正确(查数据库、验证逻辑) → 对应 “后厨”。
流程:
LoginController(Controller)收到请求 → 调用 UserService(Model)验证账号密码。
UserService(Model)查数据库,返回 “验证结果”(对 / 错)。
LoginController(Controller)根据结果,选 “登录成功页” 或 “错误提示页”(View)。
Web框架,当用户在浏览器中输入了url之后,Spring MVC项目就可以感知到用户的请求并给予响应
重点学习如何通过浏览器和用户程序进行交互
主要分为以下三个方面:
注册接口的路由映射,表示服务器收到请求时.路径为/sayHi的请求就会调用sayHi这个方法的代码
路由映射:当用户访问一个URL时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射
@Restcontroller在此处的作用:一个项目中会有很多的类,每个类下可能会有很多的方法,Spring会对所有的类进行扫描.如果类加了注解@Restcontroller才会去看这个类里面的方法有没有加@RequestMapping这个注解
@RestController用来声明标记这是一个"外卖窗口",重点检查里面的窗口
@RequestMapping指定"窗口"接收的订单类型
方法的返回值就是给顾客的餐食
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/sayHi")
public String sayHi(){
return "hello,Spring";
}
}
@RequestMapping既可修饰类也可修饰方法,当修饰类和方法时,访问的地址是类路径+方法路径
标识一个类:设置映射请求的请求路径的初始信息
标识一个方法:设置映射请求请求路径的具体信息
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/sayHi")
public String sayHi() {
return "Hello World";
}
}
类路径+方法路径:类上的 @RequestMapping("/user") 是 前缀,方法上的@RequestMapping("/sayHi") 是 子路径,最终完整路径是 /user/sayHi。
均支持

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/user/sayHi" method="post">
<input type="submit" value="提交">
</form>
</body>
</html>
指定Get/Post方法类型
@RestController
public class UserController {
@RequestMapping(value = "/sayHello",method = RequestMethod.Get)
public String sayHello() {
return "Hello World";
}
}
//另一种写法
@GetMapping("/sayHaha")
public String sayHaha(){
return "Haha";
}此时前端代码为post方法,当点击提交按钮后就会显示失败

通过查询字符串来传参,查询字符串就是请求的参数

@RequestMapping("/v1")
public String v1(String name,int age){
return "v1接收到参数"+name + ","+age;
}
(完整表示为: multipart/form-data)
表单提交的数据,在 form标签中加上enctyped="multipart/form-data",
通常用于提交图片/文件.对应Content-Type:multipart/form-data

form表单,对应Content-Type:application/x-www-form-urlencoded

可以上传任意格式的文本,可以上传text、json、xml、html等

访问不同的路径,就是发送不同的请求.在发送请求时,可能会带⼀些参数,所以学习Spring的请求,主要 是学习如何传递参数到后端以及后端如何接收.
传递参数,咱们主要是使用浏览器和Postman来模拟.
Postman/浏览器模拟传参,后端接收参数
当age的类型为int时,当不传递该参数时发起请求就会出现500的错误,当类型为Integer时不传递age默认就是null
注:key:value本质上都是字符串类型
@RequestMapping("/v1")
//传参时顺序不分先后,key:value对应即可
public String v1(String name,Integer age){
return "v1接收到参数"+name + ","+age;
}
//底层代码
@RequestMapping("/v2")
public String v2(HttpServletRequest request){
String name = request.getParameter("name");
//把传入的 String 类型参数转换为 Integer 类型的对象
Integer age = Integer.valueOf(request.getParameter("age"));
return "接收到参数,name:"+name+",age:"+age;
}
注:使用基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误 类型不匹配时,会报400错误.
当传递多个参数时可以封装成对象
@RequestMapping("/v3")
public String v3(User user){
return "User" +user;
}public class User {
private String name;
private int age;
private Integer gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}import lombok.Data;
@Data
public class User {
private String name;
private int age;
private Integer gender;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
}
此处对象中的的age为成员变量默认值为0

某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不一致,比如前端传递了一个
name给后端,而后端是使用UserName字段来接收的,这样就会出现参数接收不到的情况,如果出现
这种情况,我们就可以使用@RequestParam来重命名前后端的参数值.
此处的前端变量名为name(注解中的为前端变量名)后端名为userName
@RequestMapping("/v4")
public Object v4(@RequestParam("name") String userName){
return "接收到参数name:" + name;
}
@RequestMapping("/v4")
public Object v4(@RequestParam String UserName){ // 前后端变量名一致
return "接收到参数UserName:" + UserName;
}

//参数绑定默认是必传参数 required为true
@RequestMapping("/v6")
public String v6(@RequestParam(value="name",required = false) String userName){
return "接收到参数name:" + userName;
}
为什么前后端变量名要重命名,这里的注解不还是要知道前后端的变量名是什么,为什么不用统一的变量名?
UserName)
name)
@RequestParam 注解进行映射,实现了解耦
@RequestMapping("/v7")
public String v7(String[] arr){
return Arrays.toString(arr);
//List.of(arr)
}
//此时不传值就为null
@RequestMapping("/v8")
public String v8(@RequestParam (value = "arr",required = false) String[] arr){
return Arrays.toString(arr);
}
List是接口,需要用具体的类实现
集合类必须加注解,即便实现了接口类也必须加
//错误写法
public String v9(List<String> list)
//错误写法
public String v9(ArrayList<String> list)
@RequestMapping("/v9")
//正确写法一
public String v9(@RequestParam ArrayList<String> list){
return "size:"+list.size() + ",listParam:"+list;
}
//正确写法二
@RequestMapping("/v10")
public String v10(@RequestParam List<String> listParam){
return "size:"+listParam.size() + ",listParam:"+listParam;
}为什么必须加 @RequestParam?
list 是请求体或路径变量,但实际是查询参数 → 无法匹配。
@RequestParam 后: Spring 明确知道要从查询参数中找 list,并自动收集多个同名参数到 ArrayList。
Json语法
JSON的两种结构
接收JSON对象,需要使用 @RequestBody 注解
RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须在写在请求正文中
@RequestMapping("/v11")
public String v11(@RequestBody User user){
return "user:" + user;
}

Path variable为路径变量,该注解主要作用在请求URL路径上的数据绑定,默认传递参数写在URL上,SpringMVC就可以获取到
此时的路径是写死的,必须进行填值
@RequestMapping("/v12/{id}/{name}")
public String v12(@PathVariable Integer id, @PathVariable("name") String userName){
return "id:"+id+",name:"+userName;
}
如果方法参数名称和需要绑定的URL中的变量名一致时,可以简写,不用给@PathVariable的属性赋值,如上述中的id
如果方法参数名称和需要绑定的URL中的变量名称不一致时,需要@PathVariable的属性value赋值,如上述例子中的userName
@RequestMapping("/v13")
public String v13(MultipartFile file){
System.out.println(file.getOriginalFilename());
return "文件名称:"+file.getOriginalFilename();
}
//重命名
@RequestMapping("/v13")
public String v13(@RequestPart("fileName") MultipartFile file){
System.out.println(file.getOriginalFilename());
return "文件名称:"+file.getOriginalFilename();
}
在文件路径中,D:/JavaCode/ 和 D:/JavaCode 的区别主要在于 是否以路径分隔符(/)结尾
@RequestMapping("/v14")
public String v14(@RequestPart("fileName") MultipartFile file) throws IOException {
// 1. 获取上传文件的原始名称(包含扩展名)
String fileName = file.getOriginalFilename();
// 2. 将文件保存到指定路径(D:/JavaCode/目录下)
file.transferTo(new File("D:/JavaCode/" + file.getOriginalFilename()));
// 3. 打印文件名(用于调试)
System.out.println(file.getOriginalFilename());
// 4. 返回包含文件名的响应
return "文件名称:"+fileName;
}
HTTP自身是属于"无状态协议"
无状态:默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信没有直接的联系
在实际开发中,我们很多时候是需要知道请求之间的关联关系的;例如登陆网站后第二次访问服务器的时候服务器就能知道该求情是否已经登录过了

上述图中的"令牌"通常就存储在Cookie字段中
此时在服务器这边就需要记录"令牌"信息,以及令牌对应的用户信息,这个就是Session机制所做的工作
在计算机领域,会话是一个客户与服务器之间的不中断的请求响应,对客户的每个请求,服务器能够识别出请求来自于同一个客户,当一个未知的客户向Web应用程序发送第一个请求时就开始了一个会话,当客户明确结束会话或服务器在一个时限内没有接受客户的任何请求时,会话就结束了
服务器同一时刻收到的请求是很多的,服务器需要清楚的区分每个请求是属于哪个用户,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与用户的信息的对应关系。
Session是服务器为了保存用户信息而创建的一个特殊的对象.

Session的本质就是一个"哈希表",存储了一些键值对结构.Key就是SessionID,Value就是用户信息(用
户信息可以根据需求灵活设计).

Sessionld是由服务器生成的一个"唯一性字符串",从Session机制的角度来看,这个唯一性字符串称为"Sessionld".但是站在整个登录流程中看待,也可以把这个唯一性字符串称为"token".
上述例子中的令牌ID,就可以看做是SessionId,只不过令牌除了ID之外,还会带一些其他信息,比如时间,签名等.


Cookie和Session的区别
@ResponseBody注解,则直接返回字符串 "success" 作为响应体
key、值为value的 Cookie 对象
HttpServletResponse将 Cookie 添加到响应头
@ResponseBody
@RequestMapping("setCookie")
public String setCookie(HttpServletResponse response){
Cookie cookies = new Cookie("key","value");
response.addCookie(cookies);
return "success";
}
@RequestMapping("/getCookie")
public String getCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println(cookie.getName() + ":" + cookie.getValue());
}
}
return "获取Cookie成功";
}
@RequestMapping("/getCookie1")
public String getCookie1(HttpServletRequest request)
{
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
//打印Cookie信息
StringBuilder builder = new StringBuilder();
if (cookies!=null){
for (Cookie ck:cookies) {
builder.append(ck.getName()+":"+ck.getValue());
}
}
return "Cookie信息:"+builder;
}需要提前手动添加/设置Cookie才能获取到

@CookieValue("Jack"):从请求的 Cookie 中查找名称为 Jack 的 Cookie
name
name:cookie值)
@RequestMapping("/getCookie2")
public String getCookie3(@CookieValue("Jack") String name){
return "name:"+name;
}
设置Cookie是通过HttpServletResponse将 Cookie 添加到响应头
获取Cookie是通过HttpServletRequest将 Cookie 获取到请求头
Set-Cookie响应头发送 Cookie 给客户端,客户端存储 Cookie(内存或硬盘)。
Cookie请求头将 Cookie 回传给服务器。
操作 | 方向 | 使用的 HTTP 头 | Java API |
|---|---|---|---|
设置 Cookie | 服务器 → 客户端 | Set-Cookie(响应头) | response.addCookie(cookie) |
获取 Cookie | 客户端 → 服务器 | Cookie(请求头) | request.getCookies() |


Session是服务器的机制,我们需要先存储才能再获取
Session也是基于HttpServerRequest来存储和获取的
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("userName","Jack");
session.setAttribute("age",18);
return "设置session成功";
}① request.getSession() 的工作机制
HttpSession 对象,并生成一个唯一的 Session ID(类似 “图书馆分配借阅卡号”)。 Session ID 会通过响应头的 Set-Cookie 字段发送给客户端,客户端将其存储在浏览器的 Cookie 中。
request.getSession(false)则表示不会创建新的对象
② setAttribute() 存储的数据类型
setAttribute() 的第二个参数是 Object 类型,因此可以存储任意 Java 对象(如 String、Integer、自定义对象等)。
age 时需转为 Integer)。
这个代码中看不到SessionId这样的概念,getSession操作内部提取到请求中的Cookie里的SessionId,然后根据Session获取到对应的Session对象,Session对象用HttpSession来描述


//方式一
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request) {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("userName");
Object age = session.getAttribute("age");
return "从session中获取信息,userName:" + username + ", age:" + age;
}
//方式二
@RequestMapping("/getSession2")
public String getSession2(HttpSession session) {
String username = (String) session.getAttribute("userName");
Integer age = (Integer) session.getAttribute("age");
// 设置默认值,避免 null
if (age == null) age = 0;
return "从session中获取信息,userName:" + username + ", age:" + age;
}
//方式三
@RequestMapping("/getSession3")
public String getSession3(
@SessionAttribute(value = "userName", required = false) String userName,
@SessionAttribute(value = "age", required = false) Integer age
) {
// 设置默认值,避免 null
if (age == null) age = 0;
return "从session中获取信息,userName:" + userName + ", age:" + age;
}

HttpSession getSession(boolean create);
HttpSession getSession(); JSESSIONID 关联。
JSESSIONID 实现 “客户端 - 服务器” 的会话关联,既安全又能维持用户状态 。
操作 | 方向 | 使用的 HTTP 头 | Java API 关键用法 |
|---|---|---|---|
设置 Session 数据 | 服务器内部操作(基于 Session 关联) | 依托 Set-Cookie(响应头传递 JSESSIONID ) | HttpSession session = request.getSession(); session.setAttribute("key", "value"); |
获取 Session 数据 | 服务器内部根据关联 Session 读取 | 依托 Cookie(请求头携带 JSESSIONID ) | HttpSession session = request.getSession(false); if(session != null) { Object value = session.getAttribute("key"); } |
Session 关联标识传递(JSESSIONID) | 服务器 ↔ 客户端(建立 / 维持关联) | Set-Cookie(响应头,设置 JSESSIONID )、 Cookie(请求头,携带 JSESSIONID ) | 服务器设置:由 request.getSession() 触发,自动通过 Set-Cookie 响应头下发 JSESSIONID ; 客户端携带:浏览器自动把 JSESSIONID 放入请求头 Cookie ,服务器通过 request.getCookies() 间接拿到 JSESSIONID 关联 Session |


以下是 Java Web 开发中请求对象(HttpServletRequest)、会话对象(HttpSession)、响应对象(HttpServletResponse) 的核心区别总结:
对象 | 核心作用 |
|---|---|
HttpServletRequest | 封装 客户端→服务器 的请求数据(如 URL 参数、请求头、Cookie、请求体),是请求数据的 “输入载体”。 |
HttpSession | 存储 用户会话周期 的状态数据(如登录信息、购物车),跨请求共享,依赖 Cookie(JSESSIONID)或 URL 重写维持会话。 |
HttpServletResponse | 封装 服务器→客户端 的响应数据(如响应头、Cookie、响应体),是响应数据的 “输出载体”。 |
对象 | 创建时机 | 销毁时机 | 作用域 |
|---|---|---|---|
HttpServletRequest | 每次请求到达服务器时由容器创建 | 请求处理完毕后销毁 | 单次请求(仅本次请求有效) |
HttpSession | 首次调用 request.getSession() 时创建 | 超时(默认 30 分钟)、手动调用 invalidate() 或浏览器关闭(会话 Cookie 失效) | 会话周期(跨请求、跨页面) |
HttpServletResponse | 每次响应时由容器创建 | 响应发送给客户端后销毁 | 单次响应(仅本次响应有效) |
对象 | 关键 API | 典型场景 |
|---|---|---|
HttpServletRequest | getParameter("name"):获取 URL 参数 getHeader("User-Agent"):获取请求头 getCookies():获取客户端 Cookie getInputStream()/getReader():获取请求体 | - 登录接口获取表单参数 - 解析请求头中的 Token - 文件上传时读取请求体 |
HttpSession | setAttribute("key", value):存数据 getAttribute("key"):取数据 getId():获取 Session ID invalidate():销毁 Session | - 存储用户登录状态(如 userId) - 记录购物车数据 - 实现验证码校验 |
HttpServletResponse | setHeader("Content-Type", "application/json"):设置响应头 addCookie(cookie):添加 Cookie getWriter().write("data"):输出响应体 sendRedirect("/login"):重定向 | - 设置响应格式(JSON/HTML) - 登录成功后写入 Session ID 到 Cookie - 文件下载时设置 Content-Disposition |
HttpSession 需通过 request.getSession() 获取,依赖请求中的 Cookie(JSESSIONID)或 URL 参数关联会话。
response.addCookie() 将 JSESSIONID 写入客户端 Cookie,后续请求才能携带 JSESSIONID 关联到对应 Session。
三者共同构成 Java Web 请求 - 响应循环的核心组件。
@RequestMapping("getHeader")
public String getHeader(HttpServletRequest request){
String userAgent = request.getHeader("User-Agent");
return "userAgent:" + userAgent;
}
@RequestMapping("getHeader2")
public String getHeader2(@RequestHeader("User-Agent") String userAgent){
return "userAgent:" + userAgent;
}
在我们前面的代码例子中,都已经设置了响应数据,Http响应结果可以是数据,也可以是静态页面,也可以针对响应设置状态码,Header信息等.
@Controller
public class IndexController {
@RequestMapping("/index")
public String index() {
return "/index.html";
}
}
@RestController和@Controller有着什么样的关联和区别呢? 公式含义:@RestController=@Controller+@ResponseBody
@Controller: 标记这是一个 Spring MVC 控制器,告诉 Spring “这个类里有处理 HTTP 请求的方法”。
@ResponseBody: 让控制器方法的返回值直接转为 JSON/XML 等格式,写入 HTTP 响应体(Response Body),而不是跳转视图。
@RestController 同时具备两个注解的功能 → 既标记是控制器,又让所有方法返回数据(而非视图)。
不加 @ResponseBody 会怎样?
如果只用 @Controller,方法返回值默认是 视图名称(比如 return "index" 会跳转 index.html)。
加上 @ResponseBody(或用 @RestController),返回值会被 序列化为 JSON(或其他格式),直接给前端当数据
@RestController/@Controller + @ResponseBody返回数据
@Controller返回视图
@ResponseBody
@RequestMapping("/index1")
public String index1() {
return "/index.html";
}@ResponseBody 既是类注解,又是方法注解 如果作用在类上,表示该类的所有方法,返回的都是数据,如果作用在方法上,表示该方法返回的是数据.
@Controller
public class IndexController {
@RequestMapping("/index")
public Object index(){
return "/index.html";
}
@RequestMapping("/returnData")
public String returnData(){
return "该⽅法返回数据";
}
}程序会认为需要返回的是视图,根据内容去查找⽂件,但是查询不到,路径不存在,报404

@RequestMapping("/returnHtml")
@ResponseBody
public String returnHtml() {
return "<h1>Hello,HTML~</h1>";
}
响应中的Content-Type常见取值有以下几种:
如果请求的是js文件,SpringMVC会自动设置Content-Type为 application/javascript
如果请求的是css文件,SpringMVC会自动设置Content-Type为 text/css
@RequestMapping("/index2")
public Object index2(){
return "/a.js";
}
@RequestMapping("/index3")
public Object index3(){
return "/b.css";
} @RequestMapping("/returnJson")
@ResponseBody
public HashMap<String,String> returnJson(){
HashMap<String,String> map = new HashMap<>();
map.put("Java","Java Value");
map.put("Spring","Spring Value");
return map;
}
通过Fiddler观察响应结果, Content-Type 为application/json

SpringMVC会根据我们方法的返回结果自动设置响应状态码,程序员也可以手动指定状态码 通过SpringMVC的内置对象HttpServletResponse提供的方法来进行设置
@RequestMapping("/setStatus")
@ResponseBody
public String setStatus(HttpServletResponse response) {
response.setStatus(200);
return "设置状态码成功";
}
Http响应报头也会向客户端传递⼀些附加信息,比如服务程序的名称,请求的资源已移动到新地址等,如: Content-Type,Local等. 这些信息通过 @RequestMapping 注解的属性来实现
反斜杠 \ 是转义字符,用来处理字符串里的特殊字符(比如双引号 ")
@ResponseBody
@RequestMapping(value = "/setHeader",produces = "application/json")
public String setHeader(){
return "{\"success\":true}";
}
@ResponseBody
@RequestMapping(value = "/setHeader1",produces = "application/json")
public Map<String, Boolean> setHeader1(){
HashMap<String,Boolean> map = new HashMap<>();
map.put("sucess",true);
return map;
}

设置其他Header的话,需要使用SpringMVC的内置对象HttpServletResponse提供的方法来进行设置
@ResponseBody
@RequestMapping("setHeader2")
public String setHeader2(HttpServletResponse response){
response.setStatus(500);
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type","text/html;charset=utf-8");
return "设置Header成功";
}
需求:输入两个整数,点击"相加按钮",显示计算结果

需求分析:
加法计算器功能,对两个整数进行相加,需要客户端提供参与计算的两个数,服务端返回这两个整数计算
的结果
接口定义:
请求路径:calc/sum
请求方式:GET/POST
接口描述:计算两个整数相加
请求参数:
参数名 | 类型 | 是否必须 | 备注 |
|---|---|---|---|
num1 | Integer | 是 | 参与计算的第一个数 |
num2 | Integer | 是 | 参与计算的第二个数 |
响应数据:
示例:num1=5 num2=3
Content-Type:text/html
响应内容:计算机计算结果:8package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/calc")
public class CalcController {
@RequestMapping("/sum")
public String sum(@RequestParam("num1") Integer num1,@RequestParam("num2") Integer num2){
Integer sum = num1 + num2;
return "计算机计算结果" + sum;
}
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="calc/sum" method="post">
<h1>计算器</h1>
数字1:<input name="num1" type="text"><br>
数字2:<input name="num2" type="text"><br>
<input type="submit" value=" 点击相加 ">
</form>
</body>
</html>前端输入num1和num2,将两个参数传到后端进行相加计算后返回sum

需求分析:
对于后端开发人员而言,不涉及前端页面的展示,只需要提供两个功能
1.登录页面:通过账号和密码,校验输入的账号密码是否正确,并告知前端
2.首页:告知前端当前登录用户,如果当前已有用户登录,返回登录的账号,如果没有,返回空
接口定义:
校验接口
/user/login
请求方式:POST
接口描述:校验账号密码是否正确 请求参数:
参数名 | 类型 | 是否必须 | 备注 |
|---|---|---|---|
userName | String | 是 | 校验的账号 |
password | String | 是 | 校验的密码 |
响应数据:
Content-Type: text/html
响应内容:
true //账号密码验证成功
false//账号密码验证失败 2查询登陆用户接口
请求路径:/user/getLoginUser
请求方式:GET
接口描述:查询当前登录的用户 请求参数:无
响应数据:
Content-Type: text/html
响应内容: admin package com.example.demo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class LoginController {
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Boolean login(String userName, String password, HttpServletRequest request) {
if(!StringUtils.hasLength(userName) && !StringUtils.hasLength(password)){
return false;
}
//校验前端传来的账号密码是否正确,客户端向服务器发请求为request
if("admin".equals(userName) && "123456".equals(password)){
//设置session
HttpSession session = request.getSession(true);
session.setAttribute("userName", userName);
return true;
}
return false;
}
@RequestMapping("getLoginUser")
public Object getLoginUser(HttpSession session){
if(session.getAttribute("userName") != null){
return session.getAttribute("userName");
}
return null;
}
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h1>用户登录</h1>
用户名:<input name="userName" type="text" id="userName"><br>
密码:<input name="password" type="password" id="password"><br>
<input type="button" value="登录" onclick="login()">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
function login() {
$.ajax({
type: "post",
url: "/user/login",
data: {
"userName": $("#userName").val(),
"password": $("#password").val()
},
success: function (result) {
if (result) {
location.href = "/index.html"
} else {
alert("账号或密码有误.");
}
}
});
}
</script>
</body>
</html><!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>用户登录首页</title>
</head>
<body>
登录人: <span id="loginUser"></span>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$.ajax({
type: "get",
url: "/user/getLoginUser",
success: function (result) {
$("#loginUser").text(result);
}
});
</script>
</body>
</html>
需求:

需求分析
后端需要提供两个服务
接口定义
请求
GET /message/getList 响应:Json格式
[
{
"from": "⿊猫",
"to": "⽩猫",
"message": "喵"
},{
"from": "⿊狗",
"to": "⽩狗",
"message": "汪" },
//... ] 浏览器给服务器发送一个GET/message/getList这样的请求,就能返回当前一共有哪些留言
记录.结果以json的格式返回过来.
请求:body也为JSON格式
POST /message/publish
{
"from": "⿊猫",
"to": "⽩猫",
"message": "喵"
} 响应JSON格式
{
ok: 1
} 我们期望浏览器给服务器发送一个POST/message/publish这样的请求,就能把当前的留言提
交给服务器。
package com.example.demo;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/message")
public class MessageController {
//获取全部留言信息
private List<MessageInfo> messageInfos = new ArrayList<>();
@RequestMapping("/getList")
public List<MessageInfo> getList(){
return messageInfos;
}
@RequestMapping(value = "/publish",produces = "application/json")
public String publish(@RequestBody MessageInfo messageInfo){
System.out.println(messageInfo);
if(StringUtils.hasLength(messageInfo.getFrom())
&&StringUtils.hasLength(messageInfo.getTo())
&&StringUtils.hasLength(messageInfo.getMessage())){
messageInfos.add(messageInfo);
System.out.println(messageInfo);
return "{\"ok\":1}";
}
return "{ \"ok\":0}";
}
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>留言板</title>
<style>
.container {
width: 350px;
height: 300px;
margin: 0 auto; /*水平方向居中*/
/* border: 1px black solid; */
text-align: center;
}
.grey {
color: grey;
}
.container .row {
width: 350px;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
}
.container .row input {
width: 260px;
height: 30px;
}
#submit {
width: 350px;
height: 40px;
background-color: orange;
color: white;
border: none;
margin: 10px;
border-radius: 5px;
font-size: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>留言板</h1>
<p class="grey">输入后点击提交, 会将信息显示下方空白处</p>
<div class="row">
<span>谁:</span> <input type="text" name="" id="from">
</div>
<div class="row">
<span>对谁:</span> <input type="text" name="" id="to">
</div>
<div class="row">
<span>说什么:</span> <input type="text" name="" id="say">
</div>
<input type="button" value="提交" id="submit" onclick="submit()">
<!-- <div>A 对 B 说: hello</div> -->
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
function submit(){
let from = $("#from").val();
let to = $("#to").val();
let say = $("#say").val();
if(from=="" || to == "" || say == ""){
alert("请检查输入内容");
return;
}
let html = "<div>"+ from +" 对 "+ to +" 说: "+say+"</div>";
$(".container").append(html);
$(":text").val("");
}
</script>
</body>
</html>