系统日志/业务日志

This commit is contained in:
cwchen 2024-02-29 10:31:31 +08:00
parent 8e5fc3fe1f
commit 945f5480f6
10 changed files with 331 additions and 19 deletions

View File

@ -1,10 +1,10 @@
package com.securitycontrol.system.api; package com.securitycontrol.system.api;
import com.securitycontrol.common.core.constant.SecurityConstants; import com.securitycontrol.common.core.constant.SecurityConstants;
import com.securitycontrol.common.core.constant.ServiceNameConstants; import com.securitycontrol.common.core.constant.ServiceNameConstants;
import com.securitycontrol.common.core.domain.Result; import com.securitycontrol.common.core.domain.Result;
import com.securitycontrol.system.api.domain.SysLog;
import com.securitycontrol.system.api.domain.SysLogininfor; import com.securitycontrol.system.api.domain.SysLogininfor;
import com.securitycontrol.system.api.domain.SysOperLog; import com.securitycontrol.system.api.domain.SysOperLog;
import com.securitycontrol.system.api.factory.RemoteLogFallbackFactory; import com.securitycontrol.system.api.factory.RemoteLogFallbackFactory;
@ -20,8 +20,7 @@ import org.springframework.web.bind.annotation.RequestHeader;
*/ */
@FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class) @FeignClient(contextId = "remoteLogService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteLogFallbackFactory.class)
public interface RemoteLogService public interface RemoteLogService {
{
/** /**
* 保存系统日志 * 保存系统日志
* *
@ -41,4 +40,16 @@ public interface RemoteLogService
*/ */
@PostMapping("/sys/logs/saveLogininfor") @PostMapping("/sys/logs/saveLogininfor")
public Result<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public Result<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 保存系统日志
* @param sysLog
* @param source
* @return Result<Boolean>
* @description
* @author cwchen
* @date 2024/2/28 17:38
*/
@PostMapping("/sys/sysLog/saveLogs")
public Result<Boolean> saveSysLog(@RequestBody SysLog sysLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
} }

View File

@ -18,10 +18,10 @@ public class SysLog {
@ApiModelProperty(value = "操作ip") @ApiModelProperty(value = "操作ip")
private String ip; private String ip;
@ApiModelProperty(value = "操作人") @ApiModelProperty(value = "操作人ID")
private Integer userId; private Long userId;
@ApiModelProperty(value = "操作人") @ApiModelProperty(value = "操作人姓名")
private String operaUserName; private String operaUserName;
@ApiModelProperty(value = "操作模块") @ApiModelProperty(value = "操作模块")
@ -46,7 +46,7 @@ public class SysLog {
private String operUri; private String operUri;
@ApiModelProperty(value = "日志类型 1 业务日志 0 系统日志 2异常日志") @ApiModelProperty(value = "日志类型 1 业务日志 0 系统日志 2异常日志")
private String logType; private Integer logType;
@ApiModelProperty(value = "执行结果(1.成功/2.失败)") @ApiModelProperty(value = "执行结果(1.成功/2.失败)")
private Integer result; private Integer result;

View File

@ -1,5 +1,6 @@
package com.securitycontrol.system.api.factory; package com.securitycontrol.system.api.factory;
import com.securitycontrol.system.api.domain.SysLog;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
@ -36,6 +37,11 @@ public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogServic
{ {
return Result.fail("日志服务调用失败:" + throwable.getMessage()); return Result.fail("日志服务调用失败:" + throwable.getMessage());
} }
@Override
public Result<Boolean> saveSysLog(SysLog sysLog, String source) {
return Result.fail("日志服务调用失败:" + throwable.getMessage());
}
}; };
} }

View File

