


专栏:JavaEE 进阶跃迁营
个人主页:手握风云
目录
[1.1. 准备工作](#1.1. 准备工作)
[1.2. 约定前后端交互接口](#1.2. 约定前后端交互接口)
[1. 概念介绍](#1. 概念介绍)
[2. 需求分析](#2. 需求分析)
[3. 接口分析](#3. 接口分析)
[1.3. 服务器代码](#1.3. 服务器代码)
[2.1. 准备工作](#2.1. 准备工作)
[2.2. 约定前后端交互接口](#2.2. 约定前后端交互接口)
[1. 校验接口](#1. 校验接口)
[2. 查询登录用户接口](#2. 查询登录用户接口)
[2.3. 服务器代码](#2.3. 服务器代码)
[3.1. 准备工作](#3.1. 准备工作)
[3.2. 约定前后端交互接口](#3.2. 约定前后端交互接口)
[1. 需求分析](#1. 需求分析)
[2. 接口定义](#2. 接口定义)
[3.3. Lombok 介绍](#3.3. Lombok 介绍)
[3.4. 服务器后端代码](#3.4. 服务器后端代码)
一、加法计算器
1.1. 准备工作
创建SpringBoot项目:引入Spring Web依赖,把前端页面放在项目中。
html
<!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>


1.2. 约定前后端交互接口
1. 概念介绍
"约定前后端交互接口" 是 Web 开发(尤其是前后端分离模式下)的关键环节,这里的 "接口"(又称 API,即 Application Programming Interface)并非 JavaSE 阶段所学的 "类与接口",而是应用程序对外提供服务的描述,本质是前后端之间遵循的 "应用层协议",用于规范客户端(前端)与服务器(后端)之间的信息交换和任务执行规则。简单来说,它明确了客户端可以给服务器发送哪些 HTTP 请求,以及每种请求预期能获取到什么样的 HTTP 响应 ------ 比如客户端发起请求时应使用的路径、请求方式(GET/POST 等)、携带的参数(参数名、类型、是否必传),以及服务器返回响应时的数据格式(如 text/html、application/json)、内容结构等。
在前后端分离的开发模式中,前端与后端代码通常由不同团队负责,为避免开发过程中的混乱和对接矛盾,双方会在开发前提前约定交互接口:一般由服务提供方(后端)编写接口文档,明确上述交互细节,交由服务使用方(前端)确认。接口文档类似应用程序的 "操作说明书"。
接口文档一旦确定,需尽量保持稳定,避免随意变更;若因业务需求必须调整,需及时通知对方团队,确保前后端开发节奏一致。这种约定的核心价值在于降低前后端团队的沟通成本,明确各自开发边界,让双方可基于统一标准并行开发,最终保证前后端对接时能顺畅协作,减少因交互规则不明确导致的返工问题。
2. 需求分析
加法计算器功能,对两个整数进行相加,需要客户端提供参与计算的两个数,服务端返回这两个整数计算的结果。
3. 接口分析
html
请求路径:calc/sum
请求方式:GET/POST
接口描述:计算两个整数相加
请求参数:
|------|---------|------|-----------|
| 参数名 | 类型 | 是否必须 | 备注 |
| num1 | Integer | 是 | 参与计算的第一个数 |
| num2 | Integer | 是 | 参与计算的第二个数 |
1.3. 服务器代码
java
package com.yang.test1_19_5;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/calc")
@RestController
public class CalController {
@RequestMapping("/sum")
public String sum(Integer num1, Integer num2) {
if (num1 == null || num2 == null) {
return "输入的数据不合法";
}
Integer sum = num1 + num2;
return "计算结果:" + sum;
}
}


二、用户登录
2.1. 准备工作
创建SpringBoot项目:引入Spring Web依赖,把前端页面放在项目中。
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>
</script>
</body>
</html>
html
<!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() {
}
</script>
</body>
</html>
2.2. 约定前后端交互接口
用户登录接口:验证用户名和密码是否正确,并返回给前端。首页:告知前端当前登录用户.如果当前已有用户登录,返回登录的账号,如果没有,返回空。
1. 校验接口
请求路径:/user/login
请求方式:POST
接口描述:校验账号密码是否正确
|----------|--------|------|-------|
| 参数名 | 类型 | 是否必须 | 备注 |
| userName | String | 是 | 校验的账号 |
| passWord | String | 是 | 校验的密码 |
Content-Type: text/html
响应内容:
true //账号密码验证成功
false //账号密码验证失败
2. 查询登录用户接口
请求路径: /user/getLoginUser
请求方式: GET
接口描述: 查询当前登录的用户
Content-Type: text/html
响应内容:
zhangsan
2.3. 服务器代码
java
package com.yang.test1_20_1;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/user")
@RestController
public class UserController {
/**
* 校验用户名和密码是否正确
* @param userName 用户名
* @param password 密码
* @return 正确为 true,错误为 false
*/
@PostMapping("/login")
public Boolean login(String userName, String password, HttpSession session) {
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return false;
}
// 在开发规范中,代码嵌套最好不要超过5层
// 使用 equals 方法时,常量尽量写前面
if ("Bruce".equals(userName) && "12345".equals(password)) {
// 存储 Session
session.setAttribute("loginUser", userName);
return true;
}
return false;
}
@GetMapping("/getLoginUser")
public String getLoginUser(HttpServletRequest request) {
// 参数为 false,获取的 session 为 null 时,不会创建 session
HttpSession session = request.getSession();
if (session != null) {
String loginUser = (String) session.getAttribute("loginUser");
return loginUser;
}
return "";
}
}

三、留言板
3.1. 准备工作
html
<!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(){
//1. 获取留言的内容
var from = $('#from').val();
var to = $('#to').val();
var say = $('#say').val();
if (from== '' || to == '' || say == '') {
return;
}
//2. 构造节点
var divE = "<div>"+from +"对" + to + "说:" + say+"</div>";
//3. 把节点添加到页面上
$(".container").append(divE);
//4. 清空输入框的值
$('#from').val("");
$('#to').val("");
$('#say').val("");
}
</script>
</body>
</html>
3.2. 约定前后端交互接口
1. 需求分析
后端需要提供两个服务:用户输入留言信息之后,后端需要把留言信息保存起来;页面展示时,需要从后端获取到所有的留言信息。
2. 接口定义
获取全部留言信息,可以用 List 表示,可以用 JSON 来描述这个 List 信息。
html
GET /message/getList
html
[
{
"from":"黑猫",
"to":"白猫",
"message":"喵"
}
]
当发表新留言时,响应格式也是 JSON 数据。
html
POST message/publish
html
{
"from":"黑猫"
"to":"白猫"
"message":"喵"
}
html
{
"OK":1
}
3.3. Lombok 介绍
当我们在进行面向对象编程的时候,IDEA 可以帮我们生成带参数的构造方法、Get/Set 方法等。但是如果我们想要添加其他参数时,修改这些方法就会很不方便。而 Lombok 通过注解在编译时自动生成 Getters、Setters、构造函数、toString 等代码。
Lombok 的工作原理是,当编译器(javac)开始把你的 .java 源码翻译成 .class 字节码时,它会先把代码解析成一种树状结构。Lombok 利用 Java 提供的注解处理器机制,在这个翻译过程中"插队"。它扫描到你写的 @Getter 或 @Data 等注解后,就会直接修改这棵树,把原本不存在的 get、set 方法强行"种"进去。
我们要想使用 Lombok 的这些功能,需要现在 pom.xml 里面引入依赖,同时安装插件 Lombok。
XML
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>compile</scope>
</dependency>

| 注解 | 作用 |
|---|---|
@Getter |
自动添加 getter 方法 |
@Setter |
自动添加 setter 方法 |
@ToString |
自动添加 toString 方法 |
@EqualsAndHashCode |
自动添加 equals 和 hashCode 方法 |
@NoArgsConstructor |
自动添加无参构造方法 |
@AllArgsConstructor |
自动添加全属性构造方法,顺序按照属性的定义顺序 |
@NonNull |
标记属性不能为 null |
@RequiredArgsConstructor |
自动添加必需属性的构造方法,final + @NonNull 的属性为必需 |
3.4. 服务器后端代码
java
package com.yang.test1_21_1;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RequestMapping("/message")
@RestController
public class MessageController {
List<MessageInfo> messageInfoList = new ArrayList<>();
@PostMapping("/publish")
public Boolean publish(@RequestBody MessageInfo messageInfo) {
if (!StringUtils.hasLength(messageInfo.getFrom())
|| !StringUtils.hasLength(messageInfo.getTo())
|| !StringUtils.hasLength(messageInfo.getMessage())) {
return false;
}
messageInfoList.add(messageInfo);
return true;
}
@GetMapping("/getList")
public List<MessageInfo> getList() {
return messageInfoList;
}
}

