很多框架都用到了注解,常见的如spring,hibernate,springMvc,SpringBoot等。使用注解有什么用呢?
注解和xml一样,都能提供元数据的支持,二者都有各自的好吃,但是使用注解会和代码的结合性更密切一些,我认为注解提供元数据的支持,在接口拦截器和AOP等编程方式能很好的在业务中对需求的实现!
注解的知识点可以参考此篇博主的文章:
https://www.cnblogs.com/huajiezh/p/5263849.html
http://www.importnew.com/10294.html
javaEE项目中对项目业务具有横向切割的有2项技术:1.拦截器 2.AOP面向切面变成,后面分别来讲他们是如何与注解一起结合工作的。
一、拦截器与java注解的结合
struts2的拦截和springmvc的拦截原理差不多,在此以springMvc的拦截器为例子:
注解类:
package cn.xdf.dtmanager.system.interceptop;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import java.lang.annotation.*;
/**
* Created by fengch on 2018/1/9.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface RequestLimit {
/**
* 次数,默认最大
* @return
*/
int count() default Integer.MAX_VALUE;
/**
* 时长,单位毫秒
* @return
*/
long time() default 6000;
}
springMvc拦截器的配置:
<mvc:interceptors>
<mvc:interceptor>
<!-- 统计接口时长拦截器 -->
<mvc:mapping path="/**" />
<bean class="cn.xdf.dtmanager.system.interceptop.InterceptorTimeCount" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.xdf.dtmanager.system.interceptop.InterceptorTest" />
</mvc:interceptor>
</mvc:interceptors>
package cn.xdf.dtmanager.system.interceptop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
/**
* 计算接口访问时长问题
* Created by fengch on 2017/11/3.
*/
public class InterceptorTest extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
RequestLimit requestLimit = findAnnotation((HandlerMethod) handler, RequestLimit.class);
if(requestLimit != null) {
System.out.println(requestLimit.count() + "::::::::" + requestLimit.time());
} else {
System.out.println("此Action方法上面有没注解!");
return true;
}
}
return super.preHandle(request, response, handler);
}
private <T extends Annotation> T findAnnotation(HandlerMethod handler, Class<T> annotationType) {
T annotation = handler.getBeanType().getAnnotation(annotationType);
if (annotation != null) return annotation;
return handler.getMethodAnnotation(annotationType);
}
}
此findAnnotation方法已经封装好了注解类型的获取。通过传入的注解类进行判断是否为null,否则并上是使用了注解。在来看看实际使用注解的Controller:
@ResponseBody
@RequestMapping(value = "/test.do")
@RequestLimit(count = 10, time = 5000L)
public String test(HttpServletRequest request, HttpServletResponse response) {
try {
Boolean b = masterTeacherService.queryMasterTeacherClassRoom("73", "aaaccc", "test");
System.out.println(b);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("aaaaaaaaaaaaaaaaaa");
return "aaaaaa" + DateUtil.dateToString(new Date(), DateUtil.DATATIME_FORMMATER);
}
二、AOP和java注解的结合
AOP可以分为配置文件的方式和注解的方式,由于使用注解是特定的业务进行注解切面拦截,所以后面是以注解的方式配置AOP生效。
spring的配置文件开启AOP注解如下:
<!-- 启动AspectJ支持 -->
<aop:aspectj-autoproxy />
注解类:
package cn.xdf.dtmanager.system.interceptop;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import java.lang.annotation.*;
/**
* Created by fengch on 2018/1/9.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface RequestLimit {
/**
* 次数,默认最大
* @return
*/
int count() default Integer.MAX_VALUE;
/**
* 时长,单位毫秒
* @return
*/
long time() default 6000;
}
AOP类:
package cn.xdf.dtmanager.system.service.impl;
import cn.xdf.dtmanager.system.interceptop.RequestLimit;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* Created by fengch on 2018/1/9.
*/
@Component
@Aspect
public class AopAspectTest {
@Before("execution(* cn.xdf.dtmanager.business.*.service.*.query*(..)) && @annotation(requestLimit)")
public void aroundAdvice(JoinPoint joinPoint, RequestLimit requestLimit) {
System.out.println(requestLimit);
System.out.println("test````````````````````````");
}
}
注意拦截的是类跟注解同时存在的会被AOP所拦截。