SpringBoot @ConditionalOnProperty注解 + AOP切面控制日志打印

news2024/9/22 15:32:47

参考资料

  1. @ConditionalOnProperty的作用和用法

目录

  • 一. 前期准备
    • 1.1 错误信息实体类
    • 1.2 自定义校验异常
    • 1.3 业务页面
      • 1.3.1 前台HTML
      • 1.3.2 Form实体类
      • 1.3.3 Controller层
      • 1.3.4 Service层
  • 二. @ConditionalOnProperty注解和AOP切面的使用
    • 2.1 配置文件
    • 2.2 AOP切面 + @ConditionalOnProperty
    • 2.3 效果


一. 前期准备

1.1 错误信息实体类

import lombok.Data;

@Data
public class ErrorItemEntity {

    // 错误信息ID
    private String errorMessageId;

    // 错误信息
    private String errorMessage;

    public static ErrorItemEntity of(String errorMessage, String errorItemId) {
        ErrorItemEntity entity = new ErrorItemEntity();
        entity.errorMessage = errorMessage;
        entity.errorMessageId = errorItemId;
        return entity;
    }
}

1.2 自定义校验异常

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.List;

@Data
@EqualsAndHashCode(callSuper = true)
public class ValidationException extends RuntimeException {

    // 错误信息
    private List<ErrorItemEntity> errors;

    /**
     * 生成ValidationException异常对象
     *
     * @param errors 业务异常信息
     */
    public ValidationException(List<ErrorItemEntity> errors) {
        super();
        this.errors = errors;
    }
}

1.3 业务页面

1.3.1 前台HTML

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
</head>
<body>
    <button id="btn">点击发送请求</button>
</body>
<script src="/js/public/jquery-3.6.0.min.js"></script>
<script th:inline="javascript">

    function doAjax(url, data, callback) {

        $.ajax({
            url: url,
            type: 'POST',
            data: JSON.stringify(data),
            contentType : 'application/json;charset=utf-8',
            dataType: 'json',
            success: function (data, status, xhr) {
                if (!!callback) {
                    callback(data);
                }
            },
            error: function (xhr, textStatus, errorMessage) {

                if (xhr.status !== 400) {
                    location.href = "系统错误页面URL";
                }

                // 获取错误信息,根据错误ID将画面上的错误信息标记红色
                const data = xhr.responseJSON;
                console.log(data.errors);
            }
        });
    }

    $("#btn").click(() => {

        const url = "http://localhost:8080/test3/check";
        // 错误的数据,from的值不应该比to还要大
        const info = {
            from: 100,
            to: 10
        };

        doAjax(url, info, function (data) {

            if (!data.result) {
                return;
            }

            console.log(data);
        });
    });
</script>
</html>

1.3.2 Form实体类

import lombok.Data;

@Data
public class Test3Form {

    private Integer from;

    private Integer to;
}

1.3.3 Controller层

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/test3")
public class Test3Controller {

    @Autowired
    private Test3Service service;

    @GetMapping("/init")
    public ModelAndView init() {

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("test3");
        return  modelAndView;
    }

    @PostMapping("/check")
    @ResponseBody
    public void check(@RequestBody Test3Form form) throws ValidationException {

        service.check(form);
    }
}

1.3.4 Service层

import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;

@Service
public class Test3Service {
	
    public void check(Test3Form form) throws ValidationException {
		
		// 当from值 > to值的时候,抛出自定义的校验异常
        if (form.getFrom() > form.getTo()) {
            List<ErrorItemEntity> errors = Collections.singletonList(ErrorItemEntity.of("大小不对", "id名称"));
            throw new ValidationException(errors);
        }
    }
}

二. @ConditionalOnProperty注解和AOP切面的使用

  • @ConditionalOnProperty注解一般用于控制配置类是否生效,prefix为配置文件中的前缀,name 为配置的名称,havingValue的值若与配置文件中相同,则配置文件生效;若值不同则配置类不生效,相当于该配置类并没有被Spring管理。

2.1 配置文件

custom:
  log:
    action: true

2.2 AOP切面 + @ConditionalOnProperty

  • 当被切方法执行过程中抛出异常时,会进入@AfterThrowing注解的方法中执行,在该方法中可以做一些异常的处理逻辑。要注意的是 throwing 属性的值必须要和参数一致,否则会报错。
  • 因为@ConditionalOnProperty注解的havingValue 值和配置文件中的值相同,所以下面所示方法中的定时任务会每隔5秒钟执行一次,并且切面也会执行。如果havingValue的值和配置文件中的值不同的话,则下面类中的定时任务方法和所有的切面方法都不会执行。
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

