运用切面和拦截器进行注解类的解析判断示例
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("/**");
}
}
相关测试和上面一样,如果不符合拦截器相关就会返回"未登录,请返回登录页面",此处只做简单的模拟,可根据实际情况改造.