必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

在以往的web开发工作时必威:,使用了一些单机

2019-12-08 09:06 来源:未知

四、大旨技艺详细

  1.SAEA.RedisSocket:那么些是依靠SAEA.Socket实现的Redis编解码命令的客商端,最近包裹了多方的redis数据操作命令和全方位的redis cluster命令,更加多详细可参照。

  2.SAEA.WebApi:这一个是基于SAEA.Socket达成的http编解码命令的服务端,如今已兑现了get、post的拍卖,帮助两种form的解码;並且已购并了mvc风格的编码框架,越来越多详细可参看。

  3.LayUI:这么些是风传中面向后端开垦人士的Web框架,制版上是仿Bootstrap的品格,集成了大批量的插件,能够飞快完毕相关的web页面效用,越多详细可仿效:。

Java Spring mvc 操作 Redis 及 Redis 集群,mvcredis

 本文原创,转发请注脚:

至于 Redis 集群搭建能够参照他事他说加以考查我的另后生可畏篇小说 Redis集群搭建与简单利用

Redis 是怎么着,能做哪些

Redis 是叁个开源(BSD许可),内部存款和储蓄器存款和储蓄的数据结构服务器,可用作数据库,高速缓存和新闻队列代理。它扶植字符串、哈希表、列表、会集、有序集中,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务甚至分化等级磁盘长久化效用,同期经过Redis Sentinel 提供高可用,通过 Redis Cluster 提供自动分区。(摘自 Redis 官方网站卡塔尔(英语:State of Qatar)

用作内部存款和储蓄器数据库,在现代互连网 web 系统中,依然主要将 Redis 作为缓存使用。大型网络 Web 系统对品质须求超级高,而在前端和数据层之间增添数据缓存已化作不可贫乏的手腕之风流倜傥,当前相比流行的三个技能正是 Redis 和 Memcached,至于双方有何差别,不是本文要说的剧情。本文首要讲 Java web 怎么样操作 Redis 及 Redis 集群。

雷同 Java 程序操作Redis

Redis 提供了二种语言的客商端,在 Java 中最盛行的是 Jedis 。访问可查看源码及应用方法。最近 Jedis 最新版本是2.9.0。无论是单机照旧集群,Jedis 都有很详细的验证和实例代码,这里只做轻便表明。就算用 Maven 做包处理,需求引用  jedis 包,本例使用新型的2.9.0本子,如下:

<dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
</dependency>  

操作 Redis 单机

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Created by fengdezitai on 2016/10/9.
 */
public class JedisClient {

    private static final String host= "192.168.31.121";

    private static final JedisClient jedisClient = new JedisClient();

    private Jedis jedis = null;
    /**
     * 私有构造函数
     */
    private JedisClient(){}

    public static JedisClient getInstance(){
        return jedisClient;
    }

    private JedisPoolConfig getPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMaxTotal(100);
        jedisPoolConfig.setMaxWaitMillis(3000);
        return jedisPoolConfig;
    }

    /**
     * 添加
     * @param key
     * @param value
     * @return
     * @throws Exception
     */
    public Boolean add(String key,String value) throws Exception{
        JedisPool pool = new JedisPool(getPoolConfig(),host);
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            if(jedis.exists(key)){
                throw new Exception(String.format("key (%s) 已存在 ",key));
            }
            jedis.set(key,value);

        }catch (Exception e){
            throw e;
        }
        finally {
            if(jedis!=null){
                jedis.close();
            }
        }
        pool.destroy();
        return true;
    }

    /**
     * 获取值
     * @param key
     * @return
     * @throws Exception
     */
    public String get(String key) throws Exception{
        JedisPool pool = new JedisPool(getPoolConfig(),host);
        Jedis jedis = null;
        String result = "";
        try {
            jedis = pool.getResource();
            result = jedis.get(key);
        }catch (Exception e){
            throw e;
        }
        finally {
            if(jedis!=null){
                jedis.close();
            }
        }
        pool.destroy();
        return result;
    }

    public static void main(String[] args) {
        JedisClient jedisClient = JedisClient.getInstance();
        try {
            /*Boolean result = jedisClient.add("hello", "redis1");
            if(result){
                System.out.println("success");
            }*/

            System.out.println(jedisClient.get("hello"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

操作 redis 集群

import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by fengdezitai on 2016/10/13.
 */
public class JedisClusterClient {

    private static int count = 0;

    private static final JedisClusterClient redisClusterClient = new JedisClusterClient();

    /**
     * 私有构造函数
     */
    private JedisClusterClient() {}

    public static JedisClusterClient getInstance() {
        return redisClusterClient;
    }

    private JedisPoolConfig getPoolConfig(){
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(1000);
        config.setMaxIdle(100);
        config.setTestOnBorrow(true);
        return config;
    }

    public void SaveRedisCluster() {
        Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
        jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7000));
        jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7001));
        jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7002));
        jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7003));
        jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7004));
        jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7005));

        JedisCluster jc = new JedisCluster(jedisClusterNodes,getPoolConfig());
        jc.set("cluster", "this is a redis cluster");
        String result = jc.get("cluster");
        System.out.println(result);
    }

    public static void main(String[] args) {
        JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
        jedisClusterClient.SaveRedisCluster();
    }
}  

