博客管理系统--博客列表页

news2024/12/23 0:41:37

    • 准备工作
    • 设计数据库
    • 封装数据库操作
    • 创建实体类
    • 数据库增删查改操作(写法几乎很相似)
    • 前后端交互

准备工作

博客管理系统前端部分在学习前端、css、js部分实现;现在我们将完成后端工作;并且部署云服务上;使其能让所有联网的人使用。
创建maven项目;先导入三个依赖;jackson;mysql;servlet;

 <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <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.14.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

把前端代码;复制进去webapp;如果直接复制blog到时候代码结构比较难写路径;所以直接把这里面复制进去简单
在这里插入图片描述

还有给tomcat的投名状;不然怎么让tomcat带着我们项目跑呢;
在这里插入图片描述

设计数据库

分析:博客系统涉及两个实体;博客、用户。创建两张表;表示博客和用户;关系是一对多:一个用户可以写多篇博客;一个博客只能属于一个用户。
blog(blogId,title,content,postTime,userId)
user(userId,username,password)
有了上次表白墙的经验:这一次就知道把sql语句保存在文件里;当我们要部署云服务器上直接复制、粘贴就能完成建库建表操作。

-- 写sql语句;把这些保存下来;当需要部署在其它机器就直接复制粘贴即可

create database if not exists liao_blog;
--删除旧;创建新的;防止之前的残留数据对我们的影响;严谨起见
--创建这个数据库和选中这个数据库
use liao_blog;

drop table if exists user;
drop table if exists blog;

--创建表;
create table blog(
--设置主键
blogId int primary key auto_incremaet,
title varchar(128),
--正文
content varchar(4096),
--发布时间
postTome datetime,
userId int

);

create table user(
userId int primary key auto_incremaet,
username varchar(20) unique,--要求用户名不重复
password varchar(20)

);

封装数据库操作

前面的数据库版本表白墙程序也是有这个操作:一模一样的代码封装;以后我们使用的是框架;不需要再像这样子手动封装。


import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//数据库的连接;把连接的过程封装一下;作为工具类;提供一些static让我们使用更方便
public class DBlianjie {
//    静态成员相当于饿汉单例模式
public static DataSource dataSource=new MysqlDataSource();

//初始化DataSource
static {

    ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/liao?characterEncoding=utf8&useSSL=false");
    ((MysqlDataSource)dataSource).setUser("root");
    ((MysqlDataSource)dataSource).setPassword("111111");
}

//    通过这个方法建立连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();


}
//通过这个方法释放资源
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){

        // 此处的三个 try catch 分开写更好, 避免前面的异常导致后面的代码不能执行.
        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();
            }
        }

    }

}

创建实体类

实体类:和表中的记录对应的类;和表的结构 (列)密切相关
blog表:Blog类对应的一个对象;对应是表中的一条记录;就是一篇博客。
user表:User类对应的一个对象;对应是表中的一个记录;就是一个用户

import java.sql.Timestamp;
//都生成get和set方法;用来获取博客的内容。
public class Blog {
    private int blogId;
    private   String tatle;
    private String content;
    private Timestamp postTimel;
    private int userId;

    public int getBlogId() {
        return blogId;
    }

    public void setBlogId(int blogId) {
        this.blogId = blogId;
    }

    public String getTatle() {
        return tatle;
    }

