某些方法触发刷新redis——拦截某些方法——切面——@Pointcut("execution…或者自定义注解——选择通过自定义注解的方式实现
redis使用
/**
* redis 数据模板
*/
@Autowired
private RedisTemplate<String, String> redisTemplate;
private List<EhrOrganizationEntity> getOrgTreeList(Map<String, Object> params){
//1、从redis中获取数据,数据格式为json字符串
String orgListJson = redisTemplate.boundValueOps("org.getOrgList").get();
//2、判断是否为空
if (null == orgListJson || "orgListJson".equals(orgListJson)){
//3、不存在就从数据库中查
List<EhrOrganizationEntity> orgList = ehrOrganizationService.getOrgList(params);
//4、将查出的数据存到redis中
ObjectMapper objectMapper = new ObjectMapper();
try {
orgListJson = objectMapper.writeValueAsString(orgList);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
redisTemplate.boundValueOps("org.getOrgList").set(orgListJson);
//谁写的?冗余的一行,可删。搁这给我整死循环呢,因果自噬死循环,脑子不清醒(估计json/String和java对象的关系没整明白)
String s = JSONObject.parseArray(orgListJson).toString();
List<EhrOrganizationEntity> treeList = JSON.parseArray(s, EhrOrganizationEntity.class);
return treeList;
}else {
//谁写的?冗余的一行,可删。搁这给我整死循环呢,因果自噬死循环,脑子不清醒(估计json/String和java对象的关系没整明白)
String s = JSONObject.parseArray(orgListJson).toString();
List<EhrOrganizationEntity> treeList = JSON.parseArray(s, EhrOrganizationEntity.class);
return treeList;
}
}
自定义注解:
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ReOrgTree {
String value() default "";
}
切点:
/**
* 针对组织更新的切点
*/
@Aspect
@Component
public class OrgTreeAop {
/**
* redis
*/
@Autowired
private RedisUtil redisUtil;
/**
* 使用注解方式定义切点
*/
@Pointcut("@annotation(com.company.base.common.annotation.ReOrgTree)")
public void reRedisByOrgTreePoint(){}
/**
* 后置通知
* 织入
*/
// @After("execution(* com.company.base.modules.ehr.controller.EhrOrganizationController.*(..)) && !execution(* com.company.base.modules.ehr.controller.EhrOrganizationController.get*(..))")
@After("reRedisByOrgTreePoint()")
public void refreshRedisByOrgTree(){
System.out.println("执行切面================================1");
// 刷新组织树
redisUtil.refreshRedisByOrgTree();
}
}
RedisUtil
/**
* 缓存
*/
@Component
public class RedisUtil {
// redis模板
@Autowired
private RedisTemplate redisTemplate;
// 组织
@Autowired
private EhrOrganizationService ehrOrganizationService;
/**
* 更新缓存中的组织架构树
*/
public void refreshRedisByOrgTree() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Map<String, Object> params = new HashMap<>();
params.put("key", "");
params.put("status", "");
params.put("column", "");
String orgListJson = "";
Boolean delete = redisTemplate.delete("org.getOrgList");
if (delete) {
List<EhrOrganizationEntity> orgList = ehrOrganizationService.getOrgList(params);
if (null != orgList && orgList.size() >= 0) {
//4、将查出的数据存到redis中
ObjectMapper objectMapper = new ObjectMapper();
try {
orgListJson = objectMapper.writeValueAsString(orgList);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//当 组织树JSON串(json/String字符串) 被重新赋值 才执行缓存
//不该判断orgListJson而应该早就判断orgList非空。即使他想判orgListJson就判orgListJson吧,但,利用com.fasterxml.jackson工具转换json时,传空,是否返回的是null?所以,这里草率的用"",有隐患/漏洞,建议改成StringUtils.isNotBlank()
if (!"".equals(orgListJson)) {
redisTemplate.boundValueOps("org.getOrgList").set(orgListJson);
}
}
}
}
});
thread.start();
}
}
使用:
@ReOrgTree
@Override
@Transactional
public int updateHrActualDate(Map<String, Object> params) {
}
“Springboot自定义注解实现切点切面”详细步骤:
package com.company.base.common.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HappyStar {
// ( )里默认""
String value() default "";
}
package com.company.base.modules.ehr.aop;
import com.cowain.base.modules.ehr.utils.RedisUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 快乐星球
*/
@Aspect
@Component
public class HappyStarAop {
/**
* 切点: 被此注解修饰的方法
*/
@Pointcut("@annotation(com.cowain.base.common.annotation.HappyStar)")
public void reRedisByOrgTreePoint(){
System.out.println("快乐星球=====");
}
@Before(value = "com.cowain.base.modules.ehr.aop.HappyStarAop.reRedisByOrgTreePoint()")
public void before(JoinPoint joinPoint) {
System.out.println("快乐星球===== before advise");
}
@Around("reRedisByOrgTreePoint()")
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("快乐星球===== around advise 1");
pjp.proceed();
System.out.println("快乐星球===== around advise2");
}
@AfterReturning("reRedisByOrgTreePoint()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("快乐星球===== afterReturning advise");
}
@AfterThrowing("reRedisByOrgTreePoint()")
public void afterThrowing(JoinPoint joinPoint) {
System.out.println("快乐星球===== afterThrowing advise");
}
/**
* After
*/
@After("reRedisByOrgTreePoint()")
public void refreshRedisByOrgTree(JoinPoint joinPoint){
System.out.println("快乐星球===after advise/发生后");
}
}
使用
/**
* 列表递归
*/
@HappyStar("赌神今天RNG重拳出击")
@RequestMapping("/getOrgTreeLevel")
public R getOrgTreeLevel(@RequestParam Map<String, Object> params) {
// 只有参数都为空时,走缓存
if ((null == params.get("status") ||"".equals(params.get("status"))) &&
(null == params.get("key")||"".equals(params.get("key")))
){
结果/效果:
好处:
拦截。
提高一段代码的复用性。
配合注解,变得相当易用。