Spring mvc 操作 Redis

在 Spring mvc 中操作 Redis ,首先当然要搭好 Spring mvc 框架了。以下是在若是 Spring mvc 情形已经架好的意况下。本例中 Spring 版本为 4.3.2 RELEASE。关于 Spring 的 maven 援用如下:

<!-- spring版本号 -->
<spring.version>4.3.2.RELEASE</spring.version>

<!-- spring核心包 -->
    <!-- springframe start -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
      <exclusions>
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>


    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- springframe end -->

操作 Redis 单机

只用 Jedis 本人完成注入(差异于上边包车型地铁引用spring-data-redis) 

把前边的 JedisClient 代码拿过来援引就能够,只需兑现三个拜望 Redis 的 瑟维斯 ,就足以合二为少年老成到 Spring mvc 。Service 代码如下:

import org.springframework.stereotype.Service;
import util.JedisClient;

/**
 * Created by fengdezitai on 2016/10/9.
 */
@Service
public class RedisService {

    public String get(String key) throws Exception{
        JedisClient jedisClient = JedisClient.getInstance(); //上面实现的JedisClient
        String result = "";
        try {
            result = jedisClient.get("hello");
        }catch (Exception e){
            throw e;
        }
        return result;
    }
}

Controller 完成如下:

@Controller
@RequestMapping(value = "redisAllInOne")
public class RedisAllInOneController {

    @Autowired
    private RedisService redisService;