@ -0,0 +1,282 @@
package com.securitycontrol.common.log.aspect;
import com.alibaba.fastjson2.JSON;
import com.securitycontrol.common.core.utils.ServletUtils;
import com.securitycontrol.common.core.utils.aes.DateTimeHelper;
import com.securitycontrol.common.core.utils.ip.IpUtils;
import com.securitycontrol.common.log.annotation.Log;
import com.securitycontrol.common.log.enums.BusinessStatus;
import com.securitycontrol.common.log.service.AsyncLogService;
import com.securitycontrol.common.security.utils.SecurityUtils;
import com.securitycontrol.system.api.domain.SysLog;
import com.securitycontrol.system.api.domain.SysUser;
import com.securitycontrol.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.UUID;
/**
* @authorcwchen
* @date2024-02-28-16:47
* @version1.0
* @description日志切面
*/
@Aspect
@Component
@Slf4j
public class OperLogAspect {
private static String[] constantArr;
static {
constantArr = new String[]{"业务日志,系统日志,异常日志"};
}
ThreadLocal<Long> currentTime = new ThreadLocal<>();
@Autowired
private AsyncLogService asyncLogService;
/**
* 设置操作日志切入点 记录操作日志 在注解的位置切入代码
*/
@Pointcut("@annotation(com.securitycontrol.common.log.annotation.Log)")
public void operLogPointCut() {
}
/**
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作
*/
@Pointcut("execution( * com.securitycontrol..*.controller..*(..))")
public void operExceptionLogPointCut() {
}
@Around("operLogPointCut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result;
currentTime.set(System.currentTimeMillis());
//正常处理开始
result = joinPoint.proceed();
//正常处理结束
Long time = System.currentTimeMillis() - currentTime.get();
currentTime.remove();
handleLog(joinPoint, null, result, time);
return result;
}
@AfterThrowing(pointcut = "operExceptionLogPointCut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e, null, null);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult, Long time) {
try {
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
// HttpServletRequest request = RequestHolder.getHttpServletRequest();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
//获取注解
Log aopLog = method.getAnnotation(Log.class);
SysLog sysLog = new SysLog();
// 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser();
if (null != loginUser && null != loginUser.getSysUser()) {
SysUser sysUser = loginUser.getSysUser();
sysLog.setUserId(sysUser.getUserId());
sysLog.setOperaUserName(sysUser.getNickName());
}
String id = UUID.randomUUID().toString().replaceAll("-", "");
sysLog.setLogId(id);
sysLog.setOperUri(request.getRequestURI());
//操作结果 成功/失败
sysLog.setResult(BusinessStatus.SUCCESS.ordinal());
sysLog.setTimes(time + "");
// operLog.setOperUserAgent(CommonUtil.getUserAgent(request));
// 请求的地址
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
sysLog.setIp(ip);
// 返回参数
// sysLog.setOperResponseParam(JSON.toJSONString(jsonResult));
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
//设置请求方法名
sysLog.setMethod(className + "." + methodName + "()");
// 设置请求方式GET..
// operLog.setRequestMethod(request.getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, aopLog, sysLog);
//利用是否有异常定性记录失败信息
if (e != null) {
sysLog.setResult(BusinessStatus.FAIL.ordinal());//失败
sysLog.setFailureReason(e.getClass().getName());
// operLog.setErrorMsg(ThrowableUtil.getStackTrace(e));
log.error("耗时:{} 用户id:{} 用户名username: {} 请求ip:{} User-Agent:{} 方法路径:{} 方法参数:{}",
sysLog.getTimes(),
sysLog.getUserId(),
sysLog.getOperaUserName(),
sysLog.getIp(),
// operLog.getOperUserAgent(),
methodName,
sysLog.getParams());
log.error("==控制层方法通知异常==");
log.error("异常信息:{}", e.getMessage());
//e.printStackTrace();
return;
}
log.info(JSON.toJSONString(sysLog));
// 保存数据库
//可以借助异步持久化AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
log.info("耗时:{} 用户id:{} 用户名username: {} 请求ip:{} User-Agent:{} 方法路径:{} 方法参数:{}",
sysLog.getTimes(),
sysLog.getUserId(),
sysLog.getOperaUserName(),
sysLog.getIp(),
// sysLog.getOperUserAgent(),
methodName,
sysLog.getParams());
asyncLogService.addSaveSysLog(sysLog);
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param log 日志
* @param sysLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysLog sysLog) throws Exception {
if (log != null) {
sysLog.setModel(log.menu());
sysLog.setOperType(log.grade().getInfo());
sysLog.setOperateDetail(log.details());
sysLog.setOperTime(DateTimeHelper.getNowTime());
sysLog.setLogType(Objects.equals(log.type(),constantArr[0]) ? 1 : 0);
} else {
//用于无注解的控制层方法 异常抛出 记录
sysLog.setModel("未知模块");
sysLog.setOperType("未知操作类型");
sysLog.setOperateDetail("未知操作详情");
sysLog.setOperTime(DateTimeHelper.getNowTime());
sysLog.setLogType(3);
}
// 是否需要保存request参数和值
if (log.isSaveRequestData()) {
// 获取参数的信息传入到数据库中
setRequestValue(joinPoint, sysLog);
}
}
/**
* 获取请求的参数放到log中
*
* @param sysLog 操作日志
* @throws Exception 异常
*/
private void setRequestValue(JoinPoint joinPoint, SysLog sysLog) throws Exception {
String params = argsArrayToString(joinPoint.getArgs());
//避免过长的无用信息
sysLog.setParams(StringUtils.substring(params, 0, 2000));
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) {
for (int i = 0; i < paramsArray.length; i++) {
//排除不需要记录的参数
if (!isFilterObject(paramsArray[i])) {
Object value = paramsArray[i];
if (value instanceof MultipartFile) {
MultipartFile file = (MultipartFile) value;
Object jsonObj = JSON.toJSON(file.getOriginalFilename());
params.append(jsonObj.toString()).append(" ");
} else if (value instanceof MultipartFile[]) {
MultipartFile[] files = (MultipartFile[]) value;
for (MultipartFile file : files) {
Object jsonObj = JSON.toJSON(file.getOriginalFilename());
params.append(jsonObj.toString()).append(" ");
}
} else {
Object jsonObj = JSON.toJSON(value);
params.append(jsonObj.toString()).append(" ");
}
}
}
}
return params.toString();
}
/**
* 判断是否需要过滤
*
* @param o 对象信息
* @return 是需要过滤的对象则返回true否则返回false
*/
public boolean isFilterObject(final Object o) {
return o instanceof HttpServletRequest || o instanceof HttpServletResponse;
}
/*
//用于未定义log注解抛出异常也需要记录耗时情况
@Before("operExceptionLogPoinCut()")
public void beforeMethod(JoinPoint joinPoint){
currentTime.set(System.currentTimeMillis());
}
@After("operExceptionLogPoinCut()")
public void afterMethod(JoinPoint joinPoint){
currentTime.remove();
}*/
}