    public void setTatle(String tatle) {
        this.tatle = tatle;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Timestamp getPostTimel() {
        return postTimel;
    }

    public void setPostTimel(Timestamp postTimel) {
        this.postTimel = postTimel;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }
}

public class User {
    private int userId;
    private String username;
    private String password;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

数据库增删查改操作(写法几乎很相似)

我们需要想清楚;哪些需要存数据在数据库;哪里需要从数据库取数据库;存的时候传blog对象是存的对象。取的时候就把数据赋值于一个blog对象;到时候我们根据这个方法获取到这个对象就能取到我们想要的东西。
(比如点击发布文章;点击查看全文;博客列表页的内容;删除博客)我们通过的就是实体类来当一个中介的角色;要存什么放这个类的对象里再存;要取什么取到的结果放这个对象里。
Dao:Data Access Object访问数据的对象。
博客表:创建BlogDao
用户表:创建UserDao

import java.util.List;

//通过这个类对博客表的基本操作
public class BlogDao {
   //1.新增博客
        public void add(Blog blog){
            //这两个的声明在这里为了提升作用域;免得在finally里没法用这个对象.
            Connection connection=null;
            PreparedStatement statement=null;
            try{
                //1:创建数据库连接
                connection=DBlianjie.getConnection();
                //2:构造sql;自增主键不用我们设置;所以就是null;

                String sql="insert into blog values(null,?,?,?,?)";
                //进行替换;来源;存的过程我们要在Blog获取。
                // Blog的初始化内容来自用户前端博客;就是我们调用这个方法;会传一个Blog对象;是已经初始化后的
                statement.setString(1,blog.getTitle());
                statement.setString(2,blog.getContent());
                statement.setTimestamp(3,blog.getPostTimel());
                statement.setInt(4,blog.getUserId());
                //3:执行sql;把这个东西存到数据库
                statement.executeUpdate();
            }catch (SQLException e){
                e.printStackTrace();
            }finally {
                //4:释放资源;没用到的写null
                DBlianjie.close(connection,statement,null);
            }
        }



 // 2.根据博客id查询指定博客(博客详情页);
        // 就是对应我们查看全文的按钮后显示结果(相当于从数据库取东西;根据博客id进行条件查询想要的博客)
        public  Blog selectById(int blogId){
           Connection connection=null;
           PreparedStatement statement=null;
            ResultSet resultSet=null;
            try{
//                //1:建立连接
                connection=DBlianjie.getConnection();
                //2:构造sql
                String sql = "select * from blog where blogId = ?";
                statement=connection.prepareStatement(sql);
//                //进行替换
                statement.setInt(1,blogId);
                //3:执行
                resultSet = statement.executeQuery();
                // 4. 遍历结果集合. 由于 blogId 在 blog 表中是唯一的. (主键);
                // 说明我们这里查到数据只可能是一条;不需要循环。if就好了;
                // 我们就把结果用来初始化一个blog对象;进行返回。我们就根据这个对象获取里面博客的内容
                if(resultSet.next()){
                    Blog blog = new Blog();
                    blog.setBlogId(resultSet.getInt("blogId"));
                    blog.setTitle(resultSet.getString("title"));
                    blog.setContent(resultSet.getString("content"));
                    blog.setPostTime(resultSet.getTimestamp("postTime"));
                    blog.setUserId(resultSet.getInt("userId"));
                    return blog;


                }

            }
            catch (SQLException e){
                e.printStackTrace();
            }
            finally {
                DBlianjie.close(connection,statement,resultSet);

            }
            //没有查到这个博客id的博客
       return null;
        }







        // 3.查询数据库中的所以博客列表(博客列表页)
        public List<Blog> selectAll(){
            Connection connection=null;
            PreparedStatement statement=null;
            ResultSet resultSet=null;
            //创建一个list储存这很多篇博客
             List<Blog> blogs=new ArrayList<>();
            try {
            //1:建立连接
            connection=DBlianjie.getConnection();
            //2:构造sql语句;这里是查询所有博客的内容取前100个字进行摘要;所以是全列查询
                String sql="select * from blog";
              statement= connection.prepareStatement(sql);
                //3:执行sql
                resultSet=statement.executeQuery();

                //4:遍历结果集;把遍历的结果每一篇都放一个blog对象;
                // 每循环一次就创建这样子的一个对象;最后放list<blog>

                while (resultSet.next()){
                    Blog blog=new Blog();
                    blog.setBlogId(resultSet.getInt("blogId"));
                    blog.setTitle(resultSet.getString("title"));
                 //这里正文部分;因为是粗略显示;全部显示是在博客详情页;所以我们对读取的内容进行截取
                      String content=resultSet.getString("content");
                  if(content.length()>=100){
                      content=content.substring(0,100)+" ……";
                  }
                  blog.setContent(content);
                  blog.setPostTime(resultSet.getTimestamp("postTime"));
                  blog.setUserId(resultSet.getInt("userId"));
                  blogs.add(blog);
                }
            }catch (SQLException e){

                e.printStackTrace();
            }
            finally {
                DBlianjie.close(connection,statement,resultSet);
            }
            return blogs;

        }




