亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

淺談SpringBoot集成Redis實現緩存處理(Spring AOP實現)

2024-07-13 10:14:43
字體:
來源:轉載
供稿:網友

第一章 需求分析

計劃在Team的開源項目里加入Redis實現緩存處理,因為業務功能已經實現了一部分,通過寫Redis工具類,然后引用,改動量較大,而且不可以實現解耦合,所以想到了Spring框架的AOP(面向切面編程)。

開源項目:https://github.com/u014427391/jeeplatform

第二章 SpringBoot簡介

Spring框架作為JavaEE框架領域的一款重要的開源框架,在企業應用開發中有著很重要的作用,同時Spring框架及其子框架很多,所以知識量很廣。

SpringBoot:一款Spring框架的子框架,也可以叫微框架,是2014年推出的一款使Spring框架開發變得容易的框架。學過Spring框架的都知識,Spring框架難以避免地需要配置不少XMl,而使用SpringBoot框架的話,就可以使用注解開發,極大地簡化基于Spring框架的開發。SpringBoot充分利用了JavaConfig的配置模式以及“約定優于配置”的理念,能夠極大的簡化基于SpringMVC的Web應用和REST服務開發。

第三章 Redis簡介

3.1 Redis安裝部署(Linux)

Redis安裝部署的可以參考我的博客(Redis是基于C編寫的,所以安裝前先安裝gcc編譯器)

3.2 Redis簡介

Redis如今已經成為Web開發社區最火熱的內存數據庫之一,隨著Web2.0的快速發展,再加上半結構數據比重加大,網站對高效性能的需求也越來越多。

而且大型網站一般都有幾百臺或者更多Redis服務器。Redis作為一款功能強大的系統,無論是存儲、隊列還是緩存系統,都有其用武之地。

SpringBoot框架入門的可以參考之前的文章

第四章 Redis緩存實現

4.1下面結構圖

項目結構圖:

Spring,AOP,緩存處理,SpringBoot,Redis,緩存,springboot集成緩存

4.2 SpringBoot的yml文件配置

添加resource下面的application.yml配置,這里主要配置mysql,druid,redis

spring: datasource:  # 主數據源  shop:   url: jdbc:mysql://127.0.0.1:3306/jeeplatform?autoReconnect=true&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false   username: root   password: root  driver-class-name: com.mysql.jdbc.Driver  type: com.alibaba.druid.pool.DruidDataSource  # 連接池設置  druid:   initial-size: 5   min-idle: 5   max-active: 20   # 配置獲取連接等待超時的時間   max-wait: 60000   # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒   time-between-eviction-runs-millis: 60000   # 配置一個連接在池中最小生存的時間,單位是毫秒   min-evictable-idle-time-millis: 300000   # Oracle請使用select 1 from dual   validation-query: SELECT 'x'   test-while-idle: true   test-on-borrow: false   test-on-return: false   # 打開PSCache,并且指定每個連接上PSCache的大小   pool-prepared-statements: true   max-pool-prepared-statement-per-connection-size: 20   # 配置監控統計攔截的filters,去掉后監控界面sql無法統計,'wall'用于防火墻   filters: stat,wall,slf4j   # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄   connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000   # 合并多個DruidDataSource的監控數據   use-global-data-source-stat: true jpa:  database: mysql  hibernate:   show_sql: true   format_sql: true   ddl-auto: none   naming:    physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl mvc:  view:   prefix: /WEB-INF/jsp/   suffix: .jsp #Jedis配置 jedis :  pool :   host : 127.0.0.1   port : 6379   password : password   timeout : 0   config :    maxTotal : 100    maxIdle : 10    maxWaitMillis : 100000

編寫一個配置類啟動配置JedisConfig.java:

