我的编程空间,编程开发者的网络收藏夹
学习永远不晚

redis中怎么实现聊天记录转存功能

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

redis中怎么实现聊天记录转存功能

这篇文章将为大家详细讲解有关redis中怎么实现聊天记录转存功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。


环境搭建

我的项目是基于SpringBoot2.x搭建的,电脑已经安装了redis,用的maven作为jar包管理工具,所以只需要在maven中添加需要的依赖包即可,如果你用的是其他管理工具,请自行查阅如何添加依赖。

<!-- Redis --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 定时任务调度 --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-quartz</artifactId>    <version>2.3.7.RELEASE</version></dependency>

本文需要用到依赖:Redis 、quartz,在pom.xml文件的dependencies标签下添加下述代码。

spring:# redis配置  redis:    host: 127.0.0.1 # redis地址    port: 6379 # 端口号    password:  # 密码    timeout: 3000 # 连接超时时间,单位毫秒

实现思路

在websocket的服务中,收到客户端推送的消息后,我们对数据进行解析,构造聊天记录实体类,将其保存至redis中,最后我们使用quartz设置定时任务将redis的数据定时写入mysql中。

我们将上述思路进行下整理:

  1. 解析客户端数据,构造实体类

  2. 将数据保存至redis

  3. 使用quartz将redis中的数据定时写入mysql

实现过程

实现思路很简单,难在如何将实体类数据保存至redis,我们需要把redis这一块配置好后,才能继续实现我们的业务需求。

redis支持的数据结构类型有:

  • set 集合,string类型的无序集合,元素不允许重复

  • hash 哈希表,键值对的集合,用于存储对象

  • list 列表,链表结构

  • zset有序集合

  • string 字符串,最基本的数据类型,可以包含任何数据,比如一个序列化的对象,它的字符串大小上限是512MB

redis的客户端分为jedis 和 lettuce,在SpringBoot2.x中默认客户端是使用lettuce实现的,因此我们不用做过多配置,在使用的时候通过RedisTemplate.xxx来对redis进行操作即可。

自定义RedisTemplate

在RedisTemplate中,默认是使用Java字符串序列化,将字符串存入redis后可读性很差,因此,我们需要对他进行自定义,使用Jackson 序列化,以 JSON 方式进行存储。

我们在项目的config包下,创建一个名为LettuceRedisConfig的Java文件,我们再此文件中配置其默认序列化规则,它的代码如下:

package com.lk.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;// 自定义RedisTemplate设置序列化器, 方便转换redis中的数据与实体类互转@Configurationpublic class LettuceRedisConfig {        @Bean    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(connectionFactory);        // 使用GenericJackson2JsonRedisSerializer替换默认序列化        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();        // 设置 Key 和 Value 的序列化规则        redisTemplate.setKeySerializer(new StringRedisSerializer());        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);        // 初始化 RedisTemplate 序列化完成        redisTemplate.afterPropertiesSet();        return redisTemplate;    }}

封装redis工具类

做完上述操作后,通过RedisTemplate存储到redis中的数据就是json形式的了,接下来我们对其常用的操作封装成工具类,方便我们在项目中使用。

在Utils包中创建一个名为RedisOperatingUtil,其代码如下:

