下面我们将通过这个实例,去感受前后端交接的处理流程
首先我们先来看一个这样的html代码:
<!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> </head> <body> <!-- 通过内部样式style标签,引入CSS样式 --> <style> *{ /* 首先先去除浏览器样式 */ /* 将 内外边距设置为0,设置盒子模型为向内挤压 */ margin: 0; padding: 0; box-sizing: border-box; } .containner{ width: 100%; } h3{ /* 文本居中 */ text-align: center; /* 上下边距为 20px,左右边距为0 */ padding: 20px 0; font-size: 24px; } p{ text-align: center; color: #666; padding: 10px 0; } .row{ width: 400px; height: 50px; /* 上下外边距为零,左右外边距自适应 */ /* 就是元素水平居中操作 */ margin: 0 auto; /* 弹性布局 */ display: flex; /* 水平居中 */ justify-content: center; /* 垂直居中 */ align-items: center; } .row span{ width: 60px; font-size: 17px; } .row input{ width: 300px; height: 40px; line-height: 40px; font-size: 20px; text-indent: 0.5em; outline: none; } .row #submit{ width: 360px; height: 40px; font-size: 20px; line-height: 40px; margin: 0 auto; color: white; background-color: orange; border: none; border-radius: 15px; outline: none; } /* 当鼠标点击按钮的时候,会改变按钮颜色 */ .row #submit:active{ background-color: grey; } </style> <div class="container"> <h3>表白墙</h3> <p>输入后点击提交,会将信息显示在表格中</p> <br> <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> <script> let submitBtn = document.querySelector('#submit'); submitBtn.onclick = function(){ // 1、获取 3个input 文本框中的数据 let inputs = document.querySelectorAll('input'); let from = inputs[0].value; let to = inputs[1].value; let say = inputs[2].value; if(from == ''|| to == '' || say == ''){ // 用户填写的数据,并不完整。所以不提交。 return; } // 2、生成一个新的 div,内容就是 三个 input 文本框的内容拼接 // 再把这个 元素,挂在DOM树上。 let newDiv = document.createElement('div'); newDiv.innerHTML = from + "对" + to +"说:" + say; newDiv.className = 'row'; // 将新建节点,挂在 container 这个节点下面 let container = document.querySelector('.container'); container.appendChild(newDiv); } </script> </body> </html>
效果图
既然是前后端的交互我们就首先要搞清楚具体的流程
下面是我们的要达到的效果
接下来让我们看看具体的代码怎么写
完整的servlet代码
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; } // 这里只是把我们的数据存到了我们的内存中,服务器一重启,数据就没了 @WebServlet("/message") public class MessageWallServlet extends HttpServlet{ // 因为前后端提交数据的格式是json,我们用jackson这个第三方库来接收处理前端传来的json类型的数据 private ObjectMapper objectMapper = new ObjectMapper(); // 又因为我们两个方法都有用到这个objectMapper这个类,我们把他放到 List<Message> messages = new ArrayList<>(); @Override // 这个接口用来前端从后端获取数据,并显示在页面上 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // super.doGet(req, resp); resp.setContentType("application/json; charset=utf-8"); // 设置返回的数据类型 // 把么message对象转成json格式的字符串 String body = objectMapper.writeValueAsString(messages); resp.getWriter().write(body); // 把json格式的数据写入返回响应的body当中 } @Override // 这个接口用来后端接收从前端获取到的表单数据并储存起来 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // super.doPost(req, resp); Message message = objectMapper.readValue(req.getInputStream(), Message.class); // 读取数据到message对象当中 messages.add(message); // 最直接的办法就是把这个直接存到内存里 resp.setContentType("application/json; charset=utf-8"); // 设置返回的编码格式 // 因为前端给我的数据格式是json类型的,所以我们后端返回给前端的数据也是json类型的(为了统一格式) resp.setStatus(200); resp.getWriter().write("{\"ok\":1}"); } }
前端代码:
<!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> * { padding: 0; margin: 0; box-sizing: border-box; } .container { width: 800px; margin: 10px auto; } .container h2 { text-align: center; margin: 30px 0px; } .row { height: 50px; display: flex; justify-content: center; margin-top: 5px; line-height: 50px; } .row span { height: 50px; width: 100px; line-height: 50px; } .row input { height: 50px; width: 300px; line-height: 50px; } .row button { width: 400px; height: 50px; color: white; background-color: orange; border: none; border-radius: 10px; } .row button:active { background-color: grey; } </style> </head> <body> <!-- 这是一个顶层容器, 放其他元素 --> <div class="container"> <h2>表白墙</h2> <div class="row"> <span>谁</span> <input type="text" id="from"> </div> <div class="row"> <span>对谁</span> <input type="text" id="to"> </div> <div class="row"> <span>说什么</span> <input type="text" id="message"> </div> <div class="row"> <button>提交</button> </div> </div> <!-- 引入ajax相关的内容,我们可以通过ajax构造get请求和post请求 --> <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script> <script> let container = document.querySelector('.container'); let fromInput = document.querySelector('#from'); let toInput = document.querySelector('#to'); let messageInput = document.querySelector('#message'); let button = document.querySelector('button'); button.onclick = function() { // 1. 把用户输入的内容获取到.获取输入框的对象 let from = fromInput.value; let to = toInput.value; let message = messageInput.value; if (from == '' || to == '' || message == '') { return; } // 2. 构造一个 div, 把这个 div 插入到 .container 的末尾 let newDiv = document.createElement('div'); newDiv.className = 'row'; newDiv.innerHTML = from + " 对 " + to + " 说: " + message; // 3. 把 div 挂在 container 里面 container.appendChild(newDiv); // 4. 把之前的输入框内容进行清空 fromInput.value = ''; toInput.value = ''; messageInput.value = ''; // 5. [新的步骤] 需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器! // 这里创建出了js一个对象,js对象中的每个方法和属性都是通过键值对这样的形式来表达的,键值对之间采用逗号进行分割,键和值之间用冒号来分割 // json中的键要求是字符串的形式 let messageJson = { "from": from, "to": to, "message": message }; // 客户端也就是我们通过ajax发起的请求,这个请求通过网络发给我们的tomcat服务器,进而就会调用我们也就是后端的doxxx方法 // 之后也就是我们后端通过resp.getWriter.writer构造出http响应,通过我们的tomcat服务器传给我们的客户端,客户端这里收到数据就会触发客户端的代码(ajax的回调success函数) $.ajax({ type: 'post', // 相对路径的写法 url: 'message', contentType: 'application/json;charset=utf8', // 绝对路径的写法 // url: '/MessageWall/message', data: JSON.stringify(messageJson), success: function(body) { alert("提交成功!"); }, error: function() { // 会在服务器返回的状态码不是 2xx 的时候触发这个 error. alert("提交失败!"); } }); } // 这个函数在页面加载的时候调用. 通过这个函数从服务器获取到当前的消息列表. // 并且显示到页面上. function load() { $.ajax({ type: 'get', url: 'message', success: function(body) { // 此处得到的 body 已经是一个 js 对象的数组了. // ajax 自动帮我们进行类型转换了. // 本来服务器返回的是 JSON 格式的字符串, ajax 会自动的根据 Content-Type 为 application/json // 对响应的 body 进行解析, 解析成 js 对象. // 遍历数组的元素, 把内容构造到页面上. let container = document.querySelector('.container'); for (let message of body) { let newDiv = document.createElement('div'); newDiv.className = 'row'; newDiv.innerHTML = message.from + " 对 " + message.to + " 说 " + message.message; container.appendChild(newDiv); } } }) } // 函数调用写在这里, 就表示在页面加载的时候来进行执行. load(); // 整个前后端交互的流程,大致是我们打开这个html页面或者说刷新页面,就会调用我们的load函数, //load函数中的ajax构造了一个get请求,发送给tomcat服务器,进而调用我们后端servlet代码中的doGet方法 // 我们通过doGet方法返回一个http响应,并通过tomcat服务器把响应传给客户端, // 客户端接收到数据后就会调用ajax的回调函数succes函数,把数据显示在页面上 </script> </body> </html>