springboot-cache自定义缓存

项目需求:

项目数据存储在hbase中,每次查询数据都需将一些数据进行转换,对于大数据查询操作频繁连接数据库获取字典值,这会影响整个查询速度。

解决方案:

1、根据不同业务模块划分,项目中对于数据流处理(单独spark服务),通过redis缓存字典数据。

2、前段需要用到字典数据,将数据缓存到.net端。

3、web端java服务,考虑到redis还需要安装,运维维护不变,开发人员使用也不方便,并切需要定时操作数据库缓存到redis,所以在服务端自定义缓存处理,通过定时器间隔一定时间,将数据写入到缓存中。

具体实现如下:

源码下载地址:https://gitee.com/com_1057718341/springboot-hello

项目结构如下


在pom.xml中引入依赖包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example.springboot</groupId>
    <artifactId>springboot-cache2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-cache2</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 引入sqlserver数据连接包
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <scope>runtime</scope>
        </dependency> -->
        <!-- 引入mybatis 数据库操作包 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- 引入mybatis 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!-- 任务调度 -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.3</version>
        </dependency>

        <!-- beanutils实体类处理 -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>
        <!-- 公共处理类 -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- log4j日志记录-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.4</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

在application.properties中添加数据连接

#server.port=8090

#标示使用的是mysql/oracle/sqlserver
datasource.type=mysql
#mysql数据连接
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.max-active=20
#spring.datasource.max-idle=8
#spring.datasource.min-idle=8
#spring.datasource.initial-size=20


#mybatis 配置
# 配置映射文件加载
mybatis.mapper-locations=classpath*:mapper/*.xml
# 实体类通过别名使用
#mybatis.type-aliases-package=

#springmvc视图
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp

#单个文件上传限制
spring.http.multipart.maxFileSize=10Mb
#单次文件上传限制
spring.http.multipart.maxRequestSize=100Mb

constant类:

package com.example.springboot.cache.constant;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Constants {
   private static final Log log = LogFactory.getLog(Constants.class);
   public static String CacheXml = "cacheManage.xml";

   /**
    * 配置xml文件路劲
    */
   public static String cacheXmlPath = null;

   static {
      if (null == Constants.class.getClassLoader().getResource("/")) {
         cacheXmlPath = Constants.class.getClassLoader().getResource("").getPath() + CacheXml;
      } else {
         cacheXmlPath = Constants.class.getClassLoader().getResource("/").getPath() + CacheXml;
      }
      if (cacheXmlPath != null && !"".equals(cacheXmlPath)) {
         String os = System.getProperty("os.name");
         if (os.toLowerCase().startsWith("win") && cacheXmlPath.startsWith("/")) {
            cacheXmlPath = cacheXmlPath.substring(1);
         }
      }
      log.info("cacheXmlPath " + cacheXmlPath);
   }
}

 
 

创建dao操作数据库类

package com.example.springboot.cache.dao;

import com.example.springboot.cache.entity.dto.CacheEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;

/**
 * @desc 查询数据字典
 * @Author wangsh
 * @date 2018/5/6 18:10
 * @return
 */
@Mapper
public interface CacheManagerMapper {

   public List<Map<String, Object>> getDataFromDBSaveToTempCache(CacheEntity dto);

}
 
 

mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.springboot.cache.dao.CacheManagerMapper">
    <!-- 查询字典表数据 -->
    <select id="getDataFromDBSaveToTempCache" parameterType="com.example.springboot.cache.entity.dto.CacheEntity"
            resultType="java.util.Map">
        /*SELECT ${columns} FROM ${dbName}.${table} as rs WITH(NOLOCK) WHERE 1=1*/
        select * from test.sc_dict_sex where 1=1
        <if test="null != conditions and '' != conditions">
            AND ${conditions}
        </if>
    </select>
</mapper>

创建实体类

package com.example.springboot.cache.entity.dto;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @desc 缓存实体类
 * @Author wangsh
 * @date 2018/5/6 18:11
 * @return
 */
public class CacheEntity {
   //数据库名称
   private String dbName;
   //实例名
   private String dbo;
   //表名
   private String table;
   //数据库类型
   private String datasourceType;
   //列名称(多个以逗号分割)
   private String columns;
   //查询条件
   private String conditions;
   private String key;
   // 是否缓存
   private String fullCache;
   private String toMapField;
   private Map<String, Map<String, Object>> cacheMapData;
   private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

