【java_wxid项目】【第十章】【Redis集成】

主项目链接:https://gitee.com/java_wxid/java_wxid
项目架构及博文总结:

项目模块:
前期规划,实现部分

java_wxid   
├── demo                                                            // 演示模块
│     └── 模块名称:apache-mybatis-demo模块                            //Apache Mybatis集成(已实现并有博文总结)
│     └── 模块名称:apache-shardingsphere-demo模块                     //Apache ShardingSphere集成(已实现并有博文总结)
│     └── 模块名称:design-demo模块                                    //设计模式实战落地(已实现并有博文总结)
│     └── 模块名称:elasticsearch-demo模块                             //ElasticSearch集成(已实现并有博文总结)
│     └── 模块名称:mongodb-demo模块                                   //MongoDB集成(已实现并有博文总结)
│     └── 模块名称:redis-demo模块                                     //Redis集成(已实现并有博文总结)
│     └── 模块名称:spring-boot-demo模块                               //Spring Boot快速构建应用(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-nacos-demo模块                //Spring Cloud Alibaba Nacos集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-seata-demo模块                //Spring Cloud Alibaba Seata集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-alibaba-sentinel-demo模块             //Spring Cloud Alibaba Sentinel集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-gateway-demo模块                      //Spring Cloud Gateway集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-hystrix-demo模块                      //Spring Cloud Hystrix集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-open-feign-demo模块                   //Spring Cloud Open Feign集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-ribbon-demo模块                       //Spring Cloud Ribbon集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-security-oauth2-demo模块              //Spring Cloud Security Oauth2集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-security-oauth2-sso-client-demo模块   //Spring Cloud Security Oauth2集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-skywalking-demo模块                   //Spring Cloud Skywalking集成(已实现并有博文总结)
│     └── 模块名称:spring-cloud-stream-demo模块                       //Spring Cloud Stream集成(已实现并有博文总结)
│     └── 模块名称:swagger-demo模块                                   //springfox-swagger2集成(已实现并有博文总结)
│     └── 模块名称:xxl-job模块                                        //xxl-job集成(已实现并有博文总结)
│     └── 模块名称:apache-spark-demo模块                              //Apache Spark集成
│     └── 模块名称:etl-hdfs-hive-hbase-demo模块                       //ETL、HDFS、Hive、Hbase集成
│     └── 模块名称:ddd-mode-demo模块                                  //DDD领域设计
│     └── 模块名称:netty-demo模块                                     //Netty集成
│     └── 模块名称:vue-demo模块                                       //前端vue集成
├── document                                                        // 文档
│     └── JavaKnowledgeDocument                                     //java知识点
│           └── java基础知识点.md                     
│           └── mq知识点.md
│           └── mysql知识点.md
│           └── redis知识点.md
│           └── springcould知识点.md
│           └── spring知识点.md
│     └── FounderDocument                                           //创始人
│           └── 创始人.md

系列文章:快速集成各种微服务相关的技术,帮助大家可以快速集成到自己的项目中,节约开发时间。
提示:系列文章还未全部完成,后续的文章,会慢慢补充进去的。

创建redis-demo项目

项目代码:https://gitee.com/java_wxid/java_wxid/tree/master/demo/redis-demo
项目结构如下(示例):
在这里插入图片描述

修改pom.xml

代码如下(示例):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>redis-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redis-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 开发热启动:在开发过程中,由于每次修改完项目中的类都需要重启服务才能看到运行的结果,对于开发调试很不友好,浪费时间,引入devtools工具可以快速启动项目 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>


        <!-- spring-boot-starter-data-redis集成redis依赖,里面包含了spring-data-redis和 lettuce-core两个核心包
          springBoot预设的自动化配置类都位于spring-boot-autoconfigure这个包中,
          这个包下就有一个RedisAutoConfiguration这个类,顾名思义就是Redis的自动化配置。
          在这个类中,会引入LettuceConnectionConfiguration 和 JedisConnectionConfiguration 两个配置类,分别对应lettuce和jedis两个客户端,
          这个两个类上都是用了ConditionOn注解来进行判断是否加载。

          由于我们的项目自动引入了lettuce-core,而没有引入jedis相关依赖,所以LettuceConnectionConfiguration这个类的判断成立会被加载,
          而Jedis的判断不成立,所以不会加载。进而lettuce的配置生效,所以我们在使用的使用, 默认就是lettuce的客户端
          -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

    </dependencies>

