springAop实现权限管理数据校验操作日志的场景分析

前言

作为一个写java的使用最多的轻量级框架莫过于spring,不管是老项目用到的springmvc,还是现在流行的springboot,都离不开spring的一些操作,我在面试的时候问的最多的spring的问题就是我们在平常的项目中使用spring最多的有哪几个点
在我看来无非就两个

  1. spring的bean管理,说的高大上一点就是spring的ioc,di
  2. spring的AOP

spring是一个很强大的轻量级框架,功能远不止这两点,但是我们用的最多的就是这两点。

spring bean 管理

想我们常用的 @Controller @Service @Component 等等都是将我们的bean交给spring管理,我们在获取bean的时候就直接通过 @Resource 就可以获取,当然@Resource 不是spring的,@Autowired 才是spring的,这样我们可以很方便的管理我们的各种bean,使用起来也很方便,不用到处new

springAOP

这个应该是spring面试最常问道的问题了,我面试的时候一般不直接问,我会说一个场景,如果面试者使用过aop立马就可以回答出来。
有这么一个场景,一个系统已经开发完成了,而且已经上线运行了一段时间,很稳定了,现在要加一个功能,就是想收集用户的操作日志,操作日志要比较细致,比如 某某人,在哪个时间点,操作了哪个模块,请求的参数是什么样子的,操作结果如何,等一些比较细致的操作。很多面试者第一时间想到的就是使用过滤器,试想一下,过滤器真的能做到记录这么细致的内容吗?有的可能会想到,我们定义一个公共的方法,所有需要记录日志的地方都去调用这个方法,等等。其实这些都不好,最好的当然是使用aop,使用aop侵入性最小,系统已经稳定运行了,不能去动之前的代码,我们做个aop就可以了,对原来的代码几乎0侵入,对系统影响最小。
那aop实现的方式有哪几种呢?aop实现的步骤又是怎么样的呢?aop还能做些什么呢?这些问题如果在实际项目中使用过,一定能回答出来,如果没有使用过,估计有点难回答,这些都是项目框架的东西,很多公司的项目这一块已经封装好了,很多人直接一直在用,但是没有去查看源码,就不知道具体的实现,实现起来其实也很简单。

接下来我们就以一个小例子来说明下如何使用aop
aop总结起来最常用的就两种方式
1、采用声明的方式来实现(基于XML) 胡子眉毛一把抓,哈哈
2、是采用注解的方式来实现(基于AspectJ)精准定位
我习惯使用注解的方式,更加灵活,使用起来也方便,接下来就以注解的方式来讲下如何使用aop来做权限校验,数据校验,操作日志记录

申明切面

我们使用springaop,首先要将定义的类交给spring管理,然后使用aspectj 定义切面,我们要额外引入
aspectj

 <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.9</version>
</dependency>
@Component
@Aspect
public class OperationInterceptor {

}

定义切点

我们采用注解的方式,那么我们首先要申明一个注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {

  /**
   * 权限编码
   */
  PermissionCodeEnum permissionCode();

  /**
   * 操作模块
   *
   * @return
   */
  OperModuleEnum opObject() default OperModuleEnum.NO_OBJECT;

  /**
   * 操作描述
   *
   * @return
   */
  String opDescription() default "";

}

然后在我们的切面中定义切点

@Component
@Aspect
public class OperationInterceptor {

	@Pointcut("@annotation(com.xx.xx.GlobalInterceptor)")
	private void opMethods() {
  }

}

定义通知类型

我们要输入还想要输出,那么我们就要将目标方法包围,所以使用around

@Component
@Aspect
public class OperationInterceptor {

	@Pointcut("@annotation(com.xx.xx.GlobalInterceptor)")
	private void opMethods() {
  }

  	@Around("opMethods()")
  public Object doMethod(ProceedingJoinPoint point) throws BusinessException {
   //TODO 业务代码
   return null;
	}
}

这样一个完整的切面就定义好了