    @RequestMapping(value = "get",method = RequestMethod.GET)
    @ResponseBody
    public Object getByMyService(String key){
        try {
            String result = redisService.get(key);
            return result;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}  

用 spring-data-redis 包做集成

地方是团结实现的流入,这里用 spring-data-redis 进行集成,只需简单陈设就能够,需求援用 maven 包如下,版本为日前前卫版 1.7.2.RELEASE:

<dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>1.7.2.RELEASE</version>
    </dependency>

采纳 spring-data-redis ,即省去了本身完毕注入的进度,通过它提供的少年老成部分配置,就能够兑现连接池配置、RedisTemplate 配置、JedisConnectionFactory 配置;通过 JedisConnectionFactory 可配备连接池参数、redis 服务器、端口、密码、超时时间、database索引等;RedisTemplate 即注入的bean ,能够应用 RedisTemplate 自动注入的实业实行 redis 的一丰富多彩操作,具体看布置;

redis 服务性质配置文件:

redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
redis.host=192.168.31.121
redis.port=6379
redis.password=password
redis.timeout=3000

spring-data-redis xml 配置文件 redis-context.xml:

<!-- jedis 连接池 配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    <!-- redis服务器中心 -->
    <bean id="connectionFactory"  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
        <property name="poolConfig" ref="poolConfig" />
        <property name="port" value="${redis.port}" />
        <property name="hostName" value="${redis.host}" />
        <!--<property name="password" value="${redis.password}" />-->
        <property name="timeout" value="${redis.timeout}" ></property>
        <property name="database" value="1"></property>
    </bean>

    <bean id="commonRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

    <bean id="connectionFactory1"  class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
        <property name="poolConfig" ref="poolConfig" />
        <property name="port" value="${redis.port}" />
        <property name="hostName" value="${redis.host}" />
        <!--<property name="password" value="${redis.password}" />-->
        <property name="timeout" value="${redis.timeout}" ></property>
        <property name="database" value="2"></property>
    </bean>

    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    <bean id="cacheRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
        <property name="connectionFactory" ref="connectionFactory1" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

其后在 spring 配置文件中援用以上文件:

<import resource="redis-context.xml" />  

解释一下上边的布置:

poolConfig 即配置 redis 连接池,之后安插了四个 JedisConnectionFactory 和 RedisTemplate ,贰个 RedisTemplate 对应二个 JedisConnectionFactory ,那样能够安顿依照气象布局不一样的 Redis 连接,比方超时时间必要不均等、database 0-15 能够储存不一样的数量等。这里就铺排了database 1 和 2 ,调用 commonRedisTemplate 会存到 database1 ,调用 cacheRedisTemplate 会存到 database2。

今后在 瑟维斯 层就能够注入并引用那多少个 RedisTemplate ,如下代码:

import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.io.*;

@Repository
public class RedisCache {
  
    @Resource(name = "cacheRedisTemplate")
    private RedisTemplate<String, String> cacheRedisTemplate;

    public void put(Object key, Object value) {
        if(null == value) {
            return;
        }

        if(value instanceof String) {
            if(StringUtils.isEmpty(value.toString())) {
                return;
            }
        }

        // TODO Auto-generated method stub
        final String keyf = key + "";
        final Object valuef = value;
        final long liveTime = 86400;

        cacheRedisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                byte[] keyb = keyf.getBytes();
                byte[] valueb = toByteArray(valuef);
                connection.set(keyb, valueb);
                if (liveTime > 0) {
                    connection.expire(keyb, liveTime);
                }
                return 1L;
            }
        });
    }

    public Object get(Object key) {
        final String keyf = (String) key;
        Object object;
        object = cacheRedisTemplate.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection)
                    throws DataAccessException {

                byte[] key = keyf.getBytes();
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                return toObject(value);

            }
        });

        return object;
    }

    /**
     * 描述 : <byte[]转Object>. <br>
     * <p>
     * <使用方法说明>
     * </p>
     *
     * @param bytes
     * @return
     */
    private Object toObject(byte[] bytes) {
        Object obj = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            obj = ois.readObject();
            ois.close();
            bis.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        return obj;
    }

    private byte[] toByteArray(Object obj) {
        byte[] bytes = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            bytes = bos.toByteArray();
            oos.close();
            bos.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return bytes;
    }
}

