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

目录

定义

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

模拟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 ? " 放⾏" : " 拦截"));
}
相关推荐
_Evan_Yao6 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd7 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼7 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool1122668 小时前
TCP 1
java·1024程序员节
金銀銅鐵10 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手10 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck12 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_322414280412 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis
考虑考虑13 小时前
JDK26的JEP 500属性
java·后端·java ee
LMT流氓兔13 小时前
第五单元——第十二课:把脚本整理成项目
java·数据库·python·langchain·1024程序员节