页面如下:
需求:
1、输入留言信息,点击提交。后端把数据存储起来。
2、页面展示输入的表白墙信息。
3、网页刷新后,原本在网页上的内容不会消失
一、准备工作
把前端页面放在项目中,如图:
前端页面代码:
<!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>
二、约定前后端交互接口
1、需求分析
后端需要提供两个服务:
(1)发布留言:用户输入完留言信息后,服务器要把留言信息保存起来。
(2)获取留言:页面展示,需要从后端获取到所有的留言信息。
2、接口定义
(1)发布留言
url:/message/publish
param(参数):from,to,say
return:true / false(成功或失败)
(2)获取留言
url:/message/getList
param:无
返回结果:[{from1, to1, say1}, {from2, to2, say2}, {from3, to3, say3}.....]
三、实现服务器代码
1、lombok介绍
我们创建一个对象,写一些属性,然后有获取和设置这些属性的值的方法,代码如下:
public class MessageInfo { private Integer id; private String from; private String to; public Integer getId() {return id;} public void setId(Integer id) {this.id = id;} public String getFrom() {return from;} public void setFrom(String from) {this.from = from;} public String getTo() {return to;} public void setTo(String to) {this.to = to;} }
我们发现,这些get和set方法是有规律的,有很多重复性的操作,那么我们能不能把它们进行封装呢?让代码更简洁呢?肯定是可以的,这里就可以使用到 lombok工具包,在创建项目的时候,我就勾选了 lombok工具包,如图:
(1)引入依赖
因为勾选了,所以pom.xml文件会自动给我引入依赖,如图:
如果没有勾选,可以手动添加依赖,填入下列代码:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
(2)使用lombok
lombok是通过一些注解的方式,帮助我们消除一些冗长的代码,使代码看起来更简洁,例如上面的 MessageInfo对象,可以写成下面这种形式:
import lombok.Data; @Data public class MessageInfo { private Integer id; private String from; private String to; }
(3)原理解释
@Data注解 会帮助我们自动生成一些方法,包含getter/setter,equals,toString等。启动项目后,生成target文件,里面会有MessageInfo对象,get和set方法都有,如图
上面就是加了@Data注解之后,IDEA反编译的class文件。
注意:
上面这些代码不是真正的字节码文件,而是IDEA根据字节码进行反编译后的文件。
反编译是将可执行的程序代码转换为某种形式的高级编程语言,使其具有更易读的格式。反编译是一种逆向工程,它的作用与编译器的作用相反。
上面是我们执行了Spring项目,才生成的 MessageInfo.class文件,可以看出lombok是一款在编译期间生成代码的工具包。
java的运行原理:
lombok的作用如下图所示:
(4)更多使用
如果决定@Data比较暴力(生成的方法太多),lombok也提供了一些更精细粒度的注解,如下表:
注解 | 作用 |
@Getter | 自动添加getter方法 |
@Setter | 自动添加setter方法 |
@ToString | 自动添加toString方法 |
@EqualsAndHashCode | 自动添加equals和hashCode方法 |
@NoArgsConstructor | 自动添加无参构造方法 |
@AllArgsConstructor | 自动添加全属性构造方法,顺序按照属性的定义顺序 |
@NonNull | 属性不能为null |
@RequiredArgsConstructor | 自动添加必须属性的构造方法,final+@NonNull的属性为必须 |
@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor
2、更快捷的引入依赖
上述引入lombok依赖,需要去找lombok的坐标,接下来介绍更简单引入依赖的方式:EditStarter。安装EditStarter,重启IDEA,如图:
在pom.xml文件中,单击右键,选择Generate,操作如下图:
然后回进入Edit Starters的编辑页面,添加对应依赖即可,如图:
注意:不是所有依赖都可以在这里添加的,这个界面和SpringBoot创建项目界面一样;不在这里的依赖,还需要去Maven仓库查找坐标,添加依赖。
3、服务器代码实现
@RestController @RequestMapping("/message") public class MessageController { List<MessageInfo> messageInfos = new ArrayList<>(); /** * 发布留言 */ @RequestMapping("/publish") public Boolean publish(MessageInfo messageInfo) { //参数校验 if(!StringUtils.hasLength(messageInfo.getFrom()) || !StringUtils.hasLength(messageInfo.getTo()) || !StringUtils.hasLength(messageInfo.getSay())) { return false; } //存留言 messageInfos.add(messageInfo); return true; } /** * 获取留言 */ @RequestMapping("/getList") public List<MessageInfo> getList() { return messageInfos; } }
初学阶段,先把留言存到内存中,后面再引入数据库。
四、调整前端页面代码
<!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> $.ajax({ url: "/message/getList", type: "get", success: function (messageInfos) { var finalHtml = ""; for (var message of messageInfos) { finalHtml += '<div>' + message.from + ' 对 ' + message.to + ' 说: ' + message.say + '</div>'; } $(".container").append(finalHtml); } }); function submit() { //1. 获取留言的内容 var from = $('#from').val(); var to = $('#to').val(); var say = $('#say').val(); //参数校验 if (from == '' || to == '' || say == '') { return; } //发送ajax请求 $.ajax({ url: "/message/publish", type: "post", data: { //不好理解 // from: from, // to: to, // say: say from: $('#from').val(), to: $('#to').val(), say:$('#say').val() }, success: function (result) { if (result) { //2. 构造节点 var divE = "<div>" + from + "对" + to + "说:" + say + "</div>"; //3. 把节点添加到页面上 $(".container").append(divE); //4. 清空输入框的值 $('#from').val(""); $('#to').val(""); $('#say').val(""); } else{ alert("输入不合法"); } } }); } </script> </body> </html>
主要逻辑在JS代码里,两个ajax请求,一个点击提交按钮,获取留言板写的信息并把信息放在页面上;一个是拿到服务器所有的留言信息,放在页面上。
五、运行测试
输入内容,点击提交,如图:
刷新页面,原话内容信息也还在,如图:
因为此时的数据存储在服务器的内存中,如果重启服务器,再点击刷新,上面的信息就会消失了。如图:
六、遇到问题的解决方法
出现问题后,先定位,看是前端还是后端的问题。
后端:使用Postman测试,如果Postman测试能通过,后续出现问题的话,90%以上可以排除后端问题,另外10%是通过Postman的测试错了。
如果后端出现问题,解决方案:
1、打日志(System.out.print),Debug。看下请求是否进入到后端程序了。
2、继续使用Postman测试。
3、考虑缓存问题。
前端出现问题
1、打日志,抓包。
2、考虑缓存问题。