package org.muses.jeeplatform.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;@Configuration//@ConfigurationProperties(prefix = JedisConfig.JEDIS_PREFIX )public class JedisConfig {  //public static final String JEDIS_PREFIX = "jedis";  @Bean(name= "jedisPool")  @Autowired  public JedisPool jedisPool(@Qualifier("jedisPoolConfig") JedisPoolConfig config,                  @Value("${spring.jedis.pool.host}")String host,                  @Value("${spring.jedis.pool.port}")int port,                  @Value("${spring.jedis.pool.timeout}")int timeout,                  @Value("${spring.jedis.pool.password}")String password) {      return new JedisPool(config, host, port,timeout,password);  }  @Bean(name= "jedisPoolConfig")  public JedisPoolConfig jedisPoolConfig (@Value("${spring.jedis.pool.config.maxTotal}")int maxTotal,                        @Value("${spring.jedis.pool.config.maxIdle}")int maxIdle,                        @Value("${spring.jedis.pool.config.maxWaitMillis}")int maxWaitMillis) {      JedisPoolConfig config = new JedisPoolConfig();      config.setMaxTotal(maxTotal);      config.setMaxIdle(maxIdle);      config.setMaxWaitMillis(maxWaitMillis);      return config;    }}

4.3 元注解類編寫

編寫一個元注解類RedisCache.java,被改注解定義的類都自動實現AOP緩存處理