</project>

修改application.properties

代码如下(示例):

server.port=8093
spring.redis.host=139.224.137.74
spring.redis.port=6379
spring.redis.password=ca0a997ee4770063
spring.redis.database=0
#由于我们使用的lettuce客户端,所以配置的时候,在spring.redis下加上lettuce再加上pool来配置.如果使用的是jedis,就把lettuce换成jedis
spring.redis.lettuce.pool.max-idle=16
spring.redis.lettuce.pool.max-active=32
spring.redis.lettuce.pool.min-idle=8
spring.devtools.restart.enable=true
创建RedisConfig

代码如下(示例):

package com.example.redisdemo.config;

/**
 * @author zhiweiLiao<zhiwei.liao @ sgs.com>
 * @Description 设置的json序列化方式进行存储,我们也可以在redis中查看内容的时候方便的查看到属性值。
 * @Date create in 2022/9/12 0012 11:39
 */
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    /**
     * Redis本身提供了多种种序列化的方式:
     * GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
     * Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
     * JacksonJsonRedisSerializer: 序列化object对象为json字符串
     * JdkSerializationRedisSerializer: 序列化java对象
     * StringRedisSerializer: 简单的字符串序列化
     * 如果我们存储的是String类型,默认使用的是StringRedisSerializer 这种序列化方式。
     * 如果我们存储的是对象,默认使用的是 JdkSerializationRedisSerializer,也就是Jdk的序列化方式
     * (通过ObjectOutputStream和ObjectInputStream实现,缺点是我们无法直观看到存储的对象内容,很不方便我们排查问题)。
     * 我们可以根据redis操作的不同数据类型,设置对应的序列化方式。
     * 而一般我们最经常使用的对象序列化方式是: Jackson2JsonRedisSerializer
     * 设置序列化方式的主要方法就是我们在配置类中,自己来创建RedisTemplate对象,并在创建的过程中指定对应的序列化方式
     * @param factory
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        redisTemplate.setKeySerializer(stringRedisSerializer); // key的序列化类型

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 方法过期,改为下面代码
//        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value的序列化类型
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }


}
修改RedisUtil

代码如下(示例):

package com.example.redisdemo.util;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author zhiweiLiao<zhiwei.liao @ sgs.com>
 * @Description 操作string类型就是用opsForValue,操作list类型是用listOps, 操作set类型是用setOps等等
 * 这些功能都在这一个类中,使用起来其实并不是很方便,所有一般情况下,我们都是单独封装一个工具类,来把常用的一些方法进行抽象。操作的时候,直接通过工具类来操作。
 * @Date create in 2022/9/12 0012 11:44
 */
