java设计模式(实战)

网友投稿 247 2022-11-10

java设计模式(实战)

目录一:模式说明二:项目实战三:源代码

一:模式说明

模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果(取自《设计模式之禅》)。

翻译:Client对象调用一个处理者(类)的方法,可能有多个处理者(实现类),但是该对象只需要调用第一个处理者(类)即可,该模式会自动分配谁来处理这个请求;这多个处理者继承同一个父类(即在一条链上)。

通用类图如下:

Client发送请求到Handler,Handler自动分配请求到子类的实现类ConcreteHandler中。

二:项目实战

在文章 >手写redis@Cacheable注解 支持过期时间设置< 的基础之上做修改,原版为redis缓存注解实现,

原版实现功能:

将数据存放到redis中 设置过期时间

原业务逻辑查询人员列表listleader()接口,数据存放redis中,减少数据库负载。

由于业务发展,需要进一步优化查询接口;目前每个人都会操作redis中存放的人员列表,导致该列表会实时发生变动(比如

每个人员对应的分数),每个人都有自己的缓存人员列表而不是统一的人员列表;原列表BhgFNpJho已经无法满足现需求,每个人第一次登

录都会查询数据库,将自己的列表存放在redis中。

解决方法:设置两级缓存,第一级为该用户(uuid)唯一缓存,key值设置为参数1+uuid+参数2;第二级为第一次登录查询返

回redis中的原始leader列表,key值设置为参数1+参数2。如果当前用户leader列表(一级缓存)为空,则查询原始leader列表

(二级缓存),在操作分数的时候修改二级缓存(初始人员列表)来产生一级缓存,存放进redis,减少了数据库的直接访问。

项目中责任链相关设计类图如下:

说明:抽象类CacheHandler 一是定义了处理请求方法handleMessage;二是定义一个链的编排方法setNext,设置下一个处理者;三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务response;

FirstCacheHadler为一级缓存处理者,SecondCacheHadler为二级缓存处理者。缓存处理的方式通过CacheableAspect类调用。

三:源代码

CacheableAspect:client调用

package com.huajie.aspect;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

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.aspectj.lang.reflect.MethodSignature;

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

import org.springframework.stereotype.Component;

import com.huajie.annotation.ExtCacheable;

import com.huajie.common.cache.CacheHandler;

import com.huajie.common.cache.FirstCacheHadler;

import com.huajie.common.cache.RedisResult;

import com.huajie.common.cache.SecondCacheHadler;

import com.huajie.utils.RedisUtil;

import com.huajie.utils.StringUtil;

/**

* redis缓存处理 不适用与内部方法调用(this.)或者private

*/

@Component

@Aspect

public class CacheableAspect {

@Autowired

private RedisUtil redisUtil;

@Pointcut("@annotation(com.huajie.annotation.ExtCacheable)")

public void annotationPointcut() {

}

@Around("annotationPointcut()")

public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {

// 获得当前访问的class

Class> className = joinPoint.getTarget().getClass();

// 获得访问的方法名

String methodName = joinPoint.getSignature().getName();

// 得到方法的参数的类型

Class>[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();

Object[] args = joinPoint.getArgs();

String key = "";

String nextKey = "";

int expireTime = 1800;

try {

// 得到访问的方法对象

Method method = className.getMethod(methodName, argClass);

method.setAccessible(true);

// 判断是否存在@ExtCacheable注解

if (method.isAnnotationPresent(ExtCacheable.class)) {

ExtCacheable annotation = method.getAnnotation(Ehttp://xtCacheable.class);

key = getRedisKey(args, annotation.key());

nextKey = getRedisKey(args,annotation.nextKey());

expireTime = getExpireTime(annotation);

}

} catch (Exception e) {

throw new RuntimeException("redis缓存注解参数异常", e);

}

//责任链模式

CacheHandler firstCacheHadler = new FirstCacheHadler();

CacheHandler secondCacheHadler = new SecondCacheHadler();

//设置下级处理者

firstCacheHadler.setNext(secondCacheHadler);

//获取处理级别

int cacheLevel = getCacheLevel(key, nextKey);

RedisResult result = new RedisResult(redisUtil, key, nextKey, joinPoint, cacheLevel, expireTime);

//客户端调用

return firstCacheHadler.HandleMessage(result);

}

private int getCacheLevel(String key, String nextKey) {

if (StringUtil.isNotEmpty(key) && StringUtil.isNotEmpty(nextKey)) {

return 2;

} else {

return 1;

}

}

private int getExpireTime(ExtCacheable annotation) {

return annotation.expireTime();

}

private String getRedisKey(Object[] args, String primalKey) {

// 获取#p0...集合

List keyList = getKeyParsList(primalKey);

for (String keyName : keyList) {

int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", ""));

Object parValue = args[keyIndex];

primalKey = primalKey.replace(keyName, String.valueOf(parValue));

}

return primalKey.replace("+", "").replace("'", "");

}

// 获取key中#p0中的参数名称

private static List getKeyParsList(String key) {

List ListPar = new ArrayList();

if (key.indexOf("#") >= 0) {

int plusIndex = key.substring(key.indexOf("#")).indexOf("+");

int indexNext = 0;

String parName = "";

int indexPre = key.indexOf("#");

if (plusIndex > 0) {

indexNext = key.indexOf("#") + key.substring(key.indexOf("#")).indexOf("+");

parName = key.substring(indexPre, indexNext);

} else {

parName = key.substring(indexPre);

}

ListPar.add(parName.trim());

key = key.substring(indexNext + 1);

if (key.indexOf("#") >= 0) {

ListPar.addAll(getKeyParsList(key));

}

}

return ListPar;

}

}

CacheHandler:

package com.huajie.common.cache;

/**

* @author xiewenfeng 缓存处理接口

* 责任链模式

*/

public abstract class CacheHandler {

// 定义处理级别

protected final static int FirstCache_LEVEL_REQUEST = 1;

protected final static int SecondCache_LEVEL_REQUEST = 2;

// 能处理的级别

private int level = 0;

// 责任传递,下一个责任人是谁

private CacheHandler nextHandler;

// 每个类自己能处理那些请求

public CacheHandler(int level) {

this.level = level;

}

// 处理请求

public final Object HandleMessage(RedisResult redisResult) throws Throwable {

//如果women类型为当前处理的level

if(redisResult.getCacheLevel()==this.level){

return this.response(redisResult);

}else{

if(null!=this.nextHandler){

return this.nextHandler.HandleMessage(redisResult);

}else{

//没有下级不处理

return null;

}

}

}

public void setNext(CacheHandler handler) {

this.nextHandler = handler;

}

// 有请示的回应

protected abstract Object response(RedisResult redisResult) throws Throwable;

}

FirstCacheHadler:一级缓存处理者

package com.huajie.common.cache;

import org.aspectj.lang.ProceedingJoinPoint;

import com.huajie.utils.RedisUtil;

public class FirstCacheHadler extends CacheHandler{

public FirstCacheHadler() {

super(CacheHandler.FirstCache_LEVEL_REQUEST);

}

@Override

protected Object response(RedisResult redisResult) throws Throwable {

Strinhttp://g key = redisResult.getKey();

RedisUtil redisUtil = redisResult.getRedisUtil();

boolean hasKey = redisUtil.hasKey(key);

ProceedingJoinPoint joinPoint = redisResult.getJoinPoint();

int expireTime = redisResult.getExpireTime();

if (hasKey) {

return redisUtil.get(key);

} else {

Object res = joinPoint.proceed();

redisUtil.set(key, res);

redisUtil.expire(key, expireTime);

return res;

}

}

}

SecondCacheHadler:二级缓存处理者

package com.huajie.common.cache;

import org.aspectj.lang.ProceedingJoinPoint;

import com.huajie.utils.RedisUtil;

public class SecondCacheHadler extends CacheHandler {

public SecondCacheHadler() {

super(CacheHandler.SecondCache_LEVEL_REQUEST);

}

@Override

protected Object response(RedisResult redisResult) throws Throwable {

String nextKey = redisResult.getNextKey();

String key = redisResult.getKey();

RedisUtil redisUtil = redisResult.getRedisUtil();

ProceedingJoinPoint joinPoint = redisResult.getJoinPoint();

int expireTime = redisResult.getExpireTime();

boolean hasKey = redisUtil.hasKey(key);

if (hasKey) {

return redisUtil.get(key);

} else {

boolean hasNextKey = redisUtil.hasKey(nextKey);

if (hasNextKey) {

return redisUtil.get(nextKey);

} else {

Object res = joinPoint.proceed();

redisUtil.set(nextKey, res);

redisUtil.expire(nextKey, expireTime);

return res;

}

}

}

}

RedisResult:该业务场景对象,用于传递参数

package com.huajie.common.cache;

import org.aspectj.lang.ProceedingJoinPoint;

import com.huajie.utils.RedisUtil;

import lombok.Data;

@Data

public class RedisResult implements IRedisResult {

private int cacheLevel;

private Object result;

private RedisUtil redisUtil;

private String key;

private String nextKey;

private int expireTime;

private ProceedingJoinPoint joinPoint;

@Override

public int getCacheLevel() {

return cacheLevel;

}

@Override

public Object getResult() {

return result;

}

public RedisResult(RedisUtil redisUtil, String key, String nextKey, ProceedingJoinPoint joinPoint, int cacheLevel,int expireTime) {

this.redisUtil = redisUtil;

this.key = key;

this.joinPoint = joinPoint;

this.cacheLevel = cacheLevel;

this.nextKey = nextKey;

this.expireTime = expireTime;

}

}

使用方法如下:

@Override

@ExtCacheable(key = "middle+#p0+#p1+#p2", nextKey = "middle+#p0+#p2")

public List listMiddleManageInfo(String leadergroupId, String uuid, String yearDetailId) {

Map map = new HashMap();

map.put("leadergroupId", leadergroupId);

map.put("uuid", uuid);

map.put("yearDetailId", yearDetailId)BhgFNpJho;

List middleManageDetailList = middleManageMapper.listMiddleManageInfo(map);

return middleManageDetailList;

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:VLAN中继链路实验配置
下一篇:动态路由RIP协议的原理及配置
相关文章

 发表评论

暂时没有评论,来抢沙发吧~