        //4.删除指定博客
        public void delete(int blogId){
       Connection connection=null;
       PreparedStatement statement=null;
       try{
           //1:建立连接
           connection=DBlianjie.getConnection();
           //2:构造sql
           String sql="delete from blog where blogId=?";
           statement=connection.prepareStatement(sql);

           //3:执行sql
            statement.executeUpdate();


       }catch (SQLException e){
           e.printStackTrace();

       }finally {
           DBlianjie.close(connection,statement,null);
       }



}


// 暂时不涉及修改博客;(修改、可以通过删除和新增;前端没有这样的功能)

}

userDao:这个实体类的对应是和创建表时的密切相关

在这里插入图片描述
因为当前注册功能待开发中:注册和登录实现差不多;先不搞add先;也没有用户删号功能. 也就不必 delete

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//针对用户表的基本操作
public class UserDao {
    // 1. 根据 userId 来查用户信息;我好像还不知道这个是干嘛的;后面就知道了
    public  User selectById(int userId){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;

        try{
            //1:建立连接
            connection =DBlianjie.getConnection();
            //2:构造sql
            String sql="select * from user where userId=?";
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            //3:执行sql
            resultSet=statement.executeQuery();
            //4:遍历结果集;一条记录还是用if就可以
            if(resultSet.next()){
                User user=new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;

            }
        }catch (SQLException e){
            e.printStackTrace();


        }finally {
            DBlianjie.close(connection, statement, resultSet);
        }
        return null;

    }