最后在 Controller 中调用就能够

    @Autowired
    private RedisCache redisCache;


    @RequestMapping(value = "get", method = RequestMethod.GET)
    @ResponseBody
    public Object getByMyService(String key) {
        try {
            String result = redisService.get(key);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value = "save", method = RequestMethod.GET)
    @ResponseBody
    public Object save() {
        Token token = new Token();
        token.setAccess_token("token");
        token.setExpires_in(1000);
        try {
            redisCache.put("token", token);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "ok";
    }  

操作 Redis 集群

只用 Jedis 本身完结注入(差异于上面包车型客车征引spring-data-redis)

把前边的 JedisClusterClient 代码拿过来引用就可以,只需兑现叁个寻访 Redis 的 Service ,就足以合二为风流倜傥到 Spring mvc 。Service 代码如下:

import org.springframework.stereotype.Service;
import util.JedisClusterClient;

/**
 * Created by fengdezitai on 2016/10/13.
 */
@Service
public class RedisClusterService {

    public void save() throws Exception{
        //调用 JedisClusterClient 中的方法
        JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
        try {
            jedisClusterClient.SaveRedisCluster();
        }catch (Exception e){
            throw e;
        }
    }
}

最后在 Controller 中调用完毕的 Service 就可以

@Controller
@RequestMapping(value = "redisCluster")
public class RedisClusterController {

    @Autowired
    private RedisClusterService redisClusterService;

    @RequestMapping(value = "save",method = RequestMethod.GET)
    @ResponseBody
    public Object save(){
        try{
            redisClusterService.save();
        }catch (Exception e){
            e.printStackTrace();
            return String.format("error: %s",e.getMessage());
        }
        return "ok";
    }
}  

用 spring-data-redis 包做集成 

Spring 和 spring-data-redis maven 包引用和方今生龙活虎致,之所以引用 spring-data-redis 1.7.2.RELEASE,是因为近期独有那么些新型版本才支撑集群操作。

redis 集群服务个性配置

redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=false
redis.timeout=3000

spring-data-redis xml 集群配置文件 redis-cluster-context.xml

<!-- 连接池 配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>


    <bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="3"></property>
        <property name="clusterNodes">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.245"></constructor-arg>
                    <constructor-arg name="port" value="7000"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.245"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.245"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.210"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.210"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.31.210"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean>
            </set>
        </property>
    </bean>

    <bean id="redis4CacheConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        <property name="timeout" value="${redis.timeout}" />
        <property name="poolConfig" ref="poolConfig"/>
    </bean>


    <bean name="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>

而后在 Spring 配置文件中援引

<import resource="redis-cluster-context.xml" />

解说以上配置

poolConfig是连接池配置,redisClusterConfig 配置了 Redis 集群的大器晚成后生可畏节点(节点 host 和 port 最佳写在性质配置文件中),集群搭建可以看到小编的 另蓬蓬勃勃篇博客 。然后上边和单机配置相仿了,意气风发对 JedisConnectionFactory 和 RedisTemplate 。

之后在 Service 层就能够注入并引述这几个 RedisTemplate,代码如下:

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.io.*;

/**
 * Created by fengdezitai on 2016/9/29.
 */
@Repository
public class RedisClusterCache {

    @Autowired
    private RedisTemplate clusterRedisTemplate;


    public void put(Object key, Object value) {
        if(null == value) {
            return;
        }

        if(value instanceof String) {
            if(StringUtils.isEmpty(value.toString())) {
                return;
            }
        }

        // TODO Auto-generated method stub
        final String keyf = key + "";
        final Object valuef = value;
        final long liveTime = 86400;

        clusterRedisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                byte[] keyb = keyf.getBytes();
                byte[] valueb = toByteArray(valuef);
                connection.set(keyb, valueb);
                if (liveTime > 0) {
                    connection.expire(keyb, liveTime);
                }
                return 1L;
            }
        });
    }

    public Object get(Object key) {
        final String keyf = (String) key;
        Object object;
        object = clusterRedisTemplate.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection)
                    throws DataAccessException {

                byte[] key = keyf.getBytes();
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                return toObject(value);

            }
        });

        return object;
    }

    /**
     * 描述 : <byte[]转Object>. <br>
     * <p>
     * <使用方法说明>
     * </p>
     *
     * @param bytes
     * @return
     */
    private Object toObject(byte[] bytes) {
        Object obj = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            obj = ois.readObject();
            ois.close();
            bis.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
        return obj;
    }

    private byte[] toByteArray(Object obj) {
        byte[] bytes = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            bytes = bos.toByteArray();
            oos.close();
            bos.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return bytes;
    }
}

