首页 > 编程语言 >Java利用Aop切面记录操作日志(注解方式)

Java利用Aop切面记录操作日志(注解方式)

时间:2024-05-24 17:29:21浏览次数:29  
标签:Java String para ip AOP request 切面 Aop log

前提需求


之前收到一个新需求,要求对已有的系统上新增一个记录操作日志的功能,对于这类功能大家应该也看的很多了,必然是AOP进行解决,方便快捷,就是需要一个个方法加注释比较麻烦,说到AOP,就先粗略的介绍下AOP

AOP的概念


1.1 什么是AOP?

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的 集中处理。

1.2 什么是SpringAOP?

⽽ AOP 是⼀种思想,⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

1.3 为什要⽤ AOP?

在开发中,我们对于公共方法的处理分为三个阶段:

  1. 每个方法都去实现(初级)
  2. 抽取公共方法(中级)
  3. 采用AOP的方式,对代码进行无侵入是实现(高级)

因此,对于这种功能统⼀,且使⽤的地⽅较多的功能,在之前我们会抽取公共方法去实现,但是现在有更好的一个办法来处理这个问题,就是AOP。

也就是使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

1.4 AOP的作用?

提供声明式事务;允许用户自定义切面

开始敲代码利用AOP实现这个需求功能


 1. 添加 Spring AOP 框架⽀持。

首先我们建立一个新的Springboot项目,在配置文件中添加AOP框架。

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

2.自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
public @interface LogRecord {

    /**
     * 操作具体某个功能的描述
     * @return
     */
    String desc() default "";

    /**
     * 操作类型
     * @return
     */
    int type() default 1;
}

3.定义一个切面: 

@Aspect
@Component
@Order(100)
public class LogAop {

    @Value("${customer.name}")
    private String customerName;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private BuLogMapper buLogMapper;

@Autowired
private BuErrorLogServiceImpl buErrorLogService;

    @Autowired
    private RedisUtils redisUtils;
    @Pointcut("@annotation(com.maizhiyu.yzt.annotation.LogRecord)")
    public void logAop() {
    }

