易筋SpringBoot 2.1

编程入门 行业动态 更新时间:2024-10-25 16:21:48

易筋<a href=https://www.elefans.com/category/jswz/34/1769943.html style=SpringBoot 2.1"/>

易筋SpringBoot 2.1

写作时间:2019-10-05
Spring Boot: 2.1 ,JDK: 1.8, IDE: IntelliJ IDEA

说明

SpringBoot中默认用Redis替换Jedis来访问Redis内存数据库。

说明Redis操作数据的效率高,本章记录Redis Template, Redis Repository的用法。

配置连接工厂

  • LettuceConnectionFactory 与 JedisConnectionFactory
    • RedisStandaloneConfiguration
    • RedisSentinelConfiguration
    • RedisClusterConfiguration

RedisStandaloneConfiguration源码解析

package org.springframework.data.redis.connection;
// import ...public class RedisStandaloneConfigurationimplements RedisConfiguration, WithHostAndPort, WithPassword, WithDatabaseIndex {private static final String DEFAULT_HOST = "localhost";private static final int DEFAULT_PORT = 6379;private String hostName = DEFAULT_HOST;private int port = DEFAULT_PORT;private int database;private RedisPassword password = RedisPassword.none();/*** Create a new default {@link RedisStandaloneConfiguration}.*/public RedisStandaloneConfiguration() {}/*** Create a new {@link RedisStandaloneConfiguration} given {@code hostName}.** @param hostName must not be {@literal null} or empty.*/public RedisStandaloneConfiguration(String hostName) {this(hostName, DEFAULT_PORT);}// ...
}

解析:主要配置Host, Port, password, database, 并且都有默认值,
还有灵活参数的构造函数。

RedisSentinelConfiguration源码解析

package org.springframework.data.redis.connection;
// import ...public class RedisSentinelConfiguration implements RedisConfiguration, SentinelConfiguration {private static final String REDIS_SENTINEL_MASTER_CONFIG_PROPERTY = "spring.redis.sentinel.master";private static final String REDIS_SENTINEL_NODES_CONFIG_PROPERTY = "spring.redis.sentinel.nodes";private @Nullable NamedNode master;private Set<RedisNode> sentinels;private int database;private RedisPassword password = RedisPassword.none();/*** Creates new {@link RedisSentinelConfiguration}.*/public RedisSentinelConfiguration() {this(new MapPropertySource("RedisSentinelConfiguration", Collections.emptyMap()));}/*** Creates {@link RedisSentinelConfiguration} looking up values in given {@link PropertySource}.** <pre>* <code>* spring.redis.sentinel.master=myMaster* spring.redis.sentinel.nodes=127.0.0.1:23679,127.0.0.1:23680,127.0.0.1:23681* </code>* </pre>** @param propertySource must not be {@literal null}.* @since 1.5*/public RedisSentinelConfiguration(PropertySource<?> propertySource) {// ...

解析:master 存储为字符串名字,sentinels为多个对象的set,每个对象都包含host, port, database, 实际上master必须活跃,sentinels可以相互负载均衡。哨兵模式可以作为读写分离。

RedisClusterConfiguration源码解析

package org.springframework.data.redis.connection;
// import ...public class RedisClusterConfiguration implements RedisConfiguration, ClusterConfiguration {private static final String REDIS_CLUSTER_NODES_CONFIG_PROPERTY = "spring.redis.cluster.nodes";private static final String REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY = "spring.redis.cluster.max-redirects";private Set<RedisNode> clusterNodes;private @Nullable Integer maxRedirects;private RedisPassword password = RedisPassword.none();/*** Creates {@link RedisClusterConfiguration} looking up values in given {@link PropertySource}.** <pre>* <code>* spring.redis.cluster.nodes=127.0.0.1:23679,127.0.0.1:23680,127.0.0.1:23681* spring.redis.cluster.max-redirects=3* </code>* </pre>** @param propertySource must not be {@literal null}.*/public RedisClusterConfiguration(PropertySource<?> propertySource) {// ...

解析:

  • clusterNodes实际上就是负载均衡,只要有一个节点存活都可以访问Redis。
  • spring.redis.cluster.max-redirects=3 重定向的次数不要随意修改默认值,太小会导致重定向失败。

RedisProperties源码解析

