ruoyi-vue 整合EMQX接收MQTT协议数据

EMQX安装完成后,需要搭建客户端进行接收数据进一步对数据处理,下面介绍基于若依分离版开源框架来整合EMQX方法。

1.application.yml 添加代码

mqtt:
  hostUrl: tcp://localhost:1883
  username: dev
  password: dev
  client-id: MQTT-CLIENT-DEV
  cleanSession: true
  reconnect: true
  timeout: 100
  keepAlive: 100
  defaultTopic: client/dev/report
  serverTopic: server/dev/report
  isOpen: true
  qos: 0

2.pom.xml 引入依赖

        <!-- mqtt -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>
        <!--配置文件报错问题-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>

3.新建 MqttAcceptCallback

package com.ruoyi.iot.mqtt;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @Description : MQTT接受服务的回调类
 * @Author : lsyong
 * @Date : 2023/8/1 16:29
 */


@Component
public class MqttAcceptCallback implements MqttCallbackExtended {

    private static final Logger logger = LoggerFactory.getLogger(MqttAcceptCallback.class);

    @Autowired
    private MqttAcceptClient mqttAcceptClient;

    @Autowired
    private MqttProperties mqttProperties;

    /**
     * 客户端断开后触发
     *
     * @param throwable
     */
    @Override
    public void connectionLost(Throwable throwable) {
        logger.info("连接断开,可以重连");
        if (MqttAcceptClient.client == null || !MqttAcceptClient.client.isConnected()) {
            logger.info("【emqx重新连接】....................................................");
            mqttAcceptClient.reconnection();
        }
    }

    /**
     * 客户端收到消息触发
     *
     * @param topic       主题
     * @param mqttMessage 消息
     */
    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        logger.info("【接收消息主题】:" + topic);
        logger.info("【接收消息Qos】:" + mqttMessage.getQos());
        logger.info("【接收消息内容】:" + new String(mqttMessage.getPayload()));
        //        int i = 1/0;
    }

    /**
     * 发布消息成功
     *
     * @param token token
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        String[] topics = token.getTopics();
        for (String topic : topics) {
            logger.info("向主题【" + topic + "】发送消息成功!");
        }
        try {
            MqttMessage message = token.getMessage();
            byte[] payload = message.getPayload();
            String s = new String(payload, "UTF-8");
            logger.info("【消息内容】:" + s);
        } catch (Exception e) {
            logger.error("MqttAcceptCallback deliveryComplete error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 连接emq服务器后触发
     *
     * @param b
     * @param s
     */
    @Override
    public void connectComplete(boolean b, String s) {
        logger.info("============================= 客户端【" + MqttAcceptClient.client.getClientId() + "】连接成功!=============================");
        // 以/#结尾表示订阅所有以test开头的主题
        // 订阅所有机构主题
        mqttAcceptClient.subscribe(mqttProperties.getDefaultTopic(), 0);
    }
}

4.新建 MqttAcceptClient

package com.ruoyi.iot.mqtt;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Description : MQTT接受服务的客户端
 * @Author : lsyong
 * @Date : 2023/8/1 16:26
 */
@Component
public class MqttAcceptClient {

    private static final Logger logger = LoggerFactory.getLogger(MqttAcceptClient.class);

    @Autowired
    private MqttAcceptCallback mqttAcceptCallback;

    @Autowired
    private MqttProperties mqttProperties;

    public static MqttClient client;

    private static MqttClient getClient() {
        return client;
    }

    private static void setClient(MqttClient client) {
        MqttAcceptClient.client = client;
    }