   public String getDbName() {
      return dbName;
   }

   public void setDbName(String dbName) {
      this.dbName = dbName;
   }

   public String getDbo() {
      return dbo;
   }

   public void setDbo(String dbo) {
      this.dbo = dbo;
   }

   public String getTable() {
      return table;
   }

   public void setTable(String table) {
      this.table = table;
   }

   public String getKey() {
      return key;
   }

   public void setKey(String key) {
      this.key = key;
   }

   /**
    * 获取list
    *
    * @return list list
    */
   public List<Map<String, Object>> getList() {
      return list;
   }

   /**
    * 设置list
    *
    * @param list list
    */
   public void setList(List<Map<String, Object>> list) {
      this.list = list;
   }

   /**
    * 获取columns
    *
    * @return columns columns
    */
   public String getColumns() {
      return columns;
   }

   /**
    * 设置columns
    *
    * @param columns columns
    */
   public void setColumns(String columns) {
      this.columns = columns;
   }

   /**
    * 获取conditions
    *
    * @return conditions conditions
    */
   public String getConditions() {
      return conditions;
   }

   /**
    * 设置conditions
    *
    * @param conditions conditions
    */
   public void setConditions(String conditions) {
      this.conditions = conditions;
   }

   /**
    * 获取toMapField
    *
    * @return toMapField toMapField
    */
   public String getToMapField() {
      return toMapField;
   }

   /**
    * 设置toMapField
    *
    * @param toMapField toMapField
    */
   public void setToMapField(String toMapField) {
      this.toMapField = toMapField;
   }

   /**
    * 获取cacheMapData
    *
    * @return cacheMapData cacheMapData
    */
   public Map<String, Map<String, Object>> getCacheMapData() {
      return cacheMapData;
   }

   /**
    * 设置cacheMapData
    *
    * @param cacheMapData cacheMapData
    */
   public void setCacheMapData(Map<String, Map<String, Object>> cacheMapData) {
      this.cacheMapData = cacheMapData;
   }

   /**
    * 获取fullCache
    *
    * @return fullCache fullCache
    */
   public String getFullCache() {
      return fullCache;
   }

   /**
    * 设置fullCache
    *
    * @param fullCache fullCache
    */
   public void setFullCache(String fullCache) {
      this.fullCache = fullCache;
   }

   public String getDatasourceType() {
      return datasourceType;
   }

   public void setDatasourceType(String datasourceType) {
      this.datasourceType = datasourceType;
   }

   @Override
   public String toString() {
      return "CacheEntity{" +
            "dbName='" + dbName + '\'' +
            ", dbo='" + dbo + '\'' +
            ", table='" + table + '\'' +
            ", datasourceType='" + datasourceType + '\'' +
            ", columns='" + columns + '\'' +
            ", conditions='" + conditions + '\'' +
            ", key='" + key + '\'' +
            ", fullCache='" + fullCache + '\'' +
            ", toMapField='" + toMapField + '\'' +
            ", cacheMapData=" + cacheMapData +
            ", list=" + list +
            '}';
   }
}

service层业务处理类

package com.example.springboot.cache.service;

import com.example.springboot.cache.entity.dto.CacheEntity;
import java.util.concurrent.ConcurrentMap;

/**
 * @desc 缓存处理类
 * @Author wangsh
 * @date 2018/5/6 18:06
 * @return
 */
public interface PullDataToCache {
   public void pullData(ConcurrentMap<String, CacheEntity> cache);

   public void refreshCacheData(ConcurrentMap<String, CacheEntity> cache);
}
 
 

service实现类

package com.example.springboot.cache.service.impl;

import com.example.springboot.cache.constant.Constants;
import com.example.springboot.cache.dao.CacheManagerMapper;
import com.example.springboot.cache.entity.dto.CacheEntity;
import com.example.springboot.cache.service.PullDataToCache;
import com.example.springboot.cache.util.XmlUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * @desc 缓存处理类
 * @Author wangsh
 * @date 2018/5/6 18:07
 * @return
 */