    // 2. 根据 username 来查用户信息 (登录的时候)
public  User SelectByUsername(String username){
    Connection connection=null;
    PreparedStatement statement=null;
    ResultSet resultSet=null;

    try{
        //1:建立连接
        connection =DBlianjie.getConnection();
        //2:构造sql
        String sql="select * from user where username=?";
        statement=connection.prepareStatement(sql);
        statement.setString(1,username);
        //3:执行sql
        resultSet=statement.executeQuery();
        //4:遍历结果集;一条记录还是用if就可以
        if(resultSet.next()){
            User user=new User();
            user.setUserId(resultSet.getInt("userId"));
            user.setUsername(resultSet.getString("username"));
            user.setPassword(resultSet.getString("password"));
            return user;

        }
    }catch (SQLException e){
        e.printStackTrace();


    }finally {
        DBlianjie.close(connection, statement, resultSet);
    }
    return null;




}

}

上述就把后续会用到的操作封装成方法;后面就能直接使用。

前后端交互

第一个页面实现:
在进行前端的学习时;写的这个博客列表页数据是写死的。正确的做法是通过数据库读取数据显示页面上。
前后端交互;让博客列表页;加载这个页面的时候通过ajax等给服务器发请求;服务器查数据库获取博客列表页数据;返回给浏览器’;浏览器根据这些数据构造页面内容。(在没有前后端分离;我们页面是后端生成;返回整个页面给浏览器;前后端分离;解耦的同时;我们只需要返回数据由前端构造页面;大大提升效率;也减轻服务器的工作量)
在这里插入图片描述

三步走:不同情况可能开发前端和开发后端代码的顺序是不一样的
1:约定前后端交互接口
有什么功能;前端要发什么请求;后端要返回什么响应;交互的格式。这里需要注意五个部分;地址栏URL(html页面)、查看全文按钮、右上角的三个按钮。
URL:我们希望通过输入这个html页面然后就能发送一个请求给服务器;获得响应。这个只是普通的页面;这里的URL并不是关联到服务器的注解的路径(如果是直接关联;那就不输入URL就直接是发送一个GET请求);所以我们得在前端页面里构建这个请求。
请求 GET /blog(/blog是对应我们doGet注解的路径)

响应:使用json组织;数组的形式返回
[
{
blogId:1,
title:“我的第一篇博客”
contet:“第一次变成这样的我;让我怎么去否认……”
postTime:“2023-5-6 17:12:00”
userId:1

},

{
blogId:2,
title:“我的第二篇博客”
contet:“第二次变成这样的我;让我怎么去否认……”
postTime:“2023-5-6 17:12:00”
userId:1

},

{
blogId:3,
title:“我的第三篇博客”
contet:“第三次变成这样的我;让我怎么去否认……”
postTime:“2023-5-6 17:12:00”
userId:1

}

]

2:开发后端代码
处理这个输入URL的get请求;查数据库的过程。(写到这里就发现一个问题;光是管理和操作数据的类就有五个;再把servlet类写上去不就乱套了吗;分类一下;把这些类都放包里‘分别加上package model’)
所以创建多两个包:model;模型;管理和操作数据的部分。api:存放servle相关的类

package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;
import model.User;

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(("/blog"))
public class BlogServlet extends HttpServlet {
      //定义在这里;别的方法也能用这个对象
    public ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           //现在需要拿到数据库的数据;然后转成json格式;写回给前端
        //这里转成json格式就需要用到我们在准备工作时导入jackson依赖
        BlogDao blogDao = new BlogDao();
         //这个方法就会把数据库查到的所有博客返回List里
        List<Blog> blogs=blogDao.selectAll();

        //转成json
        String respjson=objectMapper.writeValueAsString(blogs);
        //一定不要忘记设置;告诉浏览器你返回的是什么类型和数据字符集,不然浏览器是不知道;还以为你的是普普通通字符串
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respjson);


    }
}

3:开发前端代码;
请求的构造;
在这里插入图片描述
响应的结果重新构造页面:把我们之前写死的数据进行重新构造;我们自己用ajax构造GET请求(地址栏输入也是能触发这个GET请求)
留下一份作为参考;这是我们最终要构造成的文章样式
在这里插入图片描述
在这里插入图片描述

正文部分完成;

经过一波三折的测试;调试取得
在这里插入图片描述
目前两个bug:
1:时间戳问题;是应该显示系统时间;而不是时间戳。
这里格式化字符串;一定不要去背;因为不同语言、不同库;格式化时间的操作可能不同;上网查一查才是最稳的。
想想有什么办法能解决这个问题:
方法1:不用数据库的时间戳;使用idea的;但是这样子会数据库时间设置不进去;我们数据库的类型修改才string存进去就好了。或者是再写一个设置的时间是时间戳格式。一个用来设置进入数据库;一个后来返回响应。
在这里插入图片描述

这样子时间还是同一份;不同的get方法获取到的格式是不一样的;这个方法虽然显示没有调用;但是在objectMapper.writeValueAsString把这个对象转成json时;这个get方法会有用的。
在这里插入图片描述
最好的方法还是;获取idea的时间戳;然后转成string格式化;设置进数据库时使用statement.setString();数据库里就不用postTime类型;存的时候也不用存now()。直接是当个字符串.。取就按照字符串来取。

2:新的博客应该在上面的;老的在下面。
博客顺序问题简单:加个order by postTime desc。降序的按时间查询

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【代码】一个LVQ神经网络的详解实例

本站原创文章&#xff0c;转载请说明来自《老饼讲解-BP神经网络》bp.bbbdata.com LVQ神经网络是用于样本分类的一个常用算法&#xff0c;本文先简单回顾LVQ神经网络是什么&#xff0c;然后展示如何用matlab工具箱来训练一个LVQ神经网络 目录 一. LVQ神经网络简介 1.1 LVQ神经…

