前后端交互避坑指南:从登录到留言板
大家好,很多新手小白在学习JavaSpringMVC的时候十分吃力,特别是在学习前后端如何交互的时候,如何传递参数?如何接收参数?明明知识点都会,但是为什么会一直报错呢?下面是我在学习过程中遇见的一些问题,为了帮助大家更好学习,我将通过登录案例+留言板案例讲知识点串通起来,文章末尾附全代码,希望能够帮助到大家!
目录
1.登录案例
1.1判断输入是否正确并存储信息
1.2返回信息
1.3前端代码
2.留言板(重点)
总结易错
登录案例代码
留言板代码
1.登录案例
接口一:判断输入的信息是否有效正确,正确还需存储用户信息
请求方式:get
参数:用户姓名,用户密码
参数类型:String
返回类型:Boolean
接口二:信息正确,返回登录信息,信息错误,告知用户
请求方式:get
返回值:用户姓名
返回类型:String
1.1判断输入是否正确并存储信息
我们先从后端开始写,根据接口文档描述,我们要从客户端的请求中拿到登录用户的姓名和输入的密码,判断这两个是否有效并且判断两者输入是否正确,由于本文重点是讲解前后端交互过程,所有我们暂时将用户姓名和密码定为“admin”,后续再讲解如何从数据库中获取数据
@RestController @RequestMapping("/login") public class Controller { //判断 @RequestMapping("/r1") public Boolean loginJudge(String userName, String password, HttpSession session){ if(!StringUtils.hasLength(userName)||!StringUtils.hasLength(password)){ return false; } if("admin".equals(userName)||"admin".equals(password)){ return false; } //利用Session存储用户信息 session.setAttribute("userName",userName); return true; } }注意事项:
1.如果是使用@Controller注解,还需要添加@RequestBody。因为前端向后端传递的参数是String类型
2.StringUtils.hasLength(userName)相当于userName!=null&&userName.length!=0,可互换
3."admin".equals(userName)判断用户输入的是否正确,String判断相等使用equals方法,建议把常数写在前面,因为前面若是null会报异常,而无法确定输入的userName是否是null
4.Session可以存储用户信息,并保存到服务器结束运行,所以可以将用户信息存入Session中,想了解更多Session知识可移步--->Session
1.2返回信息
接口一返回到前端后,前端会根据后端返回的来判断来选择是要告知用户输入错误还是返回正确的信息,如果是显示正确的信息,那需要发送请求给后端拿存储在Session中的有效信息
@RequestMapping("/r2") public String getName(HttpSession session) { String name = session.getAttribute("userName").toString(); return name; }注意事项:
1.获取存储在Session中的信息,使用getAttribute方法,参数要和前面设置的key名一样
2.session.getAttribute("userName")的返回类型为Object类,要将其转化为String,使用toString。
1.3前端代码
用户在浏览器页面输入信息点击提交后,要把用户输入的信息传递给后端,让后端来判断是否正确,所以在点击提交之后,前端需要写请求将数据发送给后端,下面我们将使用ajax来写(这部分对于走后端的同学可以不要求掌握,看懂即可)
<!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="js/jquery-4.0.0.min.js"></script> <script> function login() { $.ajax({ type: "post", url: "login/r1", data: { userName: $("#userName").val(), password: $("#password").val() }, success: function (resule) { if (resule) { location.assign("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:"post", url:"login/r2", success: function (userName){ $("#loginUser").text(userName); } }); </script> </body> </html>注意事项:
1.前端向后端发送请求的时候,如果需要传输数据data,传递的参数名要和发送给的后端的方法参数名一致,除非使用@RequestParam
2.请求中的url要和后端的方法路径相对应,一般是类路径/方法路径
2.留言板(重点)
接口一:获取全部留言信息,存储在List中,可以用JSON来描述这个List数据.
接口二:发表新留言
请求: body 也为 JSON 格式
使用工具:lombok
新建List存放留言,在刷新后发送给前端,展示在留言板上
public List<Message> list=new ArrayList<>(); @RequestMapping("/r1") public List<Message> getMessage(){ return list; }用户输入留言点击提交后,前端负责把留言发送给后端,后端收到请求,要先判断留言是否合规,合规再把留言存储在lsit中,在返回true,如果不合规,返回false
@RequestMapping(value = "/r2",produces = "application/json") public Boolean judge( @RequestBody Message message){//参数绑定 if(!StringUtils.hasLength(message.getFrom())||!StringUtils.hasLength(message.getMessage())||!StringUtils.hasLength(message.getTo())){ return false; } list.add(message); return true; }注意:
1.produces = "application/json"表示后端返回响应的数据格式为json,如果不加,前端不能拿到对象,而是字符串,要手动调用JSON.parse()把格式转换成对象
2.前端传递过来的json要用注解@RequestBody 绑定给message对象,spring会自动把json转换为对象方便使用
前端代码(body部分)
<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="js/jquery-4.0.0.min.js"></script> <script> load(); function load(){ //刷洗的时候就要获取list $.ajax({ type : "get", url : "message/r1", success : function (result){ if(result!=null&&result.length()>0){ for(var message of result){ var divE = "<div>"+message.from +"对" + message.to + "说:" + message.message+"</div>"; //3. 把节点添加到页面上 $(".container").append(divE); } } } }); } function submit(){ //1. 获取留言的内容 var from = $('#from').val(); var to = $('#to').val(); var say = $('#say').val(); if (from== '' || to == '' || say == '') { return; }$.ajax({ type: "post", url:"message/r2", contentType : "application/json", data : JSON.stringify({ from :from, to: to, message:say }), success : function (result){ if(!result){ alert("留言失败!"); }else { //2. 构造节点 var divE = "<div>"+from +"对" + to + "说:" + say+"</div>"; //3. 把节点添加到页面上 $(".container").append(divE); //4. 清空输入框的值 $('#from').val(""); $('#to').val(""); $('#say').val(""); } } }); } </script> </body>这段代码的核心是:
每次刷新的时候前端都会使用ajax发送请求给后端,目的是拿到存储在后端之前保存下来的留言,这样刷新之后依旧可以看到留言
用户输入留言点击提交后,前端调用submit方法
function submit(){ //1. 获取留言的内容 var from = $('#from').val(); var to = $('#to').val(); var say = $('#say').val(); if (from== '' || to == '' || say == '') { return; }$.ajax({ type: "post", url:"message/r2", contentType : "application/json", data : JSON.stringify({ from :from, to: to, message:say }), success : function (result){ if(!result){ alert("留言失败!"); }else { //2. 构造节点 var divE = "<div>"+from +"对" + to + "说:" + say+"</div>"; //3. 把节点添加到页面上 $(".container").append(divE); //4. 清空输入框的值 $('#from').val(""); $('#to').val(""); $('#say').val(""); } } }); }创建变量获得input框的值,发送请求给后端,根据返回的result判断留言是否成功,成功就把节点添加到页面上并清楚留言框里的值,如果留言失败,就跳出弹框告知失败
总结易错
1.拼写不要错误,比如请求中的数据类型是contentType,不要写成content-type
2.前端向后端传递的数据类型是JSON的时候,后端要用@RequestBody进行参数绑定,如果没有@RequestBody,String无法找到数据,同时,前端传递json给后端,Jackson会自动调用json转换成对象,后端可以直接当做对象使用
3.请求类型是get的时候,不能传递json,get请求没有请求体(body),不能传输复杂数据,如果get要传输数据,只能在查询字符串中输入,参数类型是json时,要使用post传递
| Get | Post | |
| 数据位置 | 查询字符串中 | 请求体(Body) |
| 数据格式 | ?key1=value1&&key2=value2 | JSON\XML\复杂格式均可 |
| 数据大小 | url限制大小 | 无限制大小 |
| 安全性 | 内容暴露在url中 | 相对安全,但若未加密仍可通过抓包获得 |
| 缓存 | 可以被浏览器缓存 | 默认不被缓存 |
| 语义 | 获取数据(查询数据) | 发送数据(提交数据) |
浏览器 服务端 | | | | | | 这是get请求,没有请求体,服务器等待请求体,等不到,报异常 |------发送Get请求------ | | | | | |------发送Post请求------| 这是Post请求,有请求体,服务器解析请求体拿到数据| 后端传递类型 | 前端拿到的初始状态 | 前端操作 |
| application/json(较多使用) | 自动转成对象 | 可以进行xx.操作之间取值 |
| text/plain | 字符串 | 要手动转成json对象才能取值 |
将contentType定义成application/json常出现在返回字符串的时候。告诉前端把这个字符串按json处理,如果不定义,那在传的时候前端可能会当成普通字符串,就需要前端自己手动调用JSON.parse()把字符串转成对象
前端向后端发送json和js对象的区别(重点)
| JS对象(常用) | JSON | |
| 实际输出内容 | JSON字符串 | JSON字符串 |
| 前端代码怎么写 | {name="zhangsan"} | {"name"="zhangsan"} |
| 是否需要手动序列化 | 不需要 | 需要调用JSON.Stringify() |
| 后端收到 | json | json |
后端向前端发送json和js的区别
| 对象(常用) | JSON | |
| 实际输出内容 | JSON | JSON |
| 后端代码怎么写 | return 对象; | return " {\"name":\"zhangsan\"}"; |
| 是否需要手动序列化 | 不用,spring自己调用 | 需要程序员手动拼写字符串 |
| 前端拿到 | js对象 | js对象 |
后端如果发送的是对象,在传输过程中一定是会进行序列化转成字符串,到前端后,在进行反序列化,变成js对象使用
总结:前端后端传递对象比较多,但是无论是前端还是后端,在网络运输的过程中,对象都会序列化成json,json相当于是通用的语音,到达之后再将json反序列化成对象取值,如果后端传递的是字符串(长得像json而不是普通文本,如“操作成功”这些没必要转),建议修改contentType为"application/json"告诉前端把这个字符串当成json处理,让它自动转成对象
附代码
登录案例代码
package com.by.demo; import ch.qos.logback.core.util.StringUtil; import jakarta.servlet.http.HttpSession; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * Created with IntelliJ IDEA. * Description: * User: Administrator * Date: 2026-08-01 * Time: 21:21 */ @RequestMapping("/login") @RestController public class loginController { //两个接口,一个是判断登录信息是否正确,一个是向前端传递登录用户姓名 @RequestMapping("/judge") public Boolean judgeLoginMessage(String userName, String password, HttpSession session){ if(StringUtils.hasLength(userName)&&StringUtils.hasLength(password)){ if("admin".equals(userName)&&"admin".equals(password)){ //把用户信息存储到会话中,方便返回用户姓名 session.setAttribute("userName",userName); return true; }else { return false; } }else { return false; } } @RequestMapping("/getuserName") public String getUserName(HttpSession session){ //从会话中得到userName,要把userName存储到会话中 return session.getAttribute("userName").toString(); } }<!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="js/jquery-4.0.0.min.js"></script> <script> function login() { $.ajax({ type: "post", url: "login/judge", data: { userName: $("#userName").val(), password: $("#password").val() }, success: function (resule) { if (resule) { location.assign("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:"post", url:"login/getuserName", success: function (userName){ $("#loginUser").text(userName); } }); </script> </body> </html>留言板代码
package com.by.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; /** * Created with IntelliJ IDEA. * Description: * User: Administrator * Date: 2026-08-02 * Time: 11:06 */ @RequestMapping("/message") @RestController public class MessageController { public List<Message> list=new ArrayList<>(); @RequestMapping("/r1") public List<Message> getMessage(){ return list; } @RequestMapping(value = "/r2",produces = "application/json") public Boolean judge( @RequestBody Message message){//参数绑定 if(!StringUtils.hasLength(message.getFrom())||!StringUtils.hasLength(message.getMessage())||!StringUtils.hasLength(message.getTo())){ return false; } list.add(message); return true; } }<!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="js/jquery-4.0.0.min.js"></script> <script> load(); function load(){ //刷洗的时候就要获取list $.ajax({ type : "get", url : "message/r1", success : function (result){ if(result!=null&&result.length()>0){ for(var message of result){ var divE = "<div>"+message.from +"对" + message.to + "说:" + message.message+"</div>"; //3. 把节点添加到页面上 $(".container").append(divE); } } } }); } function submit(){ //1. 获取留言的内容 var from = $('#from').val(); var to = $('#to').val(); var say = $('#say').val(); if (from== '' || to == '' || say == '') { return; }$.ajax({ type: "post", url:"message/r2", contentType : "application/json", data : JSON.stringify({ from :from, to: to, message:say }), success : function (result){ if(!result){ alert("留言失败!"); }else { //2. 构造节点 var divE = "<div>"+from +"对" + to + "说:" + say+"</div>"; //3. 把节点添加到页面上 $(".container").append(divE); //4. 清空输入框的值 $('#from').val(""); $('#to').val(""); $('#say').val(""); } } }); } </script> </body> </html>以上均属个人学习心得,如有错误请多多指教!
