天天看點

Redis入門案例(day12)1. Redis入門案例2. SpringBoot整合Redis3. JSON格式轉化

1. Redis入門案例

1.1 導入jar包

<dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
    </dependency>
           

1.2 入門案例

package com.hc.redis;

import org.junit.jupiter.api.Test;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.Transaction;

import redis.clients.jedis.params.SetParams;

public class TestRedis {

/**
 * 1.redis配置檔案3處修改
 * 2.Linux系統防火牆
 * 3.檢查redis啟動方式 redis-server redis.conf
 * */
@Test
public void testSet() throws InterruptedException {
    String host="192.168.126.129";
    int port=6379;
    Jedis jedis=new Jedis(host,port);
    //指令怎麼敲,代碼怎麼寫
    jedis.set("2021","redis入門案例");
    System.out.println(jedis.get("2021"));
    jedis.flushAll();
    //測試是否存在
    if(jedis.exists("2021")){
        jedis.del("2021");
    }else{
        jedis.set("num","100");
        //自增1
        jedis.incr("num");
        jedis.expire("num",20);
        Thread.sleep(2000);
        //檢查我們的逾時時間
        System.out.println(jedis.ttl("num"));
        //取消逾時時間
        jedis.persist("num");
    }
}
//有時我們可能為資料添加逾時時間
//原子性問題:有時業務要求要麼同時完成,要麼同時失敗
@Test
public void testSetEx() throws InterruptedException {
Jedis jedis=new Jedis("192.168.126.129",6379);
jedis.set("a","aa");
//伺服器異常
//jedis.expire("a",60);
jedis.setex("a",20,"100");
System.out.println(jedis.get("a"));

}

/**
 * 需求1:如果該資料不存在時,才會指派
 * 需求2:如果資料存在時,進行修改,并且為他設定逾時時間,滿足原子性要求
 */
@Test
public void testSetNx() throws InterruptedException {
    Jedis jedis=new Jedis("192.168.126.129",6379);
    jedis.set("a","111");
    jedis.setnx("a","123");
    System.out.println(jedis.get("a"));
    //jedis.set("b","123");
    SetParams params=new SetParams();
    params.xx().ex(20);
    jedis.set("b","bb",params);

}
//預設hash是無序的
@Test
public void testHash(){
    Jedis jedis=new Jedis("192.168.126.129",6379);
    jedis.hset("user","id","100");
    jedis.hset("user","name","101");
    jedis.hset("user","age","18");
    System.out.println(jedis.hkeys("user"));
}
//隊列:先進先出   方向相反
//棧: 先進後出    方向相同     注意可變參數類型
@Test
public void testList(){
    Jedis jedis=new Jedis("192.168.126.129",6379);
    jedis.lpush("list","1","2","3","4");
    System.out.println(jedis.rpop("list"));
}
@Test
public void testTx(){
    Jedis jedis=new Jedis("192.168.126.129",6379);
    //開啟事務
    Transaction transaction=jedis.multi();
    try {
        transaction.set("a", "a");
        transaction.set("b", "b");
        transaction.set("b", "b");
        //送出事務
        transaction.exec();
    }catch (Exception e){
        transaction.discard();
    }
}
}
           

2. SpringBoot整合Redis

2.1 編輯pro配置檔案

Redis入門案例(day12)1. Redis入門案例2. SpringBoot整合Redis3. JSON格式轉化

2.2 編輯配置類

package com.hc.config;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

import redis.clients.jedis.Jedis;

@Configuration //辨別為一個配置類,一般整合第三方

@PropertySource(“classpath:/properties/redis.properties”)

public class RedisConfig {

@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;

@Bean   //将該方法的傳回值,交給Spring容器管理
public Jedis jedis(){

    return new Jedis(host,port);
}
           

}

3. JSON格式轉化

3.1 業務說明

由于程式需要與JSON串進行資料的互動,是以通過API進行轉化

3.2 代碼如下

package com.hc.json;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.hc.pojo.ItemDesc;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

public class TestJson {

/**
 * json格式:
 *  1.object格式  {key:value,key2:value2}
 *  2.數組格式    [value,value2,value3]
 *  3.嵌套格式    value可以進行嵌套.
 *
 * 任務:  實作對象與JSON串之間的轉化.
 * 面試題: 常量是否有線程安全性問題??? 沒有
 */
 
private static final ObjectMapper MAPPER=new ObjectMapper();

@Test
public void objectToJSON() throws JsonProcessingException {
ItemDesc itemDesc=new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("json測試").setCreated(new Date())
        .setUpdated(itemDesc.getCreated());
//将對象轉化為JSON 調用對象的get方法 形成屬性/屬性值
String json=MAPPER.writeValueAsString(itemDesc);
System.out.println(json);
//将JSON對象轉化為對象 反射機制 執行個體化對象 調用對象的set方法為屬性指派
ItemDesc itemDesc2=MAPPER.readValue(json,ItemDesc.class);
System.out.println(itemDesc2.toString()+""+itemDesc2.getCreated());
}
public List<ItemDesc> getList(){
    List<ItemDesc> list = new ArrayList<>();
    ItemDesc itemDesc = new ItemDesc();
    itemDesc.setItemId(100L).setItemDesc("bbb")
            .setCreated(new Date()).setUpdated(new Date());
    ItemDesc itemDesc2 = new ItemDesc();
    itemDesc2.setItemId(200L).setItemDesc("bbb")
            .setCreated(new Date()).setUpdated(new Date());
    list.add(itemDesc);
    list.add(itemDesc2);
    return list;
}
@Test
public void ListTOJSON() throws JsonProcessingException {
List<ItemDesc> list=getList();
String json=MAPPER.writeValueAsString(list);
System.out.println(json);
//将JSON還原回對象
List<ItemDesc> list2=MAPPER.readValue(json,List.class);
System.out.println(list2);
}
           

}

