onvif库封装及qt工程调用onvif库实现设备搜索、获取码流地址等功能

news2024/11/28 11:01:19

一、前言:

    本篇的OnvifManager工程是在vs2010下进行开发编译,它实现了对onvif库的封装调用,目前工程接口实现了对onvif的搜索、码流地址获取、设备重启接口,其他接口后续可以通过更改工程代码进行添加。qt工程myonvif是对OnvifManager生成的动态库进行调用,用QTableview显示搜索后的设备信息,支持码流地址获取及设备重启功能,支持单击网页访问。

二、OnvifManager 动态库接口说明

/*****************************************************

  • 设备搜索 接口1
  • @pUser 用户名 输入
  • @pPwd 密码 输入
  • @pLocalIP 本地电脑IP 输入
  • @vecDevInfo 搜索到的设备信息 输出
  • @搜索超时时间 输入
  • @返回值 0:成功 其他:失败
  • ***************************************************/
    int FF_Onvif_Discovery1(char *pUser, char *pPwd, char *pLocalIP,
    std::vector<ONVIF_DEVICE_INFO_T>& vecDevInfo, int nTimeout);

/*****************************************************

  • 设备搜索 接口2
  • @pUser 用户名 输入
  • @pPwd 密码 输入
  • @pLocalIP 本地电脑IP 输入
  • @搜索超时时间
  • @返回值:ONVFI_DISCOVERY_DEINFO_T 结构体设备信息
  • ***************************************************/
    ONVFI_DISCOVERY_DEINFO_T FF_Onvif_Discovery2(char *pUser, char *pPwd, char *pLocalIP, int nTimeout);

/*****************************************************

  • 获取码流地址
  • @pMediaXAddress 媒体服务地址
  • @pUser 用户名 输入
  • @pPwd 密码 输入
  • @pOutUrl 码流地址 输出
  • @nOutUrlLen 码流地址长度 输入
  • @返回值:0:成功 其他:失败
  • ***************************************************/
    int FF_Onvif_GetStreamUrl(char *pMediaXAddress, char *pUser, char *pPwd,
    char *pOutUrl, int nOutUrlLen);

/*****************************************************

  • 重启设备
  • @pDeviceXAddress 设备服务地址
  • @pUser 用户名 输入
  • @pPwd 密码 输入
  • ***************************************************/
    int FF_Onvif_Reboot(char *pDeviceXAddress, char *pUser, char *pPwd);

库头文件:OnvifManager.h 代码

/**************************************************************************
Description:Onvif Lib
Author:ybLin
**************************************************************************/
#ifndef ONVIFMANAGER_H
#define ONVIFMANAGER_H

#include <windows.h>
#include <iostream>
#include <vector>
#include <list>
#include <string>

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_DEV_LEN                     64

typedef struct onvif_device_info_t
{
    std::string sDevIP;
    std::string sMac;
    std::string sNetMask;
    std::string sGateWay;
    std::string sModel;
    std::string sVersion;
    std::string sManufacturer;

    std::string sDeviceXAddrs;
    std::string sMediaAddress;
    std::string Item;
    int nPort;

}ONVIF_DEVICE_INFO_T;

typedef struct onvif_devinfo_t
{
    int nPort;
    char sDevIP[64];
    char sMac[64];
    char sNetMask[64];
    char sGateWay[64];
    char sModel[64];
    char sVersion[64];
    char sManufacturer[64];
    char sDeviceXAddrs[128];
    char sMediaAddress[128];
    char Item[512];

}ONVIF_DEVINFO_T;

typedef struct onvif_disocvey_devinfo_t
{
    ONVIF_DEVINFO_T dev[MAX_DEV_LEN];
    int nDevNum;
    
}ONVFI_DISCOVERY_DEINFO_T;

//搜索接口1
extern  __declspec(dllexport) int WINAPI FF_Onvif_Discovery1(char *pUser, char *pPwd, char *pLocalIP,
                                                            std::vector<ONVIF_DEVICE_INFO_T>& vecDevInfo, int nTimeout);
//搜索接口2
extern  __declspec(dllexport) ONVFI_DISCOVERY_DEINFO_T WINAPI FF_Onvif_Discovery2(char *pUser, char *pPwd, char *pLocalIP, int nTimeout);

//获取码流地址
extern  __declspec(dllexport) int WINAPI FF_Onvif_GetStreamUrl(char *pMediaXAddress, char *pUser, char *pPwd,
                                                            char *pOutUrl, int nOutUrlLen);
