欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > Redis

Redis

2025/3/16 23:41:34 来源:https://blog.csdn.net/weixin_51040479/article/details/146278315  浏览:    关键词:Redis

Spring Boot 整合 Redis

1、引入依赖

       <!-- Spring Boot Data Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- Redis连接池 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>

2、Redis配置(application.yml) 

  # Redis配置redis:host: localhostport: 6379database: 0password:  # 如果有密码,请设置timeout: 10000mslettuce:pool:max-active: 8max-wait: -1msmax-idle: 8min-idle: 0

3. RedisConfig配置类

package com.example.testlogin.config;
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 {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {// 创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂template.setConnectionFactory(connectionFactory);// 创建JSON序列化器Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);jackson2JsonRedisSerializer.setObjectMapper(om);// 创建String序列化器StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// 设置key的序列化方式为Stringtemplate.setKeySerializer(stringRedisSerializer);// 设置hash key的序列化方式为Stringtemplate.setHashKeySerializer(stringRedisSerializer);// 设置value的序列化方式为JSONtemplate.setValueSerializer(jackson2JsonRedisSerializer);// 设置hash value的序列化方式为JSONtemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}


RedisTemplate 操作 Redis 的五种核心数据类型

一、String

声明方式

// 注入
@Autowired
private RedisTemplate<String, Object> redisTemplate;// 获取String操作类
ValueOperations<String, Object> valueOps = redisTemplate.opsForValue();

Redis String类型操作工具类 

package com.example.testlogin.util.redis.string;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** Redis String类型操作工具类*/
@Component
public class RedisStringUtils {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 获取操作String类型的ValueOperations对象*/private ValueOperations<String, Object> valueOps() {return redisTemplate.opsForValue();}// ========== 基本操作 ==========/*** 设置键值对*/public void set(String key, Object value) {valueOps().set(key, value);}/*** 设置键值对并设置过期时间*/public void set(String key, Object value, long timeout, TimeUnit unit) {valueOps().set(key, value, timeout, unit);}/*** 获取指定key的值*/public Object get(String key) {return valueOps().get(key);}/*** 删除指定key*/public Boolean delete(String key) {return redisTemplate.delete(key);}/*** 批量删除key*/public Long delete(Collection<String> keys) {return redisTemplate.delete(keys);}/*** 判断key是否存在*/public Boolean hasKey(String key) {return redisTemplate.hasKey(key);}/*** 设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}// ========== 批量操作 ==========/*** 批量设置key-value*/public void multiSet(Map<String, Object> map) {valueOps().multiSet(map);}/*** 批量获取key-value*/public List<Object> multiGet(Collection<String> keys) {return valueOps().multiGet(keys);}// ========== 原子操作 ==========/*** 递增*/public Long increment(String key) {return valueOps().increment(key);}/*** 递增指定步长*/public Long increment(String key, long delta) {return valueOps().increment(key, delta);}/*** 递减*/public Long decrement(String key) {return valueOps().decrement(key);}/*** 递减指定步长*/public Long decrement(String key, long delta) {return valueOps().decrement(key, -delta);}/*** 追加字符串*/public Integer append(String key, String value) {return valueOps().append(key, value);}/*** 获取字符串长度*/public Long size(String key) {return valueOps().size(key);}// ========== 位操作 ==========/*** 设置位图中offset位置的值*/public Boolean setBit(String key, long offset, boolean value) {return valueOps().setBit(key, offset, value);}/*** 获取位图中offset位置的值*/public Boolean getBit(String key, long offset) {return valueOps().getBit(key, offset);}// ========== 特殊操作 ==========/*** 仅当key不存在时设置值(原子操作)*/public Boolean setIfAbsent(String key, Object value) {return valueOps().setIfAbsent(key, value);}/*** 仅当key不存在时设置值并设置过期时间(原子操作)*/public Boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {return valueOps().setIfAbsent(key, value, timeout, unit);}/*** 仅当key存在时设置值(原子操作)*/public Boolean setIfPresent(String key, Object value) {return valueOps().setIfPresent(key, value);}/*** 获取指定范围的字符串*/public String getRange(String key, long start, long end) {return valueOps().get(key, start, end);}/*** 设置从指定偏移量开始的子字符串*/public void setRange(String key, Object value, long offset) {valueOps().set(key, value, offset);}
}

支持的操作

二、Hash

声明方式

// 获取Hash操作类
HashOperations<String, Object, Object> hashOps = redisTemplate.opsForHash();

Redis Hash类型操作工具类 

package com.example.testlogin.util.redis.map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Redis Hash类型操作工具类*/
@Component
public class RedisHashUtils {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 获取操作Hash类型的HashOperations对象*/private HashOperations<String, String, Object> hashOps() {return redisTemplate.opsForHash();}// ========== 基本操作 ==========/*** 设置Hash的属性值*/public void put(String key, String hashKey, Object value) {hashOps().put(key, hashKey, value);}/*** 批量设置Hash的属性值*/public void putAll(String key, Map<String, Object> map) {hashOps().putAll(key, map);}/*** 获取Hash中指定属性的值*/public Object get(String key, String hashKey) {return hashOps().get(key, hashKey);}/*** 获取Hash中的所有属性值*/public Map<String, Object> entries(String key) {return hashOps().entries(key);}/*** 删除Hash中一个或多个属性*/public Long delete(String key, Object... hashKeys) {return hashOps().delete(key, hashKeys);}/*** 判断Hash中是否存在指定属性*/public Boolean hasKey(String key, String hashKey) {return hashOps().hasKey(key, hashKey);}/*** 获取Hash中所有的key*/public Set<String> keys(String key) {return hashOps().keys(key);}/*** 获取Hash中所有的value*/public List<Object> values(String key) {return hashOps().values(key);}/*** 获取Hash中属性的数量*/public Long size(String key) {return hashOps().size(key);}/*** 为整个Hash设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}/*** 删除整个Hash*/public Boolean delete(String key) {return redisTemplate.delete(key);}// ========== 批量操作 ==========/*** 批量获取多个属性的值*/public List<Object> multiGet(String key, Collection<String> hashKeys) {return hashOps().multiGet(key, hashKeys);}// ========== 原子操作 ==========/*** Hash中的属性值递增指定步长*/public Long increment(String key, String hashKey, long delta) {return hashOps().increment(key, hashKey, delta);}/*** Hash中的属性值递增浮点数*/public Double increment(String key, String hashKey, double delta) {return hashOps().increment(key, hashKey, delta);}// ========== 特殊操作 ==========/*** 仅当hashKey不存在时才设置值(原子操作)*/public Boolean putIfAbsent(String key, String hashKey, Object value) {return hashOps().putIfAbsent(key, hashKey, value);}/*** 获取Hash中指定属性和值的数量*/public Long lengthOfValue(String key, String hashKey) {// 获取value的类型,如果是字符串,则返回其长度Object value = get(key, hashKey);if (value instanceof String) {return (long) ((String) value).length();}return 0L;}
}

支持的操作

三、List

声明方式

// 获取List操作类
ListOperations<String, Object> listOps = redisTemplate.opsForList();

Redis List类型操作工具类 

package com.example.testlogin.util.redis.list;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** Redis List类型操作工具类*/
@Component
public class RedisListUtils {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 获取操作List类型的ListOperations对象*/private ListOperations<String, Object> listOps() {return redisTemplate.opsForList();}// ========== 基本操作 ==========/*** 将元素添加到列表左端*/public Long leftPush(String key, Object value) {return listOps().leftPush(key, value);}/*** 将多个元素添加到列表左端*/public Long leftPushAll(String key, Object... values) {return listOps().leftPushAll(key, values);}/*** 将集合中的元素添加到列表左端*/public Long leftPushAll(String key, Collection<Object> values) {return listOps().leftPushAll(key, values.toArray());}/*** 将元素添加到列表右端*/public Long rightPush(String key, Object value) {return listOps().rightPush(key, value);}/*** 将多个元素添加到列表右端*/public Long rightPushAll(String key, Object... values) {return listOps().rightPushAll(key, values);}/*** 将集合中的元素添加到列表右端*/public Long rightPushAll(String key, Collection<Object> values) {return listOps().rightPushAll(key, values.toArray());}/*** 从列表左端弹出一个元素*/public Object leftPop(String key) {return listOps().leftPop(key);}/*** 从列表右端弹出一个元素*/public Object rightPop(String key) {return listOps().rightPop(key);}/*** 从列表左端弹出一个元素,如果列表为空则阻塞指定时间*/public Object leftPop(String key, long timeout, TimeUnit unit) {return listOps().leftPop(key, timeout, unit);}/*** 从列表右端弹出一个元素,如果列表为空则阻塞指定时间*/public Object rightPop(String key, long timeout, TimeUnit unit) {return listOps().rightPop(key, timeout, unit);}/*** 获取列表长度*/public Long size(String key) {return listOps().size(key);}/*** 获取指定范围的元素*/public List<Object> range(String key, long start, long end) {return listOps().range(key, start, end);}/*** 获取指定索引位置的元素*/public Object index(String key, long index) {return listOps().index(key, index);}/*** 修改指定索引位置的元素*/public void set(String key, long index, Object value) {listOps().set(key, index, value);}/*** 从列表中删除指定数量的元素* count > 0: 从头到尾删除count个与value相等的元素* count < 0: 从尾到头删除count个与value相等的元素* count = 0: 删除所有与value相等的元素*/public Long remove(String key, long count, Object value) {return listOps().remove(key, count, value);}/*** 删除整个列表*/public Boolean delete(String key) {return redisTemplate.delete(key);}/*** 为列表设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}/*** 裁剪列表,只保留指定范围内的元素*/public void trim(String key, long start, long end) {listOps().trim(key, start, end);}// ========== 特殊操作 ==========/*** 只有当列表存在时,才从左端添加元素*/public Long leftPushIfPresent(String key, Object value) {return listOps().leftPushIfPresent(key, value);}/*** 只有当列表存在时,才从右端添加元素*/public Long rightPushIfPresent(String key, Object value) {return listOps().rightPushIfPresent(key, value);}/*** 将一个列表的最右边的元素弹出,并插入到另一个列表的最左边*/public Object rightPopAndLeftPush(String sourceKey, String destinationKey) {return listOps().rightPopAndLeftPush(sourceKey, destinationKey);}/*** 将一个列表的最右边的元素弹出,并插入到另一个列表的最左边,如果列表为空则阻塞指定时间*/public Object rightPopAndLeftPush(String sourceKey, String destinationKey, long timeout, TimeUnit unit) {return listOps().rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit);}
}

支持的操作 

四、Set 

声明方式

// 获取Set操作类
SetOperations<String, Object> setOps = redisTemplate.opsForSet();

Redis Set类型操作工具类

package com.example.testlogin.util.redis.set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Redis Set类型操作工具类*/
@Component
public class RedisSetUtils {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 获取操作Set类型的SetOperations对象*/private SetOperations<String, Object> setOps() {return redisTemplate.opsForSet();}// ========== 基本操作 ==========/*** 向集合中添加一个或多个元素*/public Long add(String key, Object... values) {return setOps().add(key, values);}/*** 从集合中删除一个或多个元素*/public Long remove(String key, Object... values) {return setOps().remove(key, values);}/*** 随机移除并返回集合中的一个元素*/public Object pop(String key) {return setOps().pop(key);}/*** 随机移除并返回集合中的多个元素*/public List<Object> pop(String key, long count) {return setOps().pop(key, count);}/*** 将元素从一个集合移动到另一个集合*/public Boolean move(String sourceKey, Object value, String destinationKey) {return setOps().move(sourceKey, value, destinationKey);}/*** 获取集合大小*/public Long size(String key) {return setOps().size(key);}/*** 判断集合中是否包含指定元素*/public Boolean isMember(String key, Object value) {return setOps().isMember(key, value);}/*** 获取集合中的所有元素*/public Set<Object> members(String key) {return setOps().members(key);}/*** 随机获取集合中的一个元素,但不删除*/public Object randomMember(String key) {return setOps().randomMember(key);}/*** 随机获取集合中的多个元素,但不删除*/public List<Object> randomMembers(String key, long count) {return setOps().randomMembers(key, count);}/*** 随机获取集合中的多个不重复元素,但不删除*/public Set<Object> distinctRandomMembers(String key, long count) {return setOps().distinctRandomMembers(key, count);}/*** 删除整个集合*/public Boolean delete(String key) {return redisTemplate.delete(key);}/*** 为集合设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}// ========== 集合间操作 ==========/*** 获取两个集合的交集*/public Set<Object> intersect(String key, String otherKey) {return setOps().intersect(key, otherKey);}/*** 获取多个集合的交集*/public Set<Object> intersect(Collection<String> keys) {return setOps().intersect(keys);}/*** 获取两个集合的交集并存储到目标集合中*/public Long intersectAndStore(String key, String otherKey, String destinationKey) {return setOps().intersectAndStore(key, otherKey, destinationKey);}/*** 获取多个集合的交集并存储到目标集合中*/public Long intersectAndStore(Collection<String> keys, String destinationKey) {return setOps().intersectAndStore(keys, destinationKey);}/*** 获取两个集合的并集*/public Set<Object> union(String key, String otherKey) {return setOps().union(key, otherKey);}/*** 获取多个集合的并集*/public Set<Object> union(Collection<String> keys) {return setOps().union(keys);}/*** 获取两个集合的并集并存储到目标集合中*/public Long unionAndStore(String key, String otherKey, String destinationKey) {return setOps().unionAndStore(key, otherKey, destinationKey);}/*** 获取多个集合的并集并存储到目标集合中*/public Long unionAndStore(Collection<String> keys, String destinationKey) {return setOps().unionAndStore(keys, destinationKey);}/*** 获取两个集合的差集(key中存在,otherKey中不存在的元素)*/public Set<Object> difference(String key, String otherKey) {return setOps().difference(key, otherKey);}/*** 获取多个集合的差集(第一个key中存在,其他key中不存在的元素)*/public Set<Object> difference(Collection<String> keys) {return setOps().difference(keys);}/*** 获取两个集合的差集并存储到目标集合中*/public Long differenceAndStore(String key, String otherKey, String destinationKey) {return setOps().differenceAndStore(key, otherKey, destinationKey);}/*** 获取多个集合的差集并存储到目标集合中*/public Long differenceAndStore(Collection<String> keys, String destinationKey) {return setOps().differenceAndStore(keys, destinationKey);}// ========== 批量操作 ==========/*** 批量判断元素是否为集合成员*/public Map<Object, Boolean> isMember(String key, Object... values) {return setOps().isMember(key, values);}
}

支持的操作 

五、ZSet 

声明方式

// 获取ZSet操作类
ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();

Redis ZSet(有序集合)类型操作工具类

package com.example.testlogin.util.redis.zset;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** Redis ZSet(有序集合)类型操作工具类*/
@Component
public class RedisZSetUtils {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;/*** 获取操作ZSet类型的ZSetOperations对象*/private ZSetOperations<String, Object> zSetOps() {return redisTemplate.opsForZSet();}// ========== 基本操作 ==========/*** 向有序集合中添加元素,如果已存在则更新分数*/public Boolean add(String key, Object value, double score) {return zSetOps().add(key, value, score);}/*** 向有序集合中批量添加元素*/public Long add(String key, Map<Object, Double> valueScoreMap) {Set<TypedTuple<Object>> tuples = new HashSet<>();valueScoreMap.forEach((value, score) -> {tuples.add(new DefaultTypedTuple<>(value, score));});return zSetOps().add(key, tuples);}/*** 从有序集合中删除一个或多个元素*/public Long remove(String key, Object... values) {return zSetOps().remove(key, values);}/*** 增加元素的分数*/public Double incrementScore(String key, Object value, double delta) {return zSetOps().incrementScore(key, value, delta);}/*** 获取元素的分数*/public Double score(String key, Object value) {return zSetOps().score(key, value);}/*** 获取元素的排名(从小到大,0表示第一位)*/public Long rank(String key, Object value) {return zSetOps().rank(key, value);}/*** 获取元素的排名(从大到小,0表示第一位)*/public Long reverseRank(String key, Object value) {return zSetOps().reverseRank(key, value);}/*** 获取有序集合的大小*/public Long size(String key) {return zSetOps().size(key);}/*** 获取有序集合中指定分数范围的元素数量*/public Long count(String key, double min, double max) {return zSetOps().count(key, min, max);}/*** 删除整个有序集合*/public Boolean delete(String key) {return redisTemplate.delete(key);}/*** 为有序集合设置过期时间*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}// ========== 范围查询操作 ==========/*** 获取指定排名范围的元素(从小到大)*/public Set<Object> range(String key, long start, long end) {return zSetOps().range(key, start, end);}/*** 获取指定排名范围的元素(从大到小)*/public Set<Object> reverseRange(String key, long start, long end) {return zSetOps().reverseRange(key, start, end);}/*** 获取指定排名范围的元素及其分数(从小到大)*/public Set<TypedTuple<Object>> rangeWithScores(String key, long start, long end) {return zSetOps().rangeWithScores(key, start, end);}/*** 获取指定排名范围的元素及其分数(从大到小)*/public Set<TypedTuple<Object>> reverseRangeWithScores(String key, long start, long end) {return zSetOps().reverseRangeWithScores(key, start, end);}/*** 获取指定分数范围的元素(从小到大)*/public Set<Object> rangeByScore(String key, double min, double max) {return zSetOps().rangeByScore(key, min, max);}/*** 获取指定分数范围的元素(从大到小)*/public Set<Object> reverseRangeByScore(String key, double min, double max) {return zSetOps().reverseRangeByScore(key, min, max);}/*** 获取指定分数范围的元素及其分数(从小到大)*/public Set<TypedTuple<Object>> rangeByScoreWithScores(String key, double min, double max, int i, int i1) {return zSetOps().rangeByScoreWithScores(key, min, max);}/*** 获取指定分数范围的元素及其分数(从大到小)*/public Set<TypedTuple<Object>> reverseRangeByScoreWithScores(String key, double min, double max) {return zSetOps().reverseRangeByScoreWithScores(key, min, max);}/*** 获取指定分数范围的元素(从小到大),带偏移量和数量限制*/public Set<Object> rangeByScore(String key, double min, double max, long offset, long count) {return zSetOps().rangeByScore(key, min, max, offset, count);}/*** 获取指定分数范围的元素(从大到小),带偏移量和数量限制*/public Set<Object> reverseRangeByScore(String key, double min, double max, long offset, long count) {return zSetOps().reverseRangeByScore(key, min, max, offset, count);}// ========== 删除操作 ==========/*** 根据排名范围删除元素*/public Long removeRange(String key, long start, long end) {return zSetOps().removeRange(key, start, end);}/*** 根据分数范围删除元素*/public Long removeRangeByScore(String key, double min, double max) {return zSetOps().removeRangeByScore(key, min, max);}// ========== 集合间操作 ==========/*** 计算多个有序集合的并集并存储到目标有序集合中*/public Long unionAndStore(String key, String otherKey, String destinationKey) {return zSetOps().unionAndStore(key, otherKey, destinationKey);}/*** 计算多个有序集合的并集并存储到目标有序集合中*/public Long unionAndStore(String key, Collection<String> otherKeys, String destinationKey) {return zSetOps().unionAndStore(key, otherKeys, destinationKey);}/*** 计算多个有序集合的交集并存储到目标有序集合中*/public Long intersectAndStore(String key, String otherKey, String destinationKey) {return zSetOps().intersectAndStore(key, otherKey, destinationKey);}/*** 计算多个有序集合的交集并存储到目标有序集合中*/public Long intersectAndStore(String key, Collection<String> otherKeys, String destinationKey) {return zSetOps().intersectAndStore(key, otherKeys, destinationKey);}// ========== 字典区间操作 ==========/*** 获取指定字典区间的元素*/public Set<Object> rangeByLex(String key, Range range) {return zSetOps().rangeByLex(key, range);}}

支持的操作 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词