使用切面

在我们的controller中直接使用,我们拿一个登录来讲

@RequestMapping("/login")
@GlobalInterceptor(permissionCode = PermissionCodeEnum.NO_PERMISSION, opObject = OperModuleEnum.OBJECT_LOGIN, opDescription = "登录账号:#{#param1}")
  public AjaxResponseVO login(HttpSession session, @VerifyParam(required = true) String account, @VerifyParam(required = true) String password,@VerifyParam(required = true) String checkCode){

}

我们要传入 切面注解需要的参数
permissionCode 权限编码,我这里定义的是一个枚举,类型自己根据实际情况定义
opObject 操作模块
opDescription 操作描述,这里简单的组织下描述文字,参数的地方使用占位符,到时候根据占位符index获取具体的参数

这样我们在切面中就可以拿到这些参数

@Component
@Aspect
public class OperationInterceptor {

	@Pointcut("@annotation(com.xx.xx.GlobalInterceptor)")
	private void opMethods() {
  }

  	@Around("opMethods()")
  public Object doMethod(ProceedingJoinPoint point) throws BusinessException {
   Object obj = null;
    try {
      /**
       * 获取登录信息
       */
      SessionUserDto sessionUserDto = getSessionUser();
      /**
       * 获取目标切点
       */
      Object target = point.getTarget();
      /**
       * 获取参数
       */
      Object[] arguments = point.getArgs();
      /**
       * 获取方法名
       */
      String method = point.getSignature().getName();
      /**
       * 获取参数类型
       */
      Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
      /**
       * 获取具体的方法
       */
      Method m = target.getClass().getMethod(method, parameterTypes);

      GlobalInterceptor interceptor = m.getAnnotation(GlobalInterceptor.class);
      if (null == interceptor) {
        return obj;
      }
      /**
       * 校验权限
       */
      if (sessionUserDto != null) {
        validatePermission(interceptor, sessionUserDto);
      }

      /**
       * 校验参数
       */
      validateParams(interceptor, m, arguments);

      /**
       * 获取描述信息,这里在执行方法之前组织好描述信息,当参数是传值引用时 执行具体方法后,会改变原始参数对象值
       */
      String description = getDescription(arguments, interceptor.opDescription());
      /**
       * 执行操作
       */
      obj = point.proceed();

      /**
       * 记录日志
       */
      wirteLog(obj, description, interceptor, sessionUserDto);

    } catch (BusinessException e) {
      logger.error("全局拦截器异常", e);
      throw e;
    } catch (Exception e) {
      logger.error("全局拦截器异常", e);
    } catch (Throwable e) {
      logger.error("全局拦截器异常", e);
    }
    return obj;
	}
}

这里只贴出了部分代码,完整的代码可以到这里获取

总结

回到最开始的问题,这样我们实现了一个对原有系统侵入极小,然后又实现了操作日志的解决方案。 我们使用spring的aop非常简单,我们使用aop结合反射,可以做很多事情。aop对代码的侵入非常小,不需要动原来的代码,只需要在原有的方法上加一个注解就可以完成对系统的改造,加权限,加日志 等等一系列操作。