//重启
extern  __declspec(dllexport) int WINAPI FF_Onvif_Reboot(char *pDeviceXAddress, char *pUser, char *pPwd);


#ifdef __cplusplus
}
#endif
#endif

三、qt-demo工程myonvif

3.1 操作介绍

1)点击搜索按钮,等待数据加载

在这里插入图片描述

2)数据加载完成(设备信息加载不全的,是因为密码不对)

在这里插入图片描述

3)单击表格数据行,获取到服务地址

在这里插入图片描述

4)点击获取码流地址按钮,获取到设备的rtsp码流地址:

在这里插入图片描述

5)点击设备重启,可以对指定设备进行重启操作:

在这里插入图片描述

6) web访问

在这里插入图片描述

3.2 demo核心代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QStandardItemModel>
#include <QRunnable>

namespace Ui {
class MainWindow;
}

enum COLUMN_NUM
{
    DCOLUMN_IP = 0,
    DCOLUMN_MAC_ADDRESS,
    DCOLUMN_PORT,
    DCOLUMN_NETMASK,
    DCOLUMN_GATEWAY,
    DCOLUMN_MANUFACTURER,
    DCOLUMN_MODEL,
    DCOLUMN_SOFT_VERSION,
    DCOLUMN_WEB
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void initTableView();

signals:
    void sig_CloseWaitBox();

public slots:
    void on_fiterSingleClick(QModelIndex index); // 过滤单双击事件
    void on_tableViewClick(); //单击响应
    void slot_finshTask(bool bSuc);

private slots:
    void on_pushButton_Search_clicked();
    void on_pushButton_GetStreamUrl_clicked();
    void on_pushButton_Restart_clicked();

private:
    QStandardItemModel *m_tableModel;//表数据模型
    // 单双击区分
    bool m_bDBclick;
    QTimer *m_click; //单击的时候触发定时器
    QModelIndex m_bakIndex;

private:
    Ui::MainWindow *ui;
};

class COnvifDiscoveryTask :public QObject, public QRunnable
{
    Q_OBJECT
public:
    COnvifDiscoveryTask(QObject *parent, QString sUser, QString sPwd, QString sIP, QStandardItemModel *pTableModel): QObject(parent),
        m_sUser(sUser), m_sPwd(sPwd), m_sIP(sIP), m_tableModel(pTableModel) {}
    virtual ~COnvifDiscoveryTask() {}
    void run();

signals:
    void sig_finshTask(bool bSuc);

private:
    QString m_sUser;
    QString m_sPwd;
    QString m_sIP;
    QStandardItemModel *m_tableModel;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLinkedList>
#include <QStringList>
#include "OnvifManager.h"
#include <QMessageBox>
#include <QDebug>
#include <string.h>
#include <QTimer>
#include <QThreadPool>
#include <QDesktopServices>
#include <QUrl>
#include "CtWaitBox.h"

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    initTableView();

