zoukankan      html  css  js  c++  java
  • Redis中在程序中的应用

    1、导入redis的配置文件,因为要交给web容器管理,所以直接命名为ApplicationContext-redis.xml,具体配置如下:

      

    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
    	<!-- 构建连接池配置信息 -->
    	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    		<!-- 最大连接数 -->
    		<property name="maxTotal" value="${redis.maxTotal}" />
    	</bean>
        
    	<bean id="jedisShardInfo1" class="redis.clients.jedis.JedisShardInfo">
    		<constructor-arg index="0" value="${redis.node1.ip}" />
    		<constructor-arg index="1" value="${redis.node1.port}"
    			type="int" />
    	</bean>
    
    	<bean id="jedisShardInfo2" class="redis.clients.jedis.JedisShardInfo">
    		<constructor-arg index="0" value="${redis.node2.ip}" />
    		<constructor-arg index="1" value="${redis.node2.port}"
    			type="int" /> <!-- 端口必须为int类型,如果不写的话,默认是字符串类型,这是时候不起作用,所以端口就是默认端口,会造成分片失败 -->
    	</bean>
    		
    
    	<bean id="jedisShardInfo3" class="redis.clients.jedis.JedisShardInfo">
    		<constructor-arg index="0" value="${redis.node3.ip}" />
    		<constructor-arg index="1" value="${redis.node3.port}"
    			type="int" />
    	</bean>
    
    	<!-- 定义集群连接池 -->
    	<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"
    		destroy-method="close">
    		<constructor-arg index="0" ref="jedisPoolConfig" />
    		<constructor-arg index="1">
    			<list>
    				<ref bean="jedisShardInfo1" />
    				<ref bean="jedisShardInfo2" />
    				<ref bean="jedisShardInfo3"/>
    			</list>
    		</constructor-arg>
    	</bean>
    
    </beans>
    

       需要说明的是,这里是通过jedis进行操作的(jedis即java版的redis)

    2、写伪service工具类

      service--封装一个新的技术,融合进业务,而不是真正的业务层需要,但是本质还是service,目的是为了在controller中注入方便。经过伪service封装可以屏蔽掉底层的api

      

    package com.jt.common.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import redis.clients.jedis.ShardedJedis;
    import redis.clients.jedis.ShardedJedisPool;
    
    @Service
    public class RedisService {
    
    	//有的工程需要,有的工程不需要。设置required=false,有就注入,没有就不注入。
        @Autowired(required = false)
        private ShardedJedisPool shardedJedisPool;
    
        private <T> T execute(Function<ShardedJedis, T> function) {
            ShardedJedis shardedJedis = null;
            try {
                // 从连接池中获取到jedis分片对象
                shardedJedis = shardedJedisPool.getResource();
                return function.execute(shardedJedis);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != shardedJedis) {
                    // 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
                    shardedJedis.close();
                }
            }
            return null;
        }
    
        /**
         * 保存数据到redis中
         * 
         * @param key
         * @param value
         * @return
         */
        public String set(final String key, final String value) {
            return this.execute(new Function<ShardedJedis, String>() {
                @Override
                public String execute(ShardedJedis shardedJedis) {
                    return shardedJedis.set(key, value);
                }
    
            });
        }
    
        /**
         * 保存数据到redis中,生存时间单位是:秒
         * 
         * @param key
         * @param value
         * @param seconds
         * @return
         */
        public String set(final String key, final String value, final Integer seconds) {
            return this.execute(new Function<ShardedJedis, String>() {
                @Override
                public String execute(ShardedJedis shardedJedis) {
                    String result = shardedJedis.set(key, value);
                    shardedJedis.expire(key, seconds);//设置生存时间
                    return result;
                }
    
            });
        }
    
        /**
         * 从redis中获取数据
         * 
         * @param key
         * @return
         */
        public String get(final String key) {
            return this.execute(new Function<ShardedJedis, String>() {
                @Override
                public String execute(ShardedJedis shardedJedis) {
                    return shardedJedis.get(key);
                }
    
            });
        }
    
        /**
         * 设置key生存时间,单位:秒
         * 
         * @param key
         * @param seconds
         * @return
         */
        public Long expire(final String key, final Integer seconds) {
            return this.execute(new Function<ShardedJedis, Long>() {
                @Override
                public Long execute(ShardedJedis shardedJedis) {
                    return shardedJedis.expire(key, seconds);
                }
    
            });
        }
    
        /**
         * 从redis中删除数据
         * 
         * @param key
         * @return
         */
        public Long del(final String key) {
            return this.execute(new Function<ShardedJedis, Long>() {
                @Override
                public Long execute(ShardedJedis shardedJedis) {
                    return shardedJedis.del(key);
                }
            });
        }
    
    }
    

     3、在对应的执行业务的service中添加缓存方法

      我这里因为是要做的查询的一个三级树目录,通过点击前台页面的父选项,传递父ID给后台,查询对应的子类,并将子类集合返回

      原代码如下:

      

    package com.jt.manage.service;
    
    import java.io.IOException;
    import java.util.List;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.fasterxml.jackson.core.JsonParseException;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.jt.common.service.BaseService;
    import com.jt.common.service.RedisService;
    import com.jt.manage.mapper.ItemCatMapper;
    import com.jt.manage.pojo.ItemCat;
    
    @Service
    public class ItemCatService extends BaseService<ItemCat> {
    	@Autowired
    	private ItemCatMapper itemCatMapper;
    
    
    	public List<ItemCat> findItemCarList(Long parentId) {
              itemCat.setParentId(parentId);
    <!--这里采用的是JPA的方式,自动构建sql语句,查询的时候如果传入的是对象,那么会根据对象的属性当做where条件进行对应的匹配-->
              return   itemCatMapper.select(itemCat);
        
    }
                         
    

     修改后的代码如下:

      

    package com.jt.manage.service;
    
    import java.io.IOException;
    import java.util.List;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.fasterxml.jackson.core.JsonParseException;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.jt.common.service.BaseService;
    import com.jt.common.service.RedisService;
    import com.jt.manage.mapper.ItemCatMapper;
    import com.jt.manage.pojo.ItemCat;
    
    @Service
    public class ItemCatService extends BaseService<ItemCat> {
    	@Autowired
    	private ItemCatMapper itemCatMapper;
    
    	@Autowired
    	private RedisService redisService;
    
    	private static final ObjectMapper MAPPER = new ObjectMapper();
    
    	public List<ItemCat> findItemCarList(Long parentId) {
    
    		/*
    		 * 如果传入的是对象,查询时就会根据对象的属性值添加where条件 写null表示不需要where条件
    		 */
    		ItemCat itemCat = new ItemCat();
    
    		/*
    		 * 1、在执行业务前判断缓存总是否所有数据,如果有数据,就获取数据,直接返回结果 
    		 * 2、如果没有数据,继续执行业务,访问数据库,获取返回的值
    		 * 3、再返回业务之前,把获取的数据在缓存中存放一份,然后再返回 
    		 * 4、放缓存:kv(String) 把java对象变成json字符串
    		 * 5、拿缓存:把字符串转换成java对象List<ItemCat>
    		 */
    		itemCat.setParentId(parentId);
    		// 判断缓存中有无数据
    		// 定义键
    		String ITEM_CAT_KEY = "ITEM_CAT_" + parentId;
    		// 根据键获取数据
    		String jsonData = redisService.get(ITEM_CAT_KEY);
    		if (StringUtils.isNotEmpty(jsonData)) { // 缓存中有数据
    			try {
    				// 直接从缓存中获取数据,把json串转换为java对象
    				JsonNode jsonNode = MAPPER.readTree(jsonData);
    
    				Object obj = null;
    				if (jsonNode.isArray() && jsonNode.size() > 0) {
    					obj = MAPPER.readValue(jsonNode.traverse(),
    							MAPPER.getTypeFactory().constructCollectionType(List.class, ItemCat.class));
    				return (List<ItemCat>) obj;
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		} else {//如果缓存中没有数据,执行业务
    			try {
    			//从数据库中获取数据
    			List<ItemCat> itemCatList = itemCatMapper.select(itemCat);
    			//将数据保存一份在缓存中
    				//将数据转换成json对象
    				String json = MAPPER.writeValueAsString(itemCatList);
    				//将对象保存进缓存
    				redisService.set(ITEM_CAT_KEY, json);
    			//返回需要的对象
    			return itemCatList;
    			} catch (JsonProcessingException e) {
    				e.printStackTrace();
    			}
    		}
    		return null;
    	}
    }
    
  • 相关阅读:
    一个简单的aJax——后台用servlet技术
    js获取项目根路径
    在SpringMVC利用MockMvc进行单元测试
    java.lang.NoSuchMethodError: javaxservlet.http.HttpServletRequest.isAsyncStarted()Z
    保利威视点播集成
    微信登录后返回微信名等信息
    极光推送发送控制/别名/取值
    每天首次登陆记录设备信息
    获取APK签名
    权限管理AppOpsManager
  • 原文地址:https://www.cnblogs.com/sxpy-lj/p/7290466.html
Copyright © 2011-2022 走看看