“首次公开一年连升两级的晋升大法”!

见字如面&#xff0c;我是军哥&#xff01; 今天把江湖上失传已久的技术人晋升大法分享给各位&#xff0c;据说当年雷jun总就是用了此法三年就干到了技术高管&#xff0c;请各位务必做好学习和分享动作。 说真的&#xff0c;用好这三个办法&#xff0c;就算在 IT 大厂一年都可以…

脑挫裂伤是什么?脑挫裂伤的4大症状要警惕!

脑挫裂伤是头部遭受暴力而引起的原发性脑器质性损伤。脑挫裂伤既可发生于着力点的脑组织&#xff0c;也可发生于对冲部位。脑挫裂伤病人的临床表现可以由于损伤部位&#xff0c;范围&#xff0c;程度的不同而有差异。受伤较轻的可以只有轻微的症状而受伤&#xff0c;较重的可以…

这玩意真的有用吗?对,是的!Kotlin 的 Nothing 详解

视频先行 下面是视频内容的脚本文案原稿分享。 文案原稿 Kotlin 的 Nothing 类&#xff0c;无法创建出任何实例&#xff1a; public class Nothing private constructor() 所以所有 Nothing 类型的变量或者函数&#xff0c;都找不到可用的值&#xff1a; val nothing: Nothing …

电脑视频录屏软件哪个好用 电脑视频录屏怎么录屏

录屏是我们的工作和生活中非常大的一个需求&#xff0c;尤其对于专业的视频制作者来说&#xff0c;经常需要录制屏幕和编辑视频&#xff0c;因此找到便捷好用的录屏软件非常重要。今天就来分享一下电脑视频录屏软件哪个好用&#xff0c;电脑视频录屏怎么录屏。 一、电脑视频录…

2023 年第八届数维杯大学生数学建模挑战赛 B 题 节能列车运行控制优化策略

在城市交通电气化进程快速推进的同时&#xff0c;与之相应的能耗增长和负面效应也 在迅速增加。城市轨道交通中的快速增长的能耗给城轨交通的可持续性发展带来 负担。2018 年&#xff0c;北京、上海、广州地铁负荷占全市总负荷的 1.5%-2.5%,成为了 城市电网的最大单体负荷[1]。…

软考A计划-真题-分类精讲汇总-第一章(计算机组成原理与体系结构)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Java每日一练(20230512) 最大间距、串联子串、最长回文子串

目录 1. 最大间距 &#x1f31f;&#x1f31f;&#x1f31f; 2. 串联所有单词的子串 &#x1f31f;&#x1f31f;&#x1f31f; 3. 最长回文子串 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 …

c++ 11标准模板(STL) std::vector<bool> (二)

定义于头文件 <vector> template<class Allocator> class vector<bool, Allocator>; std::vector<bool> 是 std::vector 对类型 bool 为空间提效的特化。 std::vector<bool> 中对空间提效的行为&#xff08;以及它是否有优化&#xff09;是实现…

使用ChatGPT完成部门和个人季度工作总结

“疫后元年“2023年的第一季度即将过去&#xff0c;相信各位社会人们都过得比往年更加紧张充实吧&#xff1f;转眼又到了完成季度工作总结的时间&#xff0c;完成本职工作之余还要抽出专门的时间完成优秀的工作总结报告&#xff0c;又更让大家本不富裕的休息时间雪上加霜。那么…

SCS【24】单细胞数据量化代谢的计算方法 (scMetabolism)

桓峰基因公众号推出单细胞生信分析教程并配有视频在线教程&#xff0c;目前整理出来的相关教程目录如下&#xff1a; Topic 6. 克隆进化之 Canopy Topic 7. 克隆进化之 Cardelino Topic 8. 克隆进化之 RobustClone SCS【1】今天开启单细胞之旅&#xff0c;述说单细胞测序的前世…