    @Around("logAop()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;
        BuLog buLog =new BuLog();
            // 获取request对象
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String networkIp = getIpAddr(request);
            networkIp = "0:0:0:0:0:0:0:1".equals(networkIp) ? InetAddress.getLocalHost().getHostAddress() : networkIp;
            String ip =  InetAddress.getLocalHost().getHostAddress();
            String path = request.getRequestURL().toString();
            String string1 = request.getRequestURI().toString();
            String mac = NetUtil.getMacAddress(InetAddress.getLocalHost());
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            String interfaceName = method.getName();
            String name = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();
            String para = new String();
            if (ObjectUtil.isNotEmpty(args)) {
                if (args[0] instanceof MultipartFile) {
                    para = ((MultipartFile) joinPoint.getArgs()[0]).getOriginalFilename();
                } else {
                    if ((args[0].getClass().isArray() && args[0].getClass().getComponentType() == MultipartFile.class)) {
                        StringBuffer asd = new StringBuffer();
                        for (MultipartFile file : (MultipartFile[]) joinPoint.getArgs()[0]) {
                            if (asd == null) asd.append(file.getOriginalFilename());
                            else asd.append("," + file.getOriginalFilename());
                        }
                        para = asd.toString();
                    } else {
                        para = JSONArray.toJSONString(Arrays.stream(args).filter(e->!(e instanceof BindingResult)).toArray());
                    }
                }
                String idcard = "\\d{18}";
                String phone = "\\d{11}";
                String password = "password";
                Pattern phoneC = Pattern.compile(phone);
                Pattern idcardC = Pattern.compile(idcard);
                if (para.contains(password)) {
                    int i = para.indexOf('"', para.indexOf(password) + 11);
                    String substring = para.substring(para.indexOf(password) + 11, i);
                    para = para.replace(substring, "***");
                    System.out.println(i);
                }
                ;
                Matcher idcardM = idcardC.matcher(para);
                if (idcardM.find()) {
                    para = para.replace(idcardM.group(), IdcardUtil.hide(idcardM.group(), 6, 14));
                }
                ;
                Matcher phoneM = phoneC.matcher(para);
                if (phoneM.find()) {
                    para = para.replace(phoneM.group(), PhoneUtil.hideBetween(phoneM.group()));
                };
            }
        buLog.setReqPara(para);
        buLog.setIp(ip);
        buLog.setMac(mac);
        buLog.setReqUrl(path);
        LogRecord anno = signature.getMethod().getAnnotation(LogRecord.class);
        buLog.setType(anno.type());
        buLog.setOperateTime(new Date());
        BuErrorLog log = new BuErrorLog();
        try {
            result = joinPoint.proceed();
            if (!result.toString().contains("请输入正确的")&&!result.toString().contains("您的账户被锁定,请稍后尝试")){
                HsUser currentUser = jwtUtil.getCurrentUser();
                log.setCustomerId(currentUser.getCustomerId());
                buLog.setUserId(jwtUtil.getCurrentUser().getId().toString());
                buLog.setUserName(jwtUtil.getCurrentUser().getRealName());
                buLog.setCustomerId(jwtUtil.getCurrentUser().getCustomerId());
                buLog.setOperateInfor(jwtUtil.getCurrentUser().getRealName()+"进行了"+anno.desc());
            }else buLog.setOperateInfor("登陆失败");
        } catch (Throwable e) {
                log.setCustomerName(customerName);
                log.setClassName(joinPoint.getTarget().getClass().getName());
                log.setMethodName(method.getName());
                log.setErrorName(e.getClass().getName());
                log.setErrorMessage(e.getMessage());
                log.setErrorStack(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace()));
                log.setReqUrl(request.getRequestURL().toString());
                log.setReqPara(para);
                log.setIsDel(0);
                log.setCustomerId(jwtUtil.getCurrentUser().getCustomerId());
                log.setCreateTime(new Date());
                log.setUpdateTime(log.getCreateTime());
                buErrorLogService.save(log);
                buLog.setErrInformation(log.getId().toString());
                throw new RuntimeException(e);
        }finally {
            buLogMapper.insert(buLog);
        }
        return result;
    }

    /**
     * 获取请求IP
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }

    public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
        StringBuffer strbuff = new StringBuffer();
        for (StackTraceElement stet : elements) {
            if(stet.getClassName().contains("com.maizhiyu.yzt"))
                strbuff.append(stet + "<br/>");
        }
        String message = exceptionName + ":" + exceptionMessage + "<br/>" + strbuff.toString();
        return message;
    }

4.使用注解

    @ApiOperation(value = "增加用户", notes = "增加用户")
    @PostMapping("/addUser")
    @LogRecord(type = LogTypeConstant.XZ,desc = "增加用户")
    public Result addUser(@RequestBody HsUser user) {
        Integer res = service.addUser(user);
        return Result.success(user);
    }

5. 执行后结果,成功记录

标签:Java,String,para,ip,AOP,request,切面,Aop,log
From: https://blog.csdn.net/m0_73774439/article/details/139059260

相关文章

  • cesium裁切面实践
    cesium裁切面实践:沙盒地址打不开的自行科学访问<style>@importurl(../templates/bucket.css);#toolbar{background:rgba(42,42,42,0.8);padding:4px;border-radius:4px;}#toolbarinput{vertical-al......
  • Golang 实现Java的AES ECB 加密
    JavapublicstaticStringencryptAesEcb(Stringtarget,StringsKey)throwsException{byte[]raw=sKey.getBytes("UTF-8");//"AES"就是用AES/ECB/PKCS5PaddingSecretKeySpecskeySpec=newSecretKeySpec(raw,......
  • Java JUC&多线程 基础完整版
    JavaJUC&多线程基础完整版目录JavaJUC&多线程基础完整版1、多线程的第一种启动方式之继承Thread类2、多线程的第二种启动方式之实现Runnable接口3、多线程的第三种实现方式之实现Callable接口4、多线的常用成员方法5、线程的优先级6、守护线程7、线程的让出8、线程插队9、同......
  • JavaScript基本语法
    JavaScript是一种高级的、解释型的编程语言。它是Web开发中不可或缺的一部分,通常用于创建交互式网页,给用户带来更丰富的体验。以下是JavaScript入门的一些基本步骤和概念:1.基本语法变量声明:使用let或const声明变量。letmessage='Hello,World!';constPI=3.14;数......
  • JAVA——接口
                               前言:接口是一种规范和标准,它是一些方法特征的集合,但无具体的实现细节。接口可以被类或其他接口实现,通过面向接口的编程,可以提高代码的复用率、可维护性、可扩展性。1.接口概念在现实......
  • Java并发编程之newFixedThreadPool线程池
    随着计算机硬件性能的不断提升,多核CPU的普及,现代计算机系统的性能越来越强大。在这样的环境下,如何更好地利用计算机系统的性能优势,提高程序的运行效率,是每一个Java开发者需要思考的问题。Java中提供了多线程编程的支持,但是在多线程编程中,线程的创建、启动、调度等都需要耗费一定的......
  • java Long 与long转换
    https://blog.51cto.com/u_16213451/7032984概述在Java中,Long是一个包装类,是long的封装类型。Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换。本文将详细介绍如何在Java中实现Long和long之间的转换。流程以下是将Long和long相互转换的流程:步骤描述......
  • Java基于saas模式云MES制造执行系统源码Spring Boot + Hibernate Validation什么是MES
    Java基于saas模式云MES制造执行系统源码SpringBoot+HibernateValidation什么是MES系统?MES制造执行系统,通过互联网技术实现从订单下达到产品完成的整个生产过程进行优化管理。能有效地对生产现场的流程进行智能控制,防错防呆防漏,自动化集成各种制造信息,使管理者准确掌控工......
  • Java 9的模块化系统(JPMS):探讨Java 9引入的模块化系统,并解释其对Java生态的影响
    Java9模块化系统(JPMS)简介Java9模块系统,也被称为Java平台模块系统(JPMS),它是Java9的核心特性之一,用于改进Java的大型应用的封装性和可维护性。 JPMS的主要功能如下: 模块化代码:JPMS允许你将代码库划分为不同的模块,在没有显示声明的情况下,模块内部的类......
  • Java异常处理:共享在设计和实现Java异常处理策略时的最佳实践
    一、概览Java异常处理的最佳实践通常包括以下几个方面:有效使用Java提供的异常类型,创建和使用自定义异常,异常链,异常处理策略,以及记录和传播异常。二、有效使用Java提供的异常类型检查异常(CheckedException):这些异常是在编译阶段就会被检查的异常,通常是预期内的问题......