View File

@ -4,6 +4,7 @@ import com.securitycontrol.common.core.constant.SecurityConstants;
import com.securitycontrol.common.core.domain.Result; import com.securitycontrol.common.core.domain.Result;
import com.securitycontrol.system.api.RemoteLogService; import com.securitycontrol.system.api.RemoteLogService;
import com.securitycontrol.system.api.RemoteUserService; import com.securitycontrol.system.api.RemoteUserService;
import com.securitycontrol.system.api.domain.SysLog;
import com.securitycontrol.system.api.domain.SysOperLog; import com.securitycontrol.system.api.domain.SysOperLog;
import com.securitycontrol.system.api.domain.decision.SysUserVo; import com.securitycontrol.system.api.domain.decision.SysUserVo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -44,5 +45,8 @@ public class AsyncLogService {
} }
@Async
public void addSaveSysLog(SysLog sysLog) {
remoteLogService.saveSysLog(sysLog, SecurityConstants.INNER);
}
} }

View File

@ -1,2 +1,2 @@
com.securitycontrol.common.log.service.AsyncLogService com.securitycontrol.common.log.service.AsyncLogService
com.securitycontrol.common.log.aspect.LogAspect com.securitycontrol.common.log.aspect.OperLogAspect

View File

@ -32,7 +32,7 @@ public class HeaderInterceptor implements AsyncHandlerInterceptor
SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME)); SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME));
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY)); SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY));
String token = SecurityUtils.getTokenFromParams(); String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token)) if (StringUtils.isNotEmpty(token))
{ {
LoginUser loginUser = AuthUtil.getLoginUser(token); LoginUser loginUser = AuthUtil.getLoginUser(token);

View File

@ -3,8 +3,12 @@ package com.securitycontrol.system.base.controller;
import com.securitycontrol.common.core.web.controller.BaseController; import com.securitycontrol.common.core.web.controller.BaseController;
import com.securitycontrol.common.core.web.domain.AjaxResult; import com.securitycontrol.common.core.web.domain.AjaxResult;
import com.securitycontrol.common.core.web.page.TableDataInfo; import com.securitycontrol.common.core.web.page.TableDataInfo;
import com.securitycontrol.common.log.annotation.Log;
import com.securitycontrol.common.log.enums.OperationType;
import com.securitycontrol.common.security.utils.SecurityUtils;
import com.securitycontrol.entity.system.dto.RoleDto; import com.securitycontrol.entity.system.dto.RoleDto;
import com.securitycontrol.entity.system.vo.RoleVo; import com.securitycontrol.entity.system.vo.RoleVo;
import com.securitycontrol.system.api.model.LoginUser;
import com.securitycontrol.system.base.service.IRoleService; import com.securitycontrol.system.base.service.IRoleService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -28,6 +32,7 @@ public class RoleController extends BaseController {
@ApiOperation(value = "获取角色列表") @ApiOperation(value = "获取角色列表")
@GetMapping("getRoleLists") @GetMapping("getRoleLists")
@Log(title = "系统管理", menu = "系统管理->角色管理", grade = OperationType.QUERY_SYS, details = "查询角色", type = "系统日志")
public TableDataInfo getRoleLists(RoleDto dto) { public TableDataInfo getRoleLists(RoleDto dto) {
startPage(); startPage();
List<RoleVo> list = service.getRoleLists(dto); List<RoleVo> list = service.getRoleLists(dto);
@ -36,12 +41,14 @@ public class RoleController extends BaseController {
@ApiOperation(value = "新增角色") @ApiOperation(value = "新增角色")
@PostMapping("addRole") @PostMapping("addRole")
@Log(title = "系统管理", menu = "系统管理->角色管理", grade = OperationType.ADD_SYS, details = "新增角色", type = "系统日志")
public AjaxResult addRole(@Valid @RequestBody RoleVo vo){ public AjaxResult addRole(@Valid @RequestBody RoleVo vo){
return service.addOrUpdateRole(vo); return service.addOrUpdateRole(vo);
} }
@ApiOperation(value = "修改角色") @ApiOperation(value = "修改角色")
@PostMapping("editRole") @PostMapping("editRole")
@Log(title = "系统管理", menu = "系统管理->角色管理", grade = OperationType.UPDATE_SYS, details = "修改角色", type = "系统日志")
public AjaxResult editRole(@Valid @RequestBody RoleVo vo){ public AjaxResult editRole(@Valid @RequestBody RoleVo vo){
return service.addOrUpdateRole(vo); return service.addOrUpdateRole(vo);
} }
@ -54,12 +61,14 @@ public class RoleController extends BaseController {
@ApiOperation(value = "删除角色") @ApiOperation(value = "删除角色")
@PostMapping("delRole") @PostMapping("delRole")
@Log(title = "系统管理", menu = "系统管理->角色管理", grade = OperationType.DELETE_SYS, details = "删除角色", type = "系统日志")
public AjaxResult delRole(RoleDto dto){ public AjaxResult delRole(RoleDto dto){
return service.delRole(dto); return service.delRole(dto);
} }
@ApiOperation(value = "角色授权菜单") @ApiOperation(value = "角色授权菜单")
@PostMapping("authMenu") @PostMapping("authMenu")
@Log(title = "系统管理", menu = "系统管理->角色管理", grade = OperationType.ADD_SYS, details = "角色授权", type = "系统日志")
public AjaxResult authMenu(@RequestBody RoleVo vo){ public AjaxResult authMenu(@RequestBody RoleVo vo){
return service.authMenu(vo); return service.authMenu(vo);
} }

View File

@ -3,7 +3,7 @@ package com.securitycontrol.system.controller;
import com.securitycontrol.common.core.web.controller.BaseController; import com.securitycontrol.common.core.web.controller.BaseController;
import com.securitycontrol.common.core.web.domain.AjaxResult; import com.securitycontrol.common.core.web.domain.AjaxResult;
import com.securitycontrol.common.log.annotation.Log; import com.securitycontrol.common.log.annotation.Log;
import com.securitycontrol.common.log.enums.BusinessType; import com.securitycontrol.common.log.enums.OperationType;
import com.securitycontrol.entity.system.dto.MenuDto; import com.securitycontrol.entity.system.dto.MenuDto;
import com.securitycontrol.entity.system.vo.MenuVo; import com.securitycontrol.entity.system.vo.MenuVo;
import com.securitycontrol.system.service.MenuService; import com.securitycontrol.system.service.MenuService;
@ -26,21 +26,21 @@ public class MenuController extends BaseController {
@ApiOperation(value = "获取菜单列表") @ApiOperation(value = "获取菜单列表")
@GetMapping("getMenuList") @GetMapping("getMenuList")
@Log(title = "系统管理", menu = "系统管理->菜单管理", businessType = BusinessType.QUERY, details = "查询菜单", type = "系统日志") @Log(title = "系统管理", menu = "系统管理->菜单管理", grade = OperationType.QUERY_SYS, details = "查询菜单", type = "系统日志")
public AjaxResult getMenuList(MenuDto dto) { public AjaxResult getMenuList(MenuDto dto) {
return service.getMenuList(dto); return service.getMenuList(dto);
} }
@ApiOperation(value = "新增菜单") @ApiOperation(value = "新增菜单")
@PostMapping("addMenu") @PostMapping("addMenu")
@Log(title = "系统管理", menu = "系统管理->菜单管理", businessType = BusinessType.INSERT, details = "新增菜单", type = "系统日志") @Log(title = "系统管理", menu = "系统管理->菜单管理", grade = OperationType.ADD_SYS, details = "新增菜单", type = "系统日志")
public AjaxResult addMenu(@Valid @RequestBody MenuVo vo){ public AjaxResult addMenu(@Valid @RequestBody MenuVo vo){
return service.addOrUpdateMenu(vo); return service.addOrUpdateMenu(vo);
} }
@ApiOperation(value = "修改菜单") @ApiOperation(value = "修改菜单")
@PostMapping("editMenu") @PostMapping("editMenu")
@Log(title = "系统管理", menu = "系统管理->菜单管理", businessType = BusinessType.UPDATE, details = "修改菜单", type = "系统日志") @Log(title = "系统管理", menu = "系统管理->菜单管理", grade = OperationType.UPDATE_SYS, details = "修改菜单", type = "系统日志")
public AjaxResult editMenu(@Valid @RequestBody MenuVo vo){ public AjaxResult editMenu(@Valid @RequestBody MenuVo vo){
return service.addOrUpdateMenu(vo); return service.addOrUpdateMenu(vo);
} }
@ -53,7 +53,7 @@ public class MenuController extends BaseController {
@ApiOperation(value = "删除菜单") @ApiOperation(value = "删除菜单")
@PostMapping("delMenu") @PostMapping("delMenu")
@Log(title = "系统管理", menu = "系统管理->菜单管理", businessType = BusinessType.DELETE, details = "删除菜单", type = "系统日志") @Log(title = "系统管理", menu = "系统管理->菜单管理", grade = OperationType.DELETE_SYS, details = "删除菜单", type = "系统日志")
public AjaxResult delMenu(MenuDto dto){ public AjaxResult delMenu(MenuDto dto){
return service.delMenu(dto); return service.delMenu(dto);
} }

View File

@ -4,7 +4,7 @@
<!--保存系统日志--> <!--保存系统日志-->
<insert id="saveLogs"> <insert id="saveLogs">
INSERT INTO sys_role INSERT INTO sys_logs
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
<if test="logId != null and logId != ''">log_id,</if> <if test="logId != null and logId != ''">log_id,</if>
<if test="ip != null and ip!=''">ip,</if> <if test="ip != null and ip!=''">ip,</if>
@ -28,8 +28,8 @@
<if test="logId != null and logId != ''">#{logId},</if> <if test="logId != null and logId != ''">#{logId},</if>
<if test="ip != null and ip!=''">#{ip},</if> <if test="ip != null and ip!=''">#{ip},</if>
<if test="userId != null">#{userId},</if> <if test="userId != null">#{userId},</if>
<if test="operaUserName != null and operaUserName!=''">#{operaUserName},</if>
<if test="model != null and model!=''">#{model},</if> <if test="model != null and model!=''">#{model},</if>
<if test="operaUserName != null and operaUserName!=''">#{operaUserName},</if>
<if test="operTime != null and operTime!=''">#{operTime},</if> <if test="operTime != null and operTime!=''">#{operTime},</if>
<if test="method != null and method!=''">#{method},</if> <if test="method != null and method!=''">#{method},</if>
<if test="params != null and params!=''">#{params},</if> <if test="params != null and params!=''">#{params},</if>