zoukankan      html  css  js  c++  java
  • HashMap与redis在项目中的应用

    刚从.net转java三个月,这里记录一下在java项目中使用缓存的学习。

    因为项目之前的开发人员离职了,在之前的项目上进行维护,对应从来没有接触过java的小白,只能自己多看多理解多动手了。

    这个项目原来是没有用java真正意义上的缓存,而是用的静态的HashMap,但是在性能测试的过程中出现了死锁的过程,因为hashmap是不安全的线程,建议使用ConcurrentHashMap这个和.net的Dictonary很像。因为性能测试不通过,所以后来加了redis,其实java的一级缓存ehcache也是很好的,因为项目到了后期阶段,项目时间紧就没改ehcahe(这个.net的asp.net cache一样)。

    言归正传:

    hashmap的使用方法:

    首先定义一个InitCacheData类,里面填充各种属性和方法。

    建议用这种

    public class InitCacheData {
        private static InitCacheData instance;
    
        private InitCacheData() {
        }
    
        /**
         * description 单例模式
         * @param @return
         * @return InitCacheData
         */
        public static InitCacheData getInstance() {
            synchronized (InitCacheData.class) {
                if (instance == null) {
                    instance = new InitCacheData();
                }
                return instance;
            }
        }
        
        /**
         * 初始化数据的缓存,key:数据类型,value:数据(key:实体类主键的值,value对应的实体类)
         */
        private Map<CacheType, Map<Integer, Object>> cacheData = new HashMap<CacheType, Map<Integer, Object>>();
        private Map<CacheType, Map<Integer, List<Object>>> cacheTreeData = new HashMap<CacheType, Map<Integer, List<Object>>>();
        private Map<CacheType, Map<String, Object>> cacheItemMappingData = new HashMap<CacheType, Map<String, Object>>();
        
        private Map<String,List<SingleTrainStudentAnswer>> cacheAnswerData = new ConcurrentHashMap<String,List<SingleTrainStudentAnswer>>();  
        private Map<CacheType,List<ProjectItem>> projectItemData = new HashMap<CacheType,List<ProjectItem>>();
    
    
        /**
         * @description 初始化数据的类型
         */
        public enum CacheType {
            CLASS, MAJOR, COLLEGE, COURSE,USER_INFO,KNOW_POINT,STUDENT,TEACHER,ITEMMAPPING,PARAMETER_TYPE,TRDCO,ANSWER,PROJECTITEM,BASEITEMS
        };
    
        public Map<Integer, Object> getCacheData(CacheType dataType){
            return this.cacheData.get(dataType);
        }
        
        public Map<CacheType, List<ProjectItem>> getBasicItemsData() {
            return basicItemsData;
        }
        
    
        
        /**
         * description 初始化数据执行的方法
         * @param 
         * @return void
         */
        public void initData() {
    
            initCourseData();
            initBasicItemsData();
            
    
        }
        
        //获取学生练习列表:对应登录后的练习菜单
        private void initBasicItemsData() {
            IProjectItemService projectItemService = (IProjectItemService) SpringContextUtil.getBean("projectItemService");
            List<ProjectItem> list = projectItemService.getBasicItems();
            if(basicItemsData.get(CacheType.BASEITEMS)!=null) {
                basicItemsData.get(CacheType.BASEITEMS).clear();
            }
            basicItemsData.put(CacheType.BASEITEMS,list);
        }
    
    
        private void initCourseData() {
            ICourseService courseService = (ICourseService)SpringContextUtil.getBean("courseService");
            List<Course> courseList = courseService.findAll();
            Map<Integer, Object> courseMap = new HashMap<Integer, Object>(courseList.size());
            Iterator<Course> courseIt = courseList.iterator();
            Course course = null;
            while(courseIt.hasNext()){
                course = courseIt.next();
                courseMap.put(course.getId(), course);
            }
            
            if(cacheData.get(CacheType.COURSE) != null){
                cacheData.get(CacheType.COURSE).clear();
            }
            cacheData.put(CacheType.COURSE, courseMap);
        }
    
        
        /**
         * @description 通过递归获得所有选中节点下面的所有节点id
         * @param 
         * @return void
         */
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public void getChildNodes(List<Integer> idsList,int nodeId){
            Map<Integer,List<Object>> knowPointMap = cacheTreeData.get(CacheType.KNOW_POINT);
            if(knowPointMap.containsKey(nodeId)){
                List<KnowPoint> knowPointList = (List)knowPointMap.get(nodeId);
                for(KnowPoint know : knowPointList){
                    idsList.add(know.getId());
                    getChildNodes(idsList,know.getId());
                }
            }
        
        }
        
    View Code

    redis的使用方法:

    1.在maven项目中添加引用依赖

     1 <dependency>  
     2             <groupId>org.springframework.data</groupId>  
     3             <artifactId>spring-data-redis</artifactId>  
     4             <version>1.5.0.RELEASE</version>
     5         </dependency> 
     6         <dependency>
     7             <groupId>redis.clients</groupId>
     8             <artifactId>jedis</artifactId>
     9             <version>2.9.0</version>
    10         </dependency>
    11         
    View Code

    2.要创建spring-redis.xml

    <beans     xmlns="http://www.springframework.org/schema/beans" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:p="http://www.springframework.org/schema/p" 
               xmlns:tx="http://www.springframework.org/schema/tx"
               xmlns:context="http://www.springframework.org/schema/context"
               xsi:schemaLocation="
                http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.0.xsd
                   ">
        
        <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
            <property name="maxIdle" value="${redis.maxIdle}" />
            <property name="minIdle" value="${redis.minIdle}" /> 
            <property name="maxTotal" value="${redis.maxTotal}" />  
            <property name="maxWaitMillis" value="${redis.max-wait-millis}" />  
        </bean>  
          
        <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  
            p:host-name="${redis.host}" 
            p:port="${redis.port}" 
            p:password="${redis.password}"  
            p:database="0" 
            p:timeout="${redis.timeout}"
            p:pool-config-ref="poolConfig"/>  
          
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
            <property name="connectionFactory"   ref="connectionFactory" /> 
            <property name="defaultSerializer"   ref="jdkSerializationRedisSerializer" />  
        </bean>   
        <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">  
            <property name="connectionFactory"   ref="connectionFactory" />  
        </bean>  
        <bean id="jdkSerializationRedisSerializer" class=" org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
    </beans>  
    View Code

    3.添加redis.properties配置文件

    #redis setting  
    redis.host=127.0.0.1
    redis.port=6379
    redis.password=123456
    redis.maxIdle=100
    redis.maxActive=300
    redis.maxWait=1000
    redis.testOnBorrow=true
    redis.timeout=100000
    
    fep.local.cache.capacity =10000
    View Code

    4.在spring-context.xml文件中导入redis配置 <import resource="spring-redis.xml"/> 

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:task="http://www.springframework.org/schema/task" 
           xmlns:jms="http://www.springframework.org/schema/jms"  
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/task 
           http://www.springframework.org/schema/task/spring-task-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
           http://www.springframework.org/schema/jms
           http://www.springframework.org/schema/jms/spring-jms-3.2.xsd">
        <!-- 启用annotation方式 -->
        <task:annotation-driven scheduler="myScheduler" />
    
        <!-- 配置任务线程池 -->
        <task:scheduler id="myScheduler" pool-size="5" />
        <context:annotation-config/>
    
        <!-- 设置属于Spring管理的类 -->
        <context:component-scan base-package="com.gta">
            <!-- 排除com.gta.demo.controller包下的类,由SpringMVC来管理 -->
            <context:exclude-filter type="regex" expression="com.gta.kjzh.controller.*"/>
        </context:component-scan>
    
        <!-- 设置项目中可以获取到的properties配置文件 -->
        <context:property-placeholder location="classpath*:/config/*.properties"/>
    
        <!-- 设置Druid数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
            <!-- 数据源URL -->
            <property name="url" value="${url}"/>
            <!-- 数据库用户名 -->
            <property name="username" value="${db.username}"/>
            <!-- 数据库密码 -->
            <property name="password" value="${db.password}"/>
            <!-- 数据库驱动 -->
            <property name="driverClassName" value="${driverClassName}"/>
    
            <!-- 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall -->
            <property name="filters" value="${druid.filters}"/>
    
            <!-- 最大连接池数量 -->
            <property name="maxActive" value="${maxActive}"/>
            <!-- 初始化时建立物理连接的个数 -->
            <property name="initialSize" value="${initialSize}"/>
            <!-- 获取连接时最大等待时间,单位毫秒 -->
            <property name="maxWait" value="${maxWait}"/>
            <!-- 启用非公平锁 -->
            <property name="useUnfairLock" value="true"/>
            <!-- 最小连接池数量 -->
            <property name="minIdle" value="${minIdle}"/>
    
            <!-- 有两个含义:
                1) Destroy线程会检测连接的间隔时间
                2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 -->
            <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}"/>
    
            <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}"/>
    
            <!-- 用来检测连接是否有效的sql,要求是一个查询语句,如果validationQuery为null,testOnBorrow、testOnReturn、 testWhileIdle都不会其作用 -->
            <property name="validationQuery" value="${validationQuery}"/>
            <!-- 建议配置为true,不影响性能,并且保证安全性。 申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。-->
            <property name="testWhileIdle" value="${testWhileIdle}"/>
            <!-- 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 -->
            <property name="testOnBorrow" value="${testOnBorrow}"/>
            <!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 -->
            <property name="testOnReturn" value="${testOnReturn}"/>
            <!-- 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 -->
            <!--<property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}"/>-->
            <!-- 打开removeAbandoned功能 -->
            <property name="removeAbandoned" value="${removeAbandoned}"/>
            <!-- 1800秒,也就是30分钟 -->
            <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"/>
            <!-- 关闭abanded连接时输出错误日志 -->
            <property name="logAbandoned" value="${logAbandoned}"/>
        </bean>
    
        <!-- spring上传文件配置,这里申明的id必须为multipartResolver -->
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="314572800" />
        </bean> 
        
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
            <property name="dataSource" ref="dataSource"></property>  
        </bean>  
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="hibernateProperties">
                <props>
                    <!-- 设置数据库方言 -->
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <!--<prop key="hibernate.current_session_context_class">${hibernate.current_session}</prop>-->
                    <!-- 设置是否在控制台输出sql语句 -->
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                    <!-- 输出格式化的sql语句 -->
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                    <!-- 设置项目启动时,hibernate检查数据库和实体类是否匹配 -->
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                    
                    <!-- hibernate ehcache 配置  EhCacheRegionFactory-->
                    <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory </prop> 
                    <prop key="hibernate.cache.use_query_cache">true</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                     <!-- 二级缓存配置文件路径 /resources/hibernate-->   
                    <prop key="net.sf.ehcache.configurationResourceName">/config/ehcache.xml</prop>
                    
                </props>
            </property>
            <!-- 扫描受Hibernate管理的实体类所在的包-->
            <property name="packagesToScan" value="com.gta.kjzh.*"/>
        </bean>
        
        <bean id="genericDao" class="com.gta.kjzh.sdk.base.dao.HibernateGenericDAO"></bean>
        
        <!-- 设置spring使用Hibernate的事务处理方式 -->
        <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
        
        <!-- 设置事务注解使用spring事务管理的方式 -->
        <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
        <!-- 通用springMVC拦截器的设置 
        <bean id="springMVCInterceptor" class="com.gta.filter.SpringMVCInterceptor"></bean>     
        <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">     
            <property name="interceptors">     
                <list>     
                    <ref bean="springMVCInterceptor"/>     
                </list>     
            </property>     
        </bean> 
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
           <tx:attributes>
              <tx:method name="get*" read-only="true" propagation="REQUIRED"/>
              <tx:method name="find*" read-only="true" propagation="REQUIRED"/>
              <tx:method name="save*" propagation="REQUIRED"/>
              <tx:method name="update*" propagation="REQUIRED"/>
              <tx:method name="remove*" propagation="REQUIRED"/>
              <tx:method name="add*" propagation="REQUIRED"/>
              <tx:method name="*"/>
           </tx:attributes>
        </tx:advice>
        
        <aop:config proxy-target-class="true">
            <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.gta.kjzh.*.service..*.*(..))"/>
        </aop:config>-->
        <!-- <import resource="activemq.xml"/> -->
        <import resource="spring-redis.xml"/> 
        <!-- <import resource="spring-quartz-answer.xml"/> 
        <import resource="spring-quartz.xml"/>  -->
    </beans>
    View Code

    5.编辑RedisCache类,里面放有redis的增删改查操作。

    package com.kjzh.redis.cache;
    
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.ListOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.SetOperations;
    import org.springframework.data.redis.core.ZSetOperations;
    import org.springframework.stereotype.Component;
    
    import com.gta.kjzh.util.SerializeUtils;
    
    import net.sf.ehcache.CacheException;
    @Component
    public class RedisCache<K, V> {
        private static String redisCode = "utf-8";
        private String prefix;
        @Autowired
        private RedisTemplate<byte[], V> redisTemplate;
        
        @Autowired
        private RedisTemplate<String, String> stringRedisTemplate;
        
        public Set<String> getKeys(String keyPattern) {
            return stringRedisTemplate.keys(keyPattern);
        }
        
        public String getString(String key) {
            return stringRedisTemplate.opsForValue().get(key);
        }
        
        public void setString(String key, String value) {
            stringRedisTemplate.opsForValue().set(key, value);
        }
        
    
        public V get(K key) {
            byte[] bkey = getByteKey(key);
            return redisTemplate.opsForValue().get(bkey);
        }
        
        public void set(K key, V value) {
            byte[] bkey = getByteKey(key);
            redisTemplate.opsForValue().set(bkey, value);
        }
        
        public void remove(K key) {
            byte[] bkey = getByteKey(key);
            redisTemplate.delete(bkey);
        }
    
        public void set(K key, V value, long timeout) {
            
             byte[] bkey = getByteKey(key);
            redisTemplate.opsForValue().set(bkey, value, timeout, TimeUnit.SECONDS);
        }
        
         String get(K key, long start, long end){
             byte[] bkey = getByteKey(key);
             return redisTemplate.opsForValue().get(bkey,start,end);
         }
         Long size(K key){
             byte[] bkey = getByteKey(key);
             return redisTemplate.opsForValue().size(bkey);
         }
         
         List<V> range(K key, long start, long end){
             byte[] bkey = getByteKey(key);
             return redisTemplate.opsForList().range(bkey,start,end);
         }
         
         public void clear() throws CacheException {
             redisTemplate.getConnectionFactory().getConnection().flushDb();
         }
         
         public List<V> getListValue(K key) {
                 byte[] bkey = getByteKey(key);
                ListOperations<byte[], V> list = redisTemplate.opsForList();
                return redisTemplate.opsForList().range(bkey, 0,list.size(bkey));
    
         }
    
         
         private byte[] getByteKey(K key){
                if(key instanceof String){
                    String preKey = this.prefix + key;
                    return preKey.getBytes();
                }else{
                    return SerializeUtils.serialize(key);
                }
            }
         
         public String getPrefix() {
                return prefix;
         }
         
         /**
         * 批量删除对应的value
         * 
         * @param keys
         */
        public void remove(final String... keys) {
            for (String key : keys) {
                remove(key);
            }
        }
    
        /**
         * 批量删除key
         * 
         * @param pattern
         */
        public void removePattern(final String pattern) {
            Set<Serializable> keys = redisTemplate.keys(pattern);
            if (keys.size() > 0)
                redisTemplate.delete(keys);
        }
        
        /**
         * 判断缓存中是否有对应的value
         * 
         * @param key
         * @return
         */
        public boolean exists(final String key) {
            return redisTemplate.hasKey(key);
        }
    
    }
    View Code

    6.具体使用

    if(redisCache.get(answerkey)!=null) {
                    redisCache.remove(answerkey);
                }
                redisCache.set(answerkey,reCombinsList);
    View Code

     

  • 相关阅读:
    【前端】Vue2全家桶案例《看漫画》之五、引入axios
    【前端】Vue2全家桶案例《看漫画》之四、漫画页
    【前端】Vue2全家桶案例《看漫画》之三、引入vuex
    【前端】Vue2全家桶案例《看漫画》之番外篇、express上传漫画(可选)
    【前端】Vue2全家桶案例《看漫画》之二、完成首页基本样式
    【前端】Vue2全家桶案例《看漫画》之一、添加四个导航页
    【前端】Vue和Vux开发WebApp日志四、增加命令行参数
    【前端】Vue和Vux开发WebApp日志三、完善gulp任务
    [TabControl] TabControl控件的最佳实践,可以把一个窗体和用户控件添加进来
    一步一步玩控件:自定义TabControl——从山寨Safari开始
  • 原文地址:https://www.cnblogs.com/songStar/p/9359176.html
Copyright © 2011-2022 走看看