@Service
public class PullDataToCacheImpl implements PullDataToCache {
   private static final Log log = LogFactory.getLog(PullDataToCacheImpl.class);

   @Value("${datasource.type}")
   private String datasourceType;

   @Autowired
   private CacheManagerMapper mapper;

   private static List<CacheEntity> cacheTableInfoList = new ArrayList<CacheEntity>();

   @Override
   public void pullData(ConcurrentMap<String, CacheEntity> cache) {
      log.info("缓存管理-->服务启动:添加缓存入口开启调用!");
      try {
         // 解析xml文件,并将要缓存的表信息保存入cacheTableInfoList;
         parseCacheXml();
         // 从数据库获取数据,并保存数据
         getDataFromDBSaveToTempCache();
         // 放入缓存中
         SaveToCacheManager(cache);
      } catch (Exception e) {
         log.error("缓存管理-->服务启动:缓存添加出现异常", e);
      }
      log.info("缓存管理-->服务启动:添加缓存入口调用完成!");
   }

   private void SaveToCacheManager(ConcurrentMap<String, CacheEntity> cache) {
      for (CacheEntity ce : cacheTableInfoList) {
         String key = ce.getKey();
         cache.put(key, ce);
      }
      cacheTableInfoList.clear();
   }

   /**
    * @param @param ce
    * @return void
    * @author cjy
    * @Description: 针对配置需要独立成一个map的缓存数据进行遍历,并保存到全局map中
    * @date 2017-6-8
    */
   private void cacheDataToMap(CacheEntity ce, List<Map<String, Object>> list) {
      // 配置并遍历所有需要单独成map的字段
      String toMapFiled = ce.getToMapField();
      // 判断需要把数据独立成map的配置是否为空
      if (StringUtils.isEmpty(toMapFiled)) {
         log.info("缓存管理-->添加缓存:" + ce.getTable() + "表没有要独立成map的字段返回!");
         return;
      }

      if (null == list || list.size() == 0) {
         log.info("缓存管理-->添加缓存:" + ce.getTable() + "表没有查询出有效的数据返回!");
         return;
      }

      String[] fields = toMapFiled.split(",", -1);
      for (int i = 0; i < fields.length; i++) {
         String field = fields[i];
         // 获取哪个字段需要独立成map
         String[] keys = field.split(":", -1);
         if (null == keys || keys.length != 3) {
            log.info("缓存管理-->添加缓存:把数据添加到缓存map中出错,原因:" + ce.getTable() + "表配置的独立缓存没有配置!");
            continue;
         }
         String tmpKey = keys[0];
         String key = keys[1];
         String value = keys[2];
         log.debug("缓存管理-->添加缓存:独立缓存" + ce.getTable() + "表设置了独立map缓存,其中取独立缓存的key:" + tmpKey + " 缓存是以" + key + "字段值做key " + value + "字段值做value!");

         Map<String, Object> tmp = new HashMap<String, Object>();
         // 遍历所有的数据,并把数据添加到临时map中
         for (Map<String, Object> data : list) {
            tmp.put(data.get(key).toString(), data.get(value));
         }
         // 改组字段遍历完成,把临时map添加到全局对象中
         ce.getCacheMapData().put(tmpKey, tmp);
      }

   }

   private void getDataFromDBSaveToTempCache() {
      for (CacheEntity ce : cacheTableInfoList) {
         try {
            // 查询数据
            List<Map<String, Object>> list = mapper.getDataFromDBSaveToTempCache(ce);

            if (null == ce.getList()) {
               ce.setList(new ArrayList<Map<String, Object>>());
            }
            // 判断是否需要把全量数据添加到缓存中
            if ("true".equals(ce.getFullCache())) {
               // 添加全量数据到缓存中
               ce.getList().addAll(list);
            }
            // 把需要独立成map的字段遍历,并添加到临时map中
            cacheDataToMap(ce, list);
         } catch (Exception e) {
            log.error("缓存管理-->添加缓存:查询数据库报错", e);
         }
      }
   }

