<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          妙用自定義注解,一行代碼搞定大功能(文末贈書)

          共 32948字,需瀏覽 66分鐘

           ·

          2022-11-01 21:35

          以下內(nèi)容來自公眾號逆鋒起筆,關(guān)注每日干貨及時送達

          1.簡介

          在使用spring完成項目的時候需要完成記錄日志,開始以為Spring 的AOP功能,就可以輕松解決,半個小時都不用,可是經(jīng)過一番了解過后,發(fā)現(xiàn)一般的日志記錄,只能記錄一些簡單的操作,例如表名、表名稱等記錄不到。
          這個時侯就用到了自定義注解,把想要記錄的內(nèi)容放在注解中,通過切入點來獲取到注解參數(shù),然后將參數(shù)插入數(shù)據(jù)庫記錄

          2.Spring AOP

          2.1.關(guān)于Spring AOP的一些術(shù)語

          • 切面(Aspect):在Spring AOP中,切面可以使用通用類或者在普通類中以@Aspect 注解(@AspectJ風格)來實現(xiàn)
          • 連接點(Joinpoint):在Spring AOP中一個連接點代表一個方法的執(zhí)行
          • 通知(Advice):在切面的某個特定的連接點(Joinpoint)上執(zhí)行的動作。通知有各種類型,其中包括"around"、"before”和"after"等通知。許多AOP框架,包括Spring,都是以攔截器做通知模型, 并維護一個以連接點為中心的攔截器鏈
          • 切入點(Pointcut):定義出一個或一組方法,當執(zhí)行這些方法時可產(chǎn)生通知,Spring缺省使用AspectJ切入點語法。
          通知類型
          • 前置通知(@Before):在某連接點(join point)之前執(zhí)行的通知,但這個通知不能阻止連接點前的執(zhí)行(除非它拋出一個異常)
          • 返回后通知(@AfterReturning):在某連接點(join point)正常完成后執(zhí)行的通知:例如,一個方法沒有拋出任何異常,正常返回
          • 拋出異常后通知(@AfterThrowing):方法拋出異常退出時執(zhí)行的通知
          • 后通知(@After):當某連接點退出的時候執(zhí)行的通知(不論是正常返回還是異常退出)
          • 環(huán)繞通知(@Around):包圍一個連接點(join point)的通知,如方法調(diào)用。這是最強大的一種通知類型,環(huán)繞通知可以在方法調(diào)用前后完成自定義的行為,它也會選擇是否繼續(xù)執(zhí)行連接點或直接返回它們自己的返回值或拋出異常來結(jié)束執(zhí)行。

          2.2.Spring AOP配置有兩種風格:

          • XML風格 = 采用聲明形式實現(xiàn)Spring AOP
          • AspectJ風格 = 采用注解形式實現(xiàn)Spring AOP

          3.首先自定義注解

          定義一個日志描述和一個表名這里根據(jù)需要自定義注解
          package com.ywj.log;
           
          import java.lang.annotation.*;
           
          /**
           * ClassName Crmlog
           * AOP日志記錄 自定義注解類
           */

          @Target({ElementType.PARAMETER, ElementType.METHOD})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public @interface SystemCrmlog {
              /**
               * 日志描述
               * 對于什么表格進行了什么操作
               */

              String description()  default "";
           
              /**
               * 操作了的表名
               * @return
               */

              String  tableName() default "";
          }

          3.1.定義切面類,從切入點獲取注解信息保存到數(shù)據(jù)庫

          對于一些可能碰到的問題我在方法的注釋里都有解決辦法,大家注意一下,這里我對于方法報錯也有處理方法
          這里是對于切面類里使用到的兩個類解釋:
          AspectJ使用org.aspectj.lang.JoinPoint接口表示目標類連接點對象,如果是環(huán)繞增強時,使用org.aspectj.lang.ProceedingJoinPoint表示連接點對象,該類是JoinPoint的子接口。任何一個增強方法都可以通過將第一個入?yún)⒙暶鳛镴oinPoint訪問到連接點上下文的信息。我們先來了解一下這兩個接口的主要方法:
          1)JoinPoint
          • java.lang.Object[] getArgs():獲取連接點方法運行時的入?yún)⒘斜恚?/span>
          • Signature getSignature() :獲取連接點的方法簽名對象;
          • java.lang.Object getTarget() :獲取連接點所在的目標對象;
          • java.lang.Object getThis() :獲取代理對象本身;
          2)ProceedingJoinPoint
          ProceedingJoinPoint繼承JoinPoint子接口,它新增了兩個用于執(zhí)行連接點方法的方法:
          • java.lang.Object proceed() throws java.lang.Throwable:通過反射執(zhí)行目標對象的連接點處的方法;
          • java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通過反射執(zhí)行目標對象連接點處的方法,不過使用新的入?yún)⑻鎿Q原來的入?yún)ⅰ?a target="_blank" textvalue="因為看了這些資料,我就成了別人眼中的大佬!" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2">因為看了這些資料,我就成了別人眼中的大佬!

          package com.ywj.log;
           
           
          import com.fasterxml.jackson.databind.ObjectMapper;
          import com.ywj.log.biz.Sys_logBiz;
          import com.ywj.log.dao.Sys_logDao;
          import com.ywj.login.biz.Sys_UserBiz;
          import com.ywj.login.dao.Sys_UserDao;
          import com.ywj.login.dao.Sys_righDao;
          import org.aspectj.lang.JoinPoint;
          import org.aspectj.lang.annotation.*;
          import org.springframework.stereotype.Component;
          import org.springframework.web.context.request.RequestAttributes;
          import org.springframework.web.context.request.RequestContextHolder;
          import org.springframework.web.context.request.ServletRequestAttributes;
           
          import javax.servlet.http.HttpServletRequest;
          import java.lang.reflect.Method;
          import java.text.SimpleDateFormat;
          import java.util.Arrays;
          import java.util.Date;
          import java.util.List;
          import java.util.Map;
           
           
          /**
           * @ClassName SystemLogAspect
           * @Author Administrator
           * @Describe  定義切入面類
           */

          @Aspect
          @Component
          public class SystemLogAspect {
           
           
              /**
               * 注解Pointcut切入點
               * 定義出一個或一組方法,當執(zhí)行這些方法時可產(chǎn)生通知
               * 指向你的切面類方法
               * 由于這里使用了自定義注解所以指向你的自定義注解
               */

              @Pointcut("@annotation(com.ywj.log.SystemCrmlog)")
              public void crmAspect() {
              }
           
           
              /**
               *拋出異常后通知(@AfterThrowing):方法拋出異常退出時執(zhí)行的通知
               * 注意在這里不能使用ProceedingJoinPoint
               * 不然會報錯ProceedingJoinPoint is only supported for around advice
               * throwing注解為錯誤信息
               * @param joinPoint
               * @param ex
               */

              @AfterThrowing(value="crmAspect()", throwing="ex")
              public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) throws Exception {
                  HttpServletRequest httpServletRequest = getHttpServletRequest();
                  //獲取管理員用戶信息\
                  WebUtil webUtil = new WebUtil();
                  Map<String, Object> user = webUtil.getUser(httpServletRequest);
                  CrmLogMessage log=new CrmLogMessage();
                  //獲取需要的信息
                  String context=getServiceMthodDescription(joinPoint);
                  String usr_name="";
                  String rolename="";
                  if(user!=null){
                      usr_name = user.get("usr_name").toString();
                      rolename=user.get("rolename").toString();
                  }
                  //管理員姓名
                  log.setUserName(usr_name);
                  //角色名
                  log.setUserRole(rolename);
                  //日志信息
                  log.setContent(usr_name+context);
                  //設(shè)置參數(shù)集合
                  log.setRemarks(getServiceMthodParams(joinPoint));
                  //設(shè)置表名
                  log.setTableName(getServiceMthodTableName(joinPoint));
                  //操作時間
                  SimpleDateFormat sif=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                  log.setDateTime(sif.format(new Date()));
                  //設(shè)置ip地址
                  log.setIp(httpServletRequest.getRemoteAddr());
                  //設(shè)置請求地址
                  log.setRequestUrl(httpServletRequest.getRequestURI());
                  //執(zhí)行結(jié)果
                  log.setResult("執(zhí)行失敗");
                  //錯誤信息
                  log.setExString(ex.getMessage());
                  //將數(shù)據(jù)保存到數(shù)據(jù)庫
                  Sys_logDao sysLogDao=new Sys_logDao();
                  sysLogDao.addSys_log(log);
              }
           
           
              /**
               * 返回后通知(@AfterReturning):在某連接點(joinpoint)
               * 正常完成后執(zhí)行的通知:例如,一個方法沒有拋出任何異常,正常返回
               * 方法執(zhí)行完畢之后
               * 注意在這里不能使用ProceedingJoinPoint
               * 不然會報錯ProceedingJoinPoint is only supported for around advice
               * crmAspect()指向需要控制的方法
               *  returning  注解返回值
               * @param joinPoint
               * @param returnValue  返回值
               * @throws Exception
               */

              @AfterReturning(value = "crmAspect()",returning = "returnValue")
              public  void doCrmLog(JoinPoint joinPoint,Object returnValue) throws Exception {
                  HttpServletRequest httpServletRequest = getHttpServletRequest();
                  //獲取管理員用戶信息
                  WebUtil webUtil = new WebUtil();
                  Map<String, Object> user = webUtil.getUser(httpServletRequest);
                  CrmLogMessage log=new CrmLogMessage();
                  String context=getServiceMthodDescription(joinPoint);
           
                  String usr_name="";
                  String rolename="";
                  if(user!=null){
                   usr_name = user.get("usr_name").toString();
                   rolename=user.get("rolename").toString();
                  }
                  //管理員姓名
                  log.setUserName(usr_name);
                  //角色名
                  log.setUserRole(rolename);
                  //日志信息
                  log.setContent(usr_name+context);
                  //設(shè)置參數(shù)集合
                  log.setRemarks(getServiceMthodParams(joinPoint));
                  //設(shè)置表名
                  log.setTableName(getServiceMthodTableName(joinPoint));
                  //操作時間
                  SimpleDateFormat sif=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                  log.setDateTime(sif.format(new Date()));
                  //設(shè)置ip地址
                  log.setIp(httpServletRequest.getRemoteAddr());
                  //設(shè)置請求地址
                  log.setRequestUrl(httpServletRequest.getRequestURI());
                  if(returnValue!=null){
                     if(returnValue instanceof List){
                         List ls= (List) returnValue;
                         if(ls.size()>0){
                             log.setResult("執(zhí)行成功");
                         }else{
                             log.setResult("執(zhí)行成功");
                         }
                     }else if(returnValue instanceof Boolean){
                         Boolean falg= (Boolean) returnValue;
                         if(falg){
                             log.setResult("執(zhí)行成功");
                         }else{
                             log.setResult("執(zhí)行失敗");
                         }
                     }else if(returnValue instanceof Integer){
                         Integer i= (Integer) returnValue;
                         if(i>0){
                             log.setResult("執(zhí)行成功");
                         }else{
                             log.setResult("執(zhí)行失敗");
                         }
                     }else{
                         log.setResult("執(zhí)行成功");
                     }
           
                  }
                  //將數(shù)據(jù)保存到數(shù)據(jù)庫
                  Sys_logDao sysLogDao=new Sys_logDao();
                  sysLogDao.addSys_log(log);
              }
           
           
              /**
               *獲取自定義注解里的日志描述
               * @param joinPoint
               * @return 返回注解里面的日志描述
               * @throws Exception
               */

              private String getServiceMthodDescription(JoinPoint joinPoint)
                      throws Exception 
          {
                  //類名
                  String targetName = joinPoint.getTarget().getClass().getName();
                  //方法名
                  String methodName = joinPoint.getSignature().getName();
                  //參數(shù)
                  Object[] arguments = joinPoint.getArgs();
                  //通過反射獲取示例對象
                  Class targetClass = Class.forName(targetName);
                  //通過實例對象方法數(shù)組
                  Method[] methods = targetClass.getMethods();
                  String description = "";
                  for(Method method : methods) {
                      //判斷方法名是不是一樣
                      if(method.getName().equals(methodName)) {
                          //對比參數(shù)數(shù)組的長度
                          Class[] clazzs = method.getParameterTypes();
                          if(clazzs.length == arguments.length) {
                              //獲取注解里的日志信息
                              description = method.getAnnotation(SystemCrmlog.class).description();
                              break;
                          }
                      }
                  }
                  return description;
              }
           
              /**
               *獲取自定義注解里的表名
               * @param joinPoint
               * @return 返回注解里的表名字
               * @throws Exception
               */

              private String getServiceMthodTableName(JoinPoint joinPoint)
                      throws Exception 
          {
                  //類名
                  String targetName = joinPoint.getTarget().getClass().getName();
                  //方法名
                  String methodName = joinPoint.getSignature().getName();
                  //參數(shù)
                  Object[] arguments = joinPoint.getArgs();
                  //通過反射獲取示例對象
                  Class targetClass = Class.forName(targetName);
                  //通過實例對象方法數(shù)組
                  Method[] methods = targetClass.getMethods();
                  //表名
                  String tableName = "";
                  for (Method method : methods) {
                      //判斷方法名是不是一樣
                      if (method.getName().equals(methodName)) {
                          //對比參數(shù)數(shù)組的長度
                          Class[] clazzs = method.getParameterTypes();
                          if (clazzs.length == arguments.length) {
                              //獲取注解里的表名
                              tableName = method.getAnnotation(SystemCrmlog.class).tableName();
                              break;
                          }
                      }
                  }
                  return tableName;
              }
           
              /**
               * 獲取json格式的參數(shù)用于存儲到數(shù)據(jù)庫中
               * @param joinPoint
               * @return
               * @throws Exception
               */

              private String getServiceMthodParams(JoinPoint joinPoint)
                      throws Exception 
          {
                  Object[] arguments = joinPoint.getArgs();
                  ObjectMapper om=new ObjectMapper();
                  return om.writeValueAsString(arguments);
              }
           
              /**
               * 獲取當前的request
               * 這里如果報空指針異常是因為單獨使用spring獲取request
               * 需要在配置文件里添加監(jiān)聽
               * <listener>
               * <listener-class>
               * org.springframework.web.context.request.RequestContextListener
               * </listener-class>
               * </listener>
               * @return
               */

              public HttpServletRequest getHttpServletRequest(){
                  RequestAttributes ra = RequestContextHolder.getRequestAttributes();
                  ServletRequestAttributes sra = (ServletRequestAttributes)ra;
                  HttpServletRequest request = sra.getRequest();
                  return request;
              }
           
          }
          每個切面?zhèn)鬟f的數(shù)據(jù)的都不一樣,最終決定,獲取切面的所有參數(shù),轉(zhuǎn)成json字符串,保存到數(shù)據(jù)庫中。

          相關(guān)類:

          日志信息類
          package com.ywj.log;
           
          /**
           * @ClassName CrmLogMessage
           * @Author Administrator
           * @Describe 數(shù)據(jù)庫日志類
           */

          public class CrmLogMessage {
              private Integer logid;//日志id
              private String UserName;//管理員姓名
              private String UserRole;//管理員角色
              private String Content;//日志描述
              private String Remarks;//參數(shù)集合
              private String TableName;//表格名稱
              private String DateTime;//操作時間
              private String resultValue;//返回值
              private String ip;//ip地址
              private String  requestUrl;//請求地址
              private String result;//操作結(jié)果
              private  String ExString;//錯誤信息
           
              public CrmLogMessage() {
              }
           
              @Override
              public String toString() {
                  return "CrmLogMessage{" +
                          "logid=" + logid +
                          ", UserName='" + UserName + '\'' +
                          ", UserRole='" + UserRole + '\'' +
                          ", Content='" + Content + '\'' +
                          ", Remarks='" + Remarks + '\'' +
                          ", TableName='" + TableName + '\'' +
                          ", DateTime='" + DateTime + '\'' +
                          ", resultValue='" + resultValue + '\'' +
                          ", ip='" + ip + '\'' +
                          ", requestUrl='" + requestUrl + '\'' +
                          ", result='" + result + '\'' +
                          ", ExString='" + ExString + '\'' +
                          '}';
              }
           
              public CrmLogMessage(Integer logid, String userName, String userRole, String content, String remarks, String tableName, String dateTime, String resultValue, String ip, String requestUrl, String result, String exString) {
                  this.logid = logid;
                  UserName = userName;
                  UserRole = userRole;
                  Content = content;
                  Remarks = remarks;
                  TableName = tableName;
                  DateTime = dateTime;
                  this.resultValue = resultValue;
                  this.ip = ip;
                  this.requestUrl = requestUrl;
                  this.result = result;
                  ExString = exString;
              }
           
              public String getExString() {
                  return ExString;
              }
           
              public void setExString(String exString) {
                  ExString = exString;
              }
           
              public Integer getLogid() {
                  return logid;
              }
           
              public void setLogid(Integer logid) {
                  this.logid = logid;
              }
           
              public String getUserName() {
                  return UserName;
              }
           
              public void setUserName(String userName) {
                  UserName = userName;
              }
           
              public String getUserRole() {
                  return UserRole;
              }
           
              public void setUserRole(String userRole) {
                  UserRole = userRole;
              }
           
              public String getContent() {
                  return Content;
              }
           
              public void setContent(String content) {
                  Content = content;
              }
           
              public String getRemarks() {
                  return Remarks;
              }
           
              public void setRemarks(String remarks) {
                  Remarks = remarks;
              }
           
              public String getTableName() {
                  return TableName;
              }
           
              public void setTableName(String tableName) {
                  TableName = tableName;
              }
           
              public String getDateTime() {
                  return DateTime;
              }
           
              public void setDateTime(String dateTime) {
                  DateTime = dateTime;
              }
           
              public String getResultValue() {
                  return resultValue;
              }
           
              public void setResultValue(String resultValue) {
                  this.resultValue = resultValue;
              }
           
              public String getIp() {
                  return ip;
              }
           
              public void setIp(String ip) {
                  this.ip = ip;
              }
           
              public String getRequestUrl() {
                  return requestUrl;
              }
           
              public void setRequestUrl(String requestUrl) {
                  this.requestUrl = requestUrl;
              }
           
              public String getResult() {
                  return result;
              }
           
              public void setResult(String result) {
                  this.result = result;
              }
          }
          用來獲取登錄用戶信息的幫助類:
          package com.ywj.log;
           
          import com.base.web.BaseAction;
           
          import javax.servlet.http.HttpServletRequest;
          import java.util.Map;
           
          /**
           * @ClassName WebUtil
           * @Author Administrator
           * @Describe  日志幫助類 用來獲取session中的用戶信息來存入數(shù)據(jù)庫
           */

          public class WebUtil  {
           
           
              /**
               * 從session中獲取到用戶對象
               * @return
               */

              public Map<String, Object>   getUser(HttpServletRequest request){
                  Map<String, Object> attribute=null;
                  if(request!=null){
                  Object user = request.getSession().getAttribute(Constans.USER_KEY);
                attribute = (Map<String, Object>) user;}
              return attribute;
          }
              
          }
          在你的spring-context.xml中配置
            <!-- 啟動對@AspectJ注解的支持  -->
              <aop:aspectj-autoproxy proxy-target-class="true" />
              <!-- 自動掃描包路徑  -->
           <!--你需要剛才的切面類的包路徑-->
              <context:component-scan base-package="com.ywj.log" />
             <!--你需要注解方法的包路徑-->
              <context:component-scan base-package="com.*.*.biz.impl" />
          然后在你需要記錄的方法上加上注解
          @SystemCrmlog(description = "進行了登錄操作",tableName =Constans.USER_TABLENAME)
          效果這里表名使用了常量類
          對于一些表的信息可以寫一個常量類
          然后執(zhí)行登錄操作數(shù)據(jù)庫記錄為:

          來源:blog.csdn.net/yjt520557/article/details/85099115



          成為一名優(yōu)秀Java開發(fā)人員的7個步驟

          40 個 SpringBoot 常用注解

          泛型會讓你的 Go 代碼運行變慢



          今日福利

          贈送如下圖書籍:

          贈送規(guī)則:

          1、給本文點贊、在看

          2、給本文留言(留言內(nèi)容與本書有關(guān)

          3、中獎后我會回復(fù)你的留言,請注意公眾號消息。



          上次中獎?wù)撸?/span>


          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼大战 | 91麻豆产精品久久久久久 | www.99热精品 | 日逼免费看| 久热免费在线视频 |