終于有時間可以在這裡寫一篇博文了,今天寫一下我在項目中用到的自定義注解,就是在每次操作項目的時候,想把它的操作加在我的資料庫中,簡單地說就是日志管理,這些東西都寫完之後,我就問我自己,問什麼要自定義注解寫,而不是什麼模式(代理模式,裝飾器模式…),原始代碼等等,一下子楞了,于是學習了這個東西,今天就在這裡總結一下。。。
程式設計思想:垂直化程式設計,就是A—B---C—D…等執行下去,一個邏輯一個邏輯完了再執行下一個,但是spring 中AOP提供了一種思想,它的作用就是,當在業務不知情的情況下,對業務代碼的功能的增強,這種思想使用的場景,例如事務送出、方法執行之前的權限檢測、日志列印、方法調用事件等等。
就利用我的日志管理來述說一下這個AOP思想下的自定義注解是如何來實作的。。。
java在我們要自定義注解的時候提供了它自己的自定義文法以及元注解,元注解(負責注解其他注解): Java5.0定義了4個标準的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。Java5.0定義的元注解:
[email protected],
[email protected],
[email protected],
[email protected]
這些類型和它們所支援的類在java.lang.annotation包中可以找到。
[email protected]:使用者描述注解的作用範圍
取值(ElementType)有:
1.CONSTRUCTOR:用于描述構造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部變量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述參數
7.TYPE:用于描述類、接口(包括注解類型) 或enum聲明
[email protected]:表示需要在什麼級别儲存該注釋資訊
取值(RetentionPoicy)有:
1.SOURCE:在源檔案中有效(即源檔案保留)
2.CLASS:在class檔案中有效(即class保留)
3.RUNTIME:在運作時有效(即運作時保留)(常用)
[email protected]:Documented是一個标記注解
[email protected] :用于聲明一個注解;
自定義注解文法:
public @interface 注解名 {定義體}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
注意:
1.隻能用public或預設(default)這兩個通路權修飾.例如,String value();這裡把方法設為default預設類型
2.這裡的參數成員可以是八種基本資料類型,和String,Enum,Class,annotations等資料類型,以及這一些類型的數組,這裡是String
3.最好把參數名稱設為"value()" 後面為預設的值。
/**
* 系統日志,切面處理類
*
* @author stm
* @email [email protected]
* @date 2017年11月21日
*/
@Aspect
@Component
public class SysLogAspect {
@Autowired
private LogService logService;
//這個裡面需要寫自定義注解的全限定名(包名+類名)
@Pointcut("@annotation(com.stm.controller.base.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//執行方法
Object result = point.proceed();
//執行時長(毫秒)
long time = System.currentTimeMillis() - beginTime;
//儲存日志
saveSysLog(point, time);
return result;
}
/**
* 儲存系統日志
* @param joinPoint
* @param time
*/
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
/*SysLog syslog = method.getAnnotation(SysLog.class);
if(syslog != null){
//注解上的描述
System.out.println(syslog.value());
}*/
/*SysLog sysLog = new ();*/
//擷取request請求
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = attr.getRequest();
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
Browser browser = userAgent.getBrowser();
String browsers = browser+"";
System.out.println("浏覽器 "+browsers);
OperatingSystem os = userAgent.getOperatingSystem();
String oss = os+"";
System.out.println("os "+oss);
String ip = "";
try {
ip = InetAddress.getLocalHost().getHostAddress(); //ip 位址
} catch (UnknownHostException e) {
e.printStackTrace();
}
System.out.println("ip "+ip);
Date date = new Date();
System.out.println(date);
com.stm.pojo.system.SysLog sysLog = new com.stm.pojo.system.SysLog();
SysLog syslog = method.getAnnotation(SysLog.class);
HttpSession session = request.getSession();
String userName = (String) session.getAttribute("userName");
if(syslog != null){
//注解上的描述
sysLog.setLogIp(ip);
sysLog.setLogRemark(syslog.value());
sysLog.setLogTime(date);
sysLog.setUserName(userName);
sysLog.setLogSystem(oss);
sysLog.setLogBrowser(browsers);
}
//請求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
//sysLog.setMethod(className + "." + methodName + "()");
logService.insert(sysLog);
}
}
如何使用?
例如在使用者登入的時候需要把相關的 資訊添加到資料庫中,這個時候就需要在登入成功之後在跳轉到清單的時候添加注解:
@SysLog("使用者登入")
@RequestMapping("/main/index")
public String index(){
return "main/index";
}
而這個注解中寫的(“使用者登入”)就是添加自定義時候的預設值的value()相對應的值。。。
對了這裡需要配置aop以及依賴
<!-- aop 注解實作 -->
<aop:aspectj-autoproxy/>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.2</version>
</dependency>
今天就到這裡,之後會更詳細的整理!!!