久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    Spring Boot (五): Redis緩存使用姿勢盤點

     新用戶32269360 2020-06-12

    1. Redis 簡介

    Redis 是目前業界使用最廣泛的內存數據存儲。相比 Memcached,Redis 支持更豐富的數據結構,例如 hashes, lists, sets 等,同時支持數據持久化。除此之外,Redis 還提供一些類數據庫的特性,比如事務,HA,主從庫??梢哉f Redis 兼具了緩存系統和數據庫的一些特性,因此有著豐富的應用場景。本文介紹 Redis 在 Spring Boot 中兩個典型的應用場景。

    2. Lettuce 簡介

    如果在 Java 應用中使用過 Redis 緩存,那么對 Jedis 一定不陌生, Lettuce 和 Jedis 一樣,都是連接 Redis Server 的客戶端程序。Jedis 在實現上是直連 Redis Server,多線程環境下非線程安全,除非使用連接池,為每個 Jedis 實例增加物理連接。 Lettuce 基于 Netty 的連接實例(StatefulRedisConnection),可以在多個線程間并發訪問,且線程安全,滿足多線程環境下的并發訪問,同時它是可伸縮的設計,一個連接實例不夠的情況也可以按需增加連接實例。

    3. Spring Boot 應用中使用方式

    • 直接通過 RedisTemplate 來使用

    • 使用 Spring Cache 集成 Redis

    • 通過 Spring Session 做 Session 共享

    4. 工程實戰

    4.1 工程依賴 pom.xml 如下:

    代碼清單:spring-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>COPY
    • spring-boot-starter-data-redis :在 Spring Boot 2.x 后底層不再是使用 Jedis ,而是換成了 Lettuce ,如圖:

    • commons-pool2 : 用作 redis 連接池,如不引入啟動會報錯。

    • spring-session-data-redis : Spring Session 引入,用作共享 Session 。

    Spring Boot (五): Redis緩存使用姿勢盤點

    4.2 配置文件 application.yml

    代碼清單:spring-boot-redis/src/main/resources/application.yml


    server:  port: 8080  servlet:    session:      timeout: 30mspring:  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: 0COPY

    這里的配置不多解釋,需要解釋的已經標注注釋。

    4.3 RedisTemplate 使用方式

    4.3.1 創建實體類 User.java

    代碼清單:spring-boot-redis/src/main/java/com/springboot/springbootredis/model/User.java


    @Data@AllArgsConstructor@NoArgsConstructorpublic class User implements Serializable {    private static final long serialVersionUID = 662692455422902539L;    private Long id;    private String name;    private int age;
    }COPY

    4.3.2 自定義 RedisTemplate

    默認情況下的模板只能支持 RedisTemplate<String, String> ,也就是只能存入字符串,這在開發中是不友好的,所以自定義模板是很有必要的,當自定義了模板又想使用 String 存儲這時候就可以使用 StringRedisTemplate 的方式,它們并不沖突,添加配置類 RedisCacheConfig.java ,代碼如下:

    代碼清單: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;
        }
    }COPY

    4.3.3 測試接口 UserController.java

    代碼清單:


    @RestController@Slf4jpublic 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./");
    
            log.info("當前獲取對象:{}",stringRedisTemplate.opsForValue().get("geekdigging"));
    
            redisCacheTemplate.opsForValue().set("", new User(1L, "geekdigging", 18));
    
            User user = (User) redisCacheTemplate.opsForValue().get("");
    
            log.info("當前獲取對象:{}", user);
        }
    }COPY

    4.3.4 測試

    啟動服務,打開瀏覽器訪問鏈接:http://localhost:8080/test ,查看控制臺日志打印,如下:

    2019-09-24 23:49:30.191  INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 當前獲取對象:https://www./
    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)COPY

    測試成功。

    4.4 使用 Spring Cache 集成 Redis

    4.4.1 Spring Cache 特點

    Spring 3.1 引入了激動人心的基于注釋(annotation)的緩存(cache)技術,它本質上不是一個具體的緩存實現方案(例如 EHCache 或者 Redis),而是一個對緩存使用的抽象,通過在既有代碼中添加少量它定義的各種 annotation,即能夠達到緩存方法的返回對象的效果。

    Spring Cache 具備相當的好的靈活性,不僅能夠使用 SpEL(Spring Expression Language)來定義緩存的 key 和各種 condition,還提供開箱即用的緩存臨時存儲方案,也支持和主流的專業緩存例如 EHCache、Redis、Guava 的集成。

    • 基于 annotation 即可使得現有代碼支持緩存

    • 開箱即用 Out-Of-The-Box,不用安裝和部署額外第三方組件即可使用緩存

    • 支持 Spring Express Language,能使用對象的任何屬性或者方法來定義緩存的 key 和 condition

    • 支持 AspectJ,并通過其實現任何方法的緩存支持

    • 支持自定義 key 和自定義緩存管理者,具有相當的靈活性和擴展性

    4.4.2 定義接口 UserService.java

    代碼清單:spring-boot-redis/src/main/java/com/springboot/springbootredis/service/UserService.java


    public interface UserService {    User save(User user);    User get(Long id);    void delete(Long id);
    }COPY

    4.4.3 接口實現 UserServiceImpl.java

    代碼清單:spring-boot-redis/src/main/java/com/springboot/springbootredis/service/impl/UserServiceImpl.java


    @Service@Slf4jpublic class UserServiceImpl implements UserService {    private static final Map<Long, User> USER_MAP = new HashMap<>();    static {
            USER_MAP.put(1L, new User(1L, "", 18));
            USER_MAP.put(2L, new User(2L, "", 19));
            USER_MAP.put(3L, new User(3L, "", 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 方法,刪除成功");
        }
    }COPY

    為了方便演示數據庫操作,直接定義了一個 Map<Long, User> USER_MAP ,這里的核心就是三個注解 @Cacheable 、 @CachePut 、 @CacheEvict 。

    4.4.3.1 @Cacheable

    根據方法的請求參數對其結果進行緩存

    • key: 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,如果不指定,則缺省按照方法的所有參數進行組合(如:@Cacheable(value="user",key="#userName")

    • value: 緩存的名稱,必須指定至少一個(如:@Cacheable(value="user") 或者 @Cacheable(value={"user1","use2"}) )

    • condition: 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行緩存(如:@Cacheable(value = "user", key = "#id",condition = "#id < 10")

    4.4.3.2 @CachePut

    根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用

    • key: 同上

    • value: 同上

    • condition: 同上

    4.4.3.3 @CachEvict

    根據條件對緩存進行清空

    • key: 同上

    • value: 同上

    • condition: 同上

    • allEntries: 是否清空所有緩存內容,缺省為 false,如果指定為 true,則方法調用后將立即清空所有緩存(如: @CacheEvict(value = "user", key = "#id", allEntries = true) )

    • beforeInvocation: 是否在方法執行前就清空,缺省為 false,如果指定為 true,則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法執行拋出異常,則不會清空緩存(如: @CacheEvict(value = "user", key = "#id", beforeInvocation = true) )

    4.4.4 啟動主類

    代碼清單:spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java


    @SpringBootApplication@EnableCachingpublic class SpringBootRedisApplication {    public static void main(String[] args) {
            SpringApplication.run(SpringBootRedisApplication.class, args);
        }
    
    }COPY
    • 這里需增加注解 @EnableCaching 開啟 Spring Session。

    4.4.5 增加測試接口

    代碼清單:spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java


    @GetMapping("/test1")public void test1() {
        User user = userService.save(new User(4L, "", 35));
    
        log.info("當前 save 對象:{}", user);
    
        user = userService.get(1L);
    
        log.info("當前 get 對象:{}", user);
    
        userService.delete(5L);
    }COPY

    4.4.6 測試

    啟動服務,打開瀏覽器訪問鏈接:http://localhost:8080/test ,刷新頁面,控制臺日志打印如下:

    2019-09-25 00:07:21.887  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 進入 save 方法,當前存儲對象:User(id=4, name=, 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=, 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=, 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=, age=18)
    2019-09-25 00:07:21.901  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 進入 delete 方法,刪除成功COPY

    再次刷新頁面,查看控制臺日志:

    2019-09-25 00:08:54.076  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 進入 save 方法,當前存儲對象:User(id=4, name=, 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=, 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=, age=18)
    2019-09-25 00:08:54.079  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 進入 delete 方法,刪除成功COPY

    結果和我們期望的一致,可以看到增刪改查中,查詢是沒有日志輸出的,因為它直接從緩存中獲取的數據,而添加、修改、刪除都是會進入 UserServiceImpl 的方法內執行具體的業務代碼。

    4.5 Session 共享

    4.5.1 Spring Session 簡介

    Spring Session 提供了一套創建和管理 Servlet HttpSession 的方案。Spring Session 提供了集群 Session(Clustered Sessions)功能,默認采用外置的 Redis 來存儲 Session 數據,以此來解決 Session 共享的問題。

    4.5.2 啟動主類 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);
        }
    
    }COPY
    • maxInactiveIntervalInSeconds: 設置 Session 失效時間,使用 Spring Session 之后,原 Spring Boot 配置文件 application.yml 中的 server.session.timeout 屬性不再生效。

    4.5.3 增加測試接口

    代碼清單: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./");
        }
        log.info("獲取session內容為: {}", request.getSession().getAttribute("url"));    return request.getRequestedSessionId();
    }COPY

    4.5.4 測試

    啟動服務,打開瀏覽器訪問鏈接:http://localhost:8080/getBlogUrl ,查看 Redis 當前存儲內容,如下圖:

    Spring Boot (五): Redis緩存使用姿勢盤點

    其中 1569339180000 為失效時間,意思是這個時間后 Session 失效, b2522824-1094-478e-a435-554a551bc8bb 為 SessionId 。

    4.5.6 如何在多臺服務中共享 Session

    按照上面的步驟在另一個項目中再次配置一次,啟動后自動就進行了 Session 共享。

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 国内精品久久久久影院蜜芽| 国产卡一卡二卡三精品| 好紧好湿好黄的视频| 高清看男人插曲女人视频 | 一本色道久久88亚洲精品综合| 美女禁区a级全片免费观看| 最新中文乱码字字幕在线| 精品人人妻人人澡人人爽人人 | 国产精品一区在线蜜臀| 999ZYZ玖玖资源站在线观看 | 2021国产精品视频网站| 成人区人妻精品一区二区不卡| 国产精品一区中文字幕| 无码精品国产VA在线观看DVD| 国产中文字幕日韩精品| 久久精品国产亚洲不AV麻豆| 在线中文字幕国产一区| 成在线人视频免费视频| 亚洲色最新高清AV网站| 国产精品毛片无码| 国精品午夜福利视频不卡| 欧美牲交a欧美牲交aⅴ图片| 精品香蕉久久久午夜福利| 精品乱码一区二区三四五区| 久久久久亚洲AV成人网人人软件 | 日韩乱码人妻无码中文字幕视频 | 爱性久久久久久久久| 波多野结衣中文字幕久久| 国产不卡精品视频男人的天堂 | 人妻少妇精品久久| 久章草在线毛片视频播放| 国产精品无码专区| 又黄又硬又湿又刺激视频免费| 国产一区二区高清不卡| 久久大蕉香蕉免费| 一个人免费视频WWW在线观看| 国产精品普通话国语对白露脸 | 无码人妻一区二区三区兔费| 一区二区中文字幕av| 3D动漫精品啪啪一区二区免费 | 永久黄网站色视频免费直播|