Spring Boot (five): Redis cache using gestures inventory

1. Redis Introduction

Redis is the industry's most widely used memory data storage. Compared Memcached, Redis support richer data structures, such as hashes, lists, sets, etc., while supporting data persistence. In addition, characteristics of the Redis also provide some type of database, such as transaction, HA, from the master library. Redis can be said that some of the features of both systems and database caching, so has a wealth of application scenarios. Redis article describes two typical application scenarios in the Spring Boot.

2. Lettuce Introduction

If you've used Redis cache in Java applications, then the Jedisno strangers, Lettuceand Jedis, are connected to Redis Serverthe client program. JedisOn the implementation is directly connected Redis Server, multi-threaded environment, non-thread-safe, unless you use connection pooling for each Jedisincrease physical connection instance. LettuceBased Nettyconnection instance (StatefulRedisConnection) may be concurrent access among multiple threads, and thread-safe, concurrent access to meet in a multithreaded environment, and it is scalable design, the case is not a connection instance can also increase demand connection instance.

3. Spring Boot application usage

  • Directly through the RedisTemplateuse
  • Use Spring CacheintegratedRedis
  • By Spring Sessiondoing Sessionsharing

4. combat engineering

4.1 Project relies pom.xml as follows:

Listing: the Spring-the Boot-Redis / pom.xml
***

<dependencies>
    <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>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  • spring-boot-starter-data- redis: the Spring Boot 2.xlonger is the use of the underlying Jedis, but replaced Lettuce, as shown:

  • commons-pool2: used as a redisconnection pool, such as promoter without introducing error.

  • spring-session-data-redis: Spring Sessionintroducing, as a shared Session.

4.2 Profile application.yml

Listing: the Spring-the Boot-Redis / src / main / Resources / application.yml
***

server:
  port: 8080
  servlet:
    session:
      timeout: 30m
spring:
  application:
    name: spring-boot-redis
  cache:
    # 使用了Spring Cache后,能指定spring.cache.type就手动指定一下,虽然它会自动去适配已有Cache的依赖,但先后顺序会对Redis使用有影响(JCache -> EhCache -> Redis -> Guava)
    type: REDIS
  redis:
    host: 192.168.0.128
    port: 6379
    password: 123456
    # 连接超时时间(ms)
    timeout: 10000
    # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
    database: 0
    lettuce:
      pool:
        # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-active: 100
        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-wait: -1
        # 连接池中的最大空闲连接 默认 8
        max-idle: 8
        # 连接池中的最小空闲连接 默认 0
        min-idle: 0

Configuration is not much to explain here, the need to explain the comment has been marked.

4.3 RedisTemplate use

4.3.1 Creating an entity class User.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/model/User.java
***

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {

    private static final long serialVersionUID = 662692455422902539L;
    private Long id;
    private String name;
    private int age;
}

4.3.2 Custom RedisTemplate

Under the default template can only support RedisTemplate<String, String>, that is only stored in the string, which is unfriendly, the custom template is necessary in development, when a custom template and want to use the Stringmemory This time we can use StringRedisTemplatemode, they do not conflict, adding configure class RedisCacheConfig.java, as follows:

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/config/RedisCacheConfig.java
***

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {

    @Bean
    public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Serializable> template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

4.3.3 Test Interface UserController.java

Listing:
***

@RestController
@Slf4j
public class UserController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    RedisTemplate<String, Serializable> redisCacheTemplate;

    @Autowired
    UserService userService;

    @GetMapping("/test")
    public void test() {
        stringRedisTemplate.opsForValue().set("geekdigging", "https://www.geekdigging.com/");

        log.info("当前获取对象:{}",stringRedisTemplate.opsForValue().get("geekdigging"));

        redisCacheTemplate.opsForValue().set("geekdigging.com", new User(1L, "geekdigging", 18));

        User user = (User) redisCacheTemplate.opsForValue().get("geekdigging.com");

        log.info("当前获取对象:{}", user);
    }
}

4.3.4 Testing

Start the service, open the browser to access the link: http: // localhost: 8080 / test, view the console log printing, as follows:

2019-09-24 23:49:30.191  INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前获取对象:https://www.geekdigging.com/
2019-09-24 23:49:30.243  INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前获取对象:User(id=1, name=geekdigging, age=18)

testing successfully.

4.4 Spring Cache Redis integration

4.4.1 Spring Cache Features

Spring 3.1 introduces exciting cache-based annotation (Annotation) of (Cache) technology, which is essentially not a particular implementation of the cache (e.g. EHCache or the Redis), but an abstract of the buffers used by the existing code adding a small amount of various annotation that defines, i.e., to achieve a caching method returns the object effects.

Spring Cache has considerable good flexibility, not only can be used SpEL (Spring Expression Language) to define the cache key and a variety of condition, also provides out of the box with a buffer for temporary storage solution also supports caching and mainstream professional such as EHCache , Redis, Guava integration.

  • Based on annotation that can support the existing code buffer
  • Out of the box Out-Of-The-Box, without having to install additional third-party components and deployment can use the cache
  • Support Spring Express Language, any property or method can be used to define the object cache key and condition
  • Support for AspectJ, and through its implementing any method of caching support
  • Support for custom and custom cache key managers have considerable flexibility and scalability

4.4.2 defines the interface UserService.java

Listing: springboot-Redis / src / main / the Java / COM / springboot / springbootredis / Service / UserService.java
***

public interface UserService {
    User save(User user);

    User get(Long id);

    void delete(Long id);
}

