<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在之前的紀錄檔記錄的寫法中,我們大多是寫一個工具類,在這個類裡面定義紀錄檔儲存的方法,然後再controller中執行請求的時候呼叫即可,雖然呼叫僅僅一行程式碼,但是不夠友好;所有可以寫一個類似於@Controller等的註解,在需要儲存紀錄檔的方法上面加上一個註解,這樣不用在每個都寫一端程式碼;話不多說上程式碼
package com.sysmg.system.domain; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Transient; import com.sysmg.common.annotation.ExportConfig; @Table(name = "t_log") public class SysLog implements Serializable { private static final long serialVersionUID = -8878596941954995444L; @Id @GeneratedValue(generator = "JDBC") @Column(name = "ID") private Long id; @Column(name = "USERNAME") @ExportConfig(value = "操作使用者") private String username; @Column(name = "OPERATION") @ExportConfig(value = "描述") private String operation; @Column(name = "TIME") @ExportConfig(value = "耗時(毫秒)") private Long time; @Column(name = "METHOD") @ExportConfig(value = "操作方法") private String method; @Column(name = "PARAMS") @ExportConfig(value = "引數") private String params; @Column(name = "IP") @ExportConfig(value = "IP地址") private String ip; @Column(name = "CREATE_TIME") @ExportConfig(value = "操作時間", convert = "c:com.sysmg.common.util.poi.convert.TimeConvert") private Date createTime; @Column(name = "LOCATION") @ExportConfig(value = "地點") private String location; // 用於搜尋條件中的時間欄位 @Transient private String timeField; /** * @return ID */ public Long getId() { return id; } /** * @param id */ public void setId(Long id) { this.id = id; } /** * @return USERNAME */ public String getUsername() { return username; } /** * @param username */ public void setUsername(String username) { this.username = username == null ? null : username.trim(); } /** * @return OPERATION */ public String getOperation() { return operation; } /** * @param operation */ public void setOperation(String operation) { this.operation = operation == null ? null : operation.trim(); } /** * @return TIME */ public Long getTime() { return time; } /** * @param time */ public void setTime(Long time) { this.time = time; } /** * @return METHOD */ public String getMethod() { return method; } /** * @param method */ public void setMethod(String method) { this.method = method == null ? null : method.trim(); } /** * @return PARAMS */ public String getParams() { return params; } /** * @param params */ public void setParams(String params) { this.params = params == null ? null : params.trim(); } /** * @return IP */ public String getIp() { return ip; } /** * @param ip */ public void setIp(String ip) { this.ip = ip == null ? null : ip.trim(); } /** * @return CREATE_TIME */ public Date getCreateTime() { return createTime; } /** * @param createTime */ public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getTimeField() { return timeField; } public void setTimeField(String timeField) { this.timeField = timeField; } }
package com.sysmg.common.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String value() default ""; }
@Target(ElementType.METHOD)代表是方法上的註解,當然也可以是類註解,欄位註解等
@Target(ElementType.TYPE) //介面、類、列舉、註解
@Target(ElementType.FIELD) //欄位、列舉的常數
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法引數
@Target(ElementType.CONSTRUCTOR) //建構函式
@Target(ElementType.LOCAL_VARIABLE)//區域性變數
@Target(ElementType.ANNOTATION_TYPE)//註解
@Target(ElementType.PACKAGE) ///包
@Retention(RetentionPolicy.RUNTIME)代表註解會被jvm保留,這個引數有三種
RetentionPolicy.SOURCE —— 這種型別的Annotations只在原始碼級別保留,編譯時就會被忽略
RetentionPolicy.CLASS —— 這種型別的Annotations編譯時被保留,在class檔案中存在,但JVM將會忽略
RetentionPolicy.RUNTIME —— 這種型別的Annotations將被JVM保留,所以他們能在執行時被JVM或其他使用反射機制的程式碼所讀取和使用。
一般預設第三種
當然也可以寫
@Documented和@Order(優先順序 數位越小優先順序越高)
@Documented 註解表明這個註解應該被 javadoc工具記錄. 預設情況下,javadoc是不包括註解的. 但如果宣告註解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以註解型別資訊也會被包括在生成的檔案中。
@Order標記定義了元件的載入順序,這個標記包含一個value屬性。屬性接受整形值。如:1,2 等等。值越小擁有越高的優先順序。Ordered.HIGHEST_PRECEDENCE這個屬性值是最高優先順序的屬性,它的值是-2147483648,對應的最低屬性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。
String value() default ""
這個代表是要傳遞的引數,類似
@Autowired(required=true) public @interface Autowired { /** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */ boolean required() default true; }
springmvc專案還需要開啟切面程式設計
<aop:aspectj-autoproxy proxy-target-class="true"/>
springboot預設是開啟的
package com.sysmg.common.aspect; import java.lang.reflect.Method; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.apache.shiro.SecurityUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.sysmg.common.annotation.Log; import com.sysmg.common.util.AddressUtilsBak; import com.sysmg.common.util.HttpContextUtils; import com.sysmg.common.util.IPUtils; import com.sysmg.system.domain.SysLog; import com.sysmg.system.domain.User; import com.sysmg.system.service.LogService; @Aspect @Component public class LogAspect { @Autowired private LogService logService; @Autowired ObjectMapper mapper; @Pointcut("@annotation(com.sysmg.common.annotation.Log)") public void pointcut() { } @Around("pointcut()") public Object around(ProceedingJoinPoint point) { Object result = null; long beginTime = System.currentTimeMillis(); try { result = point.proceed(); } catch (Throwable e) { e.printStackTrace(); } long time = System.currentTimeMillis() - beginTime; saveLog(point, time); return result; } private void saveLog(ProceedingJoinPoint joinPoint, long time) { User user = (User) SecurityUtils.getSubject().getPrincipal(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLog log = new SysLog(); Log logAnnotation = method.getAnnotation(Log.class); if (logAnnotation != null) { log.setOperation(logAnnotation.value()); } String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); log.setMethod(className + "." + methodName + "()"); Object[] args = joinPoint.getArgs(); LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); String[] paramNames = u.getParameterNames(method); if (args != null && paramNames != null) { String params = ""; for (int i = 0; i < args.length; i++) { params += " " + paramNames[i] + ": " + args[i]; } log.setParams(params); } HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); log.setIp(IPUtils.getIpAddr(request)); log.setUsername(user.getUsername()); log.setTime(time); log.setCreateTime(new Date()); log.setLocation(AddressUtilsBak.getRealAddressByIP(log.getIp(), mapper)); this.logService.save(log); } }
這裡的實現類中紀錄檔新增的方法中使用的淘寶的獲取ip服務,後續會加上去,其實這裡面可以隨便寫一個實現方法,因為我是留工具備份,所以記錄的較多
具體的@Aspect、@Pointcut、@Around、@Before、@After等aop相關的註解和引數需要自己去鞏固一下知識
package com.sysmg.controller; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.sysmg.common.annotation.Log; import com.sysmg.common.domain.QueryRequest; import com.sysmg.common.domain.ResponseBo; import com.sysmg.common.util.FileUtils; @Controller public class TestController{ @Log("規則") @RequestMapping("test") public String index() { return "test"; } }
大概這樣就可以使用了,目前裡面缺少aop相關知識的介紹以及獲取存取ip的工具類,不過跟本課題關係不大,後續會更上去
到此這篇關於springboot自定義紀錄檔註解的實現的文章就介紹到這了,更多相關springboot自定義紀錄檔註解內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45