末尾在 Controller 中调用就能够

@Controller
@RequestMapping(value = "redisCluster")
public class RedisClusterController {

    @Autowired
    private RedisClusterCache redisClusterCache;

    @RequestMapping(value = "clusterSave",method = {RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public Object clusterSave(){
        //redisClusterCache.put("cluster","save cluster");
        Token token = new Token();
        token.setExpires_in(1000);
        token.setAccess_token("hello world");
        redisClusterCache.put("token",token);
        return "ok";
    }

    @RequestMapping(value = "getKey",method = RequestMethod.GET)
    @ResponseBody
    public Object getCluster(String key){
        Object val = redisClusterCache.get(key);
        return val;
    }
} 

注意事项:

  • 本子难点,若是用 spring-data-redis 做集成操作 Reids 集群,唯有 spring-data-redis 目前新型版本1.7才含有对集群的操作,而新颖的 spring-data-redis 中的有些职能对 Spring mvc 的本子也可以有个别限定,所以尽或然筛选高版本的 Spring mvc 对应。
  • 若果存款和储蓄的value值是二个实体对象,那么必然要兑现 Serializable 接口

 

Spring mvc 操作 Redis 及 Redis 集群,mvcredis 本文原创,转发请评释: 关于 Redis 集群搭建能够参见作者的另...

二个卓有作用的方法正是行使redis的Redis Mass Insertion – Redis)方式。

二、使用mongoose访问MongoDB

mongoose对于二个pythoner来讲,使用起来实际不是很顺手,因为它跟mongoengine相当莫衷一是,后面一个使用Documentation来定义数据模型,而它用的是Schema和Model,至于具体怎么个弄法,依旧看这里。

我们的言传身教呢,简单地持续,创造文件mongo.js,代码如下:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// 使用node的Promise替换mongoose的Promise,否则会报错
mongoose.Promise = global.Promise;

// 可配置项
var host = '127.0.0.1';
var port = '27017';
var dbName = 'test';

var dbUri = `${host}:${port}/${dbName}`;
var dbConnection = mongoose.createConnection(dbUri);
dbConnection.on('error', (err) => {
    console.log('connect mongodb failed: ' + err);
    process.exit();
});

var dbSchemas = {
    // 定义user的Schema
    // 包括身份证号码、姓名、性别、手机等
    userSchema: {
        idno: {type: String, require: true, unique: true},
        name: {type: String, require: true},
        gender: {type: Number, require: true},
        phone: {type: String},
        created: {type: Date, default: Date.now}
    }
};

// 定义UserModel
class UserModel {
    constructor(connection, schema) {
        this.name = 'user';
        this.schema = new Schema(schema);
        this.model = connection.model(`userModel`, this.schema, this.name);
    }

    // 封装查询
    findByIdno(idno) {
        return new Promise((resolve, reject) => {
            this.model.findOne({'idno': {$eq: idno}}, (err, record) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(record);
                }
            });
        });
    }

    // 封装插入or更新
    insertOrUpdateByIdno(data) {
        return new Promise((resolve, reject) => {
            this.model.findOne({'idno': {$eq: data.idno}}, (err, record) => {
                if (err) {
                    reject(err);
                } else {
                    if (record == undefined) {
                        // 插入
                        var instance = new this.model(data);
                        instance.save((err) => {
                            if (err) {
                                reject(err);
                            } else {
                                resovle(data);
                            }
                        });
                    } else {
                        // 更新
                        this.model.findOneAndUpdate({'idno': {$eq: data.idno}}, data, {new: true, upsert: true}, (err, res) => {
                            if (err) {
                                reject(err);
                            } else {
                                resolve(res);
                            }
                        });
                    }
                }
            });
        });
    }
}

var user = new UserModel(dbConnection, dbSchemas.userSchema);

exports.user = user;

