【Aop+自定义注解实现日志插入】

文章介绍了如何在Java中使用AOP技术,结合自定义注解AutoApiLog,实现在业务方法执行前后自动插入日志。同时展示了如何在切面中获取参数、执行结果和用户信息,用于生成详细的接口调用日志。

Aop+自定义注解实现日志插入


1.自定义注解AutoApiLog

package org.jeecg.modules.dataark.aspect.annotation;

import java.lang.annotation.*;

/**
 * 系统日志注解
 * 
 * @Author scott
 * @email jeecgos@163.com
 * @Date 2019年1月14日
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoApiLog {

	/**
	 * 调用接口编码
	 * 
	 * @return
	 */
	String apiCode() default "";
	/**
	 * 业务类型编码
	 *
	 * @return
	 */
	String businessCode() default "";
	/**
	 * 业务类型名称
	 *
	 * @return
	 */
	String businessName() default "";

2.自定义Aop切面

```java
package org.jeecg.modules.dataark.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
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.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.constart.OperateConstant;
import org.jeecg.modules.dataark.aspect.annotation.AutoApiLog;
import org.jeecg.common.operate.entity.YwDataarkApiLog;
import org.jeecg.modules.dataark.service.IYwDataarkApiLogService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;


/**
 * DataArk接口调用日志,切面处理类
 *
 * @Author scott
 * @email jeecgos@163.com
 * @Date 2018年1月14日
 */
@Slf4j
@Aspect
@Component
public class AutoApiLogAspect {

    @Resource
    private IYwDataarkApiLogService apiLogService;

    @Pointcut("@annotation(org.jeecg.modules.dataark.aspect.annotation.AutoApiLog)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        //long beginTime = System.currentTimeMillis();
        // 接口开始执行时间
        Date startTime=new Date();
        //执行方法
        Object result = point.proceed();
        // 接口执行完成时间
        Date endTime=new Date();
        //执行时长(毫秒)
        //long time = System.currentTimeMillis() - beginTime;

        //保存日志
        saveSysLog(point,result,startTime,endTime);

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, Object result,Date startTime,Date endTime) throws NoSuchMethodException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        YwDataarkApiLog dto = new YwDataarkApiLog();
        AutoApiLog syslog = method.getAnnotation(AutoApiLog.class);
        if(syslog != null){
            //update-begin-author:taoyan date:
            // 调用接口编码
            String apiCode=syslog.apiCode();
            // 业务类型编码
            String businessCode=syslog.businessCode();
            // 业务类型名称
            String businessName=syslog.businessName();
            //注解上的描述,操作日志内容
            dto.setApiCode(apiCode);
            dto.setBusinessCode(businessCode);
            dto.setBusinessName(businessName);
        }
        // 获取请求参数
        JSONObject params=myAdvice(joinPoint);
        String paramsString=JSONObject.toJSONString(params);
        dto.setApiParam(paramsString);
        // 获取业务id
        String businessId=params.getString("businessId");
        dto.setBusinessId(businessId);
        try {
            //Object object=joinPoint.proceed();
            //获取方法返回值处理
            String objectString=JSONObject.toJSONString(result);
            dto.setApiReturn(objectString);
            log.info("返回值="+result);
            dto.setApiStatus(OperateConstant.FAIL);
            if(ObjectUtils.isNotEmpty(result) ){
                JSONObject res= JSON.parseObject(objectString);
                if("success".equals(res.getString("result"))){
                    dto.setApiStatus(OperateConstant.SUCCESS);
                }
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //获取登录用户信息
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(sysUser!=null){
            dto.setSysOrgCode(sysUser.getOrgCode());
            dto.setCreateBy(sysUser.getUsername());
            dto.setUpdateBy(sysUser.getUsername());
        }
        dto.setStartTime(startTime);
        dto.setEndTime(endTime);
        //保存日志
        apiLogService.saveData(dto);
    }
    public JSONObject myAdvice(JoinPoint joinPoint)  {
        JSONObject json=new JSONObject();
        Object[] args = joinPoint.getArgs(); // 获取参数列表
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod(); // 获取目标方法
        Parameter[] parameters = method.getParameters(); // 获取方法的参数信息
        for (int i=0; i<args.length; i++) {
            String paramName = parameters[i].getName(); // 获取参数名
            log.info("参数名:" + paramName);
            log.info("参数值:" + args[i]);
            json.put(paramName,args[i]);
        }
        return json;
    }

}

}

3.业务方法调用

```java
package org.jeecg.modules.common.component;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.tripartite.api.ITripartiteBaseAPI;
import org.jeecg.common.tripartite.vo.dataArk.MrsDatabaseSchemaVo;
import org.jeecg.common.tripartite.vo.dataArk.PrivilegesDwsGussdbParam;
import org.jeecg.common.tripartite.vo.dataArk.SyncLinkVo;
import org.jeecg.modules.common.config.DataArkConfig;
import org.jeecg.modules.dataark.aspect.annotation.AutoApiLog;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 开发场景调用dataark接口日志记录
 */
