ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量
在HandlerInterceptor的preHandle 中可以截取crud等操作的一些url
public class PlatformLogInterceptor implements HandlerInterceptor { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired UserService userService; @Autowired PlatformLogService platformLogService; @Autowired FunctionService functionService; @Override public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse response, Object handler) throws Exception { try{ String types = httpRequest.getHeader("Accept"); String uri = httpRequest.getRequestURI();//请求uri PlatformLog platformLog = new PlatformLog(); if(uri.toLowerCase().matches("[\\s\\S]*((del)|(update)|(insert)|(add)|(publish)|(export)|(import)|(upload)|(create)|(process)|(audit))[\\s\\S]*")) { Function function = getFunction(uri); //获取uri对应功能详情 String userId =(String) httpRequest.getAttribute("token_userId");//userId String ipAddr = getIpAddr(httpRequest);// 用户ip地址 User user = userService.findByUesrId(Long.valueOf(""+userId)); /*************************设置日志项**************************/ platformLog.setParamJson(JSONObject.fromObject(httpRequest.getParameterMap()).toString()); if(function!=null){ platformLog.setMethodName(function.getFuncName()); }else{ platformLog.setMethodName(uri); } platformLog.setOptionIp(ipAddr); platformLog.setOptionTime(new Date()); platformLog.setOptionUser(Long.valueOf(userId)); platformLog.setOptionUserGroupName(user.getGroupName()); platformLog.setOptionUserName(user.getName()); platformLog.setRelatedId(user.getUserId()); platformLog.setTenantId(user.getTenantId()); platformLog.setOrgId(user.getGroupId()); PlatformLog.setPlatformLog(platformLog);// put it into threadLocal } return true; }catch (Exception e){ PlatformLog.removePlatformLog(); return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // do nothing } @Override public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) throws Exception { // do nothing } private String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } private Function getFunction(String funcURl){ try { List<Function> functions = functionService.findAll(); for(Function f:functions){ if(f.getFuncURl().equals(funcURl)){ return f; } } } catch (Exception e) { // e.printStackTrace(); return null; } return null; }
spring配置
<bean id="wsLogInterceptor" class="。。。。。。.interceptor.PlatformLogInterceptor"/> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <ref bean="wsLogInterceptor"/> </mvc:interceptor> </mvc:interceptors>
在这里不能直接去记录操作的platformLog 定义的platformlog 将要记录的日志放入ThreadLocal中 ThreadLocal调用get方法前 必须调用set方法
public class PlatformLog implements Serializable { /** * */ private static final long serialVersionUID = 1L; private static final ThreadLocal<PlatformLog> PLATFORM_LOG_THREAD_LOCAL = new ThreadLocal<>(); private Integer id; private String methodName;//方法名 private String paramJson;//参数json private String resultJson;//修改后的对象json private Long relatedId;//相关ID private String relatedChar;//相关字符 private Long optionUser;//操作用户 private String optionIp;//操作Ip private String dataCode;//返回的code码 private Date optionTime;//操作时间 private Long tenantId;//日志租户(获取操作用户) private Long orgId;//orgId private String optionUserName;//操作用户名 private String optionUserGroupName;//操作用户组 private List<Object> thParamName=new ArrayList<Object>();//表头名称 private List<Object> tdParamData=new ArrayList<Object>();//值 private List<Object> thResultName=new ArrayList<Object>(); private List<Object> tdResulData=new ArrayList<Object>();//值 private List<LogValue> logValues=new ArrayList<LogValue>();//值 public String getOptionIp() { return optionIp; } public void setOptionIp(String optionIp) { this.optionIp = optionIp; } public String getOptionUserName() { return optionUserName; } public void setOptionUserName(String optionUserName) { this.optionUserName = optionUserName; } public String getOptionUserGroupName() { return optionUserGroupName; } public void setOptionUserGroupName(String optionUserGroupName) { this.optionUserGroupName = optionUserGroupName; } public List<LogValue> getLogValues() { return logValues; } public void setLogValues(List<LogValue> logValues) { this.logValues = logValues; } public List<Object> getThParamName() { return thParamName; } public void setThParamName(List<Object> thParamName) { this.thParamName = thParamName; } public List<Object> getThResultName() { return thResultName; } public void setThResultName(List<Object> thResultName) { this.thResultName = thResultName; } public List<Object> getTdParamData() { return tdParamData; } public void setTdParamData(List<Object> tdParamData) { this.tdParamData = tdParamData; } public List<Object> getTdResulData() { return tdResulData; } public void setTdResulData(List<Object> tdResulData) { this.tdResulData = tdResulData; } public Long getRelatedId() { return relatedId; } public void setRelatedId(Long relatedId) { this.relatedId = relatedId; } public String getRelatedChar() { return relatedChar; } public void setRelatedChar(String relatedChar) { this.relatedChar = relatedChar; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public String getParamJson() { try { if(StringUtils.isEmpty(this.paramJson)&&this.logValues.size()>0){ ObjectMapper mapper = new ObjectMapper(); this.paramJson=mapper.writeValueAsString(this.logValues); } } catch (JsonProcessingException e) { Logger logger = LoggerFactory.getLogger(this.getClass()); logger.error("method {} execute error,param:{} Exception:{}","setTranslationParam",logValues,e); } return paramJson; } public String getResultJson() { return resultJson; } /** * 该方法不提供对外调用,只提供数据库封装回调,要设置日志保存参数使用 * setTranslationParam,setUpdateParam方法 * @param paramJson */ @SuppressWarnings("unchecked") public void setParamJson(String paramJson) { try { if(StringUtils.isEmpty(paramJson)){ return; } ObjectMapper mapper = new ObjectMapper(); JavaType type = mapper.getTypeFactory().constructParametricType(ArrayList.class, LogValue.class); List<LogValue> logValues = (List<LogValue>) mapper.readValue(paramJson, type); for (LogValue logValue : logValues) { this.thParamName.add(logValue.getName()); this.tdParamData.add(logValue.getValue()); } } catch (Exception e) { Logger logger = LoggerFactory.getLogger(this.getClass()); logger.error("method {} execute error,param:{} Exception:{}","setParamJson",paramJson,e); this.paramJson = paramJson; } this.paramJson = paramJson; } /** * 该方法不提供对外调用,只提供数据库封装回调,要设置日志保存参数使用 * setTranslationParam,setUpdateParam方法 * @param paramJson */ public void setResultJson(String resultJson) { try { if(StringUtils.isEmpty(resultJson)){ return; } ObjectMapper mapper = new ObjectMapper(); JavaType type = mapper.getTypeFactory().constructParametricType(ArrayList.class, LogValue.class); List<LogValue> logValues = (List<LogValue>) mapper.readValue(resultJson, type); for (LogValue logValue : logValues) { this.thResultName.add(logValue.getName()); this.tdResulData.add(logValue.getValue()); } } catch (Exception e) { Logger logger = LoggerFactory.getLogger(this.getClass()); logger.error("method {} execute error,param:{} Exception:{}","setParamJson",paramJson,e); this.resultJson = resultJson; } this.resultJson = resultJson; } public Long getOptionUser() { return optionUser; } public void setOptionUser(Long optionUser) { this.optionUser = optionUser; } public String getDataCode() { return dataCode; } /** * 该方法回调使用 * 设置日志回调结果用 * setOptionResult * @param dataCode */ public void setDataCode(String dataCode) { this.dataCode = dataCode; } public Date getOptionTime() { return optionTime; } public void setOptionTime(Date optionTime) { this.optionTime = optionTime; } public Long getTenantId() { return tenantId; } public void setTenantId(Long tenantId) { this.tenantId = tenantId; } /** * 除去修改删除以外设置调用参数的时候都是调用这个方法 * @param atribute 属性字段 * @param name 属性名称中文 * @param value 属性值 */ public void setTranslationParam(String atribute,String name,Object value){ LogValue logValue=new LogValue(); logValue.setAtribute(atribute); logValue.setName(name); logValue.setValue(value); logValues.add(logValue); } /** * 修改或者删除操作需要保留日志的对象 * old 和news对象的属性获取方法一定要设置名称注解 * {@link Excel} * @param old 修改删除前的对象 * @param news 修改后的对象,删除是设置为null */ public void setUpdateParam(Object old,Object news){ try { ObjectMapper mapper = new ObjectMapper(); if(old!=null){ this.paramJson=mapper.writeValueAsString(ClassObjectValueUtile.getFiledName(old)); } if(news!=null){ this.resultJson=mapper.writeValueAsString(ClassObjectValueUtile.getFiledName(news)); } } catch (JsonProcessingException e) { Logger logger = LoggerFactory.getLogger(this.getClass()); logger.error("method {} execute error,old:{} news:{} Exception:{}","setUpdateParam",old,news,e); } } /** * 设置操作日志的返回结果 * * @param code */ public void setOptionResult(Integer code){ String codeName =PlatformErrorCode.codes.get(code); if(StringUtils.isEmpty(codeName)){ codeName ="请求失败"; } this.dataCode=PlatformErrorCode.codes.get(code); } /** * @return the orgId */ public Long getOrgId() { return orgId; } /** * @param orgId the orgId to set */ public void setOrgId(Long orgId) { this.orgId = orgId; } public static PlatformLog getPlatformLog(){ return PLATFORM_LOG_THREAD_LOCAL.get(); } public static void setPlatformLog(PlatformLog platformLog){ PLATFORM_LOG_THREAD_LOCAL.set(platformLog); } public static void removePlatformLog(){ PLATFORM_LOG_THREAD_LOCAL.remove(); } }
最后在ResponseBodyAdvice 的实现类中记录操作日志
public class LogResponseBodyAdvice implements ResponseBodyAdvice<ResultDTO> { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired PlatformLogService platformLogService; static ObjectMapper mapper = new ObjectMapper(); @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { return true;//do nothing } @Override public ResultDTO beforeBodyWrite(ResultDTO body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { PlatformLog platformLog = PlatformLog.getPlatformLog(); if (platformLog==null){ return body; } try { platformLog.setResultJson(mapper.writeValueAsString(body)); platformLog.setDataCode(""+body.getCode()); PlatformLog.removePlatformLog(); platformLogService.insert(platformLog); } catch (Exception e) { e.printStackTrace(); PlatformLog.removePlatformLog(); log.error("err method: wsLogResponseBodyAdvice.beforeBodyWrite, Exception ", e); return body; } return body; } }
就这样吧 第一次写 好渣
时间: 2024-10-07 18:58:53