package org.springframework.boot.autoconfigure.data.redis;// import ...@ConfigurationProperties(prefix = "spring.redis"
)
public class RedisProperties {private int database = 0;private String url;private String host = "localhost";private String password;private int port = 6379;private boolean ssl;private Duration timeout;private RedisProperties.Sentinel sentinel;private RedisProperties.Cluster cluster;private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();private final RedisProperties.Lettuce lettuce = new RedisProperties.Lettuce();public static class Pool {/*** Maximum number of "idle" connections in the pool. Use a negative value to* indicate an unlimited number of idle connections.*/private int maxIdle = 8;/*** Target for the minimum number of idle connections to maintain in the pool. This* setting only has an effect if it is positive.*/private int minIdle = 0;/*** Maximum number of connections that can be allocated by the pool at a given* time. Use a negative value for no limit.*/private int maxActive = 8;// ...}// ...

解析:SpringBoot通过application.yml配置文件配置RedisProperties,
比如host, port, password, pool 等。

读写分离

Lettuce 内置支持读写分离

  • 只读主、只读从
  • 优先读主、优先读从

LettuceClientConfiguration
LettucePoolingClientConfiguration
LettuceClientConfigurationBuilderCustomizer

通过 Docker 启动 Redis

如果已经存在 Redis的镜像,直接启动就好

  • docker start redis

更多知识请参考:第廿五篇:SpringBoot之Jedis访问Redis

进入Redis bash 命令行

% docker exec -it redis bash

打开redis客户端

root@8eb8d32453bb:/data# redis-cli

查看Redis中的keys值, 查看内容,删除掉key (ke值需要带双引号)

127.0.0.1:6379> keys *
1) "starbucks-menu"127.0.0.1:6379> hgetall starbucks-menu1) "espresso"2) "2000"3) "latte"4) "2500"5) "capuccino"6) "2500"7) "mocha"8) "3000"9) "macchiato"
10) "3000"127.0.0.1:6379> del "starbucks-menu"
(integer) 1

1.工程建立

下载已经创建好的Starbucks项目,
重命名根文件夹名字的JedisDemo,用Idea打开工程,运行后实际为JPA操作数据。
接下来就改造为Jedis操作Redis数据。

pom.xml增加, Redis, Pool2 连接池配置


<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>org.apachemons</groupId><artifactId>commons-pool2</artifactId>
</dependency>

这里要删掉下面的配置信息,否则会引起循环引用错误

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

循环引用报错

***************************
APPLICATION FAILED TO START
***************************Description:The dependencies of some of the beans in the application context form a cycle:servletEndpointRegistrar defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration.class]↓healthEndpoint defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]↓healthIndicatorRegistry defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthIndicatorAutoConfiguration.class]↓org.springframework.boot.actuate.autoconfigure.redis.RedisReactiveHealthIndicatorAutoConfiguration
┌─────┐
|  redisConnectionFactory defined in class path resource [org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.class]
↑     ↓
|  starbucksApplication (field private zgpeace.spring.starbucks.service.CoffeeService zgpeace.spring.starbucks.StarbucksApplication.coffeeService)
↑     ↓
|  coffeeService (field private org.springframework.data.redis.core.RedisTemplate zgpeace.spring.starbucks.service.CoffeeService.redisTemplate)
↑     ↓
|  redisTemplate defined in zgpeace.spring.starbucks.StarbucksApplication
└─────┘

1.1RedisTemplate

RedisTemplate<K, V>

  • opsForXxx()

StringRedisTemplate

切记:一定注意设置过期时间!!!

1.2 application配置

src > main > resources > application.yml

spring:jpa:hibernate:ddl-auto: noneproperties:hibernate:show_sql: trueformat_sql: trueredis:host: "localhost"lettuce:pool:max-active: 5max-idle: 5
management:endpoints:web:exposure:include: "*"

配置Redis的信息

1.3 Service

zgpeace.spring.starbucks.service.CoffeeService

package zgpeace.spring.starbucks.service;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import zgpeace.spring.starbucks.model.Coffee;
import zgpeace.spring.starbucks.repository.CoffeeRepository;import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.exact;@Slf4j
@Service
public class CoffeeService {private static final String CACHE = "starbucks-coffee";@Autowiredprivate CoffeeRepository coffeeRepository;@Autowiredprivate RedisTemplate<String, Coffee> redisTemplate;public List<Coffee> findAllCoffee() {return coffeeRepository.findAll();}public Optional<Coffee> findOneCoffee(String name) {HashOperations<String, String, Coffee> hashOperations = redisTemplate.opsForHash();if (redisTemplate.hasKey(CACHE) && hashOperations.hasKey(CACHE, name)) {log.info("Get coffee {} from Redis.", name);return Optional.of(hashOperations.get(CACHE, name));}ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", exact().ignoreCase());Optional<Coffee> coffee = coffeeRepository.findOne(Example.of(Coffee.builder().name(name).build(), matcher));log.info("Coffee Found: {}", coffee);if (coffee.isPresent()) {log.info("Put coffee {} to Redis.", name);hashOperations.put(CACHE, name, coffee.get());redisTemplate.expire(CACHE, 1, TimeUnit.MINUTES);}return coffee;}
}

解析:

  1. 先从Redis中读取,有数据则直接返回。
  2. Redis中没有数据,则从数据库中查询,接着存入Redis中,最后返回数据。
  3. redisTemplate.expire(CACHE, 1, TimeUnit.MINUTES); 缓存有效期为1分钟

1.4 Controller Redis CRUD

zgpeace.spring.starbucks.StarbucksApplication

package zgpeace.spring.starbucks;import io.lettuce.core.ReadFrom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import zgpeace.spring.starbucks.model.Coffee;
import zgpeace.spring.starbucks.service.CoffeeService;import java.util.Optional;@Slf4j
@EnableTransactionManagement
@SpringBootApplication
@EnableJpaRepositories
public class StarbucksApplication implements ApplicationRunner {@Autowiredprivate CoffeeService coffeeService;public static void main(String[] args) {SpringApplication.run(StarbucksApplication.class, args);}@Beanpublic RedisTemplate<String, Coffee> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Coffee> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);return template;}@Beanpublic LettuceClientConfigurationBuilderCustomizer customizer() {return builder -> builder.readFrom(ReadFrom.MASTER_PREFERRED);}@Overridepublic void run(ApplicationArguments args) throws Exception {Optional<Coffee> c = coffeeService.findOneCoffee("mocha");log.info("Coffee {}", c);for (int i = 0; i < 5; i++) {c = coffeeService.findOneCoffee("mocha");}log.info("Value from Redis: {}", c);}
}

解析:
ReadFrom.MASTER_PREFERRED 表示从主节点读取Redis。

运行结果如下:第一次读取数据库,然后存入Redis,后面5次查询读取Redis

Hibernate: selectcoffee0_.id as id1_0_,coffee0_.create_time as create_t2_0_,coffee0_.update_time as update_t3_0_,coffee0_.name as name4_0_,coffee0_.price as price5_0_ fromt_coffee coffee0_ wherelower(coffee0_.name)=?
Coffee Found: Optional[Coffee(super=BaseEntity(id=4, createTime=2019-10-05 11:39:45.379, updateTime=2019-10-05 11:39:45.379), name=mocha, price=CNY 30.00)]
Put coffee mocha to Redis.
Coffee Optional[Coffee(super=BaseEntity(id=4, createTime=2019-10-05 11:39:45.379, updateTime=2019-10-05 11:39:45.379), name=mocha, price=CNY 30.00)]
Get coffee mocha from Redis.
Get coffee mocha from Redis.
Get coffee mocha from Redis.
Get coffee mocha from Redis.
Get coffee mocha from Redis.
Value from Redis: Optional[Coffee(super=BaseEntity(id=4, createTime=2019-10-05 11:39:45.379, updateTime=2019-10-05 11:39:45.379), name=mocha, price=CNY 30.00)]
Closing JPA EntityManagerFactory for persistence unit 'default'

1.5 Redis中查询数据

因为设置1分钟过期时间,所以1分钟后就查不到内容

127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x12starbucks-coffee"
127.0.0.1:6379> hgetall "\xac\xed\x00\x05t\x00\x12starbucks-coffee"
1) "\xac\xed\x00\x05t\x00\x05mocha"
2) "\xac\xed\x00\x05sr\x00%zgpeace.spring.starbucks.model.Coffee\xfc|\x99\x99\xe0\x87\\H\x02\x00\x02L\x00\x04namet\x00\x12Ljava/lang/String;L\x00\x05pricet\x00\x16Lorg/joda/money/Money;xr\x00)zgpeace.spring.starbucks.model.BaseEntity\x15\xa6\x90\x00\x89\x0e\xff\x88\x02\x00\x03L\x00\ncreateTimet\x00\x10Ljava/util/Date;L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\nupdateTimeq\x00~\x00\x04xpsr\x00\x12java.sql.Timestamp&\x18\xd5\xc8\x01S\xbfe\x02\x00\x01I\x00\x05nanosxr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x01m\x9a\x00w\xe8x\x16\x97\x14\xc0sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x04sq\x00~\x00\aw\b\x00\x00\x01m\x9a\x00w\xe8x\x16\x97\x14\xc0t\x00\x05mochasr\x00\x12org.joda.money.Serq\xd7\xfe\x1b\x88\xed\x97\x9c\x0c\x00\x00xpw\x14M\x00\x03CNY\x00\x9c\x00\x02\x00\x00\x00\x02\x0b\xb8\x00\x00\x00\x02x"