package org.muses.jeeplatform.annotation;import org.muses.jeeplatform.common.RedisCacheNamespace;import java.lang.annotation.*;/** * 元注解 用來標識查詢數據庫的方法 */@Documented@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RedisCache {//  RedisCacheNamespace nameSpace();}

JDK 5提供的注解,除了Retention以外,還有另外三個,即Target 、Inherited 和 Documented?;谶@個,我們可以實現自定義的元注解

我們設置RedisCache基于Method方法級別引用。

1.RetentionPolicy.SOURCE 這種類型的Annotations只在源代碼級別保留,編譯時就會被忽略
2.RetentionPolicy.CLASS 這種類型的Annotations編譯時被保留,在class文件中存在,但JVM將會忽略
3.RetentionPolicy.RUNTIME 這種類型的Annotations將被JVM保留,所以他們能在運行時被JVM或其他使用反射機制的代碼所讀取和使用.

4.4 調用JedisPool實現Redis緩存處理

package org.muses.jeeplatform.cache;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.stereotype.Service;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import javax.annotation.Resource;@Component("redisCache")public class RedisCache {    @Autowired  private JedisPool jedisPool;  private JedisPool getJedisPool(){    return jedisPool;  }    public void setJedisPool(JedisPool jedisPool){    this.jedisPool = jedisPool;  }    /**   * 從Redis緩存獲取數據   * @param redisKey   * @return   */  public Object getDataFromRedis(String redisKey){    Jedis jedis = jedisPool.getResource();    byte[] byteArray = jedis.get(redisKey.getBytes());        if(byteArray != null){      return SerializeUtil.unSerialize(byteArray);    }    return null;  }    /**   * 保存數據到Redis   * @param redisKey   */  public String saveDataToRedis(String redisKey,Object obj){        byte[] bytes = SerializeUtil.serialize(obj);        Jedis jedis = jedisPool.getResource();        String code = jedis.set(redisKey.getBytes(), bytes);        return code;  }}

對象序列化的工具類:

package org.muses.jeeplatform.cache;import java.io.*;public class SerializeUtil {    /**   * 序列化對象   * @param obj   * @return   */  public static byte[] serialize(Object obj){    ObjectOutputStream oos = null;    ByteArrayOutputStream baos = null;    try{      baos = new ByteArrayOutputStream();      oos = new ObjectOutputStream(baos);            oos.writeObject(obj);      byte[] byteArray = baos.toByteArray();      return byteArray;          }catch(IOException e){      e.printStackTrace();    }    return null;  }    /**   * 反序列化對象   * @param byteArray   * @return   */  public static Object unSerialize(byte[] byteArray){    ByteArrayInputStream bais = null;    try {      //反序列化為對象      bais = new ByteArrayInputStream(byteArray);      ObjectInputStream ois = new ObjectInputStream(bais);      return ois.readObject();          } catch (Exception e) {      e.printStackTrace();    }    return null;  }  }

這里記得Vo類都要實現Serializable

例如菜單信息VO類,這是一個JPA映射的實體類

package org.muses.jeeplatform.core.entity.admin;import javax.persistence.*;import java.io.Serializable;import java.util.List;/** * @description 菜單信息實體 * @author Nicky * @date 2017年3月17日 */@Table(name="sys_menu")@Entitypublic class Menu implements Serializable {  /** 菜單Id**/  private int menuId;    /** 上級Id**/  private int parentId;    /** 菜單名稱**/  private String menuName;    /** 菜單圖標**/  private String menuIcon;    /** 菜單URL**/  private String menuUrl;    /** 菜單類型**/  private String menuType;    /** 菜單排序**/  private String menuOrder;  /**菜單狀態**/  private String menuStatus;  private List<Menu> subMenu;  private String target;  private boolean hasSubMenu = false;  public Menu() {    super();  }      @Id  @GeneratedValue(strategy=GenerationType.IDENTITY)  public int getMenuId() {    return this.menuId;  }  public void setMenuId(int menuId) {    this.menuId = menuId;  }  @Column(length=100)  public int getParentId() {    return parentId;  }  public void setParentId(int parentId) {    this.parentId = parentId;  }  @Column(length=100)  public String getMenuName() {    return this.menuName;  }  public void setMenuName(String menuName) {    this.menuName = menuName;  }      @Column(length=30)  public String getMenuIcon() {    return this.menuIcon;  }  public void setMenuIcon(String menuIcon) {    this.menuIcon = menuIcon;  }      @Column(length=100)  public String getMenuUrl() {    return this.menuUrl;  }  public void setMenuUrl(String menuUrl) {    this.menuUrl = menuUrl;  }      @Column(length=100)  public String getMenuType() {    return this.menuType;  }  public void setMenuType(String menuType) {    this.menuType = menuType;  }  @Column(length=10)  public String getMenuOrder() {    return menuOrder;  }  public void setMenuOrder(String menuOrder) {    this.menuOrder = menuOrder;  }  @Column(length=10)  public String getMenuStatus(){    return menuStatus;  }  public void setMenuStatus(String menuStatus){    this.menuStatus = menuStatus;  }  @Transient  public List<Menu> getSubMenu() {    return subMenu;  }  public void setSubMenu(List<Menu> subMenu) {    this.subMenu = subMenu;  }  public void setTarget(String target){    this.target = target;  }  @Transient  public String getTarget(){    return target;  }  public void setHasSubMenu(boolean hasSubMenu){    this.hasSubMenu = hasSubMenu;  }  @Transient  public boolean getHasSubMenu(){    return hasSubMenu;  }}

4.5 Spring AOP實現監控所有被@RedisCache注解的方法緩存

先從Redis里獲取緩存,查詢不到,就查詢MySQL數據庫,然后再保存到Redis緩存里,下次查詢時直接調用Redis緩存

package org.muses.jeeplatform.cache;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;/** * AOP實現Redis緩存處理 */@Component@Aspectpublic class RedisAspect {  private static final Logger LOGGER = LoggerFactory.getLogger(RedisAspect.class);  @Autowired  @Qualifier("redisCache")  private RedisCache redisCache;  /**   * 攔截所有元注解RedisCache注解的方法   */  @Pointcut("@annotation(org.muses.jeeplatform.annotation.RedisCache)")  public void pointcutMethod(){  }  /**   * 環繞處理,先從Redis里獲取緩存,查詢不到,就查詢MySQL數據庫,   * 然后再保存到Redis緩存里   * @param joinPoint   * @return   */  @Around("pointcutMethod()")  public Object around(ProceedingJoinPoint joinPoint){    //前置:從Redis里獲取緩存    //先獲取目標方法參數    long startTime = System.currentTimeMillis();    String applId = null;    Object[] args = joinPoint.getArgs();    if (args != null && args.length > 0) {      applId = String.valueOf(args[0]);    }    //獲取目標方法所在類    String target = joinPoint.getTarget().toString();    String className = target.split("@")[0];    //獲取目標方法的方法名稱    String methodName = joinPoint.getSignature().getName();    //redis中key格式:  applId:方法名稱    String redisKey = applId + ":" + className + "." + methodName;    Object obj = redisCache.getDataFromRedis(redisKey);    if(obj!=null){      LOGGER.info("**********從Redis中查到了數據**********");      LOGGER.info("Redis的KEY值:"+redisKey);      LOGGER.info("REDIS的VALUE值:"+obj.toString());      return obj;    }    long endTime = System.currentTimeMillis();    LOGGER.info("Redis緩存AOP處理所用時間:"+(endTime-startTime));    LOGGER.info("**********沒有從Redis查到數據**********");    try{      obj = joinPoint.proceed();    }catch(Throwable e){      e.printStackTrace();    }    LOGGER.info("**********開始從MySQL查詢數據**********");    //后置:將數據庫查到的數據保存到Redis    String code = redisCache.saveDataToRedis(redisKey,obj);    if(code.equals("OK")){      LOGGER.info("**********數據成功保存到Redis緩存!!!**********");      LOGGER.info("Redis的KEY值:"+redisKey);      LOGGER.info("REDIS的VALUE值:"+obj.toString());    }    return obj;  }}

然后調用@RedisCache實現緩存

/**   * 通過菜單Id獲取菜單信息   * @param id   * @return   */  @Transactional  @RedisCache  public Menu findMenuById(@RedisCacheKey int id){    return menuRepository.findMenuByMenuId(id);  }

登錄系統,然后加入@RedisCache注解的方法都會實現Redis緩存處理

Spring,AOP,緩存處理,SpringBoot,Redis,緩存,springboot集成緩存

Spring,AOP,緩存處理,SpringBoot,Redis,緩存,springboot集成緩存

可以看到Redis里保存到了緩存

Spring,AOP,緩存處理,SpringBoot,Redis,緩存,springboot集成緩存

項目代碼:https://github.com/u014427391/jeeplatform

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精视频免费在线久久完整在线看| www.亚洲男人天堂| 中文字幕精品一区久久久久| 欧美日韩在线观看视频小说| 成人在线视频福利| 久久频这里精品99香蕉| 久久99久久99精品免观看粉嫩| 欧美大片免费观看在线观看网站推荐| 国模精品一区二区三区色天香| 日韩欧美在线视频日韩欧美在线视频| 亚洲午夜精品久久久久久久久久久久| www.99久久热国产日韩欧美.com| 亚洲女人被黑人巨大进入al| 91在线观看免费| 亚洲精品美女网站| 欧美成年人视频网站欧美| 亚洲人成五月天| 成人深夜直播免费观看| 国产大片精品免费永久看nba| 国产成人鲁鲁免费视频a| 亚洲国产精品女人久久久| 中文字幕欧美日韩精品| 久国内精品在线| 夜夜狂射影院欧美极品| 欧美一级成年大片在线观看| 日韩女在线观看| 欧美色欧美亚洲高清在线视频| 欧洲成人免费aa| 精品日韩中文字幕| 97久久久免费福利网址| 欧美性生活大片免费观看网址| 久久天天躁夜夜躁狠狠躁2022| 精品偷拍一区二区三区在线看| 国产精品久久久久久久7电影| 国产日韩欧美综合| 久久91亚洲人成电影网站| 福利一区视频在线观看| 欧美电影在线免费观看网站| 92国产精品视频| 色婷婷综合久久久久中文字幕1| www.日韩.com| 日韩久久精品成人| 国产精品日韩电影| 在线观看欧美视频| 精品无码久久久久久国产| 欧美性生交xxxxxdddd| 久久久久日韩精品久久久男男| 欧美成人在线免费| 伊人伊人伊人久久| 91伊人影院在线播放| 91久热免费在线视频| 欧美午夜美女看片| 精品国产一区二区三区四区在线观看| 亚洲第一中文字幕| 欧美性猛交xxxx富婆弯腰| 久久综合电影一区| 91大神福利视频在线| 日韩不卡中文字幕| 久久天天躁夜夜躁狠狠躁2022| 精品久久久久久中文字幕大豆网| 成人av在线天堂| 精品一区二区三区三区| 日韩精品视频在线免费观看| 美日韩精品视频免费看| 亚洲国产成人一区| 91在线视频免费| 久久久久999| 国产日韩欧美视频在线| 久久综合五月天| 中文字幕国内精品| 亚洲天堂av在线免费观看| 国产精品网址在线| 亚洲精选中文字幕| 久久久久久久久久久网站| 亚洲精品大尺度| 正在播放国产一区| 国产成人精品久久亚洲高清不卡| 久久久久久久久中文字幕| 国产美女被下药99| 福利一区视频在线观看| 97视频国产在线| 国产精品偷伦免费视频观看的| 日韩中文在线观看| 欧美日韩亚洲精品一区二区三区| 久久99精品久久久久久琪琪| 国产ts人妖一区二区三区| 在线精品国产成人综合| 亚洲成人在线视频播放| 欧美激情免费在线| 国产精品久久一区主播| 日本成人免费在线| 欧美日韩国产丝袜美女| 亚洲精品动漫久久久久| 久久久精品免费视频| 国产成人av网址| 欧美精品国产精品日韩精品| 国产欧美在线播放| 日本国产高清不卡| 国产裸体写真av一区二区| 精品久久久久人成| 日韩精品高清在线观看| 国产福利成人在线| 91精品中文在线| 国产精品第一第二| 成人免费视频xnxx.com| 欧美一区亚洲一区| 欧美激情亚洲综合一区| 国产一区二区三区视频| 日韩中文娱乐网| 国产精品极品尤物在线观看| 国产精品扒开腿做爽爽爽的视频| 久久成人精品视频| 一区二区三区视频免费在线观看| 欧美性受xxx| 黑人精品xxx一区一二区| 国产91九色视频| 国产精品成人一区二区三区吃奶| 亚洲国产精品99久久| 午夜精品一区二区三区av| 欧美亚洲第一页| 92版电视剧仙鹤神针在线观看| 国产精欧美一区二区三区| 日韩高清人体午夜| 色综合男人天堂| 久久久久成人网| 日韩第一页在线| 欧美巨猛xxxx猛交黑人97人| 亚洲成年人影院在线| 日韩一二三在线视频播| 欧美午夜久久久| 久久精品国产亚洲7777| 在线日韩精品视频| 亚洲精品国产综合久久| 久久亚洲精品中文字幕冲田杏梨| xvideos国产精品| 精品国产一区二区三区久久狼黑人| 4438全国亚洲精品在线观看视频| 成人免费自拍视频| 国产精品中文字幕久久久| 国产精品中文久久久久久久| 51精品国产黑色丝袜高跟鞋| 亚洲国产精品久久久久秋霞不卡| 欧美成人精品一区| 国产精品99久久久久久久久久久久| 国产精品视频网| 欧美日韩国产综合新一区| 成人网在线观看| 日韩av网址在线观看| 青草青草久热精品视频在线网站| 98视频在线噜噜噜国产| 成人免费看片视频| 97人人模人人爽人人喊中文字| 95av在线视频| 亚洲国产一区二区三区在线观看| 亚洲精品v欧美精品v日韩精品| 久久国产加勒比精品无码| 中文字幕久久久| 国产精品96久久久久久又黄又硬| 欧美富婆性猛交| 久久精品在线视频| 久久九九亚洲综合| 欧美一区二区三区免费观看| 中文字幕一区二区三区电影| 日本一区二区不卡|