4.4.3 interface UserServiceImpl.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/service/impl/UserServiceImpl.java
***

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private static final Map<Long, User> USER_MAP = new HashMap<>();

    static {
        USER_MAP.put(1L, new User(1L, "geekdigging.com", 18));
        USER_MAP.put(2L, new User(2L, "geekdigging.com", 19));
        USER_MAP.put(3L, new User(3L, "geekdigging.com", 20));
    }

    @CachePut(value = "user", key = "#user.id")
    @Override
    public User save(User user) {
        USER_MAP.put(user.getId(), user);
        log.info("进入 save 方法,当前存储对象:{}",  user);
        return user;
    }

    @Cacheable(value = "user", key = "#id")
    @Override
    public User get(Long id) {
        log.info("进入 get 方法,当前获取对象:{}",  USER_MAP.get(id));
        return USER_MAP.get(id);
    }

    @CacheEvict(value = "user", key = "#id")
    @Override
    public void delete(Long id) {
        USER_MAP.remove(id);
        log.info("进入 delete 方法,删除成功");
    }
}

In order to facilitate the demo database operations directly define a Map<Long, User> USER_MAPcore here is three notes @Cacheable, @CachePut, @CacheEvict.

4.4.3.1 @Cacheable

The results of its cache request parameter method

  • key: cache key, can be empty, if you want to specify prepared in accordance SpEL expression, if not specified, the default parameters are combined in accordance with all methods (eg: @Cacheable(value="user",key="#userName"))
  • value: name of the cache must specify at least one (eg: @Cacheable(value="user")or @Cacheable(value={"user1","use2"}))
  • condition: buffer conditions can be empty, the SpEL write, returns true or false, it is true only for caching (eg: @Cacheable(value = "user", key = "#id",condition = "#id < 10"))
4.4.3.2 @CachePut

The method according to request parameters of their result cache, and @Cacheable different is that it will trigger a call to every true method

  • key: ditto
  • value: ditto
  • condition: ditto
4.4.3.3 @CachEvict

To empty the cache according to the conditions

  • key: ditto
  • value: ditto
  • condition: ditto
  • allEntries: whether to clear all cache content, the default is false, if you specify true, the method call will immediately empty all caches (eg: @CacheEvict(value = "user", key = "#id", allEntries = true))
  • beforeInvocation: whether it is emptied before the execution method, the default is false, if you specify is true, when the method has not been performed on empty the cache, by default, if the execution method throws an exception, it is not clear the cache ( such @CacheEvict(value = "user", key = "#id", beforeInvocation = true)as: )

4.4.4 start the main class

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java
***

@SpringBootApplication
@EnableCaching
public class SpringBootRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRedisApplication.class, args);
    }

}
  • Here notes the need to increase @EnableCachingopen Spring Session.

4.4.5 increase test interface

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java
***

@GetMapping("/test1")
public void test1() {
    User user = userService.save(new User(4L, "geekdigging.com", 35));

    log.info("当前 save 对象:{}", user);

    user = userService.get(1L);

    log.info("当前 get 对象:{}", user);

    userService.delete(5L);
}

4.4.6 Testing

Start the service, open the browser to access the link: http: // localhost: 8080 / test, refresh the page, the console log is printed as follows:

2019-09-25 00:07:21.887  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:07:21.897  INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:07:21.899  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 get 方法,当前获取对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:07:21.900  INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:07:21.901  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 delete 方法,删除成功

Refresh the page again to see the console log:

2019-09-25 00:08:54.076  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:08:54.077  INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController          : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)
2019-09-25 00:08:54.079  INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController          : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)
2019-09-25 00:08:54.079  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 进入 delete 方法,删除成功

And we expect the same results, you can see CRUD, the query is no log output because it gets the data directly from the cache, and add, modify, delete all will enter UserServiceImplthe implementation of specific business code in the method .

4.5 Session Sharing

4.5.1 Spring Session Introduction

Spring Session provides a Servlet HttpSession creation and management of the program. Spring Session provides a cluster Session (Clustered Sessions) function defaults to external Redis to store Session data, in order to solve shared problems Session.

4.5.2 start the main class SpringBootRedisApplication.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java
***

@SpringBootApplication
@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SpringBootRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRedisApplication.class, args);
    }

}
  • maxInactiveIntervalInSeconds: Set Session expiration time, after using the Spring Session, the original Spring Boot configuration file application.ymlin the server.session.timeoutproperty is no longer effective.

4.5.3 increase test interface

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java
***

@GetMapping("/getBlogUrl")
public String getSessionId(HttpServletRequest request) {
    String url = (String) request.getSession().getAttribute("url");
    if (StringUtils.isEmpty(url)) {
        request.getSession().setAttribute("url", "https://www.geekdigging.com/");
    }
    log.info("获取session内容为: {}", request.getSession().getAttribute("url"));
    return request.getRequestedSessionId();
}

4.5.4 Testing

Start the service, open the browser to access the link: http: // localhost: 8080 / getBlogUrl, view the current memory contents Redis, as shown below:

Wherein 1,569,339,180,000 is a time to failure, the failure means the Session After this time, b2522824-1094-478e-a435-554a551bc8bb is SessionId.

4.5.6 How to share multiple services in Session

Follow the above steps in another project configuration once again, after it has been automatically start Session sharing.

5. Sample Code

Sample Code -Github

Sample Code -Gitee

6. References

http://emacoo.cn/backend/spring-redis/
https://blog.battcn.com/2018/05/11/springboot/v2-nosql-redis/

Guess you like

Origin www.cnblogs.com/babycomeon/p/11595609.html