2.1 Redis Repository

实体注解

  • @RedisHash
  • @Id
  • @Indexed

处理不同类型数据源的 Repository
如何区分这些 Repository

  • 根据实体的注解
  • 根据继承的接口类型
  • 扫描不同的包

2.1 RedisTemplate

跟上面 1.1 RedisTemplate一模一样

2.2 application配置

跟上面 1.2 application配置一模一样

2.3 Cache Model

package zgpeace.spring.starbucks.model;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.joda.money.Money;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;@RedisHash(value = "starbucks-coffee", timeToLive = 60)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CoffeeCache {@Idprivate Long id;@Indexedprivate String name;private Money price;
}

解析:

  1. “starbucks-coffee” 存储类型为Hash
  2. timeToLive = 60 缓存有效期为60秒
  3. @Id 为主键
  4. @Indexed 为外键
  5. Money 接下来会有读取和写入类型转换

2.4 Money在Redis中写入和读取类型转换

从Redis中读数据
zgpeace.spring.starbucks.converter.BytesToMoneyConverter

package zgpeace.spring.starbucks.converter;import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;import java.nio.charset.StandardCharsets;@ReadingConverter
public class BytesToMoneyConverter implements Converter<byte[], Money> {@Overridepublic Money convert(byte[] bytes) {String value = new String(bytes, StandardCharsets.UTF_8);return Money.of(CurrencyUnit.of("CNY"), Long.parseLong(value));}
}

从Redis中写数据
zgpeace.spring.starbucks.converter.MoneyToBytesConverter

package zgpeace.spring.starbucks.converter;import org.joda.money.Money;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;import java.nio.charset.StandardCharsets;@WritingConverter
public class MoneyToBytesConverter implements Converter<Money, byte[]> {@Overridepublic byte[] convert(Money money) {String value = Long.toString(money.getAmountMinorLong());return value.getBytes(StandardCharsets.UTF_8);}
}

2.5 Cache Repository

zgpeace.spring.starbucks.repository.CoffeeCacheRepository

package zgpeace.spring.starbucks.repository;import org.springframework.data.repository.CrudRepository;
import zgpeace.spring.starbucks.model.CoffeeCache;import java.util.Optional;public interface CoffeeCacheRepository extends CrudRepository<CoffeeCache, Long> {Optional<CoffeeCache> findOneByName(String name);
}

2.6 Cache Service

zgpeace.spring.starbucks.service.CoffeeService

package zgpeace.spring.starbucks.service;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;
import zgpeace.spring.starbucks.model.Coffee;
import zgpeace.spring.starbucks.model.CoffeeCache;
import zgpeace.spring.starbucks.repository.CoffeeCacheRepository;
import zgpeace.spring.starbucks.repository.CoffeeRepository;import java.util.Optional;import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.exact;@Slf4j
@Service
public class CoffeeService {@Autowiredprivate CoffeeRepository coffeeRepository;@Autowiredprivate CoffeeCacheRepository cacheRepository;public Optional<Coffee> findSimpleCoffeeFromCache(String name) {Optional<CoffeeCache> cached = cacheRepository.findOneByName(name);if (cached.isPresent()) {CoffeeCache coffeeCache = cached.get();Coffee coffee = Coffee.builder().name(coffeeCache.getName()).price(coffeeCache.getPrice()).build();log.info("Coffee {} found in cache.", coffeeCache);return Optional.of(coffee);} else {Optional<Coffee> raw = findOneCoffee(name);raw.ifPresent(c -> {CoffeeCache coffeeCache = CoffeeCache.builder().id(c.getId()).name(c.getName()).price(c.getPrice()).build();log.info("Save Coffee {} to cache.", coffeeCache);cacheRepository.save(coffeeCache);});return raw;}}public Optional<Coffee> findOneCoffee(String name) {ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", exact().ignoreCase());Optional<Coffee> coffee = coffeeRepository.findOne(Example.of(Coffee.builder().name(name).build(), matcher));log.info("Coffee Found: {}", coffee);return coffee;}
}

解析:

