装饰器的实际应用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 使用装饰器模式改造slf4j打印json格式日志

上一篇文章中总结了装饰器模式,现在将装饰器结合实际应用起来。

使用装饰器模式改造slf4j打印json格式日志,以便于日志的分析


一、准备

装饰器模式得有一个抽象组件Component

这里的抽象组件可以直接是org.slf4j.Loggerorg.slf4j.LoggerFactory#getLogger(java.lang.Class)可以看作是一个具体组件(Concrete Component)

还缺少装饰器(Decorator)具体组件(Concrete Decorator)

二、实现

2.1 装饰器JsonLoggerDecorator

publicclassJsonLoggerDecoratorimplementsLogger {
protectedfinalLoggerlogger;
publicJsonLoggerDecorator(Loggerlogger) {
this.logger=logger;
    }
@OverridepublicStringgetName() {
returnnull;
    }
@OverridepublicbooleanisTraceEnabled() {
returnfalse;
    }
@Overridepublicvoidtrace(Stringmsg) {
    }
@Overridepublicvoidtrace(Stringformat, Objectarg) {
    }
@Overridepublicvoidtrace(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidtrace(Stringformat, Object... arguments) {
    }
@Overridepublicvoidtrace(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisTraceEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidtrace(Markermarker, Stringmsg) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Object... argArray) {
    }
@Overridepublicvoidtrace(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisDebugEnabled() {
returnfalse;
    }
@Overridepublicvoiddebug(Stringmsg) {
    }
@Overridepublicvoiddebug(Stringformat, Objectarg) {
    }
@Overridepublicvoiddebug(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiddebug(Stringformat, Object... arguments) {
    }
@Overridepublicvoiddebug(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisDebugEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoiddebug(Markermarker, Stringmsg) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoiddebug(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisInfoEnabled() {
returnfalse;
    }
@Overridepublicvoidinfo(Stringmsg) {
    }
@Overridepublicvoidinfo(Stringformat, Objectarg) {
    }
@Overridepublicvoidinfo(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidinfo(Stringformat, Object... arguments) {
    }
@Overridepublicvoidinfo(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisInfoEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidinfo(Markermarker, Stringmsg) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoidinfo(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisWarnEnabled() {
returnfalse;
    }
@Overridepublicvoidwarn(Stringmsg) {
    }
@Overridepublicvoidwarn(Stringformat, Objectarg) {
    }
@Overridepublicvoidwarn(Stringformat, Object... arguments) {
    }
@Overridepublicvoidwarn(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidwarn(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisWarnEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidwarn(Markermarker, Stringmsg) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoidwarn(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisErrorEnabled() {
returnfalse;
    }
@Overridepublicvoiderror(Stringmsg) {
    }
@Overridepublicvoiderror(Stringformat, Objectarg) {
    }
@Overridepublicvoiderror(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiderror(Stringformat, Object... arguments) {
    }
@Overridepublicvoiderror(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisErrorEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoiderror(Markermarker, Stringmsg) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoiderror(Markermarker, Stringmsg, Throwablet) {
    }
}

2.2 具体装饰器JsonLogger

importcom.alibaba.fastjson.JSONObject;
importorg.slf4j.Logger;
importjava.util.Arrays;
publicclassJsonLoggerextendsJsonLoggerDecorator {
publicJsonLogger(Loggerlogger) {
super(logger);
    }
@Overridepublicvoidinfo(Stringmsg) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("message", msg);
logger.info(jsonObject.toJSONString());
    }
@Overridepublicvoiderror(Stringmsg) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("message", msg);
logger.error(jsonObject.toJSONString());
    }
/*** 重载一个异常的error** @param e*/publicvoiderror(Exceptione) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("name", e.getClass().getName());
StringstackTrace=Arrays.toString(e.getStackTrace());
jsonObject.put("stackTrace", stackTrace);
logger.error(jsonObject.toJSONString());
    }
privateJSONObjectnewJsonObject() {
returnnewJSONObject();
    }
}

三、使用

Logger对外提供了一个工厂LoggerFactory,这里我们也提供一个JsonLoggerFactory

importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
publicclassJsonLoggerFactory {
publicstaticJsonLoggergetJsonLogger(Class<?>clazz) {
Loggerlogger=LoggerFactory.getLogger(clazz);
returnnewJsonLogger(logger);
    }
}

四、测试类

publicclassJsonLoggerTest {
privatestaticfinalJsonLoggerlogger=JsonLoggerFactory.getJsonLogger(JsonLoggerTest.class);
publicstaticvoidmain(String[] args) {
logger.info("info日志");
logger.error("系统异常");
logger.error(newException("抛出异常"));
    }
}

4.1 执行结果

10:30:31.368 [main] INFO com.example.validated.design.decorator.logger.JsonLoggerTest - {"message":"info日志"}
10:30:31.372 [main] ERROR com.example.validated.design.decorator.logger.JsonLoggerTest - {"message":"系统异常"}
10:30:31.372 [main] ERROR com.example.validated.design.decorator.logger.JsonLoggerTest - {"name":"java.lang.Exception","stackTrace":"[com.example.validated.design.decorator.logger.JsonLoggerTest.main(JsonLoggerTest.java:13)]"}

五、类图

image.png

六、其他

在实际的开发过程,我们也可以通过装饰器模式实现不同角色的用户去展示不同的导航菜单

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
缓存 前端开发 中间件
DDD 领域驱动设计落地实践系列:工程结构分层设计
前面几篇文章中,笔者给大家阐述了 DDD 领域驱动设计的三大过程,重点围绕如何通过战略设计与战术设计进行 DDD 落地实践进行了详细的讨论,但是还没有涉及到工程层面的落地。实际上所有的这些架构理论到最后都是为了使得我们代码结构更加清晰,从而开发出 bug 少、扩展性强、逻辑清楚的应用。因此本文就是为了解决 DDD 领域驱动落地实践最后一公里问题,将我们分析出来的领域模型通过与工程结构的映射实现真正的落地。
DDD 领域驱动设计落地实践系列:工程结构分层设计
|
前端开发 架构师 搜索推荐
COLA 4.0:直击应用架构本质的最佳实践
COLA 4.0:直击应用架构本质的最佳实践
3319 0
COLA 4.0:直击应用架构本质的最佳实践
|
存储 安全 Shell
【Shell 命令集合 系统管理 】Linux 更改用户的GECOS字段 chfn命令 使用指南
【Shell 命令集合 系统管理 】Linux 更改用户的GECOS字段 chfn命令 使用指南
147 0
|
存储 自然语言处理 前端开发
领域驱动设计(DDD)-基础思想
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂
7776 0
|
11月前
|
缓存 数据库
读写锁和互斥锁的区别
【10月更文挑战第6天】
498 58
|
消息中间件 存储 缓存
一张图进阶 RocketMQ - 消费者这个大冤种!
三此君看了好几本书,看了很多遍源码整理的 一张图进阶 RocketMQ 图片,关于 RocketMQ 你只需要记住这张图! 本以为仅仅是 Broker 把消息推给消费者,消费者消费了就完事了。可是从消费者启动、消息拉取、消息消费、负载均衡、到结果处理中的消息重试和消费位移管理。消费者这个大冤种,纯纯打工人是石锤了。
48635 12
一张图进阶 RocketMQ - 消费者这个大冤种!
|
11月前
|
负载均衡 算法 Java
微服务面试篇
微服务面试篇
350 2
|
存储 关系型数据库 MySQL
InnoDB 引擎技术文档
【7月更文挑战第6天】InnoDB 是 MySQL 数据库中最常用的关系型数据库存储引擎,自 MySQL 5.5 版本以来成为默认存储引擎。它支持事务处理、行级锁定、外键约束以及崩溃恢复能力,特别适合于高并发、高可靠性的应用场景。InnoDB 引擎还提供了对大容量数据的支持,通过聚簇索引实现数据和索引的紧密集成,优化了查询性能。
258 0
|
缓存 监控 UED
CDN(内容分发网络):加速网站加载与优化用户体验
CDN(内容分发网络):加速网站加载与优化用户体验
|
存储 缓存 算法
Shiro【散列算法、Shiro会话、退出登录 、权限表设计、注解配置鉴权 】(五)-全面详解(学习总结---从入门到深化)(下)
Shiro【散列算法、Shiro会话、退出登录 、权限表设计、注解配置鉴权 】(五)-全面详解(学习总结---从入门到深化)
143 0