springboot+自定义注解实现灵活的切面配置
利用aop我们可以实现业务代码与系统级服务例如日志记录、事务及安全相关业务的解耦,使我们的业务代码更加干净整洁。
最近在做数据权限方面的东西,考虑使用切面对用户访问进行拦截,进而确认用户是否对当前数据有访问权限,而我们的项目是springboot项目,所以花时间研究了下springboot下切面的实现。
1、首先加入相关maven依赖:
<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>
2、编写控制器
@RestController public class HelloController { @RequestMapping("/add1") public String addData1(String deviceId) { return "success"; } @RequestMapping("/add2") public String addData2(String deviceId) { return "success"; } @RequestMapping("/add3") public String addData3(String deviceId) { return "success"; } }
3、配置切面
@Aspect @Component public class TestAspect { @Pointcut("execution(public * com.example.demo.controller.HelloController.add*(..))") public void addAdvice(){} @Around("addAdvice()") public Object Interceptor(ProceedingJoinPoint pjp){ Object result = null; Object[] args = pjp.getArgs(); if(args != null && args.length >0) { String deviceId = (String) args[0]; if(!"03".equals(deviceId)) { return "no anthorization"; } } try { result =pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); } return result; } }
这样下来我们就实现了一个简单切面,在切面中实现自己的数据安全认证,此处只做一个简单判断,测试如下:
4、但是这样的切面不够灵活,所以我们添加一个自定义注解
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { }
5、修改切面类
@Aspect @Component public class TestAspect { @Pointcut("execution(public * com.example.demo.controller.HelloController.add*(..)) && @annotation(com.example.demo.controller.MyAnnotation)" ) public void addAdvice(){} @Around("addAdvice()") public Object Interceptor(ProceedingJoinPoint pjp){ Object result = null; Object[] args = pjp.getArgs(); if(args != null && args.length >0) { String deviceId = (String) args[0]; if(!"03".equals(deviceId)) { return "no anthorization"; } } try { result =pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); } return result; } }
6、修改控制器,给需要切面的方法上加上注解
@RestController public class HelloController { @MyAnnotation @RequestMapping("/add1") public String addData1(String deviceId) { return "success"; } @RequestMapping("/add2") public String addData2(String deviceId) { return "success"; } @RequestMapping("/add3") public String addData3(String deviceId) { return "success"; } }
通过自定义注解,我们可以灵活的添加切面,在需要使用切面的方法上添加注解,测试如下:
实际开发中我们可以将"execution(public * com.example.demo.controller.HelloController.add*(..)) && @annotation(com.example.demo.controller.MyAnnotation)"改为"execution(public * com.example.demo.controller.*.*(..)) && @annotation(com.example.demo.controller.MyAnnotation)",这样在controller包下,只有我们加上@MyAnnotation注解的方法切面方法才会起作用。