地方代码中利用到了ES6的好些个表征,包含Promise机制、Class以至“箭头”函数等,做的专门的学问则有:

  1. 建立与MongoDB的连接dbConnection
  2. 使用Node的Promise来替换mongoose的Promise(被弃用)
  3. 证明user的数据构造userSchema
  4. 构造UserModel的类
  5. 在UserModel中封装了对MongoDB的查询(findOne卡塔尔(英语:State of Qatar)、插入(save卡塔尔、更新(findOneAndUpdate卡塔尔(قطر‎操作
  6. 实例化UserModel对象,并export以供调用

一、简介

  近些日子因为专业急需,使用了生龙活虎部分单机版Redis的分界面化处理工具,使用进程中那伤心的体会真正独有用过的人能力体味;为此小编和友人准备入手二个Redis可视化学工业具,可是因为小同伴近年来职业比较忙,搞了大多数未有的时候间继续(会有世袭,分界面不敢说,使用体验方面分明要比现成的好);本身对wpf不是很熟,再想到从古至今的web迅雷,就想入手达成两个web版的Redis的分界面化处理工科具;这段时间这些工具已从前成型,所以放出去分享一下。

字串编码

Redis的下令为 命令+参数。全部指令中,无怪乎就只有字串和数字。编码字串的格式为,以$标志开始,然后跟随字串的尺寸,接下去是字串本人,最终再加多贰个CXC60LF分隔符就可以。大概情势如下:

$ + string_length + string + CRLF

例如hello可以编码为$5rnhellorn, 字串’21.7’编码成$3rn21.7rn。

四、设计并完毕api接口

现行反革命数据模型的定义已经做到,就足以开头展开工作逻辑的完毕。
依据model的定义,大家领会已贯彻的数据库操作包含user、token、cookie的立异(饱含创制)和查询,由于后两个都以redis的操作,大家就贯彻user和cookie的操作好了。
在app.js中,server.use代码块下方、server.listen上方区域增进如下代码:

var route = require('./route');

// api route
server.post('/user/update', route.updateUser);
server.get('/user/get', route.getUser);

server.post('/cookie/update', route.updateCookie);
server.get('/cookie/get', route.getCookie);

能够看来援用了三个route.js文件,如今还尚未该文件,须要新建route.js来落到实处业务逻辑,代码如下:

var user = require('./mongo').user;
var session = require('./redisClient').session; 

// 创建/更新user
// post的数据通过req.body传递
// 此处约定使用json格式,bodyParser可解析
exports.updateUser = function(req, res) {
    // 此处省略数据合法性的检查
    let data = {
        idno: req.body.idno,
        name: req.body.name,
        gender: req.body.gender,
        phone: req.body.phone
    };

    // 设置response为utf-8编码
    res.charSet('utf-8');   
    // 设置返回数据格式为json
    res.setHeader('Content-Type', 'application/json');
    user.insertOrUpdateByIdno(data)
        .then(function(record) {
            res.send({code: 0, msg: '创建/更新user成功', result: record});
        }, function(err) {
            console.log(err);
            res.send({code: 1, msg: '创建/更新user失败', result: {}});
        });
};

// 查询user
// get的参数直接在url中,queryParser可解析
exports.getUser = function(req, res) {
    let idno = req.query.idno;
    // 设置response为utf-8编码
    res.charSet('utf-8');   
    // 设置返回数据格式为json
    res.setHeader('Content-Type', 'application/json');
    user.findByIdno(idno)
        .then(function(record) {
            res.send({code: 0, msg: 'user查询成功', result: record});
        }, function(err) {
            console.log(err);
            res.send({code: 1, msg: 'user查询失败', result: {}});
        });
};

// 设置/更新Cookie
// post提交的数据,有uuid为更新,没uuid为新建
exports.updateCookie = function(req, res) {
    let uuid = req.body.uuid ? req.body.uuid : genUuid();
    let cookie = req.body;
    delete cookie.uuid;        // 不论有没有都是true
    res.charSet('utf-8');
    res.setHeader('Content-Type', 'application/json');
    session.updateCookie(uuid, cookie)
        .then(function(r) {
            res.send({code: 0, msg: '更新/新建Cookie成功', 
                result: {uuid: uuid, data: cookie}});
        }, function(e) {
            console.log(e);
            res.send({code: 1, msg: '更新/新建Cookie成功', result: {}});
        });
};

// 根据uuid查询Cookie
exports.getCookie = function(req, res) {
    let uuid = req.query.uuid;
    res.charSet('utf-8');
    res.setHeader('Content-Type', 'application/json');
    session.getCookie(uuid)
        .then(function(record) {
            res.send({code: 0, msg: '获取Cookie成功', result: record});
        }, function(err) {
            console.log(err);
            res.send({code: 1, msg: '获取Cookie失败', result: {}});
        });
};

function genUuid() {
    return Math.random().toString() + Math.random().toString();
}

三、开采简要介绍

  下边根本是根据SAEA.Socket通讯框架中的SAEA.RedisSocket、SAEA.WebApi八个构件来完结redis通讯、webserver以致仿asp.net mvc的便捷风格的后端程序,web端使用的是layui+ajax。项目源码布局:

  必威 1

 

实现

达成一个RedisProto的class,然后提供pack_command方法打包命令进行编码,其参数正是redis命令各部分,redis命令能够选取空格分开成为四个元组。

例如: SET hello world为 (‘SET’, ‘hello’, ‘world’)

GET hello为 (‘GET’, ‘hello’)

HSET key name python 为 (‘HSET’, ‘key’, ‘name’, ‘python’)

下面为 python2的实现。

#!/usr/bin/env python
# -*- coding:utf-8 -*-


class Token(object):
    def __init__(self, value):
        if isinstance(value, Token):
            value = value.value
        self.value = value

    def __repr__(self):
        return self.value

    def __str__(self):
        return self.value

def b(x):
    return x


SYM_STAR = b('*')
SYM_DOLLAR = b('$')
SYM_CRLF = b('rn')
SYM_EMPTY = b('')


class RedisProto(object):
    def __init__(self, encoding='utf-8', encoding_errors='strict'):
        self.encoding = encoding
        self.encoding_errors = encoding_errors

    def pack_command(self, *args):
        """将redis命令安装redis的协议编码,返回编码后的数组,如果命令很大,返回的是编码后chunk的数组"""
        output = []
        command = args[0]
        if ' ' in command:
            args = tuple([Token(s) for s in command.split(' ')]) + args[1:]
        else:
            args = (Token(command),) + args[1:]

        buff = SYM_EMPTY.join(
            (SYM_STAR, b(str(len(args))), SYM_CRLF))

        for arg in map(self.encode, args):
            # 数据量特别大的时候,分成部分小的chunk
            if len(buff) > 6000 or len(arg) > 6000:
                buff = SYM_EMPTY.join((buff, SYM_DOLLAR, b(str(len(arg))), SYM_CRLF))
                output.append(buff)
                output.append(arg)
                buff = SYM_CRLF
            else:
                buff = SYM_EMPTY.join((buff, SYM_DOLLAR, b(str(len(arg))), SYM_CRLF, arg, SYM_CRLF))

        output.append(buff)
        return output

    def encode(self, value):
        if isinstance(value, Token):
            return b(value.value)
        elif isinstance(value, bytes):
            return value
        elif isinstance(value, int):
            value = b(str(value))
        elif not isinstance(value, str):
            value = str(value)
        if isinstance(value, str):
            value = value.encode(self.encoding, self.encoding_errors)
        return value


if __name__ == '__main__':
    """ python redis_insert.py | redis-cli --pipe """

    commands_args = [('SET', 'Hello', 'World'),
                      ('Set', 'Country', '{"name": 中国"}'),
                      ('HSET', 'Key', 'Name', 'Python'),
                      ('HMSET', 'user', 'name', 'Rsj217', 'Age', '21')]

    commands = ''.join([RedisProto().pack_command(*args)[0] for args in commands_args])
    print commands

末段实施 python redis_insert.py | redis-cli --pipe 就能够,重临如下:

$ python redis_insert.py | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 4

终极实地衡量了风流洒脱晃,单条循环插入100w数据大概要求20多分钟,使用pipline方式只要求不到15s。

三、使用redis访问Redis

Redis相相比较MongoDB来讲,速度越来越快,因为存款和储蓄在内部存储器中嘛(可长久化),由此比MongoDB更适合用来管理Session。
Redis的运用也更简便,无论是写代码依旧在redis-cli中敲命令,帮助7种数据类型的读写(从前写的5种是因为本人也是看的二手资料,现改过),每一个数据类型的命令都比不上,具体的要么看一下原味的redis数据类型介绍,直接看一手新闻防止入坑,然后代码交互作用的话能够参见一下node-redis.

那边示例继续,成立redisClient.js,代码如下:

var redis = require('redis');

// 可配置项
var host = '127.0.0.1';
var port = 6379;

var client = redis.createClient(port, host, {});

client.on('ready', (res) => {
    console.log('redis ready: ' + res);
});

client.on('error', (err) => {
    console.log('connect redis error: ' + err);
    process.exit(2);
});

// 假设cookie为哈希,token为string
class Session {
    constructor(client) {
        this.client = client;
    }

    // 设置/更新Cookie以及设置/重设有效期,默认10分钟。
    updateCookie(uuid, cookie, t) {
        t = t ? t: 600;    // 默认10分钟
        return new Promise((resolve, reject) => {
            let key = uuid + ':cookie';
            this.client.hmset(key, cookie, (err, res1) => {
                if (err) {
                    console.log('redis hmset error: ' + err);
                    reject(err);
                } else {
                    // 设置有效期
                    this.client.expire(key, t, (err, res2) => {
                        if (err) {
                            console.log('erdis hmset expire error: ' + err);
                            reject(err);
                        } else {
                            resolve(res2 === 1);
                        }
                    });
                }
            });
        });
    }

    // 查询Cookie
    getCookie(uuid) {
        return new Promise((resolve, reject) => {
            let key = uuid + ':cookie';
            this.client.hgetall(key, (err, record) => {
                if (err) {
                    console.log('redis hgetall error: ' + err);
                } else {
                    resolve(record);
                }
            });
        });
    }

    // 设置or更新token,同样设置有效期,默认10分钟
    updateToken(uuid, token, t) {
        t = t ? t : 600;
        return new Promise((resolve, reject) => {
            let key = uuid + ':token';
            this.client.set(key, token, (err, res1) => {
                if (err) {
                    console.log('redis set error: ' + err);
                    reject(err);
                } else {
                    this.client.expire(key, t, (err, res2) => {
                        if (err) {
                            console.log('redis set expire error: ' + err);
                            reject(err);
                        } else {
                            resolve(res2 === 1);
                        }
                    });
                }
            });
        });
    }

    getToken(uuid) {
        return new Promise((resolve, reject) => {
            let key = uuid + ':token';
            this.client.get(key, (err, record) => {
                if (err) {
                    cosole.log('redis get error: ' + err);
                    reject(err);
                } else {
                    resolve(record);
                }
            });
        });
    }

    delUuid(uuid) {
        this.client.del(uuid + ':cookie');
        this.client.del(uuid + ':token');
    }
}

var session = new Session(client);

module.exports =  {
    session: session
};

下面达成的行事包括:

  1. 建立redis的client
  2. 定义Session的model
  3. 封装hash和string两种数据类型(库克ie和Token)的读写以至去除
  4. 实例化Session并export以供调用(这里的export操作使用了另大器晚成种样式)
TAG标签:
版权声明:本文由必威发布于必威-编程,转载请注明出处:在以往的web开发工作时必威:,使用了一些单机