通过自定义注解查询访问接口IP并初始化到数据库

本文介绍了一种使用自定义注解和AOP技术记录接口访问日志的方法,详细展示了如何获取客户端IP地址、请求URL和类型等信息,并将其初始化到数据库的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义注解获取访问接口的IP地址并初始化到数据库

这是所要引用的包
import com.alibaba.fastjson.JSON;
import com.common.annotation.SystemLogger;
import com.common.utils.TimeHelper;
import com.restful.admin.mapper.OperateLogMapper;-- 这是mybatis自动生成的文件导入的包,方便编写初始化到数据库 ,没用mybatis的可以用JDBC等方式写入
import com.restful.admin.mapper.domain.OperateLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Aspect // AOP切面
@Component
public class SystemLogAction {

@Resource
private OperateLogMapper operateLogMapper; 逆向工程mapper文件


/**
 * 切控制器记录指定用户操作日志
 * 配置接入点:第一个”*“符号表示返回值的类型任意,包名后面的”..“表示当前包及子包,
 * 第二个”*“表示类名,*即所有类,.*(..)表示任何方法名,括号表示参数,两个点表示任何参数类型
 */
@Pointcut("execution(* com.restful.admin.controller..*.*(..))")
private void controllerAspect() {}

/**
 * @explain: 环绕通知:灵活自由的在目标方法中切入代码
 * @author: MR.Li
 * @version: 1.0.0
 * @date: 2020/4/3 0003 10:49
 * @param: [joinPoint]
 * @return: void
 */
@Around("controllerAspect()") // 环绕通知切面
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    Object object = joinPoint.proceed();
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    ServletRequest servletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

    // 获取当前客户端的IP地址
    String ip = servletRequest.getRemoteAddr();

    // 获取请求URL
    String requestUrl = request.getRequestURL().toString();

    // 获取请求类型
    String requestType = request.getMethod();

    // 拦截的实体类,就是当前正在执行的controller
    Object target = joinPoint.getTarget();

    // 拦截的方法名称。当前正在执行的方法
    String methodName = joinPoint.getSignature().getName();

    // 拦截的方法参数
    Object[] args = joinPoint.getArgs();

    // 拦截的方法参数类型
    Signature sig = joinPoint.getSignature();
    MethodSignature msig = null;
    if (!(sig instanceof MethodSignature)) {
        throw new IllegalArgumentException("该注解只能用于方法");
    }
    msig = (MethodSignature) sig;
    Class[] parameterTypes = msig.getMethod().getParameterTypes();

    System.err.println(String.format("url=%s, requestType=%s, methodName=%s, param=%s, ip=%s", requestUrl, requestType, methodName, 0 == args.length ? "无" : args[0], ip));

    // 获得被拦截的方法
    Method method = null;
    try {
        method = target.getClass().getMethod(methodName, parameterTypes);
    } catch (NoSuchMethodException e1) {
        e1.printStackTrace();
    } catch (SecurityException e1) {
        e1.printStackTrace();
    }

    if (null != method) {
        // 判断是否包含自定义注解,不包含则不执行以下代码块
        if (method.isAnnotationPresent(SystemLogger.class)) {
            // 记录系统日志
            recordSystemLogger(joinPoint, method.getDeclaredAnnotation(SystemLogger.class));
        }
    }

    // 执行源方法
    return object;
}

/**
 * @explain: 记录系统日志(将数据保存到数据库中)
 * @author: MR.Li
 * @version: 1.0.0
 * @date: 2020/4/3 0003 10:49
 * @param: [joinPoint]
 * @return: void
 */
private void recordSystemLogger(ProceedingJoinPoint joinPoint, SystemLogger systemLogger) {
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    ServletRequest servletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

    // 创建保存日志信息的对象,并封装相应信息
    OperateLog operateLog = new OperateLog(); // mybatis生成的数据库表对象
    operateLog.setMemberIp(servletRequest.getRemoteAddr()); // 获取当前客户端的IP地址
    operateLog.setRequestType(request.getMethod()); // 获取请求类型
    operateLog.setUrl(request.getRequestURL().toString()); // 获取请求URL
    operateLog.setMethods(joinPoint.getSignature().getName()); // 当前正在执行的方法名称
    operateLog.setParam(JSON.toJSONString(0 == joinPoint.getArgs().length ? "无" : joinPoint.getArgs()[0])); // 拦截的方法参数
    operateLog.setModule(systemLogger.module());
    operateLog.setBusDesc(systemLogger.value());
    operateLog.setLogType(0);
    operateLog.setCreateTime(TimeHelper.time());

    // 保存系统日志信息
    this.operateLogMapper.insertSelective(operateLog);
}

}

=============================华丽的分割线 编写自定义注解
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLogger {

/** 接口业务描述 */
String value() default "";

/** 模块名 */
String module() default "";

}

编写完成之后在controller层位置编写注解即可,例如:
@restController
@requestMapping(“/test”)
@SystemLogger(“编写业务描述”,“接口模块”); // 此处即为我们刚编写的自定义注解,每当访问此接口,就会自动拦截ip和此业务接口名称保存到数据库
public ResultInfo getTestOneController(@RequestBody ){
return XXXX;// 接口业务根据自己所需编写 此处只为示例而已
}

------- 新手发博 ,没写好的请大神多指教更改 谢谢 O(∩_∩)O

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值