跳到主要内容
Spring Boot Web 三大核心交互实战:表单、AJAX 与 JSON | 极客日志
Java 大前端 java
Spring Boot Web 三大核心交互实战:表单、AJAX 与 JSON Spring Boot Web 交互涵盖表单提交、AJAX 登录及 JSON 数据交换三种模式。通过求和计算器、用户登录系统及留言板三个实战案例,详解了 @RestController、@RequestBody、Session 状态管理及前后端参数绑定的核心用法。对比不同联调模式的优缺点,帮助开发者掌握前后端协作的关键技巧与常见陷阱。
Spring Boot Web 三大核心交互实战
理解后端接口编写和前端页面交互是掌握 Spring Boot 的关键。本文将通过三个经典案例——表单提交、AJAX 登录与状态管理、以及 JSON 数据交互 ,带你梳理前后端联调的核心技巧。
1. 案例一:表单提交与参数绑定(计算求和)
这是最基础的传统 Web 交互方式,利用 HTML 表单直接提交数据。
1.1 后端代码:CalcController.java
使用 @RestController 简化接口,方法参数自动接收表单数据。
package cn.overthinker.springboot;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/calc")
@RestController
public class CalcController {
@RequestMapping("/sum")
public String sum (Integer num1, Integer num2) {
if (num1 == null || num2 == null ) {
return "请求非法:请输入两个数字!" ;
}
return "计算结果为:" + (num1 + num2);
}
}
1.2 前端代码:calc.html
界面简洁,表单直接指向后端接口。
📋 HTML 代码
<!DOCTYPE html >
<html lang = >
简单求和计算器
简单求和计算器
数字 1:
数字 2:
"en"
<head >
<meta charset ="UTF-8" >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<title >
</title >
<style >
body { font-family : sans-serif; background-color : #f4f7f6 ; display : flex; justify-content : center; align-items : center; min-height : 100vh ; margin : 0 ; }
.calculator-container { background-color : #ffffff ; padding : 40px ; border-radius : 12px ; box-shadow : 0 6px 20px rgba (0 , 0 , 0 , 0.1 ); width : 300px ; text-align : center; }
h1 { color : #333 ; margin-bottom : 30px ; font-size : 24px ; border-bottom : 2px solid #5cb85c ; display : inline-block; padding-bottom : 5px ; }
input [type="text" ] { width : 100% ; padding : 10px ; margin-bottom : 10px ; border : 1px solid #ccc ; border-radius : 6px ; box-sizing : border-box; }
input [type="submit" ] { background-color : #5cb85c ; color : white; padding : 12px 20px ; border : none; border-radius : 6px ; cursor : pointer; font-size : 16px ; margin-top : 20px ; width : 100% ; transition : background-color 0.3s ease; }
input [type="submit" ] :hover { background-color : #4cae4c ; }
</style >
</head >
<body >
<div class ="calculator-container" >
<h1 >
</h1 >
<form action ="/calc/sum" method ="post" >
<input name ="num1" type ="text" placeholder ="请输入数字 1" >
<br >
<input name ="num2" type ="text" placeholder ="请输入数字 2" >
<br >
<input type ="submit" value ="点击相加" >
</form >
</div >
</body >
</html >
1.3 联调重点解析:参数绑定
前端 Form 的 name 属性 :前端 <input name="num1"> 中的 name 必须与后端方法的参数名 Integer num1完全一致 。这是 Spring MVC 参数绑定的基础。
后端自动类型转换 :Spring Boot 会自动将 HTTP 请求中的字符串参数转换为 Java 方法所需的 Integer 类型,无需手动解析。
2. 案例二:AJAX 异步交互与 Session 状态管理(用户登录) 本案例引入 AJAX 实现无刷新登录,并利用 Session 在服务器端保存用户状态。
2.1 后端代码:UserController.java
UserController.java (核心逻辑)package cn.overthinker.springboot;
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 {
@PostMapping("/login")
public boolean login (String userName, String password, HttpSession session) {
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
return false ;
}
if ("admin" .equals(userName) && "123456" .equals(password)) {
session.setAttribute("loginUser" , userName);
return true ;
}
return false ;
}
@GetMapping("/getLoginUser")
public String getLoginUser (HttpServletRequest request) {
HttpSession session = request.getSession(false );
if (session != null ) {
String loginUser = (String) session.getAttribute("loginUser" );
return loginUser;
}
return "" ;
}
}
2.2 前端代码:login.html 和 index.html 使用 jQuery AJAX 进行异步登录,用户体验更流畅。
login.html (登录页面)
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 用户登录</title >
<style >
body { font-family : sans-serif; background-color : #e8eff1 ; display : flex; justify-content : center; align-items : center; min-height : 100vh ; margin : 0 ; }
.login-box { background-color : #fff ; padding : 40px ; border-radius : 8px ; box-shadow : 0 4px 15px rgba (0 , 0 , 0 , 0.1 ); width : 280px ; text-align : center; }
h1 { color : #3c8dbc ; margin-bottom : 25px ; }
input [type="text" ] , input [type="password" ] { width : 100% ; padding : 10px ; margin-bottom : 15px ; border : 1px solid #ccc ; border-radius : 4px ; box-sizing : border-box; }
input [type="button" ] { background-color : #3c8dbc ; color : white; padding : 10px 15px ; border : none; border-radius : 4px ; cursor : pointer; font-size : 16px ; width : 100% ; transition : background-color 0.3s ; }
input [type="button" ] :hover { background-color : #367fa9 ; }
</style >
</head >
<body >
<div class ="login-box" >
<h1 > 用户登录</h1 >
用户名:<input name ="userName" type ="text" id ="userName" placeholder ="请输入用户名" > <br >
密码:<input name ="password" type ="password" id ="password" placeholder ="请输入密码" > <br >
<input type ="button" value ="登录" onclick ="login()" > </div >
<script src ="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js" > </script >
<script >
function login ( ) {
$.ajax ({
url : "/user/login" ,
type : "post" ,
data : {
userName : $("#userName" ).val (),
password : $("#password" ).val ()
},
success : function (result ) {
if (result) {
location.href = "/index.html" ;
} else {
alert ("用户名或密码错误" );
}
}
});
}
</script >
</body >
</html >
index.html (首页 - 获取登录信息)<!doctype html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 用户登录首页</title >
<style >
body { font-family : sans-serif; background-color : #f0f4f7 ; padding : 50px ; }
.welcome { font-size : 24px ; color : #333 ; }
#loginUser { color : #d9534f ; font-weight : bold; }
</style >
</head >
<body >
<div class ="welcome" > 欢迎回来,登录人:<span id ="loginUser" > </span > </div >
<script src ="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js" > </script >
<script >
$.ajax ({
url : "user/getLoginUser" ,
type : "get" ,
success : function (userName ) {
$("#loginUser" ).text (userName || "(未登录)" );
}
});
</script >
</body >
</html >
2.3 联调重点解析:AJAX 与 Session
AJAX (Asynchronous JavaScript and XML) :允许前端在不刷新页面的情况下,与后端进行数据交换。在 login.html 中,我们使用 jQuery 的 $.ajax 实现异步请求,体验更丝滑。
Session 机制 :Session 是服务器端用来存储用户状态信息的机制。
当用户登录成功后,session.setAttribute("loginUser", userName); 在服务器上创建或关联一个 Session,并存入数据。
浏览器通过 Cookie 自动携带一个 Session ID 给服务器。
在 index.html 请求 /user/getLoginUser 时,服务器通过浏览器传来的 Session ID 找到对应的 Session,从而取出存储的 loginUser 信息,实现了状态保持。
3. 案例三:JSON 数据传输与 RESTful 接口(留言板) 现代 Web 开发最常用的方式:前后端通过 JSON 格式进行数据交互,后端使用 RESTful 风格 的接口。
3.1 后端代码:MessageController.java 和 MessageInfo.java
MessageController.java (核心逻辑)package cn.overthinker.springboot;
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 {
private 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;
}
}
MessageInfo.java (数据传输对象 DTO)使用 Lombok 的 @Data 注解自动生成 Getter/Setter。
package cn.overthinker.springboot;
import lombok.Data;
@Data
public class MessageInfo {
private String from;
private String to;
private String message;
}
3.2 前端代码:message.html
📋 HTML 代码 <!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 留言板</title >
<style >
body { font-family : sans-serif; background-color : #f0f7f4 ; padding : 20px ; }
.container { width : 400px ; margin : 20px auto; background-color : #fff ; padding : 25px ; border-radius : 10px ; box-shadow : 0 4px 10px rgba (0 , 0 , 0 , 0.08 ); text-align : center; }
h1 { color : #387063 ; margin-bottom : 5px ; }
.grey { color : #888 ; margin-bottom : 20px ; }
.row { display : flex; justify-content : space-between; align-items : center; height : 40px ; margin-bottom : 10px ; }
.row span { width : 70px ; text-align : left; color : #555 ; font-weight : bold; }
.row input { flex-grow : 1 ; height : 35px ; padding : 5px 10px ; border : 1px solid #ddd ; border-radius : 4px ; }
#submit { width : 100% ; height : 45px ; background-color : #387063 ; color : white; border : none; border-radius : 5px ; margin-top : 20px ; font-size : 18px ; cursor : pointer; transition : background-color 0.3s ; }
#submit :hover { background-color : #2b574d ; }
.message-list div { text-align : left; padding : 8px 0 ; border-bottom : 1px dashed #eee ; color : #333 ; }
</style >
</head >
<body >
<div class ="container" >
<h1 > 留言板</h1 >
<p class ="grey" > 输入后点击提交,信息将显示在下方</p >
<div class ="row" > <span > 谁:</span > <input type ="text" id ="from" placeholder ="你的名字" > </div >
<div class ="row" > <span > 对谁:</span > <input type ="text" id ="to" placeholder ="你想对谁说" > </div >
<div class ="row" > <span > 说什么:</span > <input type ="text" id ="say" placeholder ="你的留言内容" > </div >
<input type ="button" value ="提交留言" id ="submit" onclick ="submit()" >
<div class ="message-list" > </div >
</div >
<script src ="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js" > </script >
<script >
function loadMessages ( ) {
$.ajax ({
type : "get" ,
url : "/Message/getList" ,
success : function (messages ) {
$(".message-list" ).empty ();
for (let msg of messages) {
let divE = "<div>" + msg.from + " 对 " + msg.to + " 说:" + msg.message + "</div>" ;
$(".message-list" ).append (divE);
}
}
});
}
loadMessages ();
function submit ( ) {
var from = $('#from' ).val ();
var to = $('#to' ).val ();
var say = $('#say' ).val ();
if (from == '' || to == '' || say == '' ) {
return ;
}
$.ajax ({
type : "post" ,
url : ,
: ,
: . ({
: ,
: to,
: say
}),
: ( ) {
(result) {
();
$( ). ( );
$( ). ( );
$( ). ( );
} {
( );
}
}
});
}
</script >
</body >
</html >
3.3 联调重点解析:@RequestBody 与 JSON
@RequestBody :这是 Spring Boot 接收 JSON 数据的关键注解。它告诉 Spring MVC:请将 HTTP 请求体(Request Body)中的 JSON 字符串解析,并自动映射到方法参数 MessageInfo messageInfo 对象中。
前端 contentType: "application/json" :前端必须设置此头信息,告诉服务器发送的是 JSON 格式数据,否则 Spring 可能无法正确反序列化。
前端 JSON.stringify(...) :JavaScript 的内置方法,用于将一个 JS 对象(如 {from: 'A', to: 'B', message: 'Hello'})转换为后端能够识别的 JSON 字符串。
JSON 字段匹配 :前端 JSON 中的键(Key)必须与后端 DTO (MessageInfo) 中的属性名(Field Name)保持一致(例如:message 对应 private String message;),大小写敏感。
4. 总结:前后端联调模式对比 联调模式 案例 核心机制 后端注解/参数接收 优点 缺点 Form 表单提交 求和计算器 浏览器直接跳转/刷新页面 方法参数名匹配 简单、无需 JavaScript 用户体验差、无法精细控制 AJAX (Query String) 登录系统 (GET/POST) 异步通信(无刷新) 方法参数名匹配 用户体验好、可局部更新 仅适用于少量简单数据 AJAX (JSON) 留言板 异步通信(无刷新) @RequestBody 接收 DTO传输复杂结构数据、最常用 需要配置 Content-Type 和 JSON.stringify
掌握这三种交互模式,基本能覆盖大部分常规 Web 开发场景。在实际项目中,根据业务复杂度灵活选择即可。
"/Message/publish"
contentType
"application/json"
data
JSON
stringify
from
from
to
message
success
function
result
if
loadMessages
'#from'
val
""
'#to'
val
""
'#say'
val
""
else
alert
"添加留言失败,请检查输入"
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online