一、引入依赖
web和aop是必须的,fastjson只是为了输出方便;
<!-- web依赖--> <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> <!-- json工具包--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency>
二、定义切面
定义步骤:
(1)、切面类加@Aspect 、@Service注解,告诉springboot这是一个切面类,帮我管起来;
(2)、定义切点@Pointcut;
(3)、定义切入点切入的时机及完成的功能(@Around、@Before、@After、@AfterReturning、@AfterThrowing);
1.基于注解拦截
注解:@PermissionAnnotation
@Service @Aspect public class PermissionFirstAdvice { @Pointcut("@annotation(com.example.demo.anot.PermissionAnnotation)") private void permissionCheck() { } @Around("permissionCheck()") public Object permissionCheckFirst(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("第一个切面"); return joinPoint.proceed(); } }
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PermissionAnnotation { }
其中joinPoint.proceed()执行目标方法,如果没有调用,则不执行目标方法;
proceed传参数的方法可以动态的改变传入目标方法的参数,
2.基于表达式拦截
表达式:* com.example.demo.controller..*.*(..)
第一个 * 号的位置:表示返回值类型,* 表示所有类型。
包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,在本例中指 com.example.demo.controller.包、子包下所有类的方法。
第二个 * 号的位置:表示类名,* 表示所有类。
*(..):这个星号表示方法名,* 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
@Component @Aspect public class ControllerAdvice { @Pointcut("execution(* com.example.demo.controller..*.*(..))") public void chtrollerPict(){ } @Around("chtrollerPict()") public Object permissionCheckFirst(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("controllerAdvice"); return joinPoint.proceed(); } }
3、切点多个表达式或注解
多个表达式之间使用 ||,or表示 或,使用 &&,and表示 与,!表示 非
@Pointcut("execution(* com.example.demo.controller..*.*(..))||@annotation(com.example.demo.anot.PermissionAnnotation)")
三、测试
同时满足上述两个切点条件(注解和controller包),如需改变连个切入点的执行顺讯,再切面类上加@Order(0)注解,数字越小,执行越靠前;
package com.example.demo.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.example.demo.anot.PermissionAnnotation; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping(value = "/permission") public class TestController { @RequestMapping(value = "/check", method = RequestMethod.POST) @PermissionAnnotation public JSONObject getGroupList(@RequestBody JSONObject request) { System.out.println("方法执行"); return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200}"); } }