   /**
    * 解析缓存的xml文件
    */
   private void parseCacheXml() {

      try {
         String filePath = Constants.cacheXmlPath;
         Document doc = XmlUtils.loadFileByPath(filePath);
         Element ele = XmlUtils.rootElement(doc);
         List<Element> fileNodes = ele.selectNodes("/cacheManager/cache");
         for (Element e : fileNodes) {
            CacheEntity ce = new CacheEntity();
            ce.setDbName(e.attributeValue("dbName"));
            ce.setDbo(e.attributeValue("dbo"));
            ce.setTable(e.attributeValue("table"));
            //生成缓存key
//          String key = this.getDatabaseKey(e.attributeValue("dbName"), e.attributeValue("dbo"), e.attributeValue("table"));
//          ce.setKey(key);
            ce.setKey(e.attributeValue("dbName") + "_" + e.attributeValue("table"));
            ce.setDatasourceType(datasourceType);
            String columns = StringUtils.isEmpty(e.attributeValue("columns")) ? "*" : e.attributeValue("columns");
            ce.setColumns(columns);
            ce.setConditions(e.attributeValue("conditions"));
            ce.setToMapField(e.attributeValue("toMapField"));
            String fullCache = StringUtils.isEmpty(e.attributeValue("fullCache")) ? "true" : e
                  .attributeValue("fullCache");
            ce.setFullCache(fullCache);
            ce.setCacheMapData(new HashMap<String, Map<String, Object>>());
            cacheTableInfoList.add(ce);
         }
      } catch (DocumentException e) {
         e.printStackTrace();
      }
   }

   /**
    * 生成缓存的key
    *
    * @param dbName
    * @param dbo
    * @param table
    * @return
    */
   private String getDatabaseKey(String dbName, String dbo, String table) {

      String key = null;
      if (StringUtils.isNotBlank(datasourceType)) {
         if ("mysql".equals(datasourceType.toLowerCase())) {
            key = dbName + "_" + table;
         } else if ("oracle".equals(datasourceType.toLowerCase())) {
            key = dbName + "_" + table;
         } else if ("sqlserver".equals(datasourceType.toLowerCase())) {
            key = dbName + "_" + dbo + "_" + table;
         } else {
            key = dbName + "_" + table;
         }
      } else {
         //默认mysql
         key = dbName + "_" + table;
      }
      return key;
   }


   /**
    * 刷新缓存中的数据
    */
   @Override
   public void refreshCacheData(ConcurrentMap<String, CacheEntity> cache) {
      log.info("缓存管理-->刷新缓存:缓存刷新开启调用!");
      try {
         // 解析xml文件,并将要缓存的表信息保存入cacheTableInfoList;
         parseCacheXml();
         // 从数据库获取数据,并保存数据
         getDataFromDBSaveToTempCache();
         // 放入缓存中
         SaveToCacheManager(cache);
      } catch (Exception e) {
         log.error("缓存管理-->刷新缓存:缓存刷新出现异常", e);
      }
      log.info("缓存管理-->刷新缓存:缓存刷新调用完成!");
   }
}

xml解析工具类

package com.example.springboot.cache.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.*;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.List;

public class XmlUtils {

   private static Log log = LogFactory.getLog(XmlUtils.class);
   private static Document doc;

   public static Document loadFileByContent(String fileContent)
         throws DocumentException {
      doc = DocumentHelper.parseText(fileContent);
      return doc;
   }

   public static Document loadFileByPath(String FilePath)
         throws DocumentException {
      File file = new File(FilePath);
      if (file.exists()) {
         SAXReader reader = new SAXReader();
         doc = reader.read(file); // 读取一个xml的文件
      } else {
         log.info(FilePath + " xml文件不存在!");
      }
      return doc;
   }

   public static Document loadFile(File file) throws DocumentException {
      SAXReader reader = new SAXReader();
      doc = reader.read(file); // 读取一个xml的文件
      return doc;
   }

   public static List selectNodes(Node node, String tiaojian) {
      List<Node> nodelist = node.selectNodes(tiaojian);
      return nodelist;
   }

   public static Element rootElement(Document doc) {
      Element ele = doc.getRootElement();
      return ele;
   }

   public static Element element(Element m, String name) {
      Element ele = m.element(name);
      return ele;
   }

   public static List<Element> elements(Element m, String name) {
      List<Element> elist = m.elements(name);
      return elist;
   }