    connect(this, &MainWindow::sig_CloseWaitBox,
            CtWaitBox::getInstance(), &CtWaitBox::onWaitBoxClose);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initTableView()
{
    m_tableModel = new QStandardItemModel(this);
    ui->tableView->setModel(m_tableModel);

    QStringList lables;
    lables << QObject::tr("IP") << QObject::tr("Mac")
           << QObject::tr("Port") << QObject::tr("NetMask")
           << QObject::tr("Gateway") << QObject::tr("Manufacturer")
           << QObject::tr("Model") << QObject::tr("Version") << QObject::tr("Web");
    m_tableModel->setHorizontalHeaderLabels(lables);
    //ui->tableView->horizontalHeader()->setSectionResizeMode(DCOLUMN_WEB, QHeaderView::Fixed);

    int width = 840;
    ui->tableView->setColumnWidth(DCOLUMN_IP, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_MAC_ADDRESS, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_PORT, qRound(0.05*width));
    ui->tableView->setColumnWidth(DCOLUMN_NETMASK, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_GATEWAY, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_MANUFACTURER, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_MODEL, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_SOFT_VERSION, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_WEB, qRound(0.05*width));

    m_click = new QTimer(this);
    m_click->setSingleShot(true);
    m_bDBclick = false;
    connect(ui->tableView, &QTableView::clicked,
            this, &MainWindow::on_fiterSingleClick); //单击检测
    connect(m_click, &QTimer::timeout,
            this, &MainWindow::on_tableViewClick); // 处理单击

}

void MainWindow::on_fiterSingleClick(QModelIndex index)
{
    if(m_bDBclick)
    {
        m_bDBclick = false;
    }
    else
    {
        m_click->start(200); // double click interval 200ms
        m_bakIndex = index;
    }
}

void MainWindow::on_tableViewClick()
{
    int nRow = m_bakIndex.row();//选中数据的行
    int nCol = m_bakIndex.column();//选中数据的列

    QString sIP = m_tableModel->item(nRow, DCOLUMN_IP)->text();
    QString sPort = m_tableModel->item(nRow, DCOLUMN_PORT)->text();
    QString sMediaAddr = QString("http://%1:%2/onvif/Media").arg(sIP).arg(sPort);
    QString sDevAddr = QString("http://%1:%2/onvif/device_service").arg(sIP).arg(sPort);

    ui->lineEdit_MediaAddress->setText(sMediaAddr);
    ui->lineEdit_devAddress->setText(sDevAddr);

    if(nCol == DCOLUMN_WEB)
    {
        QString sUrl = QString("http://%1:%2").arg(sIP).arg(sPort);
        QDesktopServices::openUrl(QUrl(sUrl));
    }
}

void MainWindow::slot_finshTask(bool bSuc)
{
    Q_UNUSED(bSuc)
    emit sig_CloseWaitBox();
}

void MainWindow::on_pushButton_Search_clicked()
{
    QString sUserName = ui->lineEdit_User->text();
    if(sUserName.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:用户名不能为空.");
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:密码不能为空.");
        return;
    }

    QString sIP = ui->lineEdit_IP->text();
    if(sIP.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:本机IP不能为空.");
        return;
    }

    COnvifDiscoveryTask* pTask = new COnvifDiscoveryTask(NULL, sUserName, sPwd, sIP, m_tableModel);
    connect(pTask, SIGNAL(sig_finshTask(bool)),
            this, SLOT(slot_finshTask(bool)));
    QThreadPool::globalInstance()->start(pTask);

    CtWaitBox::loading(true, geometry().x()+geometry().width()/2-100, geometry().y()+geometry().height()/2-100, 60, true);
}

void MainWindow::on_pushButton_GetStreamUrl_clicked()
{
    char sUrl[128] = {0};
    QString sMediaAddr = ui->lineEdit_MediaAddress->text();
    if(sMediaAddr.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", tr("媒体服务地址不能为空"));
        return;
    }

    QString sUser = ui->lineEdit_User->text();
    if(sUser.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", tr("用户名不能为空"));
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "密码不能为空");
        return;
    }

    if(FF_Onvif_GetStreamUrl(sMediaAddr.toLatin1().data(), sUser.toLatin1().data(), sPwd.toLatin1().data(), sUrl, sizeof(sUrl)) != 0)
    {
        QMessageBox::critical(this, "myOnvif", "错误:获取码流地址失败.");
    }
    else
    {
        QString sRtspUrl = QString(sUrl);
        ui->lineEdit_Url->setText(sRtspUrl);
    }
}

void MainWindow::on_pushButton_Restart_clicked()
{
    QString sDevAddr = ui->lineEdit_devAddress->text();
    if(sDevAddr.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "设备服务地址不能为空");
        return;
    }

    QString sUser = ui->lineEdit_User->text();
    if(sUser.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "用户名不能为空");
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "密码不能为空");
        return;
    }

    if(FF_Onvif_Reboot(sDevAddr.toLatin1().data(), sUser.toLatin1().data(), sPwd.toLatin1().data()) == 0)
        QMessageBox::information(this, "myOnvif", "重启成功");
    else
        QMessageBox::critical(this, "myOnvif", "重启失败.");
}

