使用Servlet实现表白墙网站(前后端互联)小项目,Mac的M1(没有setting)在哪里找到Setting页面,下载smart tomcat及smart tomcat的配置。
引言
首先我认为,最清楚的就是了解了前后端进行的初步作用,前端是布置画面,制作用户的交互,后端相当于,保存你的每一步操作,每一步进行的操作,历史搜索记录,保存一些数据,以及和前端相互连接,当然这个也是针对这个小项目,要是更大的则也需要更加细化。
目录
一、准备工作?
(一)引入依赖
pom.xml,提前下载好的依赖(假如说你是第一次下载会耗费点时间。)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>messageWall</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
</dependencies>
</project>
(二)
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
(三)静态页面(html,css)需要放到webapp目录下面(不是WEB-INF)
(四)下载SMART-TOMCAT
这个是mac系统下的setting,假如是windows就可以直接点击file->setting,其余操作一致
下载成功会,对smart-tomcat进行配置,点击那个add,然后先找到下载的smart-TOMCAT
第一个是tomcat的路径需要选择好。其余的可以不动,我改的一个context path 是java,那么后续请求,要和这个路径一致
二、编写后端代码?
此处的表白墙页面,可以输入内容,点击提交后,也可以显示内容
所以此处后端需要的工作,主要就两个内容
1.用户点击提交的时候,把刚才输入的内容通过网络传输给服务器,由服务器来保存这个数据
2.后续有页面加载的时候,此时通过网络,从服务器获取到之前保存好的内容
需要进行前后端交互接口的约定,约定好,前端会给后端发一个什么样子的http请求,后端又回返回一个什么样的http响应
1.针对存档操作来说
前端发起一个HTTP请求
POST/messageWall/message->这里的路径怎么约定都可以,但是务必保证前后端一致
此处约定使用json格式,把数据传输到后端,前后端数据交互的时候,格式具体什么样子,随意约定。(实际上,json确实是当下最流行的一种方式)
{
from:"黑猫"
to:"白猫“
message"喵"}
服务器返回一个HTTP响应
HTTP/1.1 200 ok
2.针对读档操作(前端页面加载的时候,需要从服务器拿到之前已经提交的数据)
请求:
GET/messageWall/message
响应:
HTTP/1.1 200 ok
(响应的json应该是数组,使用[]表示,返回的数据会有多条)
[{
from:"黑猫"
to:"白猫"
message:"喵"
}
{
from:"白猫"
to:"黑猫"
message:"喵"
}
]
编写servlet的时候,每次修改代码,都要记得重新启动服务器(修改java代码,必然要重启,需要重新编译),修改前端代码建议也需要重启,这些静态页面可能会被tomcat给提前加载并缓存在内存中,此时修改代码,不一定会同步到内存里。
通过抓包可以确定是前端问题,还是后端的问题
如果抓包发现,ajax的http请求没发出来,大概率前端问题,假如是前端的代码问题,我们就更应该关注浏览器JS调试,可以使用F12,苹果就是点击开发,显示JS控制台
如果发现ajax的http请求发送了,内容符合要求,那么就是后端的问题
import com.fasterxml.jackson.databind.ObjectMapper; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; class Message{ public String from; public String to; public String message; @Override public String toString() { return "Message{" + "from='" + from + ''' + ", to='" + to + ''' + ", message='" + message + ''' + '}'; } } @WebServlet("/message") public class MessageServlet extends HttpServlet { //首先要把一个json转化为java对象 private ObjectMapper objectMapper=new ObjectMapper(); //此处把消息保存到内存中(一旦重启服务器,内存数据就会消失了。更科学的做法,应该是保存到数据库里面) private List<Message> messageList=new ArrayList<>(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.需要能够读取请求body,转换成java对象 Message message=objectMapper.readValue(req.getInputStream(),Message.class); //2.得到message之后,需要把message保存到服务器中 messageList.add(message); System.out.println("服务器收到message:"+message.toString()); //3.返回响应,(其实没啥大必要,主要是返回一个200ok就行,body可以没有) resp.setStatus(200); //设置成功状态码,会更加清晰 resp.getWriter().write("ok"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.把内存中的这些Message,组织成json格式,返回到响应中 String respJson=objectMapper.writeValueAsString(messageList); //这个代码十分关键,告诉浏览器,返回的响应的body是json格式(utf8编码) resp.setContentType("application/json; charset=utf8"); resp.getWriter().write(respJson); // 2.针对List/数组这种,jackon会自动把数据整理成json数组,里面每个对象,又会被jsckon转换成{}json对象(json对象属性名字,也是和Message类的成员名字对应的) } }
三、编写前端代码 ?
这里面的get和POST方法,和后端的相互对应,前端发出post,后端去接收,并且,在服务器的日志上显示,前端的GET,被后端进行的保存,只要服务器没有关闭,就会一致保存你的记录(前端编写的就是说,让记录保存在页面上,你下次打开页面(但是服务器未关闭的情况下),就会出现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表白墙</title>
<style>
/* * 通配符选择器, 是选中页面所有元素 */
* {
/* 消除浏览器的默认样式. */
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 600px;
margin: 20px auto;
}
h1 {
text-align: center;
}
p {
text-align: center;
color: #666;
margin: 20px 0;
}
.row {
/* 开启弹性布局 */
display: flex;
height: 40px;
/* 水平方向居中 */
justify-content: center;
/* 垂直方向居中 */
align-items: center;
}
.row span {
width: 80px;
}
.row input {
width: 200px;
height: 30px;
}
.row button {
width: 280px;
height: 30px;
color: white;
background-color: orange;
/* 去掉边框 */
border: none;
border-radius: 5px;
}
/* 点击的时候有个反馈 */
.row button:active {
background-color: grey;
}
</style>
</head>
<body>
<div class="container">
<h1>表白墙</h1>
<p>输入内容后点击提交, 信息会显示到下方表格中</p>
<div class="row">
<span>谁: </span>
<input type="text">
</div>
<div class="row">
<span>对谁: </span>
<input type="text">
</div>
<div class="row">
<span>说: </span>
<input type="text">
</div>
<div class="row">
<button id="submit">提交</button>
</div>
<!-- <div class="row">
xxx 对 xx 说 xxxx
</div> -->
</div>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script>
// 实现提交操作. 点击提交按钮, 就能够把用户输入的内容提交到页面上显示.
// 点击的时候, 获取到三个输入框中的文本内容
// 创建一个新的 div.row 把内容构造到这个 div 中即可.
let containerDiv = document.querySelector('.container');
let inputs = document.querySelectorAll('input');
let button = document.querySelector('#submit');
button.onclick = function() {
// 1. 获取到三个输入框的内容
let from = inputs[0].value;
let to = inputs[1].value;
let msg = inputs[2].value;
if (from == '' || to == '' || msg == '') {
return;
}
// 2. 构造新 div
let rowDiv = document.createElement('div');
rowDiv.className = 'row message';
rowDiv.innerHTML = from + ' 对 ' + to + ' 说: ' + msg;
containerDiv.appendChild(rowDiv);
// 3. 清空之前的输入框内容
for (let input of inputs) {
input.value = '';
}
// 4. 把用户输入的数据, 构造出 HTTP 请求, 发送给服务器.
let body = {
//后三个变量是三个输入框的内容,前面的是字符串,后面的是变量名字
from: from,
to: to,
message: msg
};
//1.ajax会根据输入的参数构造出http请求,发给服务器
//2.服务器会执行对应的doPost方法
$.ajax({
type: 'post',
//url;'message'这个和下面写法相同,只不过是相对路径还是绝对路径,相对路径的基准路径,就是html所在路径,写了相对路径message,相当于在message基础上,再加一层/messageWall/message
// url: '',/Users/lcl/messageWall/src/main/java/MessageServlet.java
url: 'message',
contentType: 'application/json; charset=utf-8',
//js,中对象虽然和json非常相似,但是仍然是两个不同的东西,js标准库,提供了JSON.stringify方法,把js对象转换成json字符串(writeValueAsString)
//还提供了JSON.parse,把json字符串转换成js对象(readValue)
data: JSON.stringify(body),
//3.响应回来之后,执行刚才设计好的success回调函数
success: function(body) {
// 预期 body 中返回 ok
console.log(body);
}
});
}
//页面加载的时候,发送一个GET请求给服务器,从服务器拿到提交过的数据
$.ajax({
type:'get',
url:'message',
success:function (body) {
//此时也需要把这个json字符串,反向转换回js对象数组,但是实际上,jQuery自动帮我们做好了这里的解析操作( resp.setContentType("application/json; charset=utf8");由于这个操作,服务器返回响应,所以它会转换成js对象数组),此时形参body,已经是js的对象数组了,不需要我们使用JSON.parse进行解析
//此时就可以直接按照数组的方式来操作body,每个元素都是js对象
//1.遍历数组,取出每个js对象
//2.根据这里的js对象构造出页面元素,显示到页面上
//经典的循环,定义变量使用let,而不是int,js表示数字是number类型,包含了int和double
//刚创建出的div,还需要加入到页面才能显示出来
//这个可以根据选择器,找到那个元素(相当于去派出所)
let container=document.querySelector('.container');
for(let i=0;i<body.length;i++){
let message=body[i];
//此处message对象,就形如
/*{
from:""
to:""
message:""
}*/
// 构造出html元素,使用浏览器提供的api
//html中的每个元素,同时都可以映射js中的一个对象
//通过对象的属性,也就能获取到页面的内容
//修改对象的属性,也就能更新页面的内容,这样也被叫做"文档对象模型"(文档html,js对象)
let div=document.createElement('div');
//设置一个css的类,应用到css样式了
div.className='row';
//给div标签设置内容,此处显示一行文本,终点理解前后端交互流程
div.innerHTML=message.from+"对"+message.to+"说:"+message.message;
//上户口的意思
container.appendChild(div);
}
}
})
</script>
</body>
</html>
最后你连接的过程可能有几个误区.
1.你的前端页面不是说你在vs打开,而是说你的页面在服务器开始启动的时候,就已经被上传到TOMCAT上了,这时候你就需要在浏览器搜索,你设置的这个东西localhosthttp://localhost:8080/messageWall/messageWall.html这里有人会疑惑,messageWall是什么,后面那个是你的前端名字,前面那个是你的url路径,你可以自己去设置,Context path(这个)
2.静态页面(html,css)需要放到webapp目录下面(不是WEB-INF)