目录
1.版本一:将数据存到内存中
①约定前后端交互接口
a.添加表白信息:
b.查询表白列表:
②在webapp包下创建message-wall.html前端文件
③在java包下创建AddMessageServlet后端类
④在java包下创建MessageListServlet后端类
2.版本二:将数据存到数据库中
①创建数据库, 创建 messages 表
②在pom.xml中添加MySQL JDBC依赖
③在utils包下创建 DBUtils 类
④在java包下创建AddMessageServletV2后端类
⑤在webapp包下创建message-wallv2.html前端页面
⑥在java包下创建MessageListServletV2后端类
1.版本一:将数据存到内存中
①约定前后端交互接口
所谓 "前后端交互接⼝" 是进⾏ Web 开发中的关键环节。
具体来说,就是允许⻚⾯给服务器发送哪些 HTTP 请求,并且每种请求预期获取什么样的 HTTP 响应。
- Java里不会直接去操作内存,但后端所有的Servlet类是运行在内存中,这里所说的将数据存到内存中,就是在后端程序中创建一个集合List,List里有一个对象,将数据存到List中,就相当于是存到内存中了。
- 当不重启Tomcat时,换浏览器都会展示提交的数据;但若重启Tomcat,会释放内存,不会展示提交的数据了。
- 后端拿到前端传递的3个数据后,将数据放到List里,并且提供一个查询接口。
- 总共2个接口:①添加表白信息的接口;②查询表白列表的接口。
a.添加表白信息:
- url:/message/add
- type:POST
- 参数:from=xxx&to=yyy&msg=zzz
- 返回值:int类型数字
b.查询表白列表:
- url:/message/list
- type:GET
- 参数:无
- 返回值:[{"from":"", "to":"", "msg":""}, ...](json对象)
注:不建议写成一个url,不同的type,触达不同的业务。因为ajax使用哪个类型不能决定执行哪个业务方法。
②在webapp包下创建message-wall.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, initialscale=1.0">
<title>表白墙</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
width: 400px;
margin: 0 auto;
}
h1 {
text-align: center;
padding: 20px 0;
}
p {
color: #666;
text-align: center;
font-size: 14px;
padding: 10px 0;
}
.row {
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
span {
width: 100px;
line-height: 40px;
}
.edit {
width: 200px;
height: 30px;
}
.submit {
width: 304px;
height: 40px;
color: white;
background-color: orange;
border: none;
}
.submit:active {
background-color: #666;
}
</style>
<script src="js/jquery-1.9.1.min.js"></script>
</head>
<body>
<div id="container" class="container">
<h1>表白墙</h1>
<p>输⼊后点击提交, 会将信息显示在表格中</p>
<div class="row">
<span>谁: </span>
<input id="from" class="edit" type="text">
</div>
<div class="row">
<span>对谁: </span>
<input id="to" class="edit" type="text">
</div>
<div class="row">
<span>说什么: </span>
<input id="message" class="edit" type="text">
</div>
<div class="row">
<input type="button" value="提交" class="submit" onclick="mySubmit()">
</div>
<div id="allMsg">
</div>
</div>
<script>
//添加表白信息
function mySubmit() {
var from = jQuery("#from");
var to = jQuery("#to");
var msg = jQuery("#message");
//1.非空效验
if(from.val().trim() == "") {
alert("请先输入from!");
from.focus(); //聚焦光标
return false; //不走下面的代码了
}
if(to.val().trim() == "") {
alert("请先输入to!");
to.focus();
return false;
}
if(msg.val().trim() == "") {
alert("请先输入msg!");
msg.focus();
return false;
}
//2.ajax提交数据给后端
jQuery.ajax({
url:"message/add", //提交到后端的地址
type:"POST", //提交类型
data:{
from:from.val(),
to:to.val(),
msg:msg.val()
}, //data是前端给后端提交的key值/参数
success:function(result) { //回调函数,匿名函数,result是后端给前端返回的数据,result是一个int类型的值
if(result != null && result > 0) {
alert("恭喜:添加成功!");
//刷新表白列表
getAllMsg();
} else {
alert("抱歉:添加失败,请重试!");
}
}
});
}
//查询表白列表
function getAllMsg() {
jQuery.ajax({
url:"message/list", //最前面没有'/'
type:"GET",
data:{},
success:function(result) { //result是一个json对象
if(result != null && result.length > 0) {
//有表白数据
var msgHtml = "";
for(var i = 0; i < result.length; i++) {
msgHtml +=
'<div class = "row">'
+ result[i].from +'对'
+ result[i].to +'说'
+ result[i].message
+ '</div>';
}
jQuery("#allMsg").html(msgHtml);
} else if(result != null && result.length == 0) {
//没有表白数据
console.log("没有表白信息");
} else {
alert("访问出错!");
}
}
});
}
//要在页面加载时就执行,那么直接在下面调用即可
getAllMsg();
</script>
</body>
</html>
③在java包下创建AddMessageServlet后端类
public class StringUtils {
/**
* 用来判null和判空的,如果为null或空,返回false
* @param str
* @return
*/
public static boolean hasLength(String str) {
return !(str == null || str.length() == 0);
}
}
import lombok.Getter;
import lombok.Setter;
import utils.StringUtils;
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;
/**
* 添加表白信息
*/
@WebServlet("/message/add")
public class AddMessageServlet extends HttpServlet {
public static List<Message> msgList = new ArrayList<>();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int result = -1;
//1.得到前端参数并效验
String from = req.getParameter("from");
String to = req.getParameter("to");
String msg = req.getParameter("msg");
if(StringUtils.hasLength(from) && StringUtils.hasLength(to) && StringUtils.hasLength(msg)) {
//2.将表白对象加入到集合(内存)
msgList.add(new Message(from, to, msg));
result = 1;
}
//3.将结果返回给前端
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().println(result);
}
}
@Setter
@Getter
class Message {
private String from;
private String to;
private String message;
public Message(String from, String to, String message) {
this.from = from;
this.to = to;
this.message = message;
}
}
④在java包下创建MessageListServlet后端类
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.List;
/**
* 查询表白列表
*/
@WebServlet("/message/list")
public class MessageListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Message> messageList = AddMessageServlet.msgList;
resp.setContentType("application/json; charset=utf-8");
ObjectMapper objectMapper = new ObjectMapper();
resp.getWriter().println(objectMapper.writeValueAsString(messageList));
}
}
2.版本二:将数据存到数据库中
把表白墙程序修改成服务器版本JDBC+Servlet,这样即使页面关闭、服务器重启,表白墙的内容也不会丢失。
①创建数据库, 创建 messages 表
②在pom.xml中添加MySQL JDBC依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
③在utils包下创建 DBUtils 类
DBUtils 类主要实现以下功能:
- 创建 MysqlDataSource 实例,设置 URL, username, password 等属性。
- 提供 getConnection ⽅法,和 MySQL 服务器建⽴连接。
- 提供 close ⽅法,⽤来释放必要的资源。
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtils {
//单例模式3步:
//①声明一个私有的构造方法
private DBUtils() {
}
//②提供一个私有的对象属性
private static volatile MysqlDataSource mysqlDataSource;
private static volatile Connection connection;
//③提供一个公共的对外访问的方法,并且这个方法要加volatile和DCL双重效验锁
private static MysqlDataSource getMysqlDataSource() {
if(mysqlDataSource == null) {
synchronized (DBUtils.class) {
if(mysqlDataSource == null) {
mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/messagewall?character=utf8&useSSL=true");
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("12345678");
}
}
}
return mysqlDataSource;
}
//1.get connect
public static Connection getConnection() {
if(connection == null) { //首次访问
synchronized (DBUtils.class) {
if(connection == null) {
try {
MysqlDataSource dataSource = getMysqlDataSource();
connection = (Connection) dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
return connection;
}
//2.提供关闭资源的方法
public static void close(ResultSet resultSet, PreparedStatement statement, Connection connection) throws SQLException {
if(resultSet != null) {
resultSet.close();
}
if(statement != null) {
statement.close();
}
}
}
④在java包下创建AddMessageServletV2后端类
import com.mysql.jdbc.Connection;
import lombok.SneakyThrows;
import utils.DBUtils;
import utils.StringUtils;
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.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
/**
* 添加表白信息
*/
@WebServlet("/message/add2")
public class AddMessageServletV2 extends HttpServlet {
public static List<Message> msgList = new ArrayList<>();
@SneakyThrows
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int result = -1;
//1.得到前端参数并效验
String from = req.getParameter("from");
String to = req.getParameter("to");
String msg = req.getParameter("msg");
if(StringUtils.hasLength(from) && StringUtils.hasLength(to) && StringUtils.hasLength(msg)) {
//2.将表白对象加入到数据库
//2.1.得到Connect
Connection connection = DBUtils.getConnection();
//2.2.拼接sql,创建执行器
String sql = "insert into messages(`from`,`to`,`message`) values(?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,from);
statement.setString(2,to);
statement.setString(3,msg);
//2.3.执行执行器,并返回结果
result = statement.executeUpdate();
//2.4.关闭资源
DBUtils.close(null, statement, connection);
}
//3.将结果返回给前端
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().println(result);
}
}
⑤在webapp包下创建message-wallv2.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, initialscale=1.0">
<title>表白墙——连接数据库版本</title>
<style>
* {
margin: 0;
padding: 0;
}
.container {
width: 400px;
margin: 0 auto;
}
h1 {
text-align: center;
padding: 20px 0;
}
p {
color: #666;
text-align: center;
font-size: 14px;
padding: 10px 0;
}
.row {
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
span {
width: 100px;
line-height: 40px;
}
.edit {
width: 200px;
height: 30px;
}
.submit {
width: 304px;
height: 40px;
color: white;
background-color: orange;
border: none;
}
.submit:active {
background-color: #666;
}
</style>
<script src="js/jquery-1.9.1.min.js"></script>
</head>
<body>
<div id="container" class="container">
<h1>表白墙</h1>
<p>输⼊后点击提交, 会将信息显示在表格中</p>
<div class="row">
<span>谁: </span>
<input id="from" class="edit" type="text">
</div>
<div class="row">
<span>对谁: </span>
<input id="to" class="edit" type="text">
</div>
<div class="row">
<span>说什么: </span>
<input id="message" class="edit" type="text">
</div>
<div class="row">
<input type="button" value="提交" class="submit" onclick="mySubmit()">
</div>
<div id="allMsg">
</div>
</div>
<script>
//添加表白信息
function mySubmit() {
var from = jQuery("#from");
var to = jQuery("#to");
var msg = jQuery("#message");
//1.非空效验
if(from.val().trim() == "") {
alert("请先输入from!");
from.focus(); //聚焦光标
return false; //不走下面的代码了
}
if(to.val().trim() == "") {
alert("请先输入to!");
to.focus();
return false;
}
if(msg.val().trim() == "") {
alert("请先输入msg!");
msg.focus();
return false;
}
//2.ajax提交数据给后端
jQuery.ajax({
url:"message/add2", //提交到后端的地址
type:"POST", //提交类型
data:{
from:from.val(),
to:to.val(),
msg:msg.val()
}, //data是前端给后端提交的key值/参数
success:function(result) { //回调函数,匿名函数,result是后端给前端返回的数据,result是一个int类型的值
if(result != null && result > 0) {
alert("恭喜:添加成功!");
//刷新表白列表
getAllMsg();
} else {
alert("抱歉:添加失败,请重试!");
}
}
});
}
//查询表白列表
function getAllMsg() {
jQuery.ajax({
url:"message/list2", //最前面没有'/',若最前面要有'/',则还需要在'/'后面加上网站的名字,再加上message/list2
type:"GET",
data:{},
//如果要设置传递的ContentType,还要传一个dataType属性
success:function(result) { //result是一个json对象
if(result != null && result.length > 0) {
//有表白数据
var msgHtml = "";
for(var i = 0; i < result.length; i++) {
msgHtml +=
'<div class = "row">'
+ result[i].from +'对'
+ result[i].to +'说'
+ result[i].message
+ '</div>';
}
jQuery("#allMsg").html(msgHtml);
} else if(result != null && result.length == 0) {
//没有表白数据
console.log("没有表白信息");
} else {
alert("访问出错!");
}
}
});
}
//要在页面加载时就执行,那么直接在下面调用即可
getAllMsg();
</script>
</body>
</html>
⑥在java包下创建MessageListServletV2后端类
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.Connection;
import lombok.SneakyThrows;
import utils.DBUtils;
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.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
/**
* 查询表白列表
*/
@WebServlet("/message/list2")
public class MessageListServletV2 extends HttpServlet {
@SneakyThrows
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查询数据库中的表白列表
List<Message> list = new ArrayList<>();
//1.得到connection
Connection connection = DBUtils.getConnection();
//2.拼接sql,创建执行器
String sql = "select * from messages";
PreparedStatement statement = connection.prepareStatement(sql);
//3.执行sql,返回resultSet,并循环将数据添加到list中
ResultSet resultSet = statement.executeQuery();
while(resultSet.next()) {
String from = resultSet.getString("from");
String to = resultSet.getString("to");
String message = resultSet.getString("message");
list.add(new Message(from,to,message));
}
//4.关闭资源
DBUtils.close(resultSet, statement, connection);
resp.setContentType("application/json; charset=utf-8");
ObjectMapper objectMapper = new ObjectMapper();
resp.getWriter().println(objectMapper.writeValueAsString(list));
}
}
PS:HashMap的遍历写法: