装饰器模式(模拟⼀个单点登录功能扩充)

目录

定义

模拟⼀个单点登录功能扩充

模拟Spring的HandlerInterceptor

模拟单点登录功能

代码实现

抽象类装饰⻆⾊

装饰⻆⾊逻辑实现

测试验证


定义

装饰器的核⼼就是再不改原有类的基础上给类新增功能。不改变原有类,使⽤装饰器模式会是另外⼀种思路更为灵活,可以避免继承导致的⼦类过多。

模拟⼀个单点登录功能扩充

⼀般在业务开发的初期,往往内部的ERP使⽤只需要判断账户验证即可,验证通过后即可访问ERP的所

有资源。但随着业务的不断发展,团队⾥开始出现专⻔的运营⼈员、营销⼈员、数据⼈员,每个⼈员对

于ERP的使⽤需求不同,有些需要创建活动,有些只是查看数据。同时为了保证数据的安全性,不会让

每个⽤户都有最⾼的权限。 那么以往使⽤的 SSO 是⼀个组件化通⽤的服务,不能在⾥⾯添加需要的⽤户访问验证功能。这个时候我们就可以使⽤装饰器模式,扩充原有的单点登录服务。但同时也保证原有功能不受破坏,可以继续使⽤。

模拟Spring的HandlerInterceptor

复制代码
public interface HandlerInterceptor {
    boolean preHandle(String request, String response, Object handler);
}

实际的单点登录开发会基于; org.springframework.web.servlet.HandlerInterceptor 实现。

模拟单点登录功能

复制代码
public class SsoInterceptor implements HandlerInterceptor{
    public boolean preHandle(String request, String response, Object handler) {
        // 模拟获取cookie
        String ticket = request.substring(1, 8);
        // 模拟校验
        return ticket.equals("success");
    }
}

代码实现

抽象类装饰⻆⾊

复制代码
public abstract class SsoDecorator implements HandlerInterceptor {
    private HandlerInterceptor handlerInterceptor;
    private SsoDecorator(){}
    
    public SsoDecorator(HandlerInterceptor handlerInterceptor) {
        this.handlerInterceptor = handlerInterceptor;
    }
    
    public boolean preHandle(String request, String response, Object handler) {
        return handlerInterceptor.preHandle(request, response, handler);
    }
}

在装饰类中有两个点的地⽅是;1)继承了处理接⼝、2)提供了构造函数、3)覆盖了⽅法 preHandle 。以上三个点是装饰器模式的核⼼处理部分,这样可以踢掉对⼦类继承的⽅式实现逻辑功能扩展。

装饰⻆⾊逻辑实现

复制代码
public class LoginSsoDecorator extends SsoDecorator {
    private Logger logger = LoggerFactory.getLogger(LoginSsoDecorator.class);
    
    private static Map<String, String> authMap = new ConcurrentHashMap<String, String>();
    static {
        authMap.put("huahua", "queryUserInfo");
        authMap.put("doudou", "queryUserInfo");
    }
    
    public LoginSsoDecorator(HandlerInterceptor handlerInterceptor) {
        super(handlerInterceptor);
    }
    
    @Override
    public boolean preHandle(String request, String response, Object handler) {
        boolean success = super.preHandle(request, response, handler);
        if (!success) return false;
        String userId = request.substring(8);
        String method = authMap.get(userId);
        logger.info("模拟单点登录⽅法访问拦截校验:{} {}", userId, method);
        // 模拟⽅法校验
        return "queryUserInfo".equals(method);
    }
}

测试验证

复制代码
@Test
public void test_LoginSsoDecorator() {
    LoginSsoDecorator ssoDecorator = new LoginSsoDecorator(new SsoInterceptor());
    String request = "1successhuahua";
    boolean success = ssoDecorator.preHandle(request, "ewcdqwt40liuiu", "t");
    System.out.println("登录校验:" + request + (success ? " 放⾏" : " 拦截"));
}
相关推荐
爱上语文3 分钟前
Redis基础(4):Set类型和SortedSet类型
java·数据库·redis·后端
lifallen17 分钟前
Paimon vs. HBase:全链路开销对比
java·大数据·数据结构·数据库·算法·flink·hbase
深栈解码1 小时前
JMM深度解析(三) volatile实现机制详解
java·后端
liujing102329291 小时前
Day04_刷题niuke20250703
java·开发语言·算法
Brookty1 小时前
【MySQL】JDBC编程
java·数据库·后端·学习·mysql·jdbc
能工智人小辰1 小时前
二刷 苍穹外卖day10(含bug修改)
java·开发语言
DKPT1 小时前
Java设计模式之结构型模式(外观模式)介绍与说明
java·开发语言·笔记·学习·设计模式
缘来是庄1 小时前
设计模式之外观模式
java·设计模式·外观模式
知其然亦知其所以然2 小时前
JVM社招面试题:队列和栈是什么?有什么区别?我在面试现场讲了个故事…
java·后端·面试
harmful_sheep2 小时前
Spring 为何需要三级缓存解决循环依赖,而不是二级缓存
java·spring·缓存