  1. 通过Redis Repository获取cache,获取到则组装对象返回
  2. 如果cache为空,则读取数据库,并通过Redis Repository存储对象到cache。最后返回数据库读取到的对象

2.7 Cache Controller

zgpeace.spring.starbucks.StarbucksApplication

package zgpeace.spring.starbucks;import io.lettuce.core.ReadFrom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import zgpeace.spring.starbucks.converter.BytesToMoneyConverter;
import zgpeace.spring.starbucks.converter.MoneyToBytesConverter;
import zgpeace.spring.starbucks.model.Coffee;
import zgpeace.spring.starbucks.model.CoffeeOrder;
import zgpeace.spring.starbucks.model.OrderState;
import zgpeace.spring.starbucks.repository.CoffeeRepository;
import zgpeace.spring.starbucks.service.CoffeeOrderService;
import zgpeace.spring.starbucks.service.CoffeeService;import java.util.Arrays;
import java.util.Optional;@Slf4j
@EnableTransactionManagement
@EnableJpaRepositories
@EnableRedisRepositories
@SpringBootApplication
public class StarbucksApplication implements ApplicationRunner {@Autowiredprivate CoffeeService coffeeService;@Beanpublic LettuceClientConfigurationBuilderCustomizer customizer() {return builder -> builder.readFrom(ReadFrom.MASTER_PREFERRED);}@Beanpublic RedisCustomConversions redisCustomConversions() {return  new RedisCustomConversions(Arrays.asList(new MoneyToBytesConverter(), new BytesToMoneyConverter()));}@Overridepublic void run(ApplicationArguments args) throws Exception {Optional<Coffee> c = coffeeService.findSimpleCoffeeFromCache("mocha");log.info("Coffee: {}", c);for (int i = 0; i < 5; i++) {c = coffeeService.findSimpleCoffeeFromCache("mocha");}log.info("Value from Redis: {}", c);}public static void main(String[] args) {SpringApplication.run(StarbucksApplication.class, args);}}

解析:

  1. LettuceClientConfigurationBuilderCustomizer customizer() 指定读取Redis从主机中读取
  2. RedisCustomConversions 定制Money转换的对象数组
  3. 第一次从数据库中读取,1分钟内(缓存过期时间)都是从Redis Cache中读取

源码解析
Money Converter可以自定义是因为RegisterBeansForRoot预留了定制方法registerIfNotAlreadyRegistered(…)

package org.springframework.data.redis.repository.configuration;// import ...
public class RedisRepositoryConfigurationExtension extends KeyValueRepositoryConfigurationExtension {private static final String REDIS_CONVERTER_BEAN_NAME = "redisConverter";private static final String REDIS_REFERENCE_RESOLVER_BEAN_NAME = "redisReferenceResolver";private static final String REDIS_ADAPTER_BEAN_NAME = "redisKeyValueAdapter";private static final String REDIS_CUSTOM_CONVERSIONS_BEAN_NAME = "redisCustomConversions";// ...@Overridepublic void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource configurationSource) {// ...// register coustom conversionsRootBeanDefinition customConversions = new RootBeanDefinition(RedisCustomConversions.class);registerIfNotAlreadyRegistered(customConversions, registry, REDIS_CUSTOM_CONVERSIONS_BEAN_NAME,configurationSource);

2.8 Redis中查询数据

查询keys值

127.0.0.1:6379> keys *
1) "starbucks-coffee:name:mocha"
2) "starbucks-coffee:4"
3) "starbucks-coffee:4:phantom"
4) "starbucks-coffee"
5) "starbucks-coffee:4:idx"

查看key对应value的类型,并用对应的数据类型查询

127.0.0.1:6379> type "starbucks-coffee:4"
hash
127.0.0.1:6379> hgetall "starbucks-coffee:4"
1) "_class"
2) "zgpeace.spring.starbucks.model.CoffeeCache"
3) "id"
4) "4"
5) "name"
6) "mocha"
7) "price"
8) "3000"
127.0.0.1:6379> type "starbucks-coffee:name:mocha"
set
127.0.0.1:6379> smembers "starbucks-coffee:name:mocha"
1) "4"
127.0.0.1:6379> hgetall "starbucks-coffee"
(error) WRONGTYPE Operation against a key holding the wrong kind of value

解析: 如果查询方法与真实数据不符,就会报错:
(error) WRONGTYPE Operation against a key holding the wrong kind of value

总结

恭喜你,学会了Redis template,Redis Repository操作数据。
代码下载:

.1/tree/master/Nosql/RedisTemplate

.1/tree/master/Nosql/RedisRepository

参考


/

.html
.html

.1/tree/master/db/DemoDBStarbucks

/redis-demo

/redis-repository-demo

更多推荐

易筋SpringBoot 2.1

本文发布于:2024-02-07 12:04:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1756915.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:易筋   SpringBoot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!