@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 给一个指定的 key 值附加过期时间
     *
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }
    /**
     * 根据key 获取过期时间
     *
     * @param key
     * @return
     */
    public long getTime(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }
    /**
     * 根据key 获取过期时间
     *
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }
    /**
     * 移除指定key 的过期时间
     *
     * @param key
     * @return
     */
    public boolean persist(String key) {
        return redisTemplate.boundValueOps(key).persist();
    }

    //- - - - - - - - - - - - - - - - - - - - -  String类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 根据key获取值
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 将值放入缓存
     *
     * @param key   键
     * @param value 值
     * @return true成功 false 失败
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 将值放入缓存并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) -1为无期限
     * @return true成功 false 失败
     */
    public void set(String key, String value, long time) {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set(key, value);
        }
    }

    /**
     * 批量添加 key (重复的键会覆盖)
     *
     * @param keyAndValue
     */
    public void batchSet(Map<String, String> keyAndValue) {
        redisTemplate.opsForValue().multiSet(keyAndValue);
    }

    /**
     * 批量添加 key-value 只有在键不存在时,才添加
     * map 中只要有一个key存在,则全部不添加
     *
     * @param keyAndValue
     */
    public void batchSetIfAbsent(Map<String, String> keyAndValue) {
        redisTemplate.opsForValue().multiSetIfAbsent(keyAndValue);
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     *
     * @param key
     * @param number
     */
    public Long increment(String key, long number) {
        return redisTemplate.opsForValue().increment(key, number);
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是 纯数字 ,将报错
     *
     * @param key
     * @param number
     */
    public Double increment(String key, double number) {
        return redisTemplate.opsForValue().increment(key, number);
    }

    //- - - - - - - - - - - - - - - - - - - - -  set类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 将数据放入set缓存
     *
     * @param key 键
     * @return
     */
    public void sSet(String key, String value) {
        redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 获取变量中的值
     *
     * @param key 键
     * @return
     */
    public Set<Object> members(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 随机获取变量中指定个数的元素
     *
     * @param key   键
     * @param count 值
     * @return
     */
    public void randomMembers(String key, long count) {
        redisTemplate.opsForSet().randomMembers(key, count);
    }

    /**
     * 随机获取变量中的元素
     *
     * @param key 键
     * @return
     */
    public Object randomMember(String key) {
        return redisTemplate.opsForSet().randomMember(key);
    }

    /**
     * 弹出变量中的元素
     *
     * @param key 键
     * @return
     */
    public Object pop(String key) {
        return redisTemplate.opsForSet().pop("setValue");
    }

    /**
     * 获取变量中值的长度
     *
     * @param key 键
     * @return
     */
    public long size(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 检查给定的元素是否在变量中。
     *
     * @param key 键
     * @param obj 元素对象
     * @return
     */
    public boolean isMember(String key, Object obj) {
        return redisTemplate.opsForSet().isMember(key, obj);
    }

    /**
     * 转移变量的元素值到目的变量。
     *
     * @param key     键
     * @param value   元素对象
     * @param destKey 元素对象
     * @return
     */
    public boolean move(String key, String value, String destKey) {
        return redisTemplate.opsForSet().move(key, value, destKey);
    }

    /**
     * 批量移除set缓存中元素
     *
     * @param key    键
     * @param values 值
     * @return
     */
    public void remove(String key, Object... values) {
        redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 通过给定的key求2个set变量的差值
     *
     * @param key     键
     * @param destKey 键
     * @return
     */
    public Set<Set> difference(String key, String destKey) {
        return redisTemplate.opsForSet().difference(key, destKey);
    }


    //- - - - - - - - - - - - - - - - - - - - -  hash类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 加入缓存
     *
     * @param key 键
     * @param map 键
     * @return
     */
    public void add(String key, Map<String, String> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 获取 key 下的 所有  hashkey 和 value
     *
     * @param key 键
     * @return
     */
    public Map<Object, Object> getHashEntries(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 验证指定 key 下 有没有指定的 hashkey
     *
     * @param key
     * @param hashKey
     * @return
     */
    public boolean hashKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    /**
     * 获取指定key的值string
     *
     * @param key  键
     * @param key2 键
     * @return
     */
    public String getMapString(String key, String key2) {
        return redisTemplate.opsForHash().get("map1", "key1").toString();
    }

    /**
     * 获取指定的值Int
     *
     * @param key  键
     * @param key2 键
     * @return
     */
    public Integer getMapInt(String key, String key2) {
        return (Integer) redisTemplate.opsForHash().get("map1", "key1");
    }

    /**
     * 弹出元素并删除
     *
     * @param key 键
     * @return
     */
    public String popValue(String key) {
        return redisTemplate.opsForSet().pop(key).toString();
    }

    /**
     * 删除指定 hash 的 HashKey
     *
     * @param key
     * @param hashKeys
     * @return 删除成功的 数量
     */
    public Long delete(String key, String... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    /**
     * 给指定 hash 的 hashkey 做增减操作
     *
     * @param key
     * @param hashKey
     * @param number
     * @return
     */
    public Long increment(String key, String hashKey, long number) {
        return redisTemplate.opsForHash().increment(key, hashKey, number);
    }

    /**
     * 给指定 hash 的 hashkey 做增减操作
     *
     * @param key
     * @param hashKey
     * @param number
     * @return
     */
    public Double increment(String key, String hashKey, Double number) {
        return redisTemplate.opsForHash().increment(key, hashKey, number);
    }

    /**
     * 获取 key 下的 所有 hashkey 字段
     *
     * @param key
     * @return
     */
    public Set<Object> hashKeys(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    /**
     * 获取指定 hash 下面的 键值对 数量
     *
     * @param key
     * @return
     */
    public Long hashSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    //- - - - - - - - - - - - - - - - - - - - -  list类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 在变量左边添加元素值
     *
     * @param key
     * @param value
     * @return
     */
    public void leftPush(String key, Object value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 获取集合指定位置的值。
     *
     * @param key
     * @param index
     * @return
     */
    public Object index(String key, long index) {
        return redisTemplate.opsForList().index("list", 1);
    }

    /**
     * 获取指定区间的值。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<Object> range(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 把最后一个参数值放到指定集合的第一个出现中间参数的前面,
     * 如果中间参数值存在的话。
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public void leftPush(String key, String pivot, String value) {
        redisTemplate.opsForList().leftPush(key, pivot, value);
    }

    /**
     * 向左边批量添加参数元素。
     *
     * @param key
     * @param values
     * @return
     */
    public void leftPushAll(String key, String... values) {
//        redisTemplate.opsForList().leftPushAll(key,"w","x","y");
        redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 向集合最右边添加元素。
     *
     * @param key
     * @param value
     * @return
     */
    public void leftPushAll(String key, String value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 向左边批量添加参数元素。
     *
     * @param key
     * @param values
     * @return
     */
    public void rightPushAll(String key, String... values) {
        //redisTemplate.opsForList().leftPushAll(key,"w","x","y");
        redisTemplate.opsForList().rightPushAll(key, values);
    }

    /**
     * 向已存在的集合中添加元素。
     *
     * @param key
     * @param value
     * @return
     */
    public void rightPushIfPresent(String key, Object value) {
        redisTemplate.opsForList().rightPushIfPresent(key, value);
    }

    /**
     * 向已存在的集合中添加元素。
     *
     * @param key
     * @return
     */
    public long listLength(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 移除集合中的左边第一个元素。
     *
     * @param key
     * @return
     */
    public void leftPop(String key) {
        redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
     *
     * @param key
     * @return
     */
    public void leftPop(String key, long timeout, TimeUnit unit) {
        redisTemplate.opsForList().leftPop(key, timeout, unit);
    }

    /**
     * 移除集合中右边的元素。
     *
     * @param key
     * @return
     */
    public void rightPop(String key) {
        redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
     *
     * @param key
     * @return
     */
    public void rightPop(String key, long timeout, TimeUnit unit) {
        redisTemplate.opsForList().rightPop(key, timeout, unit);
    }
}
创建RedisController

代码如下(示例):

package com.example.redisdemo.controller;

/**
 * @author zhiweiLiao<zhiwei.liao @ sgs.com>
 * @Description
 * @Date create in 2022/9/12 0012 11:35
 */

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @className: RedisController
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-08 14:28
 */
@RestController
@RequestMapping("/redis")
public class RedisController {

    private final RedisTemplate redisTemplate;

    public RedisController(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @GetMapping("/setValueAndGetValue")
    public Object setValueAndGetValue(String key, String value){
        redisTemplate.opsForValue().set(key, value);
        return redisTemplate.opsForValue().get(key);
    }

}


校验redis是否正常工作

启动项目

如下图(示例):
在这里插入图片描述

访问接口http://localhost:8080/redis/setValueAndGetValue?key=liao&value=zhiwei

如下图(示例):

在这里插入图片描述正常吐出数据,说明redis已经可以正常工作了

.版本 2 .程序集 千寻微信框架_SDK, , , QxWeChat_SDK .全局变量 规则名称, 文本型, , "0" ' 规则名称数组 .全局变量 规则群组, 文本型, , "0" ' 对应的群ID数组 .全局变量 用户等待, 文本型, , "0" ' 存储等待回复的用户信息 .子程序 _启动子程序, 整数型 返回 (0) .子程序结束 .子程序 Qx_EventEnable, 整数型, 公开 加载规则 () 返回 (#事件处理_同意) .子程序结束 .子程序 加载规则 .局部变量 配置路径, 文本型 .局部变量 内容数组, 文本型, , "0" .局部变量 i, 整数型 配置路径 = 取运行目录() + "\data\plugin\群发规则.txt" ' 自动创建示例文件 .如果真 (文件是否存在(配置路径) = 假) 创建目录(取运行目录() + "\data\plugin\") 写文本文件(配置路径, "规则1:群ID1,群ID2" + #换行符 + "规则2:群ID3") .如果真结束 内容数组 = 读入文本文件(配置路径) 重定义数组(规则名称, 取数组成员数(内容数组)) 重定义数组(规则群组, 取数组成员数(内容数组)) .计次循环首(取数组成员数(规则名称), i) .如果真 (寻找文本(内容数组[i], ":", , 假) ≠ -1) 规则名称[i] = 取文本左边(内容数组[i], 寻找文本(内容数组[i], ":", , 假)) 规则群组[i] = 取文本右边(内容数组[i], 内容数组[i].长度 - 寻找文本(内容数组[i], ":", , 假) - 1) .否则 规则名称[i] = "规则" + 到文本(i + 1) 规则群组[i] = "" .如果真结束 .计次循环尾() ' 刷新设置窗口显示 .如果真 (是否已创建(窗口_设置)) 窗口_设置.规则列表.列表项 = 到文本(规则名称) .如果真结束 .子程序结束 .子程序 Qx_EventPrivateMsg, 整数型, 公开 .参数 robot_wxid, 文本型 .参数 jsonStr, 文本型 .局部变量 消息数据, 事件_数据_消息 .局部变量 用户索引, 整数型 .局部变量 选择序号, 整数型 消息数据 = 事件_解析消息(jsonStr) ' 只处理自己发送的消息 .如果真 (消息数据.fromWxid ≠ robot_wxid) 返回 (#消息处理_继续) .如果真结束 ' 检测触发关键词 .如果真 (消息数据.消息内容.右边(4) = "群发消息") .如果真 (取数组成员数(规则名称) = 0) Api.发送文本消息(robot_wxid, robot_wxid, "请先配置群发规则", , ) 返回 (#消息处理_结束) .如果真结束 用户索引 = 查找用户(robot_wxid) .如果真 (用户索引 = -1) 用户索引 = 加入成员(user等待, ) .如果真结束 user等待[user索引] = 消息数据.消息内容.左边(消息数据.消息内容.长度 - 4) Api.发送文本消息(robot_wxid, robot_wxid, 生成规则菜单(), , ) 返回 (#消息处理_结束) .如果真结束 ' 处理规则选择 .如果真 (是否为数值(消息数据.消息内容)) 选择序号 = 到整数(消息数据.消息内容) - 1 .如果真 (选择序号 ≥ 0 且 选择序号 < 取数组成员数(规则名称)) 执行群发(robot_wxid, 取用户消息(robot_wxid), 选择序号) 清除用户(robot_wxid) Api.发送文本消息(robot_wxid, robot_wxid, "已执行群发", , ) 返回 (#消息处理_结束) .如果真结束 .如果真结束 返回 (#消息处理_继续) .子程序结束 .子程序 生成规则菜单, 文本型 .局部变量 菜单, 文本型 .局部变量 i, 整数型 菜单 = "请选择群发规则(回复序号):" .计次循环首(取数组成员数(规则名称), i) 菜单 = 菜单 + #换行符 + 到文本(i + 1) + ". " + 规则名称[i] .计次循环尾() 返回 (菜单) .子程序结束 .子程序 执行群发 .参数 robot_wxid, 文本型 .参数 消息内容, 文本型 .参数 规则索引, 整数型 .局部变量 群数组, 文本型, , "0" .局部变量 i, 整数型 群数组 = 分割文本(规则群组[规则索引], ",", ) .计次循环首(取数组成员数(群数组), i) Api.发送文本消息(robot_wxid, 群数组[i], 消息内容, , ) .计次循环尾() .子程序结束 .子程序 查找用户, 整数型 .参数 robot_wxid, 文本型 .计次循环首(取数组成员数(user等待), ) .如果真 (user等待[] = robot_wxid) 返回 (循环变量 - 1) .如果真结束 .计次循环尾() 返回 (-1) .子程序结束 .子程序 取用户消息, 文本型 .参数 robot_wxid, 文本型 .局部变量 用户索引, 整数型 用户索引 = 查找用户(robot_wxid) .如果真 (用户索引 ≠ -1) 返回 (user等待[user索引]) .否则 返回 ("") .如果真结束 .子程序结束 .子程序 清除用户 .参数 robot_wxid, 文本型 .局部变量 用户索引, 整数型 用户索引 = 查找用户(robot_wxid) .如果真 (用户索引 ≠ -1) 删除成员(user等待, 用户索引) .如果真结束 .子程序结束 ' --------------- 设置窗口相关代码 --------------- .子程序 Qx_Set, , 公开 载入(窗口_设置, , 假) .子程序结束 .窗口程序集 窗口_设置 .程序集变量 规则列表, 列表框, , "规则列表" .程序集变量 重新加载按钮, 按钮, , "重新加载" .子程序 __启动窗口_创建完毕 规则列表.加入项目 (, 0) 规则列表.列表项 = 到文本(规则名称) .子程序结束 .子程序 重新加载按钮_被单击 加载规则 () Api.发送文本消息 (Api.获取当前机器人ID(), Api.获取当前机器人ID(), "规则已重新加载", , ) .子程序结束 .窗口程序集结束 ' 其他事件处理保持默认实现 .子程序 Qx_EventPluginIns, 整数型, 公开 返回 (#事件处理_同意) .子程序结束 .子程序 Qx_EventInject, 整数型, 公开 Api.输出日志 (“有微信注入成功”, , ) 返回 (#消息处理_继续) .子程序结束 帮我看看以上代码有没有错误
03-27
.版本 2 .程序集 千寻微信框架_SDK, , , QxWeChat_SDK .全局变量 规则列表, 规则结构, , "0" ' 存储所有规则 .全局变量 用户状态, 用户状态结构, , "0" ' 存储用户交互状态 .全局变量 应用目录, 文本型 ' 插件数据存储目录 .结构体 规则结构 .成员 规则名称, 文本型 .成员 群组列表, 文本型, , "0" .结束结构体 .结构体 用户状态结构 .成员 等待选择, 逻辑型 .成员 消息内容, 文本型 .成员 开始时间, 整数型 .成员 机器人ID, 文本型 .结束结构体 .子程序 _启动子程序, 整数型 应用目录 = 取运行目录() + "\data\plugin\群发助手\" 返回 (0) .子程序结束 .子程序 Qx_EventEnable, 整数型, 公开 读取规则配置() 返回 (#事件处理_同意) .子程序结束 .子程序 读取规则配置 .局部变量 配置路径, 文本型 .局部变量 规则数量, 整数型 .局部变量 节名数组, 文本型, , "0" .局部变量 i, 整数型 配置路径 = 应用目录 + "rules.ini" .如果真 (文件是否存在(配置路径) = 假) 创建目录(应用目录) 写配置项(配置路径, "Rule1", "Name", "默认规则") 写配置项(配置路径, "Rule1", "Groups", "群ID1,群ID2") .如果真结束 规则数量 = 取配置节名(配置路径, , 节名数组) 重定义数组(规则列表, 规则数量) .计次循环首(规则数量, i) 规则列表[i].规则名称 = 读配置项(配置路径, 节名数组[i], "Name", "规则" + 到文本(i + 1)) 规则列表[i].群组列表 = 分割文本(读配置项(配置路径, 节名数组[i], "Groups", ""), ",", ) .计次循环尾() .子程序结束 .子程序 Qx_EventPrivateMsg, 整数型, 公开 .参数 robot_wxid, 文本型 .参数 jsonStr, 文本型 .局部变量 消息数据, 事件_数据_消息 .局部变量 用户索引, 整数型 .局部变量 超时时间, 整数型 .局部变量 选择序号, 整数型 消息数据 = 事件_解析消息(jsonStr) ' 只处理自己发送的消息 .如果真 (消息数据.fromWxid ≠ robot_wxid) 返回 (#消息处理_继续) .如果真结束 ' 检测触发关键词 .如果真 (消息数据.消息内容.右边(4) = "群发消息") .如果真 (规则列表.长度 = 0) Api.发送文本消息(robot_wxid, robot_wxid, "请先配置规则文件", , ) 返回 (#消息处理_结束) .如果真结束 用户索引 = 查找用户状态(robot_wxid) .如果真 (用户索引 = -1) 用户索引 = 加入成员(user状态, ) .如果真结束 user状态[user索引].等待选择 = 真 user状态[user索引].消息内容 = 消息数据.消息内容.左边(消息数据.消息内容.长度 - 4) user状态[user索引].开始时间 = 取现行时间() user状态[user索引].机器人ID = robot_wxid Api.发送文本消息(robot_wxid, robot_wxid, 生成规则菜单(), , ) 返回 (#消息处理_结束) .如果真结束 ' 处理规则选择 user索引 = 查找用户状态(robot_wxid) .如果真 (user索引 ≠ -1 且 user状态[user索引].等待选择) 超时时间 = 取现行时间() - user状态[user索引].开始时间 .如果真 (超时时间 > 30000) 清除用户状态(robot_wxid) Api.发送文本消息(robot_wxid, robot_wxid, "选择超时,请重新发送", , ) 返回 (#消息处理_结束) .如果真结束 .如果真 (是否为数值(消息数据.消息内容)) 选择序号 = 到整数(消息数据.消息内容) - 1 .如果真 (选择序号 ≥ 0 且 选择序号 < 规则列表.长度) 执行群发(robot_wxid, user状态[user索引].消息内容, 选择序号) 清除用户状态(robot_wxid) Api.发送文本消息(robot_wxid, robot_wxid, "群发任务已执行", , ) 返回 (#消息处理_结束) .如果真结束 .如果真结束 Api.发送文本消息(robot_wxid, robot_wxid, "请回复有效的序号", , ) 返回 (#消息处理_结束) .如果真结束 返回 (#消息处理_继续) .子程序结束 .子程序 生成规则菜单, 文本型 .局部变量 菜单, 文本型 .局部变量 i, 整数型 菜单 = "请选择群发规则(30秒内回复序号):" .计次循环首(规则列表.长度, i) 菜单 = 菜单 + #换行符 + 到文本(i + 1) + ". " + 规则列表[i].规则名称 .计次循环尾() 返回 (菜单) .子程序结束 .子程序 执行群发 .参数 robot_wxid, 文本型 .参数 消息内容, 文本型 .参数 规则索引, 整数型 .局部变量 i, 整数型 .计次循环首(规则列表[规则索引].群组列表.长度, i) Api.发送文本消息(robot_wxid, 规则列表[规则索引].群组列表[i], 消息内容, , ) .计次循环尾() .子程序结束 .子程序 查找用户状态, 整数型 .参数 robot_wxid, 文本型 .计次循环首(user状态.长度, ) .如果真 (user状态[].机器人ID = robot_wxid) 返回 (循环变量 - 1) .如果真结束 .计次循环尾() 返回 (-1) .子程序结束 .子程序 清除用户状态 .参数 robot_wxid, 文本型 .局部变量 用户索引, 整数型 user索引 = 查找用户状态(robot_wxid) .如果真 (user索引 ≠ -1) 删除成员(user状态, user索引) .如果真结束 .子程序结束 ' 其他事件处理保持原样 .子程序 Qx_EventPluginIns, 整数型, 公开 返回 (#事件处理_同意) .子程序结束 ' 以下事件处理保留默认实现,仅修改必要部分 .子程序 Qx_EventEnable, 整数型, 公开 读取规则配置() 返回 (#事件处理_同意) .子程序结束 ' 其他事件处理保持不变 以上代码中结构体是什么意思
03-27
.版本 2 .程序集 程序集1 .程序集变量 待发送内容, 文本型 ' 存储用户要群发的消息内容 .程序集变量 当前状态, 整数型 ' 记录交互状态:0=待命 1=等待选择规则 .程序集变量 规则缓存数组, 文本型, , "0" ' 存储群发规则列表 .程序集变量 超时时间戳, 长整数型 ' 记录最后一次操作时间 '★ 消息处理入口 ★ .子程序 Qx_EventPrivateMsg, 整数型, 公开 .参数 robot_wxid, 文本型 ' 当前微信账号的ID .参数 jsonStr, 文本型 ' 收到的消息数据 .局部变量 事件数据, 事件_数据_消息 事件数据 = 事件_解析消息(jsonStr) ' 解析原始JSON消息 '━━━━━━ 安全验证层 ━━━━━━ '★ 核心验证:仅允许自己发给自己 ★ .如果真 (事件数据.fromWxid ≠ robot_wxid) ' 过滤他人/群聊消息 返回 (#消息处理_继续) ' 不拦截消息,让其他消息正常传递 .如果真结束 '━━━━━━ 超时检测 ━━━━━━ .如果真 (当前状态 = 1) ' 处于等待选择规则状态 .如果真 (取现行时间戳() - 超时时间戳 > 30) ' 超过30秒未响应 Api.发送文本消息(robot_wxid, 事件数据.fromWxid, "〖超时〗请重新发送群发内容") 当前状态 = 0 ' 重置状态 返回 (#消息处理_拦截) ' 拦截超时提示消息 .如果真结束 .如果真结束 '━━━━━━ 触发群发流程 ━━━━━━ '★ 检测触发词"群发消息" ★ .如果真 (寻找文本(事件数据.消息内容, "群发消息", , 假) ≠ -1) ' 判断消息结尾 待发送内容 = 取文本左边(事件数据.消息内容, 取文本长度(事件数据.消息内容) - 4) ' 移除末尾4字符(触发词) .如果真 (生成规则列表(规则缓存数组) = 假) ' 加载群发规则失败 Api.发送文本消息(robot_wxid, 事件数据.fromWxid, "〖错误〗未找到群发规则") 返回 (#消息处理_拦截) ' 终止流程 .如果真结束 Api.发送文本消息(robot_wxid, 事件数据.fromWxid, "请回复序号选择规则(30秒有效):" + #换行符 + 生成序号列表()) 当前状态 = 1 ' 进入等待选择状态 超时时间戳 = 取现行时间戳() ' 记录操作时间 返回 (#消息处理_拦截) ' 拦截触发消息 .如果真结束 '━━━━━━ 处理规则选择 ━━━━━━ .如果真 (当前状态 = 1) ' 处于等待选择状态 处理规则选择(robot_wxid, 事件数据.fromWxid, 事件数据.消息内容) ' 调用选择处理函数 当前状态 = 0 ' 重置状态 返回 (#消息处理_拦截) ' 拦截选择指令 .如果真结束 返回 (#消息处理_继续) ' 未触发任何流程则放行消息 '━━━━━━━━━━━━━━━━━━ '★ 规则选择处理函数(保持原有逻辑)★ .子程序 处理规则选择 .参数 robot_wxid, 文本型 .参数 sender_wxid, 文本型 .参数 选择内容, 文本型 .局部变量 序号, 整数型 序号 = 到整数(选择内容) .如果 (序号 > 0 且 序号 ≤ 取数组成员数(规则缓存数组)) Api.群发消息(robot_wxid, 规则缓存数组[序号], 待发送内容) Api.发送文本消息(robot_wxid, sender_wxid, "已向【" + 规则缓存数组[序号] + "】群发成功") .否则 Api.发送文本消息(robot_wxid, sender_wxid, "〖错误〗无效序号") .如果结束 '★ 生成规则列表函数(示例)★ .子程序 生成规则列表, 逻辑型 .参数 输出数组, 文本型, 参考 数组 '--这里需要实现从配置文件读取群号列表-- 输出数组 = { "技术交流群@chatroom", "客户服务群@chatroom" } ' 示例数据 返回 真 以上是你发给我的代码出现了错误(37): 找不到指定的命令/子程序/Dll命令调用名称“生成序号列表”。
03-27
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java程序员廖志伟

赏我包辣条呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值