package com.lk.utils;import org.springframework.data.redis.connection.DataType;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.util.Arrays;import java.util.Collections;import java.util.List;import java.util.Map;import java.util.concurrent.TimeUnit;@Component// Redis操作工具类public class RedisOperatingUtil {    @Resource    private RedisTemplate<Object, Object> redisTemplate;        public void setKeyTime(String key, long time) {        redisTemplate.expire(key, time, TimeUnit.SECONDS);    }        public Long getKeyTime(String key) {        return redisTemplate.getExpire(key, TimeUnit.SECONDS);    }        public Boolean hasKey(String key) {        return redisTemplate.hasKey(key);    }        public Long delKey(String... key) {        if (key == null || key.length < 1) {            return 0L;        }        return redisTemplate.delete(Arrays.asList(key));    }        public String keyType(String key) {        DataType dataType = redisTemplate.type(key);        assert dataType != null;        return dataType.code();    }        public void barchSet(Map<String, Object> map) {        redisTemplate.opsForValue().multiSet(map);    }        public List<Object> batchGet(List<String> list) {        return redisTemplate.opsForValue().multiGet(Collections.singleton(list));    }        public Object objectGetKey(String key) {        return redisTemplate.opsForValue().get(key);    }        public void objectSetValue(String key, Object value) {        redisTemplate.opsForValue().set(key, value);    }        public Long listLeftPush(String key, Object value) {        return redisTemplate.opsForList().leftPush(key, value);    }        public Long listRightPush(String key, Object value) {        return redisTemplate.opsForList().rightPush(key, value);    }        public Long listLeftPushAll(String key, List<Object> value) {        return redisTemplate.opsForList().leftPushAll(key, value);    }        public Long listRightPushAll(String key, List<Object> value) {        return redisTemplate.opsForList().rightPushAll(key, value);    }        public void listIndexSet(String key, long index, Object value) {        redisTemplate.opsForList().set(key, index, value);    }        public Object listRange(String key, long start, long end) {        return redisTemplate.opsForList().range(key, start, end);    }        public Object listPopLeftKey(String key) {        return redisTemplate.opsForList().leftPop(key);    }        public Object listPopRightKey(String key) {        return redisTemplate.opsForList().rightPop(key);    }        public Long listLen(String key) {        return redisTemplate.opsForList().size(key);    }        public Object listIndex(String key, long index) {        return redisTemplate.opsForList().index(key, index);    }        public Long listRem(String key, long count, Object value) {        return redisTemplate.opsForList().remove(key, count, value);    }        public void listTrim(String key, long start, long end) {        redisTemplate.opsForList().trim(key, start, end);    }}

进行单元测试

做完上述操作后,最难弄的一关我们就已经搞定了,接下来我们来对一会需要使用的方法进行单元测试,确保其能够正常运行。

创建一个名为RedisTest的Java文件,注入需要用到的相关类。

  • redisOperatingUtil为我们的redis工具类

  • subMessageMapper为聊天记录表的dao层

@RunWith(SpringRunner.class)@SpringBootTest@Slf4jpublic class RedisTest {    @Resource    private RedisOperatingUtil redisOperatingUtil;    @Resource    private SubMessageMapper subMessageMapper;}

接下来,我们看下SubMessage实体类的代码。

package com.lk.entity;import lombok.AllArgsConstructor;import lombok.Getter;import lombok.NoArgsConstructor;import lombok.Setter;@Getter@Setter@NoArgsConstructor@AllArgsConstructor// 聊天记录-消息内容public class SubMessage {  private Integer id;  private String msgText; // 消息内容  private String createTime; // 创建时间  private String userName; // 用户名  private String userId; // 推送方用户id  private String avatarclass="lazy" data-src; // 推送方头像  private String msgId; // 接收方用户id  private Boolean status; // 消息状态}
测试list数据的写入与获取

在单元测试类内部加入下述代码:

@Test    public void testSerializableListRedisTemplate() {        // 构造聊天记录实体类数据        SubMessage subMessage = new SubMessage();        subMessage.setAvatarclass="lazy" data-src("https://www.kaisir.cn/uploads/1ece3749801d4d45933ba8b31403c685touxiang.jpeg");        subMessage.setUserId("1090192");        subMessage.setUserName("神奇的程序员");        subMessage.setMsgText("你好");        subMessage.setMsgId("2901872");        subMessage.setCreateTime("2020-12-12 18:54:06");        subMessage.setStatus(false);        // 将聊天记录对象保存到redis中        redisOperatingUtil.listRightPush("subMessage", subMessage);        // 获取list中的数据        Object resultObj = redisOperatingUtil.listRange("subMessage", 0, redisOperatingUtil.listLen("subMessage"));        // 将Object安全的转为List        List<SubMessage> resultList = ObjectToOtherUtil.castList(resultObj, SubMessage.class);        // 遍历获取到的结果        if (resultList != null) {            for (SubMessage message : resultList) {                System.out.println(message.getUserName());            }        }    }

在上述代码中,我们从redis中取出的数据是Object类型的,我们要将它转换为与之对应的实体类,一开始我是用的类型强转,但是idea会报黄色警告,于是就写了一个工具类用于将Object对象安全的转换为与之对应的类型,代码如下:

package com.lk.utils;import java.util.ArrayList;import java.util.List;public class ObjectToOtherUtil {    public static <T> List<T> castList(Object obj, Class<T> clazz) {        List<T> result = new ArrayList<>();        if (obj instanceof List<?>) {            for (Object o : (List<?>) obj) {                result.add(clazz.cast(o));            }            return result;        }        return null;    }}

执行后,我们看看redis是否有保存到我们写入的数据,如下所示,已经成功保存。

redis中怎么实现聊天记录转存功能

我们再来看看,代码的执行结果,看看有没有成功获取到数据,如下图所示,也成功取到了。

redis中怎么实现聊天记录转存功能

注意:如果你的项目对websocket进行了启动配置,可能会导致单元测试失败,报错java.lang.IllegalStateException: Failed to load ApplicationContext,解决方案就是注释掉websocket配置文件中的@Configuration即可。

测试list数据的取出

当我们把redis中存储的数据迁移到mysql后,需要删除redis中的数据,一开始我用的是它的delete方法,但是他的delete方法只能删除与之匹配的值,不能选择一个区间进行删除,于是就决定用它的pop方法进行出栈操作。

我们来测试下工具类中的listPopLeftKey方法。

@Test    public void testListPop() {        long item = 0;        // 获取存储在redis中聊天记录的条数        long messageListSize = redisOperatingUtil.listLen("subMessage");        for (int i = 0; i < messageListSize; i++) {            // 从头向尾取出链表中的元素            SubMessage messageResult = (SubMessage) redisOperatingUtil.listPopLeftKey("subMessage");            log.info(messageResult.getMsgText());            item++;        }        log.info(item+"条数据已成功取出");    }

执行结果如下所示,成功取出了redis中存储的两条数据。

redis中怎么实现聊天记录转存功能

测试聊天记录转移至数据库

redis中怎么实现聊天记录转存功能

接下来我们在redis中放入三条数据用于测试

我们测试下将redis中的数据取出,然后写入数据库,代码如下:

// 测试聊天记录转移数据库    @Test    public void testRedisToMysqlTask() {        // 获取存储在redis中聊天记录的条数        long messageListSize = redisOperatingUtil.listLen("subMessage");        // 写入数据库的数据总条数        long resultCount = 0;        for (int i = 0; i < messageListSize; i++) {            // 从头到尾取出链表中的元素            SubMessage subMessage= (SubMessage) redisOperatingUtil.listPopLeftKey("subMessage");            // 向数据库写入数据            int result = subMessageMapper.addMessageTextInfo(subMessage);            if (result > 0) {                // 写入成功                resultCount++;            }        }        log.info(resultCount+ "条聊天记录,已写入数据库");    }

执行结果如下,数据已成功写入数据库且redis中的数据也被删除。

redis中怎么实现聊天记录转存功能

redis中怎么实现聊天记录转存功能

redis中怎么实现聊天记录转存功能

解析客户端数据保存至redis

完成上述操作后,我们redis那一块的东西就搞定了,接下来就可以实现将客户端的数据存到redis里了。

这里有个坑,因为websocket服务类中用到了@Component,会导致redis的工具类注入失败,出现null的情况,解决这个问题需要将当前类名声明为静态变量,然后在init中获取赋值redis工具类,代码如下:

// 解决redis操作工具类注入为null的问题    public static WebSocketServer webSocketServer;    @PostConstruct    public void init() {        webSocketServer = this;        webSocketServer.redisOperatingUtil = this.redisOperatingUtil;    }

在websocket服务的@OnMessage注解中,收到客户端发送的消息,我们将其保存到redis中,代码如下:

    @OnMessage    public void onMessage(String message) {        // 客户端发送的消息        JSONObject jsReply = new JSONObject(message);        // 添加在线人数        jsReply.put("onlineUsers", getOnlineCount());        if (jsReply.has("buddyId")) {            // 获取推送方id            String userId = jsReply.getString("userID");            // 获取被推送方id            String buddyId = jsReply.getString("buddyId");            // 非测试数据则推送消息            if (!buddyId.equals("121710f399b84322bdecc238199d6888")) {                // 发送消息至推送方                this.sendInfo(jsReply.toString(), userId);            }            // 构造聊天记录实体类数据            SubMessage subMessage = new SubMessage();            subMessage.setAvatarclass="lazy" data-src(jsReply.getString("avatarclass="lazy" data-src"));            subMessage.setUserId(jsReply.getString("userID"));            subMessage.setUserName(jsReply.getString("username"));            subMessage.setMsgText(jsReply.getString("msg"));            subMessage.setMsgId(jsReply.getString("msgId"));            subMessage.setCreateTime(DateUtil.getThisTime());            subMessage.setStatus(false);            // 将聊天记录对象保存到redis中            webSocketServer.redisOperatingUtil.listRightPush("subMessage", subMessage);            // 发送消息至被推送方            this.sendInfo(jsReply.toString(), buddyId);        }    }

做完上述操作后,收到客户端发送的消息就会自动写入redis。

定时将redis的数据写入mysql

接下来,我们使用quartz定时向mysql中写入数据,他执行定时任务的步骤分为2步:

  1. 创建任务类编写任务内容

  2. 在QuartzConfig文件中设置定时,执行第一步创建的任务。

首先,创建quartzServer包,在其下创建RedisToMysqlTask.java文件,在此文件内实现redis写入mysql的代码

package com.lk.quartzServer;import com.lk.dao.SubMessageMapper;import com.lk.entity.SubMessage;import com.lk.utils.RedisOperatingUtil;import lombok.extern.slf4j.Slf4j;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.scheduling.quartz.QuartzJobBean;import javax.annotation.Resource;// 将redis数据放进mysql中@Slf4jpublic class RedisToMysqlTask extends QuartzJobBean {    @Resource    private RedisOperatingUtil redisOperatingUtil;    @Resource    private SubMessageMapper subMessageMapper;    @Override    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {        // 获取存储在redis中聊天记录的条数        long messageListSize = redisOperatingUtil.listLen("subMessage");        // 写入数据库的数据总条数        long resultCount = 0;        for (int i = 0; i < messageListSize; i++) {            // 从头到尾取出链表中的元素            SubMessage subMessage= (SubMessage) redisOperatingUtil.listPopLeftKey("subMessage");            // 向数据库写入数据            int result = subMessageMapper.addMessageTextInfo(subMessage);            if (result > 0) {                // 写入成功                resultCount++;            }        }        log.info(resultCount+ "条聊天记录,已写入数据库");    }}

在config包下创建QuartzConfig.java文件,创建定时任务

package com.lk.config;import com.lk.quartzServer.RedisToMysqlTask;import org.quartz.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class QuartzConfig {    @Bean    public JobDetail RedisToMysqlQuartz() {        // 执行定时任务        return JobBuilder.newJob(RedisToMysqlTask.class).withIdentity("CallPayQuartzTask").storeDurably().build();    }    @Bean    public Trigger CallPayQuartzTaskTrigger() {        //cron方式,从每月1号开始,每隔三天就执行一次        return TriggerBuilder.newTrigger().forJob(RedisToMysqlQuartz())                .withIdentity("CallPayQuartzTask")                .withSchedule(CronScheduleBuilder.cronSchedule("* * 4 1/3 * ?"))                .build();    }}

关于redis中怎么实现聊天记录转存功能就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

redis中怎么实现聊天记录转存功能

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

redis中怎么实现聊天记录转存功能

这篇文章将为大家详细讲解有关redis中怎么实现聊天记录转存功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。环境搭建我的项目是基于SpringBoot2.x搭建的,电脑已经安装了redis
2023-06-20

Android怎么实现聊天功能

要实现聊天功能,可以使用 Android 提供的 Socket 和网络通信技术。以下是一个简单的实现聊天功能的步骤:1. 创建一个服务器端和一个客户端:- 服务器端:使用 ServerSocket 创建一个服务器端的 Socket,并监听指
2023-10-09

android聊天功能怎么实现

要实现Android聊天功能,你可以按照以下步骤进行:1. 创建一个用于显示聊天信息的界面。可以使用RecyclerView或ListView来展示聊天消息的列表。2. 创建一个用于输入消息的界面。可以使用EditText和Button来实
2023-08-18

java怎么实现聊天功能

要实现聊天功能,可以使用Java中的Socket编程和多线程技术。首先,需要创建一个服务器端和多个客户端。服务器端负责接收和转发客户端之间的消息,而客户端则负责发送和接收消息。服务器端的代码示例:```javaimport java.io.
2023-08-11

Java NIO怎么实现聊天室功能

这篇文章主要介绍了Java NIO怎么实现聊天室功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体内容如下代码里面已经包含了必要的注释,这里不详述了。实现了基本的聊天室功
2023-06-21

C#中怎么用websocket实现简易聊天功能

本篇内容主要讲解“C#中怎么用websocket实现简易聊天功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#中怎么用websocket实现简易聊天功能”吧!前言使用C#语言进行开发,基于.
2023-06-29

怎么用python实现简单聊天功能

本篇内容主要讲解“怎么用python实现简单聊天功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用python实现简单聊天功能”吧!服务端:from socket import socke
2023-06-20

Java基于NIO怎么实现聊天室功能

Java基于NIO怎么实现聊天室功能,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Sever端package com.qst.one;import java.io.IOExce
2023-06-21

Java怎么用局域网实现聊天室功能

这篇文章主要介绍了Java怎么用局域网实现聊天室功能的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java怎么用局域网实现聊天室功能文章都会有所收获,下面我们一起来看看吧。类和接口Server类(服务器端)pa
2023-06-30

在php中怎么实现7天免登录功能

这篇文章主要介绍了在php中怎么实现7天免登录功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。所谓7天免登录,即用户在登录的时候选择了记住用户信息,后台会自动设置7天的有效
2023-06-14

Android应用中怎么实现一个搜索记录保存功能

今天就跟大家聊聊有关Android应用中怎么实现一个搜索记录保存功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。要点:就是缓存输入的内容到 本地 下面就是实现保存 搜索内容到本地
2023-05-31

怎么使用QGraphicsView实现气泡聊天窗口+排雷功能

这篇“怎么使用QGraphicsView实现气泡聊天窗口+排雷功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用QG
2023-06-30

thinkphp中怎么利用redis实现秒杀缓存功能

thinkphp中怎么利用redis实现秒杀缓存功能,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1,安装redis,根据自己的php版本安装对应的redis扩
2023-06-19

怎么用Java Socket+多线程实现多人聊天室功能

这篇文章主要讲解了“怎么用Java Socket+多线程实现多人聊天室功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Java Socket+多线程实现多人聊天室功能”吧!思路简介分
2023-06-20

Vue怎么实现微信聊天窗口展示组件功能

这篇文章主要介绍“Vue怎么实现微信聊天窗口展示组件功能”,在日常操作中,相信很多人在Vue怎么实现微信聊天窗口展示组件功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Vue怎么实现微信聊天窗口展示组件功能
2023-07-04

Android中怎么实现登录记住多个密码功能

这篇文章将为大家详细讲解有关Android中怎么实现登录记住多个密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在popouWindow里面加上ListView,数据是把List以字符
2023-05-31

JAVA项目中怎么实现一个通用日志记录功能

今天就跟大家聊聊有关JAVA项目中怎么实现一个通用日志记录功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。使用Aop记录操作日志第一步:添加Aop/** * 统一日志处理Handl
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录