SpringBoot+自定义注解+AOP高级玩法打造通用开关

1.项目结构
在这里插入图片描述
2.引入依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies>

3.yml配置

server:port: 8080
spring:redis:database: 0host: x.x.x.xport: 6379password: 123456jedis:pool:max-active: 10max-wait: -1msmax-idle: 5min-idle: 1

4.自定义注解

package com.example.springbootaop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*** 通用开关注解* @author shixc* 2023/10/17*/
@Target({ElementType.METHOD})  // 作用在方法上
@Retention(RetentionPolicy.RUNTIME)  // 运行时起作用
public @interface ServiceSwitch {/*** 业务开关的key(不同key代表不同功效的开关)* {@link Constant.ConfigCode}*/String switchKey();// 开关,0:关(拒绝服务并给出提示),1:开(放行)String switchVal() default "0";// 提示信息,默认值可在使用注解时自行定义。String message() default "当前请求人数过多,请稍后重试。";
}

5.定义常量

package com.example.springbootaop.constant;
/*** 常量* @author shixc* 2023/10/17*/
public class Constant {// .... 其他业务相关的常量 ....// 配置相关的常量public static class ConfigCode {// 挂号支付开关(0:关,1:开)public static final String REG_PAY_SWITCH = "reg_pay_switch";// 其他业务相关的配置常量// ....}
}

6.AOP核心实现

