java切面做日志记录

前言

   众说周知,aop是oop思想的延续,是为了我们更好的程序的开发,更便于我们对技术及代码的维护。今天就利用aop来做一个日志的记录。废话不多说,上代码。

实例

entity

import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name="tb_operate_record")
@Data
@NoArgsConstructor
public class TbOperateRecord implements Serializable {

    private static final long serialVersionUID = 4907931420975674126L;
    
    @Id
    @GeneratedValue(generator ="paymentableGenerator")
    @GenericGenerator(name ="paymentableGenerator", strategy = "uuid")
    @Column(name= "log_record_id")
    private String id;     // 主键 采用UUID 策略目的是为了适配数据库(具体项目可以选择合适的生成策略)
    
    @Column(name="input_Params")
    private String inputParams; //方法输入的参数
    
    @Column(name="user_name")
    private String userName; //操作人
    
    @Column(name="operate_description")
    private String operateDescription ; //用户操作记录描述
    
    @Column( name = "req_ip")
    private String reqIp;  //请求ip地址
    
    @Column(name="req_url")
    private String reqUrl; //请求reqURL
    
    @Column(name = "take_time")
    private String  takeTime; //耗时
    
    @Column(name="operate_time")
    private String  operateTime; //操作时间
    
    @Column(name= "method_description")
    private String methodDescription; //接口功能描述
    
    @Column(name="method_name")
    private String methodName; //方法名

切面类

@Component
@Aspect
public class LoggerRecord {

    private final  static Logger logger = LoggerFactory.getLogger(LoggerRecord.class);

    private final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 规定日期格式

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private TbOperateRecordRepository tbOperateRecordRepository;

    //定义切点
    @Pointcut(value = "execution(* com.*.controller.*.*(..))")
    public void  PointCutJcLog(){

    }
    @Around(value = "PointCutJcLog()")     //编写逻辑
    public Object saveJcRecordLogger(ProceedingJoinPoint joinPoint)throws Throwable{
        TbOperateRecord operateRecord = new TbOperateRecord();  //创建日志记录对象
        long startTime = System.currentTimeMillis();
        Object retVal = joinPoint.proceed();
        long entTime = System.currentTimeMillis();
        String consumeTime = formatDuring(entTime - startTime);
        operateRecord.setTakeTime(consumeTime);
        operateRecord.setOperateTime(df.format(new Date()));
        //从session中取出用户及部门信息
        getUserInfo(operateRecord); //获取用户信息方法
        //创建日志操作对象
        Class<?> target = joinPoint.getTarget().getClass();
        getJcLoggerSource(operateRecord, target); //获取日志目录
        MethodSignature signature =(MethodSignature)joinPoint.getSignature(); //从切面织入点处通过反射机制获取织入点处的方法
        Method method = signature.getMethod();
        operateRecord.setMethodName(method.getName());
        getUsingAndInterfaceFunction(operateRecord, method); //获取用途及接口功能描述
        Object[] args = joinPoint.getArgs();
        getRequestAgrs(operateRecord, args);
        String remoteAddr = request.getRemoteAddr();//获取请求地址
        operateRecord.setReqIp(remoteAddr);
        String url = request.getRequestURL().toString();
        operateRecord.setReqUrl(url);
        try {
            tbOperateRecordRepository.save(operateRecord);
            logger.info("操作日志记录成功");
        } catch (Exception e) {
            logger.error("操作日志记录新增失败",e.getMessage());
        }
        return  retVal;  // 使用 ProceedingJoinPoin 该类必须返回,即释放拦截的
    }
  
    //获取请求参数
    private void getRequestAgrs(TbOperateRecord operateRecord, Object[] args) {
        if(null!= args){
            List<Map<String, Object>> paramsMap = new ArrayList<Map<String, Object>>();
            HttpServletRequest request;
            for (int i = 0; i <args.length ; i++) {
                try{
                    request = (HttpServletRequest) args[i];  //过滤参数为接口类型的
                    //如果是HttpServletRequest则跳过
                    continue;
                }catch (Exception e){
                    ConcurrentHashMap<String, Object> eachParam = new ConcurrentHashMap<>();
                    eachParam.put("第"+(i+1)+"参数",args[i]);
                    paramsMap.add(eachParam);
                }
            }
            String content = JSON.toJSONString(paramsMap);
            operateRecord.setInputParams(content);

        }else{
            operateRecord.setInputParams("该方法没有请求参数");
        }
    }
    //记录信息的组装
    private void getOperateDescription(TbOperateRecord operateRecord, String name) {
        String description = "";
        StringBuffer buffer = new StringBuffer("用户【");
        description = buffer.append(operateRecord.getUserName() + "】,于【")
                .append(operateRecord.getOperateTime() + "】,执行【")
                .append(operateRecord.getMethodDescription()+ "】操作,请求接口【")
                .append(name + "】,请求ip【")
                .append(operateRecord.getReqIp() + "】,请求参数【")
                .append(operateRecord.getInputParams() + "】").toString();
        operateRecord.setOperateDescription(description);
    }

    //请求耗时计算
    public static String formatDuring(long time) {
        long minutes = (time % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (time % (1000 * 60)) / 1000;
        long subsec = time % 1000;
        return minutes + "分钟," + seconds + "秒," + subsec + "毫秒 ";
    }

// 用户信息的获取 (根据自己项目封装的工具类取值)
 private void getUserInfo(TbOperateRecord operateRecord) {
        String userName="";
        try {
            Session currentUser = Session.getCurrentUser(request.getSession());
            UserInfo userinfo = currentUser.getUserinfo();
            if(null !=userinfo){
                  userName = userinfo.getUserName();
            }
        } catch (Exception e) {
            logger.error("未获取当前登录人相关信息",e.getMessage());
        }
        operateRecord.setUserName(userName);

    }

Repository

import com.sanling.credit.wd.entity.TbOperateRecord;
import org.springframework.data.jpa.repository.JpaRepository;
public interface  TbOperateRecordRepository extends JpaRepository<TbOperateRecord,String> {
}

注意

切点的选择及正则的写法很重要,必须写对
推荐一篇博客,关于切点的详解:
(https://blog.csdn.net/qq_26860451/article/details/100554377)

猜你喜欢

转载自blog.csdn.net/WindwirdBird/article/details/105606701