自定义注解获取访问接口的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