Oracle Cloud和足球

Oracle除了我们熟知的数据库产品&#xff0c;它还有很多技术和产品栈&#xff0c;而且在实践层面&#xff0c;已经有了很多可借鉴的案例&#xff0c;如果了解英超的朋友&#xff0c;可以发现最近几个赛季&#xff0c;英超的转播画面图标中&#xff0c;会出现Oracle Cloud&#…

操作系统的最强入门科普(Unix/Linux篇)

大家好&#xff0c;我是小枣君。 今天这篇文章&#xff0c;我们来聊聊操作系统&#xff08;Operating System&#xff09;。 说到操作系统&#xff0c;大家都不会陌生。我们天天都在接触操作系统——用台式机或笔记本电脑&#xff0c;使用的是windows和macOS系统&#xff1b;用…

为什么拿低绩效的人从来不反思自己的原因?连公司的前90%都挤不进去,还好意思找别人的理由?...

绩效是关乎打工人切身利益的大事&#xff0c;拿了高绩效欢天喜地&#xff0c;拿了低绩效垂头丧气&#xff0c;这是人之常情&#xff0c;但最近一位字节跳动的程序员却怒斥那些拿低绩效的人&#xff1a; 为什么拿m-&#xff08;低绩效&#xff09;的人从来不反思自己垫底的原因&…

C++三部曲|C++核心思想

| 导语 C 的起源可以追溯到 40 年前&#xff0c;但它仍然是当今使用最广泛的编程语言之一&#xff0c;C发明人Bjarne Stroustrup 一开始没想到 C 会获得如此大的成功&#xff0c;他说&#xff1a;“C 的成功显然令人惊讶。我认为它的成功取决于其最初的设计目标&#xff0c;就是…

前端014_标签模块_修改功能

标签模块_修改功能 1、需求分析2、Mock 添加查询数据3、Mock 添加提交修改数据4、Api 调用接口回显数据5、提交修改后的数据6、验证1、需求分析 当点击 编辑 按钮后,弹出编辑窗口,并查询出标签信息渲染。修改后点击确定 提交修改数据。 2、Mock 添加查询数据 请求URL: /a…

在OpenCV中使用Canny边缘检测

边缘检测是非常常见和广泛使用的图像处理&#xff0c;对于许多不同的计算机视觉应用非常必要&#xff0c;如数据提取&#xff0c;图像分割&#xff0c;在更细粒度的特征提取和模式识别中。它降低了图像中的噪声和细节数量&#xff0c;但保留了图像的结构。 Python中的Canny边缘…

祁宁:社区问答是激荡企业高级智慧的头脑风暴 | 开发者说

在祁宁家里&#xff0c;有一套完整的赛车模拟器&#xff0c;他甚至还请人到国外代购了最新的 VR 设备。作为沉浸式赛车游戏发烧友&#xff0c;除了享受速度与激情带来的愉悦感&#xff0c;祁宁在玩的过程中更多的是思考如何将技术能力进行产品化的问题。 Answer.dev 就是将技术…

Studio Bot - 让 AI 帮我写 Android 代码

Google I/O 2023 不出所料&#xff0c;今年的 I/O 大会只突出了一个关键词 “AI”。Google 旗下的各类产品都成了其展示 AI 实力的舞台。连面向开发者的产品 Android Studio 也新增了 Studio bot 功能&#xff0c;希望通过 AI 帮助开发者更轻松地写代码&#xff1a; Studio Bot…

STM32F4_内部温度传感器

目录 1. 什么是温度传感器 2. 温度传感器简介 3. 库函数配置内部温度传感器 4. 实验程序 4.1 main.c 4.2 ADC.c 4.3 ADC.h 1. 什么是温度传感器 温度传感器是一种测量物体冷热程度的设备&#xff0c;以可读的方式通过电信号提供温度测量。比较常见的如热电偶温度传感器。…