实现的这个表白墙,就通过服务器,来保存这里的消息数据。
从而进一步的做到“持久化”存储~~
在实现这个程序的时候,就需要先考虑清楚,客户端和服务器如何进行交互~
约定前后端交互的接口~
(自定义应用层协议)
既然是搞一个服务器,服务器就得提供一些服务,具体是提供啥样的服务?以及这些服务该如何触发?
对于表白墙来说,主要要提供两个接口~
约定好,为了实现这个效果,客户端要发送一个啥样的HTTP请求,服务器返回一个啥样的HTTP响应~
请求:
POST /message
{from: "黑猫",to: "白猫",message: "喵"
}
或者
POST /messageWall
from=黑猫&to=白猫&message=喵
或者
GET /message?from=黑猫&to=白猫&message=喵
或者
POST /message{f: "黑猫",t: "白猫",m: "喵" }
按照上述的思路发散开,有无数种方式来约定请求格式!
方法可以变,路径可以变,参数的名字可以变~
这么多的约定方式,到底采取哪一种?
哪种都可以!只要能够明确下来其中的一种,并且在后续编写前端/后端代码的时候能够严格执行,就是ok的。
这也是约定前后端接口的意义!
自定义协议!(约束程序员的自由,不能随便乱写代码~)
当前就是用第一种方式!
请求:
POST /message
{from: "黑猫",to: "白猫",message: "喵"
}响应:
HTTP/1.1 200 OK
{ok: true
}
请求:
GET /message响应:
HTTP/1.1 200 OK
Content-Type:application/json
[{from: "黑猫",to: "白猫", message: "喵",},{from: "黑猫",to: "白猫", message: "喵",},{from: "黑猫",to: "白猫", message: "喵",},
]
确定接口之后,就可以编写代码了~
先进行准备工作.
引入Servlet,去中央仓库找~
接下来就是jackson
Archetype Created Web Application
这个和前面约定的前后端交互接口是匹配的~
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;@WebServlet("/message")
public class MessageServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 处理提交消息请求resp.getWriter().write("hello post");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取消息列表resp.getWriter().write("hello get");}
}
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 MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();private List messages = new ArrayList<>();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 处理提交消息请求Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 最简单的保存方法就是保存在内存中messages.add(message);// 通过 ContentType 来告知页面,返回的数据是 json格式// 有了这样的声明,此时 jquery ajax 就会自动的帮我们把字符串转成 js 对象// 如果没有, jquery ajax 就只是当成字符串来处理resp.setContentType("application/json; charset=utf8");resp.getWriter().write("{ \"ok\":true }");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取消息列表,只要把消息列表中的内容整个返回给客户端即可// 此处需要使用 ObjectMapper 把 Java 对象,转成 JSON 格式字符串String jsonString = objectMapper.writeValueAsString(messages);System.out.println("jsonString: " +jsonString);resp.getWriter().write(jsonString);}
}
当前我们已经把后端逻辑编写完毕,接下来来写前端代码
在webapp里面放~
表白墙
表白墙
输入后点击提交, 会将信息显示在表格中
谁: 对谁: 说什么:
当页面加载的时候,我们就能够看到有一个这个ajax请求,这个请求就是从服务器获取消息列表的~
此处看到是空着了,刚才不是明明往服务器上提交了三条记录?
刚刚这个代码是把消息保存到了list中,内容中的数据我们一旦程序重启就会丢失。
因此,上述逻辑,只能保证页面刷新后数据不丢失,而不能保证服务器重启后数据不丢失~
当然,要想更加彻底解决这个问题,就需要把数据保存到硬盘上(可以是文件,也可以是数据库)
当前确实可以证明,即使页面关闭之后,之前提交的消息是不丢失的~
(页面加载的时候,从服务器获取到了消息列表,并显示在了浏览器页面中)
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;public class DBUtil {private static final String URL = "jdbc:mysql://127.0.0.1:3306/java107?characterEncoding=utf8&useSSL=false";private static final String USERNAME = "root";private static final String PASSWORD = "1234";private volatile static DataSource dataSource = null;private static DataSource getDataSource() {if (dataSource == null) {synchronized (DBUtil.class) {if (dataSource == null) {dataSource = new MysqlDataSource();((MysqlDataSource) dataSource).setURL(URL);((MysqlDataSource) dataSource).setUser(USERNAME);((MysqlDataSource) dataSource).setPassword(PASSWORD);}}}return dataSource;}public static Connection getConnection() throws SQLException {return getDataSource().getConnection();}public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
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.io.Reader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;class Message {public String from;public String to;public String message;
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 处理提交消息请求Message message = objectMapper.readValue(req.getInputStream(), Message.class);// 最简单的保存方法就是保存在内存中//messages.add(message);// 通过 ContentType 来告知页面,返回的数据是 json格式// 有了这样的声明,此时 jquery ajax 就会自动的帮我们把字符串转成 js 对象// 如果没有, jquery ajax 就只是当成字符串来处理save(message);resp.setContentType("application/json;charset=utf8");resp.getWriter().write("{ \"ok\":true }");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取消息列表,只要把消息列表中的内容整个返回给客户端即可// 此处需要使用 ObjectMapper 把 Java 对象,转成 JSON 格式字符串List messages = load();String jsonString = objectMapper.writeValueAsString(messages);System.out.println("jsonString: " + jsonString);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(jsonString);}private void save(Message message) {// 把一条消息保存到数据库中Connection connection = null;PreparedStatement statement = null;try {// 1. 和数据库建立连接connection = DBUtil.getConnection();// 2. 构造 SQLString sql = "insert into message values(?, ?, ?)";statement = connection.prepareStatement(sql);statement.setString(1, message.from);statement.setString(2, message.to);statement.setString(3, message.message);// 3. 执行 SQLstatement.executeUpdate();} catch (SQLException e) {throw new RuntimeException(e);} finally {DBUtil.close(connection, statement, null);}}private List load() {// 从数据库中获取到所有的消息List messages = new ArrayList<>();Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = DBUtil.getConnection();String sql = "select * from message";statement = connection.prepareStatement(sql);resultSet = statement.executeQuery();while (resultSet.next()) {Message message = new Message();message.from = resultSet.getString("from");message.to = resultSet.getString("to");message.message = resultSet.getString("message");messages.add(message);}} catch (SQLException e) {throw new RuntimeException(e);} finally {DBUtil.close(connection, statement, resultSet);}return messages;}
}