3.3 JSON轉化工具API

說明: 在hc-common中添加工具API

package com.hc.util;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperUtil {

public static final ObjectMapper MAPPER=new ObjectMapper();
//1.對象轉化為JSON
public static String toJSON(Object obj){
    try {
        return MAPPER.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
        //将檢查異常轉化為運作異常
        e.printStackTrace();
        throw new RuntimeException(e);
    }
    
     }
//2.JSON轉化為對象  傳遞什麼樣的類型,傳回什麼樣的對象???
public static <T>T toObject(String json,Class<T> target){
    try {
        return MAPPER.readValue(json,target);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}
           

}

4. 商品分離緩存實作

4.1 編輯工具ItemCatServiceImpl

/**
 *
 * 1.将商品分類資訊添加到緩存中
 * 2.資料結構:  k-v結構   ITEM_CAT_PARENT::0 - JSON
 * 3.業務流程:
 *      1.先查緩存    true/false
 *      2.false  使用者第一次查詢資料庫, 将結果儲存到redis緩存中
 *      3.true   查詢緩存
 *  AOP機制
 */
@Override
public List<EasyUITree> findItemCatCache(Long parentId) {
    long startTime=System.currentTimeMillis();
    //1.定義key
    String key="ITEM_CAT_PARENT::"+parentId;
    List<EasyUITree> treeList = new ArrayList<>();
    //2.判斷資料是否存在
    if(jedis.exists(key)){
    String json=jedis.get(key);
    treeList=
            ObjectMapperUtil.toObject(json,treeList.getClass());

        long endTime=System.currentTimeMillis();
        System.out.println("redis查詢!!!耗時:"+(endTime-startTime));
    }else {
        //資料不存在,查詢資料庫
        treeList= findItemCatList(parentId);
       //将資料庫的記錄,轉化為json
        String json=ObjectMapperUtil.toJSON(treeList);
       //将資料儲存到redis中
        jedis.set(key,json);
        long endTime=System.currentTimeMillis();
        System.out.println("查詢資料庫!耗時:"+(endTime-startTime));
    }
    return treeList;
}
           

4.2 Redis效果展現

Redis入門案例(day12)1. Redis入門案例2. SpringBoot整合Redis3. JSON格式轉化

5.Spring中AOP複習

5.1 什麼是AOP

名稱解釋: 面向切面程式設計

作用: 在不修改源碼的條件下,對方法進行了額外了擴充.

意義: 降低了代碼的耦合性.

公式: AOP = 切入點表達式 + 通知方法

5.2 切入點表達式

1.bean(“包名.類名”) 具體某個類 按類比對 粗粒度

2.within(“包名.類名”) 可以使用通配符 幾個類一起比對 粗粒度

3.execution(傳回值類型 包名.類名.方法名(參數清單)) 細粒度

4.注解方式 @annotation(注解的類型) 細粒度

5.3 通知方法

1.before 目标方法執行之前執行.

2.afterReturning 目标方法執行之後執行

3.afterThrowing 目标方法抛出異常時執行

4.after 不管上述操作如何運作,最終都要執行.

上述的4大通知,都不能控制目标方法是否執行,一般隻會做程式的監控.

5.around 在目标方法執行前後 都要執行. 可以控制目标方法的執行軌迹.

5.4 AOP入門案例

Redis入門案例(day12)1. Redis入門案例2. SpringBoot整合Redis3. JSON格式轉化

package com.hc.aop;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

@Component //将對象交給spring容器管理

@Aspect //辨別AOP切面

public class RedisAOP {

/**
 * 1.定義切入點表達式
 * bean: 被spring容器管理的對象稱之為bean
 * 1.1 bean(bean的ID) 按類比對  1個
 *      bean(itemCatServiceImpl)
 * 1.2 within(包名.類名) 按類比對  一堆
 *      within(com.hc.service.*)
 * 1.3 execution(傳回值類型 包名.類名.方法名(參數清單))
 *     execution(* com.hc.service..*.*(..))
 *     解釋:  傳回值為任意類型 com.hc.service包所有的子孫包的類
 *            類中的任意方法,任意參數
 *     execution(Integer com.hc.service..*.add*(int))
 *     execution(int com.hc.service..*.add*(int))
 */
@Pointcut("execution(* com.hc.service..*.*(..))")
public void pointCut(){

}

//如何了解什麼是連接配接點? 被切入點攔截的方法
//ProceedingJoinPoint is only supported for around advice
//隻有環繞通知可以控制目标方法
@Before("pointCut()")
public void before(JoinPoint joinPoint){
    String methodName = joinPoint.getSignature().getName();
    String className = joinPoint.getSignature().getDeclaringTypeName();
    Object[] args = joinPoint.getArgs();
    Object target = joinPoint.getTarget();
    System.out.println(methodName);
    System.out.println(className);
    System.out.println(args);
    System.out.println(target);
    System.out.println("我是一個前置通知");
}
           

}

6. 自定義注解實作緩存

控制緩存操作

如何設計 自己定!!!