12-代码实战——服务器版表白墙

目录

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.添加表白信息:

  1. url:/message/add
  2. type:POST
  3. 参数:from=xxx&to=yyy&msg=zzz
  4. 返回值:int类型数字

b.查询表白列表:

  1. url:/message/list
  2. type:GET
  3. 参数:无
  4. 返回值:[{"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 类主要实现以下功能:

  1. 创建 MysqlDataSource 实例,设置 URL, username, password 等属性。
  2. 提供 getConnection ⽅法,和 MySQL 服务器建⽴连接。
  3. 提供 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的遍历写法:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/29730.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Azure】微软 Azure 基础解析(七)Azure 网络服务中的虚拟网络 VNet、网关、负载均衡器 Load Balancer

本系列博文还在更新中&#xff0c;收录在专栏&#xff1a;「Azure探秘&#xff1a;构建云计算世界」 专栏中。 本系列文章列表如下&#xff1a; 【Azure】微软 Azure 基础解析&#xff08;三&#xff09;描述云计算运营中的 CapEx 与 OpEx&#xff0c;如何区分 CapEx 与 OpEx…

通过 Python 封装关键词搜索阿里巴巴商品api接口

以下是使用 Python 封装关键词搜索阿里巴巴商品列表数据的步骤&#xff1a; 使用 requests 库向阿里巴巴搜索接口发送 HTTP 请求&#xff0c;可以使用 GET 或 POST 方法&#xff0c;请求参数中应包含搜索关键词、每页展示数量、当前页码等信息。 解析返回的 response 中的 HTM…

【Java高级语法】(六)内部类Inner Class:这可能是史上最全的关于内部类的学习资料~

Java高级语法详解之包装类 :one: 概念:two: 优缺点:three: 使用2.1 成员内部类2.2 局部内部类2.3 匿名内部类2.4 静态内部类2.5 小结&#xff1a;外部类访问四种内部类的特点2.6 小结&#xff1a;其他类访问四种内部类的特点 :four: 内部类与外部类的关系:five: 应用场景:six: …

01-抒写代码之诗:Golang 关键字的文学探索

&#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;Golang基础 &#x1f4ac;Go&#xff08;又称Golang&#xff09;是由Google开发的开源编程语言。它结合了静态类型的安全性和动态语言的灵活性&#xff0c;拥有高效的并发编程能力和简洁的语法。G…

Jenkins结合gitee自动化部署SpringBoot项目

安装 安装教程 插件选择 Gitee Plugin 配置 源码管理 填写源码地址 注意&#xff1a;请确保genkins所在的服务器有权限git拉取远程仓库代码&#xff0c;如果不可以请参考ssh配置centos 配置ssh拉取远程git代码 源码管理 构建触发器 1.勾选Gitee webhook 触发构建 2.生成we…

论文笔记:MEASURING DISENTANGLEMENT: A REVIEW OF METRICS

0 摘要 学习解缠和表示数据中的变化因素是人工智能中的一个重要问题。虽然已经取得了许多关于学习这些表示的进展&#xff0c;但如何量化解缠仍然不清楚。 虽然存在一些度量标准&#xff0c;但对它们的隐含假设、真正衡量的内容以及限制了解甚少。因此&#xff0c;当比较不同的…

一键开启GPT 平行时空模式

不知道大家日常使用GPT的时候&#xff0c;在一次会话中是如何完成同类任务的对话的? 简单点来说&#xff0c;假设你已经完成了角色设定&#xff0c;比如你设定GPT是一名文案编辑&#xff0c;那么接下来你会多次给它提交稿件让它进行编辑&#xff0c;那么在多次提交的时候&…

抽象工厂模式

一.定义 抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式&#xff0c;其定义如下: Provide an interface for creating families of related or dependent objects without specifyingtheir concrete classes.(为创建一组相关或相互依赖的对象提供一个接口&#…

算法刷题-双指针-二分法

27. 移除元素 力扣题目链接 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需…

Web前端开发技术储久良第三版课后答案

P16-第1章 练习与实验答案 练习1 1.选择题 (1)B (2)B (3)B (4)D (5)A 2.填空题 (1)标记、文本 (2)Tim Berners-Lee&#xff08;蒂姆伯纳斯李&#xff09; (3)查看 (4)NotePad、EditPlus、TextPad、TopStyle、UltraEdit等 (5)超文本标记语言、统一资源定位符&#xff08;器&am…

Axios和Spring MVC[前端和后端的请求和响应处理]

在前后端交互中&#xff0c;Axios和Spring MVC扮演着不同的角色&#xff0c;分别负责前端和后端的请求和响应处理。它们之间的作用如下&#xff1a; Axios&#xff08;前端&#xff09;&#xff1a; 发送HTTP请求&#xff1a;前端使用Axios库发送HTTP请求到后端。可以使用Axi…

webpack生产模式配置

一、生产模式和开发模式介绍 生成模式&#xff08;production mode&#xff09;是指在开发完成后将代码部署到生产环境中运行的模式&#xff0c;通常需要进行代码压缩、优化、合并&#xff0c;以减少文件大小和请求次数&#xff0c;提高页面加载速度和运行效率。 开发模式&am…

02_LinuxLED驱动开发

目录 Linux下LED灯驱动原理 地址映射 ioremap函数 iounmap函数 I/O内存访问函数 LED灯驱动程序编写 编写测试APP 编译驱动程序 编译测试APP 运行测试 Linux下LED灯驱动原理 Linux下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以LED灯驱动最终也是对I.MX6ULL…

LVS-DR群集部署

目录 一、LVS-DR数据包流向分析 二、 DR 模式的特点 总结 三、LVS-DR中的ARP问题 1.在局域网中具有相同的IP地址&#xff0c;势必会造成各服务器ARP通信的紊乱 2.路由器根据ARP表项&#xff0c;会将新来的请求报文转发给RealServer&#xff0c;导致Director的VIP失效 3.解…

React 对比class与Effect Hook优化响应式数据更新监听,感受useEffect真正的强大

还是之前写过的一个组件 import React from "react"export default class index extends React.Component{constructor(props){super(props);this.state {name: "小猫猫"}}componentDidMount ()>{document.title this.state.name;}componentDidUpda…

吴恩达ChatGPT课爆火

点上方计算机视觉联盟获取更多干货 没想到时至今日&#xff0c;ChatGPT竟还会犯低级错误&#xff1f; 吴恩达大神最新开课就指出来了&#xff1a; ChatGPT不会反转单词&#xff01; 比如让它反转下lollipop这个词&#xff0c;输出是pilollol&#xff0c;完全混乱。 哦豁&#…

【调制BFSK】二进制频移键控FSK的数字调制(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

简要介绍 | 单目深度估计

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对单目深度估计进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 注2&#xff1a;"简要介绍"系列的所有创作均使用了AIGC工具辅助 探索视觉世界的无限可能&#xff1a;单目深度估计介绍…

【Android开发基础】Canvas画笔(以刮刮乐为例)

文章目录 一、引言二、设计1、获取图片资源2、获取屏幕信息3、Canvas涂层4、随机内容5、屏幕监听 三、附件1、UI设计2、总代码&#xff08;1&#xff09;控件初始化&#xff08;2&#xff09;图层初始化 3、源代码 一、引言 &#xff08;本篇博客只说明Canvas画笔的使用&#…

HTML5 介绍

目录 1. HTML5介绍 1.1 介绍 1.2 内容 1.3 浏览器支持情况 2. 创建HTML5页面 2.1 <!DOCTYPE> 文档类型声明 2.2 <html>标签 2.3 <meta>标签 设置字符编码 2.4 引用样式表 2.5 引用JavaScript文件 3. 完整页面示例 4. 资料网站 1. HTML5介绍 1.1 介绍 …