   public static List<Element> elements(Element m) {
      List<Element> elist = m.elements();
      return elist;
   }

   public static String attributeValue(Element m, String attriName) {
      String val = m.attributeValue(attriName);
      return val;
   }

   public static List<String> attributeValues(Element m) {
      List<String> vals = m.attributes();
      return vals;
   }

   public static void main(String[] args) {
      String path = "C:\\Users\\Administrator\\Desktop\\sdfsdf\\cacheManage.xml";
      try {
         Document doc = XmlUtils.loadFileByPath(path);
         Element ele = XmlUtils.rootElement(doc);
         List<Element> fileNodes = ele.selectNodes("/cacheManager/cache");
//       Element e = (Element) e.selectSingleNode("/cacheManager/cache");
         for (Element e : fileNodes) {
            System.out.println(e.attributeValue("dbName"));
            System.out.println(e.attributeValue("dbo"));
            System.out.println(e.attributeValue("table"));
         }
      } catch (DocumentException e) {
         e.printStackTrace();
      }


   }
}

创建缓存定时任务类

package com.example.springboot.cache.job;

import com.example.springboot.cache.entity.dto.CacheEntity;
import com.example.springboot.cache.service.PullDataToCache;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
public class CacheManager implements CommandLineRunner {

   private static final Log log = LogFactory.getLog(CacheManager.class);

   private static ConcurrentMap<String, CacheEntity> CACHE = new ConcurrentHashMap<String, CacheEntity>();
   //    @Autowired
//    private ServletContext servletContext;
   @Autowired
   private ConfigurableEnvironment env;

   @Autowired
   private PullDataToCache pullDataToCache;

   //每5分钟执行一次(单位秒)
   //@Value("${cachemanager_refresh_period}")
   protected String PERIOD = "300";

   // 定时任务启动之后间隔时长开始执行定时任务
   private final int INITIAL_DELAY = 10;

   // 定时任务的执行周期(单位:毫秒)
   private final int PERIOD_TMP = 5 * 60;

   @Override
   public void run(String... args) throws Exception {

      log.info("缓存管理-->缓存初始化:服务启动!");
      refreshCacheData();
      log.info(CACHE.toString());
      log.info("缓存管理-->缓存初始化:服务加载结束!");
   }

   /**
    * @param
    * @return void
    * @author cjy
    * @Description: 定时刷新缓存数据
    * @date 2017-6-2
    */
   private void refreshCacheData() {
      ScheduledExecutorService executors = Executors.newSingleThreadScheduledExecutor();
      if (StringUtils.isEmpty(PERIOD)) {
         // 当数据库配置的为空时走默认5分钟
         executors.scheduleAtFixedRate(new CacheDataRefresh(), INITIAL_DELAY, PERIOD_TMP, TimeUnit.SECONDS);
      } else {
         executors.scheduleAtFixedRate(new CacheDataRefresh(), INITIAL_DELAY, Integer.parseInt(PERIOD),
               TimeUnit.SECONDS);
      }
   }

   // 加载缓存
   public void load() {
      pullDataToCache.pullData(CACHE);
   }

   // 重新加载缓存
   public void reload() {
      CACHE.clear();
      load();
   }

   // 获取缓存
   public ConcurrentMap<String, CacheEntity> getCache() {
      return CACHE;
   }

   // 获取某个缓存
   public List<Map<String, Object>> getCache(String key) {
      CacheEntity cacheEntity = CACHE.get(key);
      if (cacheEntity == null) {
         return new ArrayList<Map<String, Object>>();
      } else {
         return CACHE.get(key).getList();
      }

   }

   // 获取某个表的map缓存
   public Map<String, Object> getCache(String key, String field) {
      CacheEntity cacheEntity = CACHE.get(key);
      if (cacheEntity == null) {
         return new HashMap<String, Object>();
      } else {
         if (null == CACHE.get(key).getCacheMapData().get(field)) {
            return new HashMap<String, Object>();
         }
         return CACHE.get(key).getCacheMapData().get(field);
      }

   }