@Aspect
@Component
@EnableScheduling
@ConditionalOnProperty(prefix = "custom.log", name = "action", havingValue = "true")
public class LogAspect {

    // 定时任务, 每五秒执行一次。
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMail(){
        System.out.println("模拟邮件已经发送出去");
    }

    @Before("execution(* com.example.jmw.controller..*(..))")
    public void beforeInit(JoinPoint join) {

        Signature signature = join.getSignature();
        Class declaringType = signature.getDeclaringType();
        String simpleName = declaringType.getSimpleName();
        String name = declaringType.getName();
        Logger log = LoggerFactory.getLogger(name);

        log.info("====================================================================");
        log.info("[" + simpleName + "." + name + "] START");
        log.info("====================================================================");
    }

    @After("execution(* com.example.jmw.controller..*(..))")
    public void afterInit(JoinPoint join) {

        Signature signature = join.getSignature();
        Logger log = LoggerFactory.getLogger(signature.getDeclaringType().getName());

        log.info("====================================================================");
        log.info("[" + signature.getDeclaringType().getSimpleName() + "." + signature.getName() + "] START");
        log.info("====================================================================");
    }

    @AfterThrowing(value = "execution(* com.example.jmw.controller..*(..))", throwing = "ex")
    public void afterExceptionThrowing(JoinPoint jp, Exception ex) {

        // 如果抛出的是我们自定义的校验异常的话
        if (ex instanceof ValidationException) {

            // 获取出所有的异常信息
            ValidationException exception = (ValidationException) ex;
            List<ErrorItemEntity> errors = exception.getErrors();
            String errorMsg = errors.stream().map(ErrorItemEntity::getErrorMessage).collect(Collectors.joining("-"));

            Signature signature = jp.getSignature();
            Logger log = LoggerFactory.getLogger(signature.getDeclaringType().getName());
            log.info("====================================================================");
            log.debug("[" + signature.getDeclaringType().getSimpleName() + "." + signature.getName() + "] Validation: {}", errorMsg);
            log.info("====================================================================");
        }
    }
}

2.3 效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/594046.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深剖 Linux 信号量

目录 传统艺能&#x1f60e;POSIX信号量&#x1f60d;概念&#x1f602; 信号量函数&#x1f60d;初始化信号量&#x1f44c;销毁信号量&#x1f44c;等待&#xff08;申请&#xff09;信号量&#x1f44c;发布&#xff08;释放&#xff09;信号量&#x1f923; 二元信号量模拟…

Linux下C、C++、和Java程序设计

1.创建用户和之前一样。 RHEL7.2用户名和密码的创建以及DHCP服务的安装_封奚泽优的博客-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/130763469?spm1001.2014.3001.55012.用yum安装&#xff08;分别是c,c,java,javac)(之前我以为是分开安装的&#xff0c…

Sui Builder House首尔站倒计时!

Sui主网上线后的第一场Builder House活动即将在韩国首尔举行&#xff0c;同期将举办首场线下面对面的黑客松。活动历时两天&#xff0c;将为与会者提供独特的学习、交流和娱乐的机会。活动详情请查看&#xff1a;Sui Builder House首尔站&#xff5c;主网上线后首次亮相。 Sui…

2. 虚拟环境

一、为什么要搭建虚拟环境&#xff1f; 在实际开发过程中&#xff0c;多个程序可能需要调试各种版本的不同环境&#xff0c;比如不同的Python解释器&#xff0c;不同的flask版本 二、如何搭建虚拟环境&#xff1f; 什么是虚拟环境&#xff1f; 它就是一个特殊的文件夹&…

一个matlab colorbar的简易代码cmocean

matlab自带的色阶不全&#xff0c;无法满足绘图的需求&#xff0c;而cmocean函数提供了一些常用的色阶。 函数命令&#xff1a;cmocean(ColormapName,varargin)&#xff0c;其中的ColormapName有如下的可选参数&#xff1a; 各个参数的绘图效果如下&#xff1a; 另外的一个参…

基于CAPL版本的CRC32算法

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

UI设计用什么软件做?

1、即时设计 即时设计是一款国内的在线协同设计工具&#xff0c;提供原型设计、UI/UX 设计和设计交付等核心功能。它无需第三方插件&#xff0c;拥有丰富的组件样式、中英文字体库和本地化资源&#xff0c;受到专业设计师的好评。与其他国外的 UI 工具相比&#xff0c;即时设计…

加拿大访问学者博士后签证材料清单指南

加拿大作为一个受欢迎的留学和研究目的地&#xff0c;吸引着许多国际学者和博士后前往交流和深造。作为准备申请加拿大访问学者或博士后签证的申请人&#xff0c;准备充分的材料是至关重要的。下面是知识人网小编整理的个关于加拿大访问学者博士后签证材料清单的指南&#xff0…

