运用切面和拦截器进行注解类的解析判断示例

553 阅读2分钟

1.注解简介

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。

2.相关Demo示例

①使用切面方式使注解生效

项目结构:

├─.idea
│  ├─codeStyles
│  ├─dictionaries
│  ├─inspectionProfiles
│  └─libraries
├─.mvn
│  └─wrapper
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─demo
│  │  │          └─annotationdemo
│  │  │              ├─annotation
│  │  │              ├─aop
│  │  │              ├─constant
│  │  │              └─controller
│  │  └─resources
│  └─test
│      └─java
│          └─com
│              └─demo
│                  └─annotationdemo
└─target
    ├─classes
    │  └─com
    │      └─demo
    │          └─annotationdemo
    │              ├─annotation
    │              ├─aop
    │              ├─constant
    │              └─controller
    ├─generated-sources
    │  └─annotations
    ├─generated-test-sources
    │  └─test-annotations
    └─test-classes
        └─com
            └─demo
                └─annotationdemo

项目代码示例

ChekLongin

/**
 * 校验登录必备条件
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ChekLongin {
    String condition() default "";
}

AnnotationAop

@Aspect
@Component
public class AnnotationAop {


    @Pointcut("@annotation(com.demo.annotationdemo.annotation.ChekLongin)")
    public void controllerPointcut() {
    }

    @Before("controllerPointcut()&& @annotation(chekLongin)")
    public void doBefore(JoinPoint joinPoint, ChekLongin chekLongin) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String[] parameterNames = signature.getParameterNames();
        Object[] args = joinPoint.getArgs();
        if (parameterNames == null || args == null) {
            System.out.println("参数不能为空");
        }
        String param = chekLongin.condition();
        // 这里只做示例 其余的参数校验和这个一样
        if (param != null && ConditionConstant.NAME.equals(param)) {
            for (int i = 0; i < parameterNames.length; i++) {
                if (param.equals(parameterNames[i])) {
                    if (args[i] != null) {
                        System.out.println("传入的参数Key->" + ConditionConstant.NAME + "  value->" + args[i].toString());
                    }
                    break;
                }
            }
        } else {
            System.out.println("必传参数不能为空");
        }
    }
}

ConditionConstant

public interface ConditionConstant {
    String NAME = "name";
    String PHONE = "phone";
    String ADDRESS = "address";
}

TestController

@RestController
public class TestController {

     @RequestMapping("/aopAnnotation")
    @ChekLongin(condition = ConditionConstant.NAME)
    public String aopAnnotation(String name) {
        return "name="+name;
    }


    @RequestMapping("/test")
    public String test() {
        return "test";
    }

}

最后记得在启动类加上@EnableAspectJAutoProxy,启动后请求http://127.0.0.1:8080/aopAnnotation?name=test,返回结果如下:

name=test
②使用拦截器方式

​ 这里我们先注释掉AnnotationAop这个切面类,然后我们改造项目添加拦截器的类和配置:

AuthenticationHandler

public class AuthenticationHandler extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        HandlerMethod method = (HandlerMethod) handler;
        ChekLongin chekLongin = method.getMethodAnnotation(ChekLongin.class);
        if(Objects.nonNull(chekLongin)){
            String condition = chekLongin.condition();
            if(ConditionConstant.NAME.equals(condition)){
                String name = request.getParameter("name");
                if(Objects.isNull(name)){
                    // 为空则返回需要登录 此次只是简单做模拟
                    PrintWriter writer = response.getWriter();
                    writer.println("未登录,请返回登录页面");
                    writer.flush();
                    writer.close();
                    return false;
                }
            }
        }
        return true;
    }
}

WebConfig

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationHandler()).addPathPatterns("/**");
    }

}

相关测试和上面一样,如果不符合拦截器相关就会返回"未登录,请返回登录页面",此处只做简单的模拟,可根据实际情况改造.