package com.example.springbootaop.aop;
import com.example.springbootaop.annotation.ServiceSwitch;
import com.example.springbootaop.constant.Constant;
import com.example.springbootaop.util.Result;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/*** AOP核心实现* @author shixc* 2023/10/17*/
@Aspect
@Component
public class ServiceSwitchAOP {private final StringRedisTemplate redisTemplate;public ServiceSwitchAOP(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}/*** 定义切点,使用了@ServiceSwitch注解的类或方法都拦截*/@Pointcut("@annotation(com.example.springbootaop.annotation.ServiceSwitch)")public void pointcut() {}@Around("pointcut()")public Object around(ProceedingJoinPoint point) {// 获取被代理的方法的参数Object[] args = point.getArgs();// 获取被代理的对象Object target = point.getTarget();// 获取通知签名MethodSignature signature = (MethodSignature) point.getSignature();try {// 获取被代理的方法Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());// 获取方法上的注解ServiceSwitch annotation = method.getAnnotation(ServiceSwitch.class);// 核心业务逻辑if (annotation != null) {String switchKey = annotation.switchKey();String switchVal = annotation.switchVal();String message = annotation.message();/*获取配置项说明这里有两种方式:1、配置加在Redis,查询时从Redis获取;2、配置加在数据库,查询时从表获取。(MySQL单表查询其实很快,配置表其实也没多少数据)我在工作中的做法:直接放到数据库,但是获取配置项的方法用SpringCache缓存,然后在后台管理中操作配置项,变更时清理缓存即可。我这么做就是结合了上面两种各自的优点,因为项目中配置一般都是用后台管理来操作的,查表当然更舒适,同时加上缓存提高查询性能。*/// 下面这块查询配置项,大家可以自行接入并修改。// 数据库这么查询:String configVal = systemConfigService.getConfigByKey(switchKey);// 这里我直接从redis中取,使用中大家可以按照意愿自行修改。String configVal = redisTemplate.opsForValue().get(Constant.ConfigCode.REG_PAY_SWITCH);if (switchVal.equals(configVal)) {// 开关打开,则返回提示。return Result.fail(HttpStatus.FORBIDDEN.value()+"", message);}}// 放行return point.proceed(args);} catch (Throwable e) {throw new RuntimeException(e.getMessage(), e);}}
}

7.使用注解

package com.example.springbootaop.service;
import com.example.springbootaop.annotation.ServiceSwitch;
import com.example.springbootaop.constant.Constant;
import com.example.springbootaop.util.Result;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
/*** @author shixc* 2023/10/17*/
@Service
public class RegService {/*** 挂号下单*/@ServiceSwitch(switchKey = Constant.ConfigCode.REG_PAY_SWITCH)public Result createOrder() {// 具体下单业务逻辑省略....return Result.succeed("挂号下单成功");}
}

8.工具类

import java.io.Serializable;
/*** @author shixc* 2023/10/17*/
public final class Result<T> implements Serializable {private static final long serialVersionUID = -8780880627029425781L;private String code;private long timestamp = System.currentTimeMillis();private String message;private T data;public Result() {}private Result(String code, String message, T data) {this.code = code;this.message = message;this.data = data;}public String getCode() {return this.code;}public long getTimestamp() {return this.timestamp;}public String getMessage() {return this.message;}public T getData() {return this.data;}public static <T> Result<T> succeed() {return new Result("0", "", (Object) null);}public static <T> Result<T> succeed(T data) {return new Result("0", "", data);}public static <T> Result<T> panic() {return new Result("000000", "系统运行发生异常,请联系IT处理", (Object) null);}public static <T> Result<T> illegalArgument(String message) {return new Result("000001", message, (Object) null);}public static <T> Result<T> fail(String code, String message) {return new Result(code, message, (Object) null);}public static <T> Result<T> fail(String code, String message, T data) {return new Result(code, message, data);}public boolean success() {return this.code.equals("0");}public boolean failure() {return !this.success();}
}

9.测试接口

package com.example.springbootaop.controller;
import com.example.springbootaop.service.RegService;
import com.example.springbootaop.util.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*** 挂号Controller* @author shixc* 2023/10/17*/
@RestController
@RequestMapping("reg")
public class RegController {private final RegService regService;public RegController(RegService regService) {this.regService = regService;}@GetMapping("/create")public Result createOrder() {return regService.createOrder();}
}

10.Redis中把开关加上
在这里插入图片描述
11.启动服务
在这里插入图片描述
将redis中开关置为1
在这里插入图片描述
欢迎大家积极留言交流学习心得,点赞的人最美丽!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 查询 唯一约束 对应的字段,列名称合并

MySQL 查询 唯一约束 对应的字段&#xff0c;列名称合并 SELECT F.DbName,F.TableName,F.ConstraintName,GROUP_CONCAT(ColumnName) ColumnName FROM ( SELECT t1.TABLE_SCHEMA DbName, t1.TABLE_NAME TableName,t1.CONSTRAINT_NAME ConstraintName,t2.COLUMN_NAME ColumnNam…

UI自动化测试的痛点

当我们找工作的时候查看招聘信息发现都需要有自动化测试经验&#xff0c;由此看来测试人员不会一点自动化测试技术都不好意思说自己是做软件测试的。大部分测试人员也都是从使用自动化测试工具、录制回放、测试脚本、开发小工具入门自动化测试的&#xff0c;然后在慢慢的接触 U…

Rust-类型转换进阶

这篇文章收录于Rust 实战专栏。这个专栏中的相关代码来自于我开发的笔记系统。它启动于是2023年的9月14日。相关技术栈目前包括&#xff1a;Rust&#xff0c;Javascript。关注我&#xff0c;我会通过这个项目的开发给大家带来相关实战技术的分享。 关于Rust的类型转换&#xff…

美国绿氢项目开发商NovoHydrogen完成2000万美元融资

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于美国科罗拉多州戈尔登的绿氢项目开发商NovoHydrogen今日宣布已完成2000万美元融资。 本轮融资由现代能源公司领投。 该公司打算利用这笔资金进一步扩大其团队&#xff0c;并将其绿氢项目的…

纳米软件科普:开关电源测试方案之如何测试短路保护

开关电源短路保护测试是通过模拟短路状态来检测电源在短路时是否有保护能力&#xff0c;是开关电源一个重要测试项目。通过测试&#xff0c;不仅可以测试开关电源的保护能力&#xff0c;还可以保护电路系统以及对设备的保护&#xff0c;防止受到损坏。那么短路保护要如何测试呢…

Linux创建与删除用户

Linux创建与删除用户 新增用户&#xff1a; adduser 用户名【添加用户】 passwd 用户名【设置用户密码】删除用户&#xff1a; userdel -r 用户名【删除用户】

205、使用消息队列实现 RPC(远程过程调用)模型的 服务器端 和 客户端

目录 ★ RPC模型&#xff08;远程过程调用通信模型&#xff09;▲ 完整过程&#xff1a;代码演示总体流程解释&#xff1a;ConstantUtil 常量工具类ConnectionUtil RabbitMQ连接工具类Server 服务端Client 客户端测试结果服务端客户端 完整代码ConstantUtil 常量工具类Connecti…

文献阅读快速法-ChatPDF

如题&#xff0c;直接提供给大家一款能够快速阅读文档的好工具——iTextMaster。 iTextMaster是一款免费的pdf阅读浏览器&#xff0c;上传pdf文档后等待几秒钟&#xff0c;AI就会自动反馈给用户关于文档的摘要总结。十分的方便且实用。 ChatPDF为您提供简洁的文档摘要。对于那…

plink分析100个性状的批量gwas分析

大家好&#xff0c;我是邓飞。 GWAS分析时&#xff0c;3~5个性状是正常操作&#xff0c;要分析100个性状呢&#xff0c;手动修改参数&#xff0c;工作量是够了&#xff0c;但是程序员的修养体现在哪里了&#xff1f;&#xff1f;&#xff1f; 如果还是按照每个性状一个文件夹…

2023年中国液晶电视出口现状、品牌格局及行业发展趋势[图]

液晶电视指采用液晶显示面板的电视机&#xff0c;是目前最主流的彩色电视机&#xff0c;主要结构包括液晶面板模组、电子线路模块、结构件等。 目前常用的液晶电视有STN-LCD&#xff08;SuperTN-LCD&#xff0c;超扭曲向列LCD&#xff09;、DSTN-LCD&#xff08;DoublelayerSTN…

百度发布全新 AI 互动式搜索:百度简单搜索

本心、输入输出、结果 文章目录 百度发布全新 AI 互动式搜索&#xff1a;百度简单搜索前言主要能力 相关资料能力介绍 百度搜索升级发文告用户如何获取百度简单搜索百度简单搜索的定位百度简单搜索在 APP 上面的体验讨论和点评我们关注的几个问题 弘扬爱国精神 百度发布全新 AI…

Netty系列教程之NIO基础知识

近30集的孙哥视频课程&#xff0c;看完一集整理一集来的&#xff0c;内容有点多&#xff0c;请大家放心食用~ 1. 网络通讯的演变 1.1 多线程版网络通讯 在传统的开发模式中&#xff0c;客户端发起一个 HTTP 请求的过程就是建立一个 socket 通信的过程&#xff0c;服务端在建立…

机器学习,神经网络中,自注意力跟卷积神经网络之间有什么样的差异或者关联?

如图 6.38a 所示&#xff0c;如果用自注意力来处理一张图像&#xff0c;假设红色框内的“1”是要考虑的像素&#xff0c;它会产生查询&#xff0c;其他像素产生 图 6.37 使用自注意力处理图像 键。在做内积的时候&#xff0c;考虑的不是一个小的范围&#xff0c;而是整张图像的…

代码的艺术-Writing Code Like a Pianist | 京东云技术团队

前言 如何评定一个系统的质量&#xff1f;什么样的系统或者软件可以称之为高质量&#xff1f;可以从三个角度来看&#xff0c;一是架构设计&#xff0c;例如技术选型、分布式系统中的数据一致性考虑等&#xff0c;二是项目管理&#xff0c;无论是敏捷开发还是瀑布式开发&#…

【SpringCloud微服务项目实战-mall4cloud项目(4)】——mall4cloud-rbac

mall4cloud-rbac角色权限访问控制模块 系统架构与模块介绍系统架构rbac模型介绍 相关代码权限校验接口代码 补充 代码地址 github地址 fork自github原始项目 gitee地址 fork自gitee原始项目 系统架构与模块介绍 系统架构 从图中可以看到&#xff0c;微服务集群中&#xff0c;…

基于Qt QSlider滑动条小项目

QSlider 是滑动条控件,滑动条可以在一个范围内拖动,并将其位置转换为整数 1. 属性和方法 QSlider 继承自 QAbstractSlider,它的绝大多数属性都是从 QAbstractSlider 继承而来的。 2.QSlider信号 - `valueChanged(int value)`: 当滑块的值改变时发出信号,传递当前滑块的值…

基于SVM+Webdriver的智能NBA常规赛与季后赛结果预测系统——机器学习算法应用(含python、ipynb工程源码)+所有数据集(三)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 特征提取3. 模型训练及评估1&#xff09;常规赛预测模型2&#xff09;季后赛模型创建 4. 模型训练准确率 相关其它博客工程源代码下载其它资料下载 前言 本项目使用了从NBA官方网站获得的数据&…

JOSEF约瑟 漏电继电器 JHOK-ZBG1 φ25mm AC220V 0.1A/0.1S 分体式

系列型号 JHOK-ZBG1 φ25mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG2 φ25mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG1 φ45mm漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG2 φ45mm 漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBG1 φ100mm漏电&a…

猜数字游戏(Rust实现)

文章目录 游戏说明游戏效果展示游戏代码游戏代码详解生成神秘数字读取用户输入解析用户输入进行猜测比较 游戏说明 游戏说明 游戏运行逻辑如下&#xff1a; 随机生成一个1-100的数字作为神秘数字&#xff0c;并提示玩家进行猜测。如果玩家猜测的数字小于神秘数字&#xff0c;则…

初始web项目tomcat部署报错404

问题 简单地创建了一个web项目&#xff0c;结果一运行就404咧&#xff0c;真滴烦。。。接下来的项目也没法继续了 问题原因&#xff1a;缺少文件 其实造成这样问题的原因有不少&#xff0c;但在这里我是踩了一个坑。在出问题之前&#xff0c;我运行的其他项目都是可以跑的&…