• 表白墙程序


    目录

    一、页面代码部分

    二、设计程序

    二、实现 doPost​编辑

    三、实现 doGet

    四、前端代码部分

    五、使用数据库存储数据


    一、页面代码部分

    在之前的一篇博客中,已经写过了表白墙的页面代码实现,这里就不再重复了

    页面代码如下:

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>表白墙title>
    6. head>
    7. <body>
    8. <div class="container">
    9. <h1>表白墙h1>
    10. <p>输入后点击提交,会将信息显示在表格中p>
    11. <div class="row">
    12. <span>谁:span>
    13. <input type="text" class="edit">
    14. div>
    15. <div class="row" >
    16. <span>对谁:span>
    17. <input type="text" class="edit">
    18. div>
    19. <div class="row">
    20. <span>说什么:span>
    21. <input type="text" class="edit">
    22. div>
    23. <div class="row">
    24. <input type="button" value="提 交" id="submit">
    25. div>
    26. <script>
    27. let submitButton=document.querySelector('#submit');
    28. submitButton.onclick=function(){
    29. //1.先获取到编辑框的内容
    30. let edits=document.querySelectorAll('.edit');
    31. //依靠.value来获得其输入框的值
    32. let from=edits[0].value;
    33. let to=edits[1].value;
    34. let message=edits[2].value;
    35. console.log(from,to,message);
    36. //这里是对用户输入进行合法的校验,看用户输入是否合法
    37. if(from==''||to==' '||message==''){
    38. return;
    39. }
    40. //2.根据内容,构造HTML元素(.row里面包含用户输入的话)
    41. //createElement:创建一个元素
    42. let row=document.createElement('div');
    43. row.className='row';
    44. row.innerHTML=from+'对'+to+'说:'+message;
    45. //3.把这个新的元素添加到DOM树上
    46. let container=document.querySelector('.container');
    47. container.appendChild(row);
    48. //4.清空原来的输入框
    49. for(let i=0;ilength;i++){
    50. edits[i].value='';
    51. }
    52. }
    53. script>
    54. <style>
    55. /*去除浏览器默认样式:内边距,外边距,内边框和外边框不会撑大盒子*/
    56. *{
    57. margin:0;
    58. padding: 0;
    59. box-sizing: border-box;
    60. }
    61. /*margin:0 auto :意思是 中央居中*/
    62. .container{
    63. width: 400px;
    64. margin:0 auto;
    65. }
    66. /*padding:20px auto :h1标签:上下间距20*/
    67. h1{
    68. text-align:center;
    69. padding:20px auto;
    70. }
    71. p{
    72. text-align:center;
    73. color:#666;
    74. padding: 10px 0;
    75. font-size:14px;
    76. }
    77. /*display:flex:基于弹性布局
    78. justify-content:center:水平居中
    79. align-items:center:垂直居中
    80. */
    81. .row{
    82. height:50px ;
    83. display: flex;
    84. justify-content: center;
    85. align-items:center;
    86. }
    87. /*现在对于span和input的长度进行调整*/
    88. span{
    89. width:90px;
    90. font-size: 20px;
    91. }
    92. input{
    93. width:310px;
    94. height: 40px;
    95. font-size: 18px;
    96. }
    97. /*现在处理一下 提交 按钮
    98. 首先,提交按钮宽度和父元素一样宽
    99. 其次,设置字体颜色和背景颜色
    100. 然后,border:none:作用:为了去除黑边框
    101. border-radius:设置四个角角为圆矩形
    102. font-size:设置 提交 字体的大小
    103. */
    104. #submit{
    105. width: 400px;
    106. color: white;
    107. background-color:orange;
    108. border:none;
    109. border-radius:5px;
    110. font-size: 18px;
    111. }
    112. /*点击 提交 按钮 就会改变其背景颜色*/
    113. #submit:active{
    114. background-color: black;
    115. }
    116. style>
    117. div>
    118. body>
    119. html>

    二、设计程序

    之前写的页面有两个非常严重的问题:

    1、如果刷新页面 / 关闭页面 重开,之前输入的消息就不见了

    2、如果一个机器上输入了数据,第二个机器是看不到的(这些数据都是在本地浏览器中)

    解决思路:

    让服务器来存储用户提交的数据,由服务器保存

    当由新的浏览器打开页面的时候,再从服务器获取数据

    此处服务器就可以用来存档和读档的操作

    写 web 程序,务必要重点考虑前后端如何交互,也就是约定好前后端交互的数据格式

    这个过程,称为 设计前后端交互接口

    请求时什么样的,响应是什么样的,浏览器什么时候发送请求,浏览器按照什么格式来解析....

    那么哪些环节涉及到前后端交互呢?

    1、点击提交,浏览器把表白信息发送到服务器这里

    2、页面加载,浏览器从服务器获取到表白信息

    1、点击提交,浏览器把表白信息发送到服务器这里

    2、页面加载,浏览器从服务器获取到表白信息

    此处的约定,没有固定的强制要求,只要保证能够实现必要的需求即可,此处的目的是为了前后端可以对上号

    注意:这里的路径得和之前约定的保持一致


    二、实现 doPost

    我们要先定义一个类,描述请求的 body 内容,方便 jackson 进行 json 解析

    1. class Message{
    2. public String from;
    3. public String to;
    4. public String message;
    5. }

    然后使用 List 来存储数据

    1. //使用 List 变量保存所有消息
    2. private List messagesList = new ArrayList<>();
    3. //向服务器提交数据
    4. @Override
    5. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    6. ObjectMapper objectMapper = new ObjectMapper();
    7. //把 body 中的内容读取出来,解析成 message 对象
    8. Message message = objectMapper.readValue(req.getInputStream(),Message.class);
    9. //此处,通过一个简单粗暴的方式来完成保存
    10. messagesList.add(message);
    11. //此处的设定状态码可以省略,不设置,默认也是200
    12. resp.setStatus(200);
    13. }

    doPost 做的事情,就是把解析的 message 往 List 里面添加


    三、实现 doGet

    另一方面,实现 doGet ,也就是把 List 的结果,返回给前端

    响应数据,也是一个 json 数据

    基于 objectMapper 的 writeValue 方法,就可以把 List 转换成 json 格式

    这个方法,同时完成了把 java 对象,转换成 json 和把 json 字符串写到响应对象中

    第一个参数是 Writer 对象,表示转成的 json 字符串,往哪个地方去写,第二个参数就是当前存储消息的 List ,意思是要把哪个对象转换成 json 

    如果分成两步,就是这样写的:

    1. //从服务器获取数据
    2. @Override
    3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    4. ObjectMapper objectMapper = new ObjectMapper();
    5. //显示告诉浏览器,数据是 json 格式,并且字符集是 utf8
    6. resp.setContentType("applicaion/json; charseet=utf8");
    7. objectMapper.writeValue(resp.getWriter(),messagesList);
    8. }

    针对 doGet ,只是把 MessageList 给转换成 json 字符串,返回给浏览器

    1. class Message{
    2. public String from;
    3. public String to;
    4. public String message;
    5. }
    6. @WebServlet("/message")
    7. public class MessageServlet extends HttpServlet {
    8. //使用 List 变量保存所有消息
    9. private List messagesList = new ArrayList<>();
    10. //向服务器提交数据
    11. @Override
    12. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13. ObjectMapper objectMapper = new ObjectMapper();
    14. //把 body 中的内容读取出来,解析成 message 对象
    15. Message message = objectMapper.readValue(req.getInputStream(),Message.class);
    16. //此处,通过一个简单粗暴的方式来完成保存
    17. messagesList.add(message);
    18. //此处的设定状态码可以省略,不设置,默认也是200
    19. resp.setStatus(200);
    20. }
    21. //从服务器获取数据
    22. @Override
    23. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    24. ObjectMapper objectMapper = new ObjectMapper();
    25. //显示告诉浏览器,数据是 json 格式,并且字符集是 utf8
    26. resp.setContentType("applicaion/json; charset=utf8");
    27. //objectMapper.writeValue(resp.getWriter(),messagesList);
    28. //把 java 对象转换成 json 字符串
    29. String jsonResp = objectMapper.writeValueAsString(messagesList);
    30. //把字符串写回到响应 body 中
    31. resp.getWriter().write(jsonResp);
    32. }
    33. }

    写到这里,表白墙的后端就大功告成了,我们可以打开 postman 对代码进行测试

    当前这只是给前端返回 json 字符串,要想成为键值对,还需要额外的代码


    四、前端代码部分

    接下来,我们来编写前端代码,也就是让页面能够发起上述请求,并解析响应

    post 是点击提交按钮的时候发起,get 是页面加载的时候发起

    这个代码是在定义一个 js 对象(类似于 json 的键值对)

    key 其实是字符串,value 则是 js 中的变量/常量

    js 中要求, 对象中的 key 务必是 字符串,所以这里的 "" 可以省略

    当前 body 是个 js 对象,不是字符串,网络传输,只能串字符串,不能传对象

    所以,我们需要把目前这个对象转成字符串

    js 内置了转换 json 的库

    1. //4、[新增] 给服务器发起 post 请求,把上述数据提交到服务器
    2. let body = {
    3. from :from,
    4. to:to,
    5. message:msg
    6. };
    7. strBody = JSON.stringify(body);
    8. console.log("strBody: " + strBody);
    9. $.ajax({
    10. type:'post',
    11. url:'message',
    12. data:strBody,
    13. contentType:"application/json;charset=utf8",
    14. success:function(body){
    15. console,log("数据发布成功");
    16. }
    17. });

    接下来需要实现下 读档操作,让 ajax 发送 GET 请求

    1. //[新增] 在页面加载的时候,发送 GET 请求,从服务器获取到数据并添加到页面中
    2. $.ajax({
    3. type:'get',
    4. url:'message',
    5. success:function(body){
    6. //此处拿到的 body 就是一个 js 的对象数组了
    7. //本来服务器返回的是一个 json 格式的字符串,但是 jquery 的 ajax 可以自动识别,
    8. //自动帮我们把 json 字符串转成 js 对象数组
    9. //接下来,遍历这个数组,把元素取出来,并且构造到页面中即可
    10. for(let message of body){
    11. //针对每个元素构造一个 div
    12. let row=document.createElement('div');
    13. row.className='row';
    14. row.innerHTML=message.from +'对'+message.to +'说:'+message.message;
    15. containerDiv.appendChild(rowDiv);
    16. }
    17. }
    18. });

    五、使用数据库存储数据

    当前我们的数据是在内存(变量) 中保存的,重启服务器就没了

    要想持久化保存,就需要写入文件中(硬盘)

    1、直接使用 流对象 写入文本文件

    2、借助数据库

    创建数据表

    此处只有一个表:message(from ,to,message)

    实现数据库操作:

    1. //通过这个类,把数据库连接过程封装一下
    2. //此处,把 DBUtil 作为一个工具类,提供 static 方法,供其它方法来调用
    3. public class DBUtil {
    4. //静态成员是跟随类对象的,类对象在整个进程中,只有唯一一份
    5. //静态成员相当于也是唯一的实例(单例模式,饿汉模式)
    6. private static DataSource dataSource = new MysqlDataSource();
    7. static {
    8. //使用静态代码块,针对 dataSourse 进行初始化
    9. ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java?charactorEncoding=utf8&useSSL=false");
    10. ((MysqlDataSource)dataSource).setUser("root");
    11. ((MysqlDataSource)dataSource).setPassword("123456");
    12. }
    13. //通过这个方法来建立连接
    14. public static Connection getConnection() throws SQLException {
    15. return dataSource.getConnection();
    16. }
    17. //通过这个方法来断开连接,释放资源
    18. public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
    19. //此处的三个 try catch 分开写更好,避免前面的异常导致后面的代码无法执行
    20. if (resultSet != null){
    21. try {
    22. resultSet.close();
    23. } catch (SQLException e) {
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. if (statement != null){
    28. try {
    29. statement.close();
    30. } catch (SQLException e) {
    31. throw new RuntimeException(e);
    32. }
    33. }
    34. if (connection != null){
    35. try {
    36. connection.close();
    37. } catch (SQLException e) {
    38. throw new RuntimeException(e);
    39. }
    40. }
    41. }
    42. }

    要插入的数据,是三个变量,要把这三个变量给填充到 Sql 中,就需要占位符

    1. class Message{
    2. public String from;
    3. public String to;
    4. public String message;
    5. }
    6. @WebServlet("/message")
    7. public class MessageServlet extends HttpServlet {
    8. //使用 List 变量保存所有消息
    9. //private List messagesList = new ArrayList<>();
    10. //向服务器提交数据
    11. @Override
    12. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13. ObjectMapper objectMapper = new ObjectMapper();
    14. //把 body 中的内容读取出来,解析成 message 对象
    15. Message message = objectMapper.readValue(req.getInputStream(),Message.class);
    16. //此处,通过一个简单粗暴的方式来完成保存
    17. //messagesList.add(message);
    18. save(message);
    19. //此处的设定状态码可以省略,不设置,默认也是200
    20. resp.setStatus(200);
    21. }
    22. //从服务器获取数据
    23. @Override
    24. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    25. ObjectMapper objectMapper = new ObjectMapper();
    26. //显示告诉浏览器,数据是 json 格式,并且字符集是 utf8
    27. resp.setContentType("applicaion/json; charset=utf8");
    28. //objectMapper.writeValue(resp.getWriter(),messagesList);
    29. //把 java 对象转换成 json 字符串
    30. List messagesList = load();
    31. String jsonResp = objectMapper.writeValueAsString(messagesList);
    32. //把字符串写回到响应 body 中
    33. resp.getWriter().write(jsonResp);
    34. }
    35. //提供一对方法
    36. //往数据库中存一条消息
    37. private void save(Message message) {
    38. //JDBC 操作
    39. //1、建立连接
    40. Connection connection = null;
    41. PreparedStatement statement = null;
    42. try {
    43. connection = DBUtil.getConnection();
    44. //2、构造 SQL 语句
    45. String sql = "insert into message values(?,?,?)";
    46. statement = connection.prepareStatement(sql);
    47. statement.setString(1,message.from);
    48. statement.setString(2,message.to);
    49. statement.setString(3,message.message);
    50. //3、执行 SQL
    51. statement.executeUpdate();
    52. } catch (SQLException e) {
    53. throw new RuntimeException(e);
    54. }finally {
    55. //4、关闭连接
    56. DBUtil.close(connection,statement,null);
    57. }
    58. }
    59. //从数据库中取所有消息
    60. private List load(){
    61. List messageList = new ArrayList<>();
    62. PreparedStatement statement = null;
    63. Connection connection = null;
    64. ResultSet resultSet = null;
    65. try {
    66. //1、和数据库建立连接
    67. connection = DBUtil.getConnection();
    68. //2、构造 SQL
    69. String sql = "select *from message";
    70. statement = connection.prepareStatement(sql);
    71. //3、执行 SQL
    72. resultSet = statement.executeQuery();
    73. //4、遍历结果集合
    74. while (resultSet.next()){
    75. Message message = new Message();
    76. message.from = resultSet.getString("from");
    77. message.to = resultSet.getString("to");
    78. message.message = resultSet.getString("message");
    79. messageList.add(message);
    80. }
    81. }catch (SQLException e){
    82. e.printStackTrace();
    83. }finally {
    84. //5、需要释放资源,断开连接
    85. DBUtil.close(connection,statement,resultSet);
    86. }
    87. return messageList;
    88. }
    89. }

  • 相关阅读:
    刷题记录:牛客NC16536[NOIP2013]华容道
    《KAN》论文笔记
    【UI自动化测试】Jenkins配置
    Matlab数组操作进阶:扩维与构造
    需求解析思路
    中职网络安全技能大赛P100-漏洞检测
    红帽社区论坛
    【算法|动态规划No.27】leetcode516. 最长回文子序列
    CNVD-2021-26422:亿邮电子邮件系统moni_detail.do远程命令执行漏洞复现 [附POC]
    【MyBatis Plus】初识 MyBatis Plus,在 Spring Boot 项目中集成 MyBatis Plus,理解常用注解以及常见配置
  • 原文地址:https://blog.csdn.net/weixin_73616913/article/details/132501260