Java注解-一文就懂,mysql数据库sql语句面试题 迅雷尊享版 • 2022-12-16 • 随笔 • 阅读 11 Java注解-一文就懂,mysql数据库sql语句面试题 int period() default 5000 } 定义注解处理器 - 切面 @Aspect @Component public class RetryAspect { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @AfterThrowing(pointcut=(“execution(* com.liziba.web.service.impl.RetryHttpRequestClient.*(…)) && @annotation(com.liziba.web.annotation.Retry)”)) public void tryAgain(JoinPoint point) { logger.info("------------开始重试------------"); try { // 获取方法上定义的Retry注解 MethodSignature methodSignature = (MethodSignature) point.getSignature(); Retry retry = methodSignature.getMethod().getAnnotation(Retry.class); // ThreadLocal做线程隔离 times记录已经重试的次数 Object object = point.getTarget(); Field field = object.getClass().getDeclaredField(“threadLocal”); field.setAccessible(true); ThreadLocal> threadLocal = (ThreadLocal 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》 【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享 tring, Object>>) field.get(object); Map threadLocalMap = threadLocal.get(); AtomicInteger times = (AtomicInteger)threadLocalMap.get(“times”); // 重试 -1一直循环 if (retry.value() == -1 || (times.intValue() < retry.value())) { logger.info(“开始重试第”+ index + “次”); int index = times.incrementAndGet(); MethodInvocationProceedingJoinPoint methodPoint = ((MethodInvocationProceedingJoinPoint) point); methodPoint.proceed(); } else { // 数据库服务异常捕获,防止异常中异常导致StackOverFlowError try { // ToDo // 此处可以保存到数据库,做周期性失败重试,重试次数达到阈值后通过消息平台通知到运维及时处理异常任务 // 移除threadLocal,防止线程生命周期过长导致内存泄露 threadLocal.remove(); } catch (Exception e) { e.printStackTrace(); } } } catch (Throwable throwable) { logger.error(throwable.getMessage(),throwable); // 失败后继续重试 tryAgain(point); } } } 4.2 日志记录注解 定义注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String value() default “”; boolean enable() default true; LogActionType type() default LogActionType.SELECT; } 日志类型 public enum LogActionType { ADD(“新增”), SELECT(“查询”), UPDATE(“更新”), DELETE(“删除”); private String value; LogActionType(String value) { this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } 定义注解处理器 - 切面 @Component @Aspect @Slf4j public class LogAspect { // 保存日志信息服务 private final LogService logService; // 线程隔离,用于计算每个方法的执行时间 ThreadLocal currentTime = new ThreadLocal<>(); public LogAspect(LogService logService) { this.logService = logService; } @Pointcut("@annotation(com.liziba.annotation.Log)") public void logPointcut() { } @Around(“logPointcut()”) public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { Object result; // 计算方法 *** 作时间 currentTime.set(System.currentTimeMillis()); result = joinPoint.proceed(); Log log = new Log(“INFO”,System.currentTimeMillis() - currentTime.get()); currentTime.remove(); HttpServletRequest request = RequestHolder.getHttpServletRequest(); // 记录用户名、浏览器信息、ip地址、切入点、日志信息 logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log); return result; } @AfterThrowing(pointcut = “logPointcut()”, throwing = “e”) public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { Log log = new Log(“ERROR”,System.currentTimeMillis() - currentTime.get()); currentTime.remove(); // 获取日志堆栈信息,并设值 log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes()); HttpServletRequest request = RequestHolder.getHttpServletRequest(); // 记录用户名、浏览器信息、ip地址、切入点、日志信息 logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log); } public String getUsername() { try { return SecurityUtils.getCurrentUsername(); }catch (Exception e){ return “”; } } } 4.3 限流注解 - redis+lua限流 注解定义 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Limit { // 资源名称,用于描述接口功能 String name() default “”; // 资源 key String key() default “”; // key prefix String prefix() default “”; // 时间的,单位秒 int period(); // 限制访问次数 int count(); // 限制类型 LimitType limitType() default LimitType.CUSTOMER; } 注解类型 public enum LimitType { // 默认 CUSTOMER, // IP限流 IP } 定义注解处理器 - 切面 @Aspect @Component public class LimitAspect { // redis用于执行lua脚本 private final RedisTemplate redisTemplate; private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class); public LimitAspect(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Pointcut("@annotation(com.liziba.annotation.Limit)") public void pointcut() { } @Around(“pointcut()”) public Object around(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request = RequestHolder.getHttpServletRequest(); // 获取方法的Limit注解 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method signatureMethod = signature.getMethod(); Limit limit = signatureMethod.getAnnotation(Limit.class); LimitType limitType = limit.limitType(); String key = limit.key(); if (StringUtils.isEmpty(key)) { if (limitType == LimitType.IP) { key = StringUtils.getIp(request); } else { key = signatureMethod.getName(); } } // 通过方法或者ip 结合资源请求路径定义限流key ImmutableList keys = ImmutableList.of(StringUtils.join(limit.prefix(), “", key, "”, request.getRequestURI().replaceAll("/","_"))); // Lua限流脚本 String luascript = buildLuascript(); Redisscript redisscript = new DefaultRedisscript<>(luascript, Number.class); 欢迎分享,转载请注明来源:内存溢出原文地址: http://outofmemory.cn/zaji/5672648.html 注解 定义 切面 日志 线程 赞 (0) 打赏 微信扫一扫 支付宝扫一扫 迅雷尊享版 一级用户组 0 0 生成海报 【无标题】 上一篇 2022-12-16 【无标题】 下一篇 2022-12-16 发表评论 请登录后评论... 登录后才能评论 提交 评论列表(0条)
评论列表(0条)