首页 > 代码库 > ThreadLocal 在记录操作日志中的应用

ThreadLocal 在记录操作日志中的应用

   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=http://www.mamicode.com/new ArrayList<Object>();//
    private List<Object> thResultName=new ArrayList<Object>();
    private List<Object> tdResulData=http://www.mamicode.com/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 =http://www.mamicode.com/ tdParamData;
    }
    public List<Object> getTdResulData() {
        return tdResulData;
    }
    public void setTdResulData(List<Object> tdResulData) {
        this.tdResulData =http://www.mamicode.com/ 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;
    }
}

就这样吧 第一次写 好渣

 

ThreadLocal 在记录操作日志中的应用