void COnvifDiscoveryTask::run()
{
    if(m_tableModel->rowCount() > 0)
    {
        m_tableModel->removeRows(0, m_tableModel->rowCount());
    }

    ONVFI_DISCOVERY_DEINFO_T devInfos = FF_Onvif_Discovery2(m_sUser.toLatin1().data(), m_sPwd.toLatin1().data(), m_sIP.toLatin1().data(), 5);

    qDebug() << "devInfos.nDevNum:" << devInfos.nDevNum;
    //数据
    for(int i = 0; i < devInfos.nDevNum; i++)
    {
        qDebug() << "Dev" << i << " IP:" << devInfos.dev[i].sDevIP;
        qDebug() << "Dev" << i << " Port:" << devInfos.dev[i].nPort;
        qDebug() << "Dev" << i << " Mac:" << devInfos.dev[i].sMac;
        qDebug() << "Dev" << i << " NetMask:" << devInfos.dev[i].sNetMask;
        qDebug() << "Dev" << i << " GateWay:" << devInfos.dev[i].sGateWay;
        qDebug() << "Dev" << i << " Manufacturer:" << devInfos.dev[i].sManufacturer;
        qDebug() << "Dev" << i << " Model:" << devInfos.dev[i].sModel;
        qDebug() << "Dev" << i << " Version:" << devInfos.dev[i].sVersion;
        qDebug() << "\r\n"<< endl;

        m_tableModel->insertRow(i, QModelIndex());
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_IP), devInfos.dev[i].sDevIP);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MAC_ADDRESS), devInfos.dev[i].sMac);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_PORT), devInfos.dev[i].nPort);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_NETMASK), devInfos.dev[i].sNetMask);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_GATEWAY), devInfos.dev[i].sGateWay);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MANUFACTURER), devInfos.dev[i].sManufacturer);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MODEL), devInfos.dev[i].sModel);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_SOFT_VERSION), devInfos.dev[i].sVersion);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_WEB), QImage(":/image/web.png"), Qt::DecorationRole);

        // 设置全部列居中显示
        for(int j = DCOLUMN_IP; j < DCOLUMN_WEB; j++)
        {
            m_tableModel->item(i, j)->setTextAlignment(Qt::AlignCenter);
        }
    }

    emit sig_finshTask(true);
}

四、下载

体验地址下载:https://download.csdn.net/download/linyibin_123/88036919
onvif库源码及qt-demo工程源码下载:https://download.csdn.net/download/linyibin_123/88036934

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

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

相关文章

Zotero翻译插件“zotero pdf translate”——使用时出现广告的问题的解决办法

一、背景&#xff1a; 在Zotero上安装了“zotero-pdf-translate”插件来辅助翻译。今天忽然发现&#xff0c;在使用CNKI翻译引擎的时候&#xff0c;末尾被加上了广告&#xff1a; (查看名企职位领高薪offer&#xff01;--->智联招聘https***dict.cnki.net/ad.html) 如下&…

【IMX6ULL驱动开发学习】16.睡眠机制_poll机制_fasync异步通知(按键控制LED)

学完了休眠唤醒机制、poll机制、异步通知、定时器、tasklet、工作队列、mmap、input子系统后&#xff0c;该沉淀沉淀了 一、睡眠机制 案例&#xff1a;APP程序读取按键值 - 睡眠机制&#xff08;阻塞或非阻塞&#xff09; 1.等待队列头创建 static DECLARE_WAIT_QUEUE_HEA…

从零实现深度学习框架——带Attentiond的Seq2seq机器翻译

引言 本着“凡我不能创造的,我就不能理解”的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导。 要深入理解深度学习,从零开始创建的经验非常重要,从自己可以理解的角度出发,尽量不使用外部完备的框架前提下,实现我…

【Windows】PowerToys - 微软超强生产力工具

Windows用户必看 - 电脑系统增强工具 下载 下载地址 简介 PowerToys 是一组由 Microsoft 创建和维护的开源实用工具集&#xff0c;旨在为 Windows 操作系统提供额外的功能和增强体验。它是为 Windows 10 及更高版本设计的&#xff0c;可帮助用户提高效率、个性化和定制化他们…

apache 安装配置 基础篇(三) 之 虚拟机

apache虚拟主机类型有两种 1、基于名称的虚拟主机 2、基于地址或IP地址的虚拟主机 基于名称的虚拟主机 ## httpd-vhosts.conf 添加如下代码&#xff0c; ## 同时要在httpd.conf中追加监听89端口 Listen 89 ## 修改apache 文件要 在bin路径下面的cmd 录入 httpd -t 检测 代…

centos7搭建postgresql主从(主备)架构

本篇介绍如何在centos7系统搭建一个postgresql主备集群实现最近的HA&#xff08;高可用&#xff09;架构。后续更高级的HA模式都是基于这个最基本的主备搭建。 节点规划 ip 主机名 用途 192.168.182.4 node1 主库&#xff08;读写&#xff09; 192.168.182.5 node2 备库&#…

大神都在用的4个AI绘画工具,记得收藏

AI绘画工具是一种利用人工智能辅助绘画创作的工具&#xff0c;它可以帮助设计师快速绘制高质量的艺术作品。本文列出了国内外4款免费的AI绘画工具&#xff0c;它们使用起来非常简单&#xff0c;而且创作效果非常不错&#xff0c;一起来看看吧&#xff01; 1.即时灵感 即时灵感…

【字符串 简单】LeetCode 14. 最长公共前缀 Java