   /**
    * @param @param tableKey 修改的表名称(例如:WFBDCMain_dbo_WFBDC_tb_Machine,
    *               表示是WFBDCMain数据库dbo对象中的WFBDC_tb_Machine表)
    * @param @param key 单独成map的key
    * @param @param subKey 要修改的子类map的key
    * @param @param subValue 要修改的子类map的key对应的值
    * @return void
    * @author cjy
    * @Description: 修改某个表中具体一个map中的值, 例如:cacheManager.setCacheData("WFBDCMain_dbo_ISIP_tb_BaseInfo", "cacheCcicBaseInfo", "sdf", "fdasdfffffffff");
    * @date 2017-7-5
    */
   public void setCacheData(String tableKey, String key, String subKey, Object subValue) {
      CacheEntity cacheEntity = CACHE.get(tableKey);
      if (null != cacheEntity) {
         // 获取子类map是否为空
         if (null != CACHE.get(tableKey).getCacheMapData().get(key)) {
            // 更新缓存中的map数据
            CACHE.get(tableKey).getCacheMapData().get(key).put(subKey, subValue);
         }
      }
   }

   // 缓存添加数据
   public void put(String key, Map<String, Object> o, CacheEntity ce) {
      List<Map<String, Object>> list = CACHE.get(key).getList();
      if (list != null) {
         list.add(o);
      } else {
         list = ce.getList();
         list.add(o);
         CACHE.put(key, ce);
      }
   }

   // 缓存中删除数据
   public void remove(String key, Object o) {
      List<Map<String, Object>> list = CACHE.get(key).getList();
      if (list != null) {
         for (Object to : list) {
            if (to.equals(o)) {
               list.remove(o);
            } else {
               log.info(o + " 缓存中不存在该对象!");
            }
         }
      }
   }

   // 销毁缓存
   public void destory() {
      CACHE.clear();
   }


   /**
    * @author cjy
    * @Description: 刷新缓存定时处理类
    * @date 2017-6-2 下午6:48:36
    */
   private class CacheDataRefresh implements Runnable {
      @Override
      public void run() {
         try {
            pullDataToCache.refreshCacheData(CACHE);
            log.info("刷新缓存数据 :" + CACHE.toString());
         } catch (Exception e) {
            log.error("缓存管理-->刷新缓存:定时调用刷新服务出现异常", e);
         }
      }

   }
}
创建controller测试缓存类

package com.example.springboot.cache.controller;

import com.example.springboot.cache.job.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * @desc 测试缓存加载数据
 * @Author wangsh
 * @date 2018/5/6 18:56
 */
@RestController
@RequestMapping("/cache")
public class CacheController {

   @Autowired
   private CacheManager cacheManager;

   @ResponseBody
   @RequestMapping("/hello")
   public List<Map<String, Object>> hello() {

      List<Map<String, Object>> list = cacheManager.getCache("test_SC_dict_Sex");
      System.out.println("缓存数据: " + list.toString());
      return list;
   }
}
服务启动类

package com.example.springboot.cache;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.example.springboot.*")
public class SpringbootCache2Application {

   public static void main(String[] args) {
      SpringApplication.run(SpringbootCache2Application.class, args);
   }
}

启动服务测试

测试如下,定时器每5分钟刷新一次,刷新频率可以根据项目情况自行调整。


访问服务测试

浏览器访问服务 http://localhost:8080/cache/hello ,后台调用缓存处理类并返回数据如下。



解析xml错误

D:\Program Files\maven-repository\dom4j\dom4j\1.6.1\dom4j-1.6.1.jar;D:\Program Files\maven-repository\xml-apis\xml-apis\1.4.01\xml-apis-1.4.01.jar" com.example.springboot.cache.util.XmlUtils
Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException
at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:230)
at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:207)
at org.dom4j.tree.AbstractNode.selectNodes(AbstractNode.java:164)
at com.example.springboot.cache.util.XmlUtils.main(XmlUtils.java:80)
Caused by: java.lang.ClassNotFoundException: org.jaxen.JaxenException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 4 more

Process finished with exit code 1

项目中引入的dom4j-1.6.1版本,在解析时没有找到依赖包jaxen,导致解析失败。

解决办法:在pom.xml中引入依赖包

<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.4</version>
</dependency>

源码下载地址:https://gitee.com/com_1057718341/springboot-hello


猜你喜欢

转载自blog.csdn.net/seashouwang/article/details/80216551