由于博主之前学前端的时候写的表白墙数据不能保存,所以此次是把之前实现的表白墙程序修改成服务器版本, 这样即使页面关闭, 表白墙的内容也不会丢失,那么为实现数据做到"持久化"存储,因此我这里用数据库来存储信息。
<!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>
<?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>message_Wall</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 加入 servlet 依赖 -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<!-- servlet 版本和 tomcat 版本有对应关系,切记 -->
<version>3.1.0</version>
<!-- 这个意思是我们只在开发阶段需要这个依赖,部署到 tomcat 上时就不需要了 -->
<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.12.6.1</version>
</dependency>
<!--引入mysql驱动包-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表白墙title>
head>
<body>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100%;
}
h3 {
text-align: center;
padding: 30px 0;
font-size: 24px;
}
p {
text-align: center;
color: #999;
padding: 10px 0;
}
.row {
width: 400px;
height: 50px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.row span {
width: 70px;
}
.row input {
width: 300px;
height: 30px;
font-size: 15px;
text-indent: 0.5em;
outline:none ;
}
.row #btn {
width:300px;
height: 40px;
font-size: 20px;
line-height: 40px;
margin: 0 auto;
color: white;
background-color: orange;
border:none;
border-radius: 10px;
}
.row #btn:active {
background-color: gray;
}
style>
<div class="container">
<h3>表白墙h3>
<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="btn">提交button>
div>
div>
<script>
//当用户点击submit,就会获取到input中的内容,从而把内容构成一个div,插入到页面末尾
let submitBtn=document.querySelector('#btn');
submitBtn.onclick=function(){
// 1. 获取到 3 个 input 中的内容
let input=document.querySelectorAll('input');
let from=input[0].value;
let to=input[1].value;
let msg=input[2].value;
if(from==''||to==''||msg==''){
// 用户还没填写完, 暂时先不提交数据
return ;
}
//2.生成一个新的div,内容就是input里面的内容,把这个新的div加到页面中
let newDiv=document.createElement('div');
newDiv.innerHTML=from+'对'+to+'说:'+msg;
newDiv.className='row';
let container=document.querySelector('.container');
container.appendChild(newDiv);
//3.清空之前输入框的内容
for (let i = 0; i < input.length; i++) {
input[i].value='';
}
}
script>
body>
html>
所谓 “前后端交互接口”: 是进行 Web 开发中的关键环节
具体来说:就是允许页面给服务器发送哪些 HTTP 请求,并且每种请求预期获取什么样的 HTTP 响 应。
请求:
GET /message
响应: JSON 格式
[
{
from: "易烊千玺",
to: "鹤儿",
message: "很高兴遇见你们"
},
{
from: "玺子哥",
to: "肥鹤",
message: "努力来见我"
},
......
]
我们期望浏览器给服务器发送一个 GET /message 这样的请求, 就能返回当前一共有哪些留言记
录, 结果以 json 的格式返回过来
POST /message
{
from: "大佬",
to: "鹤子",
message: "要开心"
}
响应: JSON 格式
{
ok: true
}
我们期望浏览器给服务器发送一个 POST /message 这样的请求, 就能把当前的留言提交给服务器
创建 Message 类
class Message{
public String from;
public String to;
public String message;
}
创建 MessageServlet 类
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
// 用于转换 JSON 字符串
private ObjectMapper objectMapper=new ObjectMapper();
//用于保存所有的留言
private List<Message>messages=new ArrayList<>();
// 获取所有留言
@Override
protected 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}");
}
// 新增留言
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取到消息列表,只要把消息列表中的内容整个的返回给客户端即可
//此处需要使用ObjectMapper把Java对象,转换成json格式字符串
String jsonString=objectMapper.writeValueAsString(messages);
System.out.println("jsonString:"+jsonString);
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(jsonString);
}
ObjectMapper 的 readValue方法也能直接从一个 InputStream 对象读取数据;
ObjectMapper 的 writeValueAsString方法也能把一个对象数组直接转成 JSON 格式的字符串
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js">script>
<script>
//加入Ajax的代码,此处要加入的逻辑有两个部分
//点击按钮提交的时候,Ajax要构造数据发送给服务器
//页面加载的时候,从服务器获取消息列表,并在界面上直接显示
function getMessages(){
$.ajax({
type:'get',
url:'message',
success:function(body){
//当前body已经是一个js对象数组了,Ajax会根据响应的contentType来自动进行解析
//如果服务器返回的contentType已经是application/json了,Ajax就会把body自动转成js的对象
//如果客户端没有自动转,也可以通过JSON.parse()这个函数来手动转换
//依次来取数组中的每个元素
let container=document.querySelector('.container');
for(let message of body){
let div=document.createElement('div');
div.innerHTML=message.from+'对'+message.to+'说:'+message.message;
div.className='row';
container.appendChild(div);
}
}
});
}
//加上函数调用
getMessages();
//当用户点击submit,就会获取到input中的内容,从而把内容构成一个div,插入到页面末尾
let submitBtn=document.querySelector('#btn');
submitBtn.onclick=function(){
//1.获取到3个input中的内容
let input=document.querySelectorAll('input');
let from=input[0].value;
let to=input[1].value;
let msg=input[2].value;
if(from==''||to==''||msg==''){
//用户还没填写完,暂时先不提交数据
return ;
}
//2.生成一个新的div,内容就是input里面的内容,把这个新的div加到页面中
let newDiv=document.createElement('div');
newDiv.innerHTML=from+'对'+to+'说:'+msg;
newDiv.className='row';
let container=document.querySelector('.container');
container.appendChild(newDiv);
//3.清空之前输入框的内容
for (let i = 0; i < input.length; i++) {
input[i].value='';
}
//4.把当前获取到的输入框的内容,构造成一个HTTP POST请求,通过Ajax发给服务器
let body={
from:from,
to:to,
message:msg
};
$.ajax({
type:"post",
url:"message",
contentType:"application/json;charset=utf8",
data:JSON.stringify(body),
success:function(body){
alert("消息提交成功!");
},
error:function(){
alert("消息提交失败!");
}
});
}
script>
此时我们每次提交的数据都会发送给服务器, 每次打开页面的时候页面都会从服务器加载数据, 因此即使关闭页面, 数据也不会丢失了。
但是数据此时是存储在服务器的内存中 ( private List messages = new ArrayList(); ), 一旦服务器重启, 数据仍然会丢失。
针对上面的问题, 如果把数据保存在数据库中, 那么重启服务器也不会丢失数据了。
create table message(`from` varchar(1000), to varchar(1000), message varchar(3000));
ps:由于from是sql语句中的关键字,因此要用反引号``包围
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;
public class DBUtil {
private static final String URL="jdbc:mysql://127.0.0.1:3306/wall?characterEncoding=utf8&useSSL=false";
private static final String USERNAME="root";
private static final String PASSWORD="root";
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.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();
//改成数据库,就不需要这个变量了
//private Listmessages=new ArrayList<>();
@Override
protected 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}");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取到消息列表,只要把消息列表中的内容整个的返回给客户端即可
//此处需要使用ObjectMapper把Java对象,转换成json格式字符串
List<Message>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.构造sql语句
String 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.执行SQL
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
private List<Message>load(){
//从数据库中获取到所有的消息
Connection connection=null;
PreparedStatement statement=null;
ResultSet resultSet=null;
List<Message>messages=new ArrayList<>();
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) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return messages;
}
}
重新部署程序,此时使用数据库之后就可以保证即使服务器重启,数据也不丢失,达到了永久保存的效果。
HttpServletRequest 类方法:
方法 | 描述 |
---|---|
Part getPart(String name) | 获取请求中给定 name 的文件 |
Collection getParts()}获取所有的文件 |
Part类方法:
方法 | 描述 |
---|---|
String getSubmittedFileName() | 获取提交的文件名 |
String getContentType() | 获取提交的文件类型 |
long getSize() | 获取文件的大小 |
void write(String path) | 把提交的文件数据写入磁盘文件 |
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="MyImage">
<input type="submit" value="提交">
form>
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
@MultipartConfig
@WebServlet("/upload")
public class UpLoadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part=req.getPart("MyImage");
System.out.println(part.getSubmittedFileName());
System.out.println(part.getContentType());
System.out.println(part.getSize());
part.write("e:/yyqx.jpg");
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("上传成功!");
}
}