用Servlet实现一个简单的表白墙

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代码都是被下载到浏览器中,并执行的)

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-02 10:40:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-02 10:40:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-02 10:40:02       82 阅读
  4. Python语言-面向对象

    2024-04-02 10:40:02       91 阅读

热门阅读

  1. appium用例参数化

    2024-04-02 10:40:02       36 阅读
  2. 探索Django:打造高效、可扩展的Web应用(中)

    2024-04-02 10:40:02       42 阅读
  3. ES6中的解构赋值

    2024-04-02 10:40:02       35 阅读
  4. 2404d,d取参数标识元组

    2024-04-02 10:40:02       36 阅读
  5. 3.4 Python复数类型(complex)

    2024-04-02 10:40:02       33 阅读
  6. Python学习(二)

    2024-04-02 10:40:02       32 阅读
  7. QT(19)-QCamera

    2024-04-02 10:40:02       29 阅读
  8. QT 无标题栏 实现窗体移动

    2024-04-02 10:40:02       34 阅读
  9. HTTPS ECDHE 握手解析(计算机网络)

    2024-04-02 10:40:02       36 阅读
  10. HTTP和HTTPS的区别

    2024-04-02 10:40:02       37 阅读
  11. 生命周期钩子

    2024-04-02 10:40:02       34 阅读
  12. 正则表达式 (regex) 简介和基本用法

    2024-04-02 10:40:02       33 阅读