千家信息网

SpringBoot2集成日志以及复杂业务下的自定义实现是怎样的

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,这期内容当中小编将会给大家带来有关SpringBoot2集成日志以及复杂业务下的自定义实现是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、日志体系集成1、
千家信息网最后更新 2025年02月03日SpringBoot2集成日志以及复杂业务下的自定义实现是怎样的

这期内容当中小编将会给大家带来有关SpringBoot2集成日志以及复杂业务下的自定义实现是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

一、日志体系集成

1、日志管理

在系统的开发中,最关键的一个组件工具就是日志,日志打印方便问题排查,或者生产事故回溯,日志记录用来监控并分析系统性能点,并以此为依据,不断对系统进行优化;同时基于用户的操作日志,对用户行为进行分析,开发智能推荐的功能,或者进行营销投放,这在系统中都是常见且关键的业务流程。

2、ELK日志体系

在大型系统架构中,ELK的日志管理系统是系统必备功能,ELK-Stack是Elasticsearch、Logstash、Kiban三个开源软件的组合,通常用来做日志分析,实时数据检索。基于Logstash做数据流动通道,使日志数据不断的流入搜索组件,基于Elasticsearch做数据实时查询,基于Kiban的ES可视化界面,以此实现日志数据的搜集、存储、分析等核心功能,且该体系方便扩展。

基于ELK体系的核心操作,有关于ElasticSearch其他文章可以自行查阅之前的内容,这里不在陈列,好像很多东西都是这样一点点积累出来的。

二、集成环境

1、项目结构

defined-log-api:测试工程;

defined-log-config:日志核心模块,依赖之后使用该模块下注解即可;

2、数据表结构

CREATE TABLE dt_defined_log (        id INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT '主键',        class_name VARCHAR ( 200 ) DEFAULT NULL COMMENT '请求类名',        method_name VARCHAR ( 100 ) DEFAULT NULL COMMENT '请求方法名',        method_desc VARCHAR ( 100 ) DEFAULT NULL COMMENT '请求方法描述',        api_type INT ( 1 ) DEFAULT 0 COMMENT 'API类型',        biz_nature INT ( 1 ) DEFAULT 0 COMMENT '业务性质类型',        data_flow_type INT ( 1 ) DEFAULT 0 COMMENT '日志数据流向',        req_param VARCHAR ( 200 ) DEFAULT NULL COMMENT '请求报文',        res_param VARCHAR ( 200 ) DEFAULT NULL COMMENT '响应报文',        PRIMARY KEY ( `id` ) ) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '日志记录表';

这里完全基于业务需求自定义即可。

三、核心代码说明

1、注解参数

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface DefinedLog {    /**     * 操作类型     */    ApiTypeEnum apiType () ;    /**     * 方法描述     */    String methodDesc();    /**     * 业务性质     */    BizNatureEnum bizNature() ;    /**     * 数据流向,与业务性质关联     */    DataFlowEnum dataFlow() ;    /**     * 存储入参     */    boolean isSaveReqParam () default true ;    /**     * 存储出参     */    boolean isSaveResParam() default true ;    /**     * 是否需要异步处理     */    boolean isAsync () default false ;}

这里描述一下如下几个参数的意思:

bizNature:业务性质,即该日志是否有分析,或者营销推广操作,例如在在电商业务中,浏览系列商品后是否推送广告;

dataFlow:数据流向,即数据存储后是否向其他数据源推送,常见可能推送到MQ或者Redis或者分析引擎中,推荐类系统中对关键日志实时性要求极高,可以基于此做用户行为实时分析;

isAsync:是否异步处理,在一些并发高的接口中,避免日志记录成为性能问题的一个因素;

其他相关参数都是十分常见,例如接口类型增删改查,入参出参报文存储,方法模块的描述等等,这些都可以基于业务的需求自定义,然后做相关业务处理开发,思路开阔即可。

2、切面拦截

基于切面编程是方式,做相关日志处理,获取相应参数,构建日志模型即可。

@Component@Aspectpublic class LogAop {    private static final Logger LOGGER = LoggerFactory.getLogger(LogAop.class);    @Value("${spring.application.app-id}")    private String appId ;    @Resource    private DefineLogService defineLogService ;    /**     * 日志切入点     */    @Pointcut("@annotation(com.defined.log.annotation.DefinedLog)")    public void logPointCut() {    }    /**     * 环绕切入     */    @Around("logPointCut()")    public Object around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        Object result = null ;        StopWatch stopWatch = new StopWatch();        stopWatch.start();        try{            // 执行方法            result = proceedingJoinPoint.proceed();            stopWatch.stop();        } catch (Exception e){            stopWatch.stop();        } finally {            // 保存日志            LOGGER.info(" execute time: {} ms ", stopWatch.getTotalTimeMillis());            DefineLogModel defineLogModel = buildLogParam (proceedingJoinPoint);            defineLogModel.setResParam(JSONObject.toJSONString(result));            defineLogService.saveLog(defineLogModel) ;        }        return result ;    }    private DefineLogModel buildLogParam (ProceedingJoinPoint point){        DefineLogModel defineLogModel  = new DefineLogModel() ;        MethodSignature signature = (MethodSignature) point.getSignature();        Method reqMethod = signature.getMethod();        String className = point.getTarget().getClass().getName();        Object[] reqParam = point.getArgs();        LOGGER.info("请求方法:"+reqMethod.getName());        LOGGER.info("请求类名:"+className);        LOGGER.info("请求参数:"+ JSONObject.toJSONString(reqParam));        // 获取方法上注解        reqMethod.getAnnotation(DefinedLog.class).getClass();        DefinedLog definedLog = reqMethod.getAnnotation(DefinedLog.class);        // 构建参数        String methodName = reqMethod.getName() ;        Integer apiType = definedLog.apiType().getApiType();        String apiTypeDesc = definedLog.apiType().getApiTypeDesc();        String methodDesc = definedLog.methodDesc() ;        Integer bizNature = definedLog.bizNature().getBizNature() ;        Integer dataFlowType = definedLog.dataFlow().getDataFlowType();        boolean isSaveReqParam = definedLog.isSaveReqParam();        boolean isSaveResParam = definedLog.isSaveResParam();        boolean isAsync = definedLog.isAsync() ;        defineLogModel.setAppId(appId);        defineLogModel.setClassName(className);        defineLogModel.setMethodName(methodName);        defineLogModel.setMethodDesc(methodDesc);        defineLogModel.setApiType(apiType);        defineLogModel.setApiTypeDesc(apiTypeDesc);        defineLogModel.setBizNature(bizNature);        defineLogModel.setDataFlowType(dataFlowType);        defineLogModel.setSaveReqParam(isSaveReqParam);        defineLogModel.setSaveResParam(isSaveResParam);        defineLogModel.setAsync(isAsync);        defineLogModel.setReqParam(JSONObject.toJSONString(reqParam));        return defineLogModel ;    }}

3、使用方式

DefinedLog注解在接口方法上即可。

@RestControllerpublic class LogController {    @GetMapping("/logApi")    @DefinedLog(apiType=ApiTypeEnum.COMPOSITE,                methodDesc="测试日志",                bizNature= BizNatureEnum.DEFAULT,                dataFlow= DataFlowEnum.DEFAULT)    public String logApi (@RequestParam("param") String param){        return "success-re" ;    }}

4、记录参数

这样自定义日志流程就完成了。

上述就是小编为大家分享的SpringBoot2集成日志以及复杂业务下的自定义实现是怎样的了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0