1. 准备工作
创建项目,引入依赖......
将静态页面放到项目中(放在webapp目录下):
当前,这个表白墙页面,已经可以输入内容,点击提交之后也能显示内容,后续后端要做的工作即:
①存档
用户点提交的时候,把刚才输入的内容通过网络传输给服务器,由服务器保存这个数据.
②读档
后续有页面加载的时候,此时就通过网络,从服务器获取到之前保存好的内容.
都需要进行前后端交互接口的约定.
约定好,前端会给后端发起一个什么样的HTTP请求,后端返回什么样的HTTP响应.
html中的每个元素,同时都可以映射到js中的一个对象.(文档-对象模型)
通过对象的属性,就能获取到页面的内容.
修改对象的属性,也就能更新页面的内容.
2. 后端操作
非持久化保存数据:
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 {
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 );
//3.返回响应(不太必要,主要是返回一个200 OK就行了,body可以没有)
resp.setStatus(200);
resp.getWriter().write("ok");
}
//用来实现读档操作
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//把我们内存中的这些Message,组织成json格式,返回到响应中.
String respJson = objectMapper.writeValueAsString(messageList);
//告诉浏览器,返回的响应的body是一个json格式.
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}
}
持久化保存数据:
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 {
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);
try {
save(message);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("服务器收到message: "+ message );
//3.返回响应(不太必要,主要是返回一个200 OK就行了,body可以没有)
resp.setStatus(200);
resp.getWriter().write("ok");
}
//用来实现读档操作
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//把我们内存中的这些Message,组织成json格式,返回到响应中.
List<Message> messageList = null;
try {
messageList = load();
} catch (SQLException e) {
e.printStackTrace();
}
String respJson = objectMapper.writeValueAsString(messageList);
//告诉浏览器,返回的响应的body是一个json格式.
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(respJson);
}
//通过jdbc,往数据库中存一个数据.
private void save(Message message) throws SQLException {
//1.创建数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("808250");
//2.建立连接
Connection connection = dataSource.getConnection();
//3.构造SQL
String sql = "insert into message values(?,?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,message.from);
statement.setString(2,message.to);
statement.setString(3,message.message);
//4.执行SQL
statement.executeUpdate();
//5.释放资源,关闭连接
statement.close();
connection.close();
}
private List<Message> load() throws SQLException {
//1.创建数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("808250");
//2.建立连接
Connection connection = dataSource.getConnection();
//3.构造SQL
String sql = "select * from message";
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行SQL
ResultSet resultSet = statement.executeQuery();
//5.遍历结果集合
List<Message> messageList = new ArrayList<>();
while (resultSet.next()){
Message message = new Message();
message.from = resultSet.getString("from");
message.to = resultSet.getString("to");
message.message = resultSet.getString("message");
messageList.add(message);
}
//6.关闭连接,释放资源
resultSet.close();;
statement.close();
connection.close();
return messageList;
}
}
2.1 存档(非持久化保存数据)
针对存档操作来说,前端发起一个HTTP请求.
此处约定使用json格式,把数据输出到后端.
让服务器返回一个HTTP响应. HTTP/1.1 200OK.
当前这个程序并不能在服务器重启之后保存数据,也就是把数据保存在了内存里,这样的设定并不科学.应该让数据持久化保存.
在刚才的代码基础上,引入数据库,来保存上述数据.
2.2 读档
前端页面加载的时候,需要从服务器拿到之前已经提交的数据.
响应的json应该是数组了,返回的数据会有多条.
2.3 用数据库-持久化保存数据
2.3.1 引入数据库的依赖(驱动包)
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
2.3.2 创建数据库,创建数据表
2.3.3 编写代码
JDBC操作数据库,完成这里的数据存和取.
3. 前端操作
3.1 "存档"请求
先让js代码发起"存档"请求.
需要前端和后端通过HTTP交互,使用ajax.
这个相对路径的基准路径,就是当前HTML所在的路径.
写了相对路径message,就相当于在message基础上,加上一层/messageWall
一般会优先写作相对路径的方式.
后续如果要修改context path就比较方便,对于代码影响比较小了.
用户点击提交按钮,触发js提交数据的代码.
1.ajax方法会根据输入的参数,构造出HTTP请求,发给服务器.
2.服务器就会执行到对应的doPost方法.
3.响应回来之后,执行刚才设置好的success回调函数.
回调函数,其实是有三个参数的.
success(result,status,xhr)
对于JS的函数来说,参数如果不用,可以不写.
这里的body是形参,名字无所谓,一个参数的时候,就表示响应的body.
这个操作是把收到的数据显示到浏览器的控制台上,而不是页面上.
3.2 "读档"请求
此时也需要把这个json字符串,反向转换回js对象数组.
但是,实际上,jquery自动帮我们做好了这里的解析操作.
此时,形参body,已经是js的对象数组了,不需要使用JSON.parse进行解析.
4. 修改代码后,重启服务器没反应
4.1 先抓包
通过抓包,就能先把问题确定出,是前端还是后端的问题.
如果抓包发现,ajax的HTTP请求就没发出来,大概率是前端的问题.
如果发出来了,并且内容符合要求,大概率是后端的问题.
4.2 关注前端代码(HTTP请求没发出来)
此时更需要关注的是,浏览器里的情况.(js代码都是被下载到浏览器中,并执行的)