    /**
     * 客户端连接
     */
    public void connect() {
        MqttClient client;
        try {
            client = new MqttClient(mqttProperties.getHostUrl(), mqttProperties.getClientId(),
                    new MemoryPersistence());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(mqttProperties.getUsername());
            options.setPassword(mqttProperties.getPassword().toCharArray());
            options.setConnectionTimeout(mqttProperties.getTimeout());
            options.setKeepAliveInterval(mqttProperties.getKeepAlive());
            options.setAutomaticReconnect(mqttProperties.getReconnect());
            options.setCleanSession(mqttProperties.getCleanSession());
            MqttAcceptClient.setClient(client);
            // 设置回调
            client.setCallback(mqttAcceptCallback);
            client.connect(options);
        } catch (Exception e) {
            logger.error("MqttAcceptClient connect error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 重新连接
     */
    public void reconnection() {
        try {
            client.connect();
        } catch (MqttException e) {
            logger.error("MqttAcceptClient reconnection error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 订阅某个主题
     *
     * @param topic 主题
     * @param qos   连接方式
     */
    public void subscribe(String topic, int qos) {
        logger.info("========================【开始订阅主题:" + topic + "】========================");
        try {
            client.subscribe(topic, qos);
        } catch (MqttException e) {
            logger.error("MqttAcceptClient subscribe error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 取消订阅某个主题
     *
     * @param topic
     */
    public void unsubscribe(String topic) {
        logger.info("========================【取消订阅主题:" + topic + "】========================");
        try {
            client.unsubscribe(topic);
        } catch (MqttException e) {
            logger.error("MqttAcceptClient unsubscribe error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }
}

5.新建 MqttCondition

package com.ruoyi.iot.mqtt;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * @Description : 自定义配置,通过这个配置,来控制启动项目的时候是否启动mqtt
 * @Author : lsyong
 * @Date : 2023/8/1 16:32
 */
public class MqttCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //1、能获取到ioc使用的beanfactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2、获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //3、获取当前环境信息
        Environment environment = context.getEnvironment();
        String isOpen = environment.getProperty("mqtt.isOpen");
        return Boolean.valueOf(isOpen);
    }
}

6.新建 MqttConfig

package com.ruoyi.iot.mqtt;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

/**
 * @Description : 启动服务的时候开启监听客户端
 * @Author : lsyong
 * @Date : 2023/8/1 16:35
 */
@Configuration
public class MqttConfig {

    @Autowired
    private MqttAcceptClient mqttAcceptClient;

    /**
     * 订阅mqtt
     *
     * @return
     */
    @Conditional(MqttCondition.class)
    @Bean
    public MqttAcceptClient getMqttPushClient() {
        mqttAcceptClient.connect();
        return mqttAcceptClient;
    }
}

7.新建 MqttProperties

package com.ruoyi.iot.mqtt;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Description : MQTT配置信息
 * @Author : lsyong
 * @Date : 2023/8/1 16:25
 */
@Component
@ConfigurationProperties("mqtt")
@Data
public class MqttProperties {

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 连接地址
     */
    private String hostUrl;

    /**
     * 客户端Id,同一台服务器下,不允许出现重复的客户端id
     */
    private String clientId;

    /**
     * 默认连接主题,以/#结尾表示订阅所有以test开头的主题
     */
    private String defaultTopic;

    /**
     * 默认服务器发送主题前缀,格式:server:${env}:report:${topic}
     */
    private String serverTopic;

    /**
     * 超时时间
     */
    private int timeout;

    /**
     * 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端
     * 发送个消息判断客户端是否在线,但这个方法并没有重连的机制
     */
    private int keepAlive;

    /**
     * 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连
     * 接记录,这里设置为true表示每次连接到服务器都以新的身份连接
     */
    private Boolean cleanSession;

    /**
     * 是否断线重连
     */
    private Boolean reconnect;

    /**
     * 启动的时候是否关闭mqtt
     */
    private Boolean isOpen;

    /**
     * 连接方式
     */
    private Integer qos;

    /**
     * 获取默认主题,以/#结尾表示订阅所有以test开头的主题
     *
     * @return
     */
    public String getDefaultTopic() {
        return defaultTopic + "/#";
    }

    /**
     * 获取服务器发送主题,格式:server/${env}/report/${topic}
     *
     * @param topic
     * @return
     */
    public String getServerTopic(String topic) {
        return serverTopic + "/" + topic;
    }
}

8.新建 MqttSendCallBack

package com.ruoyi.iot.mqtt;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @Description : MQTT发送客户端的回调类
 * @Author : lsyong
 * @Date : 2023/8/1 16:31
 */
@Component
public class MqttSendCallBack implements MqttCallbackExtended {

    private static final Logger logger = LoggerFactory.getLogger(MqttSendCallBack.class);

    /**
     * 客户端断开后触发
     *
     * @param throwable
     */
    @Override
    public void connectionLost(Throwable throwable) {
        logger.info("连接断开,可以重连");
    }

    /**
     * 客户端收到消息触发
     *
     * @param topic       主题
     * @param mqttMessage 消息
     */
    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        logger.info("【接收消息主题】: " + topic);
        logger.info("【接收消息Qos】: " + mqttMessage.getQos());
        logger.info("【接收消息内容】: " + new String(mqttMessage.getPayload()));
    }

    /**
     * 发布消息成功
     *
     * @param token token
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        String[] topics = token.getTopics();
        for (String topic : topics) {
            logger.info("向主题【" + topic + "】发送消息成功!");
        }
        try {
            MqttMessage message = token.getMessage();
            byte[] payload = message.getPayload();
            String s = new String(payload, "UTF-8");
            logger.info("【消息内容】:" + s);
        } catch (Exception e) {
            logger.error("MqttSendCallBack deliveryComplete error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 连接emq服务器后触发
     *
     * @param b
     * @param s
     */
    @Override
    public void connectComplete(boolean b, String s) {
        logger.info("============================= 客户端【" + MqttAcceptClient.client.getClientId() + "】连接成功!=============================");
    }
}

9.新建 MqttSendClient

package com.ruoyi.iot.mqtt;


import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * @Description : MQTT发送客户端
 * @Author : lsyong
 * @Date : 2023/8/1 16:30
 */
@Component
public class MqttSendClient {

    private static final Logger logger = LoggerFactory.getLogger(MqttSendClient.class);

    @Autowired
    private MqttSendCallBack mqttSendCallBack;

    @Autowired
    private MqttProperties mqttProperties;

    public MqttClient connect() {
        MqttClient client = null;
        try {
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            client = new MqttClient(mqttProperties.getHostUrl(), uuid, new MemoryPersistence());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(mqttProperties.getUsername());
            options.setPassword(mqttProperties.getPassword().toCharArray());
            options.setConnectionTimeout(mqttProperties.getTimeout());
            options.setKeepAliveInterval(mqttProperties.getKeepAlive());
            options.setCleanSession(true);
            options.setAutomaticReconnect(false);
            // 设置回调
            client.setCallback(mqttSendCallBack);
            client.connect(options);
        } catch (Exception e) {
            logger.error("MqttSendClient connect error,message:{}", e.getMessage());
            e.printStackTrace();
        }
        return client;
    }

    /**
     * 发布消息
     *
     * @param retained 是否保留
     * @param topic    主题,格式: server:${env}:report:${topic}
     * @param content  消息内容
     */
    public void publish(boolean retained, String topic, String content) {
        MqttMessage message = new MqttMessage();
        message.setQos(mqttProperties.getQos());
        message.setRetained(retained);
        message.setPayload(content.getBytes());
        MqttDeliveryToken token;
        MqttClient mqttClient = connect();
        try {
            mqttClient.publish(mqttProperties.getServerTopic(topic), message);
        } catch (MqttException e) {
            logger.error("MqttSendClient publish error,message:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            disconnect(mqttClient);
            close(mqttClient);
        }
    }

    /**
     * 关闭连接
     *
     * @param mqttClient
     */
    public static void disconnect(MqttClient mqttClient) {
        try {
            if (mqttClient != null)
                mqttClient.disconnect();
        } catch (MqttException e) {
            logger.error("MqttSendClient disconnect error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 释放资源
     *
     * @param mqttClient
     */
    public static void close(MqttClient mqttClient) {
        try {
            if (mqttClient != null)
                mqttClient.close();
        } catch (MqttException e) {
            logger.error("MqttSendClient close error,message:{}", e.getMessage());
            e.printStackTrace();
        }
    }
}

10.新建测试类 MqttController

package com.ruoyi.iot.mqtt;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description : 测试类
 * @Author : lsyong
 * @Date : 2023/8/1 16:35
 */
@RestController
@RequestMapping("/mqtt")
public class MqttController {

    @Autowired
    private MqttSendClient mqttSendClient;

    @GetMapping(value = "/publishTopic")
    public String publishTopic(String topic, String sendMessage) {
        System.out.println("topic:" + topic);
        System.out.println("message:" + sendMessage);
        this.mqttSendClient.publish(false, topic, sendMessage);
        return "topic:" + topic + "\nmessage:" + sendMessage;
    }

}

放开测试类的访问权限,在com.ruoyi.framework.config 路径下的 SecurityConfig 类中添加如下代码

 .antMatchers("/mqtt/**").permitAll()

11.启动项目进行测试

如果连接不上,确认emqx是否启动成功,详细可以查看Windows安装EMQX(搭建MQTT服务)-CSDN博客

连接成功后可以登入EMQX去查看

浏览器访问 http://localhost:8080/mqtt/publishTopic?sendMessage=你好啊

控制台打印

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

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

相关文章

从0开始学习JavaScript--JavaScript 中 `let` 和 `const` 的区别及最佳实践

在JavaScript中&#xff0c;let 和 const 是两个用于声明变量的关键字。尽管它们看起来很相似&#xff0c;但它们之间有一些重要的区别。本篇博客将深入探讨 let 和 const 的用法、区别&#xff0c;并提供一些最佳实践&#xff0c;以确保在代码中正确使用它们。 let 和 const …

简单字符串处理

答案&#xff1a; #include <stdio.h> #include <string.h> #define MAX 51 //该定义宏为字符串最大长度 int main() {char arr[MAX] { 0 }; gets(arr); //读取存给arrint len 0, i 0, num 0;len strlen(arr); //len代表字符串长度for (i 0; i &l…

基于卷积神经网络的人体行为识别系统开发与设计

摘 要 基于卷积神经网络的人体行为识别的开发与设计 摘要&#xff1a;随着计算机领域不断的创新、其它行业对计算机的应用需求的提高以及社会对解放劳动力的迫切&#xff0c;人机交互成为人们关注的问题。深度学习的出现帮助了人们实现人机交互&#xff0c;而卷积神经网络是其…

从基础到进阶:实现div控件的拖拽和缩放功能

说在前面 元素拖拽和缩放现在也是一个很常见的功能&#xff0c;如果你正在寻找一个详细的教程&#xff0c;从基础到进阶地学习如何实现具备拖拽和缩放特性的div控件&#xff0c;那么本文将是你需要的&#xff01;我们将从HTML、CSS和JavaScript的基本知识入手&#xff0c;深入讨…

pgsql 更新A表的x字段通过查询b表的z字段

查询表t_local_warning_hit_source的send_time 更新到表t_local_warning_source WITH t2 AS ( SELECT ID, send_time FROM t_local_warning_hit_source WHERE send_time > 2023-09-27 00:00:00 AND send_time < 2023-11-28 00:00:00 ) UPDATE t_local_warning_source t…

牛客算法题 HJ99 自守数 golang实现

题目 HJ99 自守数 描述 自守数是指一个数的平方的尾数等于该数自身的自然数。例如&#xff1a;25^2 625&#xff0c;76^2 5776&#xff0c;9376^2 87909376。请求出n(包括n)以内的自守数的个数数据范围&#xff1a; 1 ≤ &#xfffd; ≤ 100001≤n≤10000 输入描述&…

ApiSix的docker 容器化部署及使用

⼀&#xff0e;etcd安装 Docekr安装Etcd 环境准备 此处安装&#xff0c;是利⽤下载的 etcd 源⽂件&#xff0c;利⽤ docker build 构建完整镜像&#xff0c;具体操作如下&#xff1a; 1.环境准备 1.1. 新建⽂件夹 在磁盘某个路径下新建⼀个⽂件夹&#xff0c;⽤处操作 Dockerfi…

ES6中对Set、Map两种数据结构的理解

Set、Map两种数据结构的理解 前言什么是集合&#xff1f;什么又是字典&#xff1f;区别&#xff1f; 一、Set理解增删改查add()delete()has()clear() 遍历keys方法、values 方法、entries 方法forEach() 方法扩展运算符和 Set 结构相结合实现数组或字符串去重实现并集、交集、…

php爬虫实现把目标页面变成自己的网站页面

最近又被烦的不行&#xff0c;琐事不断&#xff0c;要是比起懒来一个人比一个人懒&#xff0c;但是懒要转换成动力啊&#xff0c;能让自己真正的偷懒&#xff0c;而不是浪费时间。每天还是需要不断的学习的&#xff0c;才能更好的提高效率&#xff0c;把之前做的简单小功能爬虫…

HotSpot 虚拟机中的对象

1、对象的创建 Java 是一门面向对象的编程语言&#xff0c;程序运行过程中无时无刻都有对象被创建出来。在语言层面上&#xff0c;创建对象通常仅仅是一个 new 关键字&#xff0c;而虚拟机中&#xff0c;对象&#xff08;仅限于普通 Java 对象&#xff0c;不包括数组和 Class …

Spring Cloud Gateway集成SpringDoc,集中管理微服务API

本文目标 Spring Cloud微服务集成SpringDoc&#xff0c;在Spring Cloud Gateway中统一管理微服务的API&#xff0c;微服务上下线时自动刷新SwaggerUi中的group组。 依赖版本 框架版本Spring Boot3.1.5Spring Cloud2022.0.4Spring Cloud Alibaba2022.0.0.0Spring Doc2.2.0Nac…

C#图像处理OpenCV开发指南(CVStar,03)——基于.NET 6的图像处理桌面程序开发实践第一步

1 Visual Studio 2022 开发基于.NET 6的OpenCV桌面程序 1.1 为什么选择.NET 6开发桌面应用&#xff1f; 选择 .NET 6&#xff08;最早称为 .NET Core&#xff09;而非 Frameworks.NET 的理由是&#xff1a;&#xff08;1&#xff09;跨平台&#xff1b;已经支持Windows,Linux…

yolov1网络结构说明

文章目录 一. 网络结构二. 网络说明1. 网络的输入2. 网络的输出(1) 5 5表示:每个网格使用两个先验框进行预测。(2) “5”表示&#xff1a;每个先验框包含的预测信息的数量。(3) 20表示&#xff1a;20个分类预测值(4) 每个网格能预测几个目标&#xff1f; 一. 网络结构 论文下…

eNSP实验

前言 本文记录了使用eNSP进行组网&#xff0c;学习、巩固一些之前学的网络基础知识和协议。 一&#xff1a;同网段、网关互通 网络拓扑如下&#xff1a; AR1的配置&#xff1a; interface G0/0/0 ip address 192.168.10.1 24 PC1和PC2的配置(IP地址和网关设置) 最终实现PC1…

C/C++ Zlib库封装MyZip压缩类

Zlib是一个开源的数据压缩库&#xff0c;提供了一种通用的数据压缩和解压缩算法。它最初由Jean-Loup Gailly和Mark Adler开发&#xff0c;旨在成为一个高效、轻量级的压缩库&#xff0c;其被广泛应用于许多领域&#xff0c;包括网络通信、文件压缩、数据库系统等。其压缩算法是…

NX二次开发UF_CURVE_create_bridge_curve 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_create_bridge_curve Defined in: uf_curve.h int UF_CURVE_create_bridge_curve(int bridge_method, tag_t curve_ids [ 2 ] , double parms [ 2 ] , int reverse_tangent…

MySQL安装与配置教程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

基于Java SSM框架实现美食推荐管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现美食推荐管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

什么是透明加密技术?透明加密有哪些优势?

透明加密技术是一种特殊的加密方法&#xff0c;它在用户毫不知情的情况下对数据进行加密和解密&#xff0c;保障了数据的安全性。用户在使用这种加密技术时&#xff0c;无需改变他们的日常操作习惯&#xff0c;加密和解密过程在后台自动进行&#xff0c;使得用户在享受数据安全…

Python语言学习笔记之六(程序调试及异常处理)

本课程对于有其它语言基础的开发人员可以参考和学习&#xff0c;同时也是记录下来&#xff0c;为个人学习使用&#xff0c;文档中有此不当之处&#xff0c;请谅解。 1、Python程序常见的错误 语法错误:不正确的缩进、未定义的变量、括号不匹配等.运行时错误: 尝试访问不存在的…