县网站建设检查情况汇报,财务软件单机版,添加网站备案号链接,手机怎么制作自己的网站介绍
我们在日常开发工作中#xff0c;肯定逃不开与日志接触#xff0c;一些比较严谨的后台管理系统里面会涉及到一些比较重要的资料#xff0c;有些公司为了知道有哪些人登录了系统#xff0c;是谁在什么时候修改了用户信息或者资料#xff0c;所以就有了操作日志这么个…介绍
我们在日常开发工作中肯定逃不开与日志接触一些比较严谨的后台管理系统里面会涉及到一些比较重要的资料有些公司为了知道有哪些人登录了系统是谁在什么时候修改了用户信息或者资料所以就有了操作日志这么个需求。
此文章介绍的是SpringBoot下如何通过注解的形式实现操作日志仅供学习参考不喜勿喷。
具体实现
pom依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!--aspectj依赖--dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.2.25.RELEASE/version/dependency!--swagger依赖--dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.8.0/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-ui/artifactIdversion2.8.0/version/dependency!--工具依赖--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.9/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion2.0.32/version/dependency代码实现
系统日志注解
/**
* 系统日志注解
*
*/
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
Documented
public interface SysOperateLog {//用户操作String value();//保存入参boolean isSaveParams() default true;//保存返回结果boolean isSaveResult() default false;//异常信息boolean isRecordError() default false;//忽略属性String [] ignoreFields() default {};}切面处理类
/**
* 系统日志切面处理类
*/
Component
Aspect
public class SysLogAspect {private static final Logger logger LoggerFactory.getLogger(SysLogAspect.class);Resourceprivate SysLogService sysLogService;// 定义切点,被SysOperateLog注解标注的方法作为切点Pointcut(annotation(com.ou.common.annotation.SysOperateLog))public void logPointCut() {}Around(logPointCut())public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime System.currentTimeMillis();//执行方法Object result null;try {result point.proceed();} catch (Throwable throwable) {//异常日志记录MethodSignature signature (MethodSignature) point.getSignature();Method method signature.getMethod();SysOperateLog syslog method.getAnnotation(SysOperateLog.class);if(syslog ! null syslog.isRecordError()){//执行时长(毫秒)long time System.currentTimeMillis() - beginTime;result 异常返回 throwable.getMessage();sysLogService.aopTransactionalSysLog(point,error!!, time);}throw throwable;}//执行时长(毫秒)long time System.currentTimeMillis() - beginTime;//保存日志sysLogService.aopSysLog(point,result, time);return result;}}过滤器
public class FastJsonByteArrayValueFilter implements ValueFilter {public FastJsonByteArrayValueFilter() {}public Object process(Object object, String name, Object value) {try {if (value null) {return value;}Field declaredField object.getClass().getDeclaredField(name);Class? type declaredField.getType();if (type.toString().equals(class [B)) {return null;}} catch (NoSuchFieldException var6) {}return value;}
}日志实体类
/*** 系统操作日志实体类*/
Data
EqualsAndHashCode(callSuper false)
Accessors(chain true)
ApiModel(value SysLog对象, description 系统操作日志)
public class SysLog implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 日志主键ID)private String id;ApiModelProperty(value 用户ID)private String userId;private String userName;ApiModelProperty(value 用户操作)private String operation;ApiModelProperty(value 请求方法)private String method;private String params;private String result;ApiModelProperty(value 执行时长)private Long time;ApiModelProperty(value IP地址)private String ip;ApiModelProperty(value 逻辑删除标志0正常1删除)private Integer delFlag;ApiModelProperty(value 创建人)private String createUser;ApiModelProperty(value 创建时间)private Date createTime;ApiModelProperty(value 更新人)private String updateUser;ApiModelProperty(value 更新时间)private Date updateTime;}业务层接口
/**
* 系统操作日志
*/
public interface SysLogService{void aopTransactionalSysLog(ProceedingJoinPoint joinPoint, Object result, long time);void aopSysLog(ProceedingJoinPoint joinPoint, Object result, long time);
}
业务层实现类
/**
* 系统操作日志 服务实现类
*/
Service
public class SysLogServiceImpl implements SysLogService {private static final Logger logger LoggerFactory.getLogger(SysLogServiceImpl.class);//MediumTextprivate static final int MAX_BTYE_LENGTH 16777215;//Transactional(propagation Propagation.REQUIRES_NEW,rollbackFor Exception.class)Overridepublic void aopTransactionalSysLog(ProceedingJoinPoint joinPoint, Object result, long time){aopSysLog(joinPoint,result,time);}/*** ProceedingJoinPoint继承了JoinPoint* JoinPoint.getSignature() 获取到了方法的【修饰符 包名 组件名(类名) 方法】*/Overridepublic void aopSysLog(ProceedingJoinPoint joinPoint, Object result, long time) {MethodSignature signature (MethodSignature) joinPoint.getSignature();Method method signature.getMethod();SysLog sysLog new SysLog();//这里我是用UUID来模仿ID可自行设置//sysLog.setId(UUIDCreater.create());SysOperateLog sysOperateLog method.getAnnotation(SysOperateLog.class);boolean isSaveResult false;boolean isSaveParams false;if(sysOperateLog ! null){//注解上的描述sysLog.setOperation(sysOperateLog.value());isSaveResult sysOperateLog.isSaveResult();isSaveParams sysOperateLog.isSaveParams();}//请求的方法名String className joinPoint.getTarget().getClass().getName();String methodName signature.getName();String[] parameterNames signature.getParameterNames();// 设置 com.ou.controller.SysLogController.testParam(map)sysLog.setMethod(className . methodName ( StringUtils.join(parameterNames,,)));try{//保存参数信息if(isSaveParams){Object[] args joinPoint.getArgs();StringBuffer params new StringBuffer();for(int i 0 ; i args.length; i){if(args[i] instanceof ServletResponse){continue;}else if(args[i] instanceof Class){continue;}else if(args[i] instanceof byte[]){continue;} else if(args[i] instanceof ServletRequest){ServletRequest request (ServletRequest)args[i];params.append(JSON.toJSONString(request.getParameterMap()));}else {Object json JSON.toJSON(args[i]);String jsonString JSON.toJSONString(json, new ValueFilter[]{new FastJsonByteArrayValueFilter()});params.append(jsonString);}if(i args.length - 1){params.append(; );}}byte[] paramsBytes params.toString().getBytes();if(paramsBytes.length MAX_BTYE_LENGTH){byte[] subBytes new byte[MAX_BTYE_LENGTH];System.arraycopy(paramsBytes, 0, subBytes, 0, MAX_BTYE_LENGTH);sysLog.setParams(new String(subBytes));}else{sysLog.setParams(params.toString());}}//保存返回结果if(isSaveResult result ! null){Object json JSON.toJSON(result);String[] ignoreFields sysOperateLog.ignoreFields();if(ignoreFields.length 0){if(json instanceof JSONObject){JSONObject jsonObject (JSONObject) json;for(String field : ignoreFields){jsonObject.remove(field);}}else if(json instanceof JSONArray){JSONArray jsonArray (JSONArray) json;for(Object obj : jsonArray){if(obj instanceof JSONObject){JSONObject jsonObject (JSONObject) obj;for(String field : ignoreFields){jsonObject.remove(field);}}}}}String transferResult JSON.toJSONString(json, new ValueFilter[]{new FastJsonByteArrayValueFilter()});byte[] transferResultBytes transferResult.toString().getBytes();if(transferResultBytes.length MAX_BTYE_LENGTH){byte[] subBytes new byte[MAX_BTYE_LENGTH];System.arraycopy(transferResultBytes, 0, subBytes, 0, MAX_BTYE_LENGTH);sysLog.setResult(new String(subBytes));}else{sysLog.setResult(transferResult);}}try {//获取requestHttpServletRequest request HttpContextUtils.getHttpServletRequest();//设置IP地址sysLog.setIp(IPUtils.getIpAddr(request));} catch (Exception e) {}sysLog.setTime(time);//保存系统日志--这里是打印logger.info(系统日志:{},JSONObject.toJSONString(sysLog));}catch (Exception e){logger.error(系统日志记录失败,e);}}
}工具类
public class HttpContextUtils {public static HttpServletRequest getHttpServletRequest() {return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();}
}/**
* 获取IP地址的工具类
*/
public class IPUtils {private static Logger logger LoggerFactory.getLogger(IPUtils.class);/*** 获取IP地址*/public static String getIpAddr(HttpServletRequest request) {String ip null;try {ip request.getHeader(x-forwarded-for);if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {ip request.getHeader(Proxy-Client-IP);}if (StringUtils.isEmpty(ip) || ip.length() 0 || unknown.equalsIgnoreCase(ip)) {ip request.getHeader(WL-Proxy-Client-IP);}if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {ip request.getHeader(HTTP_CLIENT_IP);}if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {ip request.getHeader(HTTP_X_FORWARDED_FOR);}if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {ip request.getRemoteAddr();}} catch (Exception e) {logger.error(IPUtils ERROR , e);}return ip;}}
Controller接口 RestController
RequestMapping(/sys/log)
public class SysLogController {/*** 触发操作日志*/SysOperateLog(触发-操作日志接口-不带参数)RequestMapping(/test)public String test() {return OK;}/*** 触发操作日志*/SysOperateLog(触发-操作日志接口-带参数)RequestMapping(/testParam)public String testParam(RequestBody Map map) {return OK;}
}测试 控制台输出 系统日志:{id:9e088286efe64183aa5992f30a8aa34b,ip:127.0.0.1,method:com.ou.controller.SysLogController.testParam(map),operation:触发-操作日志接口-带参数,params:{\sex\:\男\,\name\:\张三\,\age\:18,\desc\:\描述啊啊啊\},time:10}我这里是直接输出日志具体怎么存库还是由各自的业务来进行修改。
--------END