@Component
@Slf4j
public class SceneApiComponent {

    @Resource
    public ITripartiteBaseAPI tripartiteBaseAPI;

    @AutoApiLog(apiCode="scene_empower_createWorkspaces",businessCode="scene_empower",businessName="场景授权")
    public JSONObject apiWorkspacesAdd(String businessId, String name, String desc) {
        // 具体实现逻辑
        return null;
    }
    



}
### 通过AOP结合自定义注解实现TCP数据传输功能 在Java中,AOP(面向切面编程)通常用于将横切关注点(如日志记录、事务管理、安全控制等)与业务逻辑分离。对于TCP数据传输这样的场景,可以利用Spring AOP自定义注解来封装网络通信的细节,使得业务代码更加简洁,并提高可维护性。 #### 1. 自定义注解设计 首先,定义一个自定义注解,用于标记需要进行TCP传输的方法。该注解可以包含一些配置参数,例如目标主机、端口、超时时间等。 ```java @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface TcpTransmission { String host() default "localhost"; int port() default 8080; int timeout() default 5000; } ``` #### 2. 实现TCP客户端逻辑 接下来,编写一个基于`Socket`的TCP客户端类,用于处理实际的数据发送和接收。这个类可以通过依赖注入的方式被AOP切面所使用。 ```java @Component public class TcpClient { public String sendData(String host, int port, String message, int timeout) throws IOException { try (Socket socket = new Socket()) { socket.connect(new InetSocketAddress(host, port), timeout); socket.setSoTimeout(timeout); // 发送数据 OutputStream out = socket.getOutputStream(); out.write(message.getBytes(StandardCharsets.UTF_8)); out.flush(); // 接收响应 InputStream in = socket.getInputStream(); byte[] buffer = new byte[1024]; int bytesRead = in.read(buffer); return new String(buffer, 0, bytesRead, StandardCharsets.UTF_8); } } } ``` #### 3. 编写AOP切面 然后,创建一个切面类,用于拦截带有`@TcpTransmission`注解的方法,并在其执行前后插入TCP传输逻辑。可以通过获取注解中的参数来动态设置连接信息。 ```java @Aspect @Component public class TcpTransmissionAspect { @Autowired private TcpClient tcpClient; @Around("@annotation(tcpTransmission)") public Object handleTcpTransmission(ProceedingJoinPoint joinPoint, TcpTransmission tcpTransmission) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 获取方法参数 Object[] args = joinPoint.getArgs(); // 构建请求内容(可以根据业务需求定制) String requestMessage = buildRequestMessage(method, args); // 执行TCP传输 String response = tcpClient.sendData(tcpTransmission.host(), tcpTransmission.port(), requestMessage, tcpTransmission.timeout()); // 解析响应并返回结果(根据实际情况处理) return parseResponse(response); } private String buildRequestMessage(Method method, Object[] args) { // 可以使用JSON序列化等方式构建请求体 StringBuilder sb = new StringBuilder(); sb.append("Method: ").append(method.getName()).append("\n"); for (int i = 0; i < args.length; i++) { sb.append("Arg[").append(i).append("]: ").append(args[i].toString()).append("\n"); } return sb.toString(); } private Object parseResponse(String response) { // 根据响应格式解析为特定对象或直接返回字符串 return response; } } ``` #### 4. 在业务方法上使用自定义注解 最后,在需要进行TCP传输的业务方法上添加`@TcpTransmission`注解,并指定相关参数。 ```java @Service public class BusinessService { @TcpTransmission(host = "192.168.1.100", port = 9090, timeout = 3000) public String performRemoteOperation(String param1, int param2) { // 这里可以不实际执行任何本地操作,而是通过AOP触发远程调用 return null; // 返回值由AOP切面处理 } } ``` #### 5. 配置Spring AOP支持 确保你的Spring Boot项目已经启用了AOP支持。通常情况下,只需引入以下依赖即可自动启用: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` #### 6. 测试与验证 启动应用后,调用`BusinessService#performRemoteOperation`方法,观察是否能够正确地通过TCP协议向指定的目标发送请求并接收响应。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值