終於有時間可以在這裏寫一篇博文了,今天寫一下我在項目中用到的自定義註解,就是在每次操作項目的時候,想把它的操作加在我的數據庫中,簡單地說就是日誌管理,這些東西都寫完之後,我就問我自己,問什麼要自定義註解寫,而不是什麼模式(代理模式,裝飾器模式…),原始代碼等等,一下子楞了,於是學習了這個東西,今天就在這裏總結一下。。。
編程思想:垂直化編程,就是A—B---C—D…等執行下去,一個邏輯一個邏輯完了再執行下一個,但是spring 中AOP提供了一種思想,它的作用就是,當在業務不知情的情況下,對業務代碼的功能的增強,這種思想使用的場景,例如事務提交、方法執行之前的權限檢測、日誌打印、方法調用事件等等。
就利用我的日誌管理來述說一下這個AOP思想下的自定義註解是如何來實現的。。。
java在我們要自定義註解的時候提供了它自己的自定義語法以及元註解,元註解(負責註解其他註解): Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。Java5.0定義的元註解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
這些類型和它們所支持的類在java.lang.annotation包中可以找到。
1.@Target:用戶描述註解的作用範圍
取值(ElementType)有:
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述局部變量
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述參數
7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明
2.@Retention:表示需要在什麼級別保存該註釋信息
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)(常用)
3.@Documented:Documented是一個標記註解
4.@Inherited :用於聲明一個註解;
自定義註解語法:
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>
今天就到這裏,之後會更詳細的整理!!!