我的思路&#xff1a; 给字符串数组按照字符串的长度从长到短排序&#xff0c;因为最长公共前缀最长的话&#xff0c;也只能是字符串数组中最短的那一个字符串设置一个index变量&#xff0c;表示当前正在检查字符数组中所有字符串的index位置循环遍历字符串数组n遍&#xff0c…

Java设计模式之结构型-桥接模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色分析 四、案例分析 1、支付方式 2、支付渠道 五、总结 一、基础概念 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;其主要目的是“将抽象部分与实现部分分离&#xff0c;使它们都可以独立地…

微信小程序扫码邀请,小程序码生成带参数

代码一&#xff1a; public String generateQRCode(String appId, String appSecret, String pagePath) throws IOException {String accessToken getAccessToken(appId, appSecret);String apiUrl "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token&qu…

springboot家乡特色推荐系统

本次设计任务是要设计一个家乡特色推荐系统&#xff0c;通过这个系统能够满足家乡特色文章的管理功能。系统的主要功能包括首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;文章分类管理&#xff0c;文章分享管理&#xff0c;系统管理等。 管理员可以根据系统给定的账…

前端工程化与webpack

一、目标 能够说出什么是前端工程化能够说出webpack的作用能够掌握webpack的基本使用了解常用plugin的基本使用了解常用loader的基本使用能够说出Source Map的作用 二、目录 前端工程化webpack的基本使用webpack中的插件webpack中的loader打包发布Source Map 1.前端工程化 …

2023年Q2京东冰箱行业品牌销售排行榜(京东销售数据分析)

近年我国的冰箱零售呈波动变化的趋势&#xff0c;由于冰箱市场趋于饱和&#xff0c;因此消费者对冰箱的需求逐渐变为替换需求&#xff0c;这也进一步推动了产品的更新迭代。接下来结合具体数据&#xff0c;我们来分析一下2023年Q2冰箱行业的销售详情。 根据鲸参谋电商数据分析平…

MySQL环境配置

MySQL在centos7环境安装 一.卸载不要的环境二.获取mysql官方yum源三.安装mysql服务四.mysql登陆五.设置配置文件my.cnf六.设置开机启动【可以不设】七.常见问题 安装与卸载中&#xff0c;⽤⼾全部切换成为root&#xff0c;⼀旦安装&#xff0c;普通⽤⼾也能使⽤。 一.卸载不要…

Python编程——字符串的三种定义方式讲解

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 前言 上篇文章讲了python字符串的一些知识&#xff0c;现在…

[ICASSP 2019] 差分隐私压缩 K 均值

Differentially Private Compressive K-means Differentially Private Compressive K-means | IEEE Conference Publication | IEEE Xplore 摘要&#xff1a; 这项工作解决了从大量数据中学习并保证隐私的问题。概述的学习框架建议通过将大规模数据集压缩为广义随机矩的单个向…

Arduino为GD32芯片编程

GD32F103用Arduino编程 板子线路图Ardunino编程程序编制编译下载 板子线路图 这个STM32F103C8T6用国产的GD32来代替。 Ardunino编程 使用Arduino编程&#xff0c;在板子管理器中安装&#xff1a; 安装需要一些时间&#xff0c;在这里可以看到&#xff0c;STM32F1xx支持GD32F…

Flink-intervalJoin源码和并行度问题

1.源码 底层用的是connect 把两个流的数据先保存到状态中 先判断有没有迟到&#xff0c;迟到就放到侧输出流 再根据范围找数据 然后根据上界删除数据 package com.atguigu.gmall.realtime.test;import org.apache.flink.api.common.eventtime.SerializableTimestampAssigne…

【Java基础教程】(十一)面向对象篇 · 第五讲:透彻讲解Java中的static关键字及代码块——静态属性、静态方法和普通代码块、构造块、静态块的使用~

Java基础教程之面向对象 第五讲 本节学习目标1️⃣ static 关键字1.1 static定义静态属性1.2 static定义静态方法1.3 主方法1.4 实际应用功能一&#xff1a;实现类实例化对象个数的统计功能二&#xff1a; 实现属性的自动设置 2️⃣ 代码块2.1 普通代码块2.2 构造块2.3 静态块…

gulimall-首页渲染-nginx域名搭建

首页渲染与nginx域名搭建 前言一、首页1.1 整合 thymeleaf1.2 整合 dev-tools1.3 渲染分类数据 二、Nginx 域名搭建2.1 搭建域名访问环境2.2 nginx 配置文件2.3 总结 前言 本文继续记录B站谷粒商城项目视频 P136-140 的内容&#xff0c;做到知识点的梳理和总结的作用。 一、首…