到此这篇关于springAop实现权限管理数据校验操作日志的场景分析的文章就介绍到这了,更多相关springAop权限管理数据校验内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring AOP实现功能权限校验功能的示例代码

    实现功能权限校验的功能有多种方法,其一使用拦截器拦截请求,其二是使用AOP抛异常. 首先用拦截器实现未登录时跳转到登录界面的功能.注意这里没有使用AOP切入,而是用拦截器拦截,因为AOP一般切入的是service层方法,而拦截器是拦截控制器层的请求,它本身也是一个处理器,可以直接中断请求的传递并返回视图,而AOP则不可以. 1.使用拦截器实现未登录时跳转到登录界面的功能 1.1 拦截器SecurityInterceptor package com.jykj.demo.filter; import

  • spring aop实现用户权限管理的示例

    AOP 在实际项目中运用的场景主要有 权限管理(Authority Management).事务管理(Transaction Management).安全管理(Security).日志管理(Logging)和调试管理(Debugging) 等. 问题源于项目开发 最近项目中需要做一个权限管理模块,按照之前同事的做法是在controller层的每个接口调用之前上做逻辑判断,这样做也没有不妥,但是代码重复率太高,而且是体力劳动,so,便有了如题所说的使用spring aop做一个切点来实现通用功能的

  • Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化

    导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.5.Final</version> </dependency> <dependency> <

  • Springboot使用@Valid 和AOP做参数校验及日志输出问题

    项目背景 最近在项目上对接前端的的时候遇到了几个问题 1.经常要问前端要请求参数 2.要根据请求参数写大量if...else,代码散步在 Controller 中,影响代码质量 3.为了解决问题1,到处记日志,导致到处改代码 解决方案 为了解决这类问题,我使用了@Valid 做参数校验,并使用AOP记录前端请求日志 1.Bean实体类增加注解 对要校验的实体类增加注解,如果实体类中有List结构,就在List上加@Valid @Valid注解 注解 备注 @Null 只能为null @NotNu

  • 详解Spring AOP 实现“切面式”valid校验

    why: 为什么要用aop实现校验? answer: spring mvc 默认自带的校验机制 @Valid + BindingResult, 但这种默认实现都得在Controller方法的中去接收BindingResult,从而进行校验. eg: if (result.hasErrors()) { List<ObjectError> allErrors = result.getAllErrors(); List<String> errorlists = new ArrayList

  • springAop实现权限管理数据校验操作日志的场景分析

    前言 作为一个写java的使用最多的轻量级框架莫过于spring,不管是老项目用到的springmvc,还是现在流行的springboot,都离不开spring的一些操作,我在面试的时候问的最多的spring的问题就是我们在平常的项目中使用spring最多的有哪几个点 在我看来无非就两个 spring的bean管理,说的高大上一点就是spring的ioc,di spring的AOP spring是一个很强大的轻量级框架,功能远不止这两点,但是我们用的最多的就是这两点. spring bean 管

  • C#校验时间格式的场景分析

    目录 前言: 场景描述 前戏一 前戏二 正戏 尾戏 前言: 晚上打算睡觉的时候,群里反馈订单接收失败,开工排查问题,日志显示验签失败,发现一个蛮有意思的BUG,总算有了一个写作的素材 场景描述 本次的场景属于比较常见的收单API,对第三方的订单进行签名验证,然后持久化到数据库,签名规则大致是将参数key按照升序排序,然后根据key=value&进行字符串拼接,最后加上秘钥,按照指定的加密方式生成签名 前戏一 设计之初,肯定是怎么简单怎么来,粗略代码如下 [HttpPost] public asy

  • SpringBoot使用AOP记录接口操作日志的方法

    目录 一.操作日志简介 1.1.系统日志和操作日志的区别 1.2.操作日志记录实现方式 二.AOP面向切面编程 2.1.AOP简介 2.2.AOP作用 2.3.AOP相关术语 2.4.JointPoint和ProceedingJoinPoint 2.5.AOP相关注解 三.AOP切面实现接口日志记录 3.1.引入AOP依赖 3.2.创建日志信息封装类WebLog 3.3.创建切面类WebLogAspect 3.4.调用接口进行测试 四.AOP切面+自定义注解实现接口日志记录 4.1.自定义日志注

  • mysql数据校验过程中的字符集问题处理

    场景:主库DB:utf8字符集备库DB:gbk字符集 需求:校验主备数据是否一致,并且修复 校验过程:设置主库连接为utf8,设置备库连接为gbk,分别进行查询,将返回的的结果集按记录逐字段比较. 显示结果:原本相同的汉字字符,数据校验认为不一致. 原因分析:对于主库而已,由于建立连接的字符集为UTF8,则返回的汉字字符编码为UTF8格式:对于备库而言则是GBK格式,而程序中通过字符串比较函数strcasecmp进行比较,显然不同的字符集编码,相同的字符有不同的二进制,因此结果肯定不会相等. 进

  • 详解基于SpringBoot使用AOP技术实现操作日志管理

    操作日志对于程序员或管理员而言,可以快速定位到系统中相关的操作,而对于操作日志的管理的实现不能对正常业务实现进行影响,否则即不满足单一原则,也会导致后续代码维护困难,因此我们考虑使用AOP切面技术来实现对日志管理的实现. 文章大致内容: 1.基本概念 2.基本应用 3.日志管理实战 对这几部分理解了,会对AOP的应用应该很轻松. 一.基本概念 项目 描述 Aspect(切面) 跨越多个类的关注点的模块化,切面是通知和切点的结合.通知和切点共同定义了切面的全部内容--它是什么,在何时和何处完成其功

  • SpringAop实现操作日志记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人,操作的描述,ip等.好一点的增加了修改的数据和执行时间.那么!我这篇有什么不同呢!今天这种不仅可以记录上方所说的一切,还增加记录了操作前的数据,错误的信息,堆栈信息等.正文开始~~~~~ 思路介绍 记录操作日志的操作前数据是需要思考的重点.我们以修改场景来作为探讨.当我们要完全记录数据的流向的时候,

  • 使用SpringAOP获取用户操作日志入库

    目录 SpringAOP获取用户操作日志入库 记录操作日志的一般套路 SpringAOP获取用户操作日志入库 切service层中所有的方法,将有自定义注解的方法的操作日志入库,其中需要注意的几点: 注意aspectjweaver.jar包的版本,一般要1.6以上版本,否则会报错 注意是否使用了双重代理,spring.xml中不需要配置切面类的<bean>,否则会出现切两次的情况 注意返回的数据类型,如果是实体类需要获取实体类中每个属性的值,若该实体类中的某个属性也是实体类,需要再次循环获取该

  • Laravel框架实现的rbac权限管理操作示例

    本文实例讲述了Laravel框架实现的rbac权限管理操作.分享给大家供大家参考,具体如下: 介绍:根据不同的权限,在菜单栏显示不同的功能,只对菜单进行了限制,若对路由也进行限制,请自行完善 1.建表(用户表.角色表.权限表.用户角色表.角色权限表) CREATE TABLE IF NOT EXISTS mr_role ( id int(11) PRIMARY KEY AUTO_INCREMENT COMMENT '自增id', name varchar(30) NOT NULL COMMENT

  • MySQL用户和数据权限管理详解

    目录 1.管理用户 1.1.添加用户 1.2.删除用户 1.3.修改用户名 1.4.修改密码 2.授予权限和回收权限 2.1.授予权限 2.2.权限的转移和限制 2.3.回收权限 1.管理用户 1.1.添加用户 可以使用CREATE USER语句添加一个或多个用户,并设置相应的密码 语法格式: CREATE USER 用户名 [IDENTIFIED BY [PASSWORD]'密码'] CREATE USER用于创建新的MySQL账户.CREATE USER会在系统本身的mysql数据库的use

  • Java SpringBoot项目如何优雅的实现操作日志记录

    目录 前言 一.AOP是什么? 二.AOP做了什么? 三.实现步骤 1. 添加AOP依赖 2. 自定义一个日志注解 3. 切面声明 4. 标注在接口上 5. 实现的效果 总结 前言 在实际开发当中,对于某些关键业务,我们通常需要记录该操作的内容,一个操作调一次记录方法,每次还得去收集参数等等,会造成大量代码重复. 我们希望代码中只有业务相关的操作,在项目中使用注解来完成此项功能. 通常就是使用Spring中的AOP特性来实现的,那么在SpringBoot项目当中应该如何来实现呢? 一.AOP是什

随机推荐