mysql-xtrabackup的使用

一、安装 1.下载压缩包 根据当前地址选择对应的版本和系统 wget https://downloads.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.28/binary/tarball/percona-xtrabackup-2.4.28-Linux-x86_64.glibc2.17.tar.gz2.解压缩 tar xvf percona-xtrabac…

【分布鲁棒和多目标非负矩阵分解】基于DR-NMF的对NMF问题噪声模型的识别鲁棒性研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

A*寻路之旅:用SDL图形化演示

前言 欢迎来到小K的数据结构专栏的第十小节&#xff0c;本节将为大家带来A*寻路算法的图形化详解&#xff0c;学了之后寻路不再迷路&#xff08;✨当然也为大家准备了完整的源码&#xff0c;好像在文章顶部欸~ &#xff09;~希望你看完之后&#xff0c;能对你有所帮助&#xff…

ctfshow 每周大挑战 RCE极限挑战4、5

看过官方wp之后复现的&#xff0c;用的payload是自己后来写的&#xff0c;可能不如官方的看着清晰 有点强迫症似的在抠细节&#xff08;x 目录 挑战4最初的思路通过HackBar拿flag的写法写法一写法二 挑战5burp中的payload 大佬们也太极限啦 挑战4 最初的思路 第4题的长度限制…

UM2082F08 125k三通道低频无线唤醒ASK接收功能的SOC芯片 汽车PKE钥匙

1产品描述 UM2082F08是基于单周期8051内核的超低功耗8位、具有三通道低频无线唤醒ASK接收功能的SOC芯片。芯片可检测30KHz~300KHz范围的LF (低频)载波频率数据并触发唤醒信号&#xff0c;同时可以调节接收灵敏度&#xff0c;确保在各种应用环境下实现可靠唤醒&#xff0c;其拥…

母婴健康老人护理医护上门陪诊产后恢复预约上门小程序源码

母婴健康老人护理医护上门陪诊产后恢复预约上门小程序 在线预约 上门打针 产后恢复 会员卡 余额充值 优惠券 分销商 unippthinkphp <template> <view class"container" :style"{background:pagebase.base.bc}"> <Pengp…

Django+Vue实现文件上传下载功能

目录 前言 上传功能 后端代码 前端代码 下载功能 后端代码 前端代码 前言 首先我要实现的页面效果是这样的 当点击上传文件按钮&#xff0c;弹出上传文件的弹出框&#xff0c;可以上传多个文件&#xff0c;点击确定后才正式开始上传 点击右侧下载按钮&#xff0c;可以直…

springboot中将logback切换为log4j2

前言 springboot默认使用logback作为日志记录框架&#xff0c;常见的日志记录框架有log4j、logback、log4j2。这篇文章我们来学习怎样将logbak替换为log4j2。 一、为什么使用log4j2&#xff1f; 我们在项目中经常使用一个叫SLF4J的依赖&#xff0c;它是做什么的呢&#xff1f; …

Java 实现在顺序表末尾插入一个元素

一、思路 1.因为我们是用数组实现的顺序表&#xff0c;因此首先要保证数组有足够的空间来进行插入元素. 2.如果数组满了就需要将数组扩容&#xff0c;没满就开始插入. 3.当前数组中的元素个数就是每一次要插入的末尾位置的下标. 4.定义一个 usedSize 来表示当前的元素个数. 5.插…

Pandas+ChatGPT强强结合诞生PandasAI,数据分析师行业要变天了?

大家好&#xff0c;我是千与千寻&#xff0c;可以叫我千寻&#xff0c;我自己主要的编程语言是Python和Java。 说到Python编程语言&#xff0c;使用Python语言主要使用的是数据科学领域的从业者。 Python编程语言之所以在数据科学领域十分火热&#xff0c;源于Python语言的三…

9.Ansible Conditions介绍

Ansible条件语句 1)上面的例子在不同的机器上安装nginx&#xff0c;不同的操作系统风格使用不同的软件包管理器&#xff61;debian使用APT, Red Hat使用Yum, 但这是两个独立的Playbook,您必须为各自的服务器使用正确的剧本&#xff61; 可以使用条件语句&#xff0c;将这两个P…

Mongodb在Linux下载安装及部署

前言 一、下载安装包 Mongodb官网&#xff1a;Download MongoDB Community Server | MongoDB 二、安装及配置 博主下载的安装包是&#xff1a;mongodb-linux-x86_64-rhel70-6.0.6.tgz 新建目录 # 进入 usr 文件夹 cd /usr# 新建 mongodb 文件夹 mkdir mongodb# 进入 mongodb …