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注解的方法切面方法才会起作用。

原文地址:https://www.cnblogs.com/hhhshct/p/8428045.html