Redis(3)-----初识Redis-----redis连接方式(java代码)

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

一,链接redis

1.1,java代码

 

  static Jedis jedis = new Jedis("127.0.01");

    /**
     * https://blog.csdn.net/z23546498/article/details/73556260 测试链接
     */
    @Test
    public void getJedis() {

        jedis.set("hello", "world");
        String output = jedis.get("hello");
        System.out.println(output);
    }

1.2,连接池连接

 

@Test
    public void testJedisPool() {
        //创建一连接池对象
        JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
        //从连接池中获得连接
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get("mytest");
        System.out.println(result);
        //关闭连接
        jedis.close();
        
        //关闭连接池
        jedisPool.close();
    }

 

 

 

1.3,Spring整合jedisPool

<?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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!-- 连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大连接数 -->
        <property name="maxTotal" value="30" />
        <!-- 最大空闲连接数 -->
        <property name="maxIdle" value="10" />
        <!-- 每次释放连接的最大数目 -->
        <property name="numTestsPerEvictionRun" value="1024" />
        <!-- 释放连接的扫描间隔(毫秒) -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 连接最小空闲时间 -->
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
        <property name="maxWaitMillis" value="1500" />
        <!-- 在获取连接的时候检查有效性, 默认false -->
        <property name="testOnBorrow" value="false" />
        <!-- 在空闲时检查有效性, 默认false -->
        <property name="testWhileIdle" value="true" />
        <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
        <property name="blockWhenExhausted" value="false" />
    </bean>

    <!-- redis单机 通过连接池 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool"
        destroy-method="close">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="192.168.242.130" />
        <constructor-arg name="port" value="6379" />
    </bean>
</beans>

 

测试代码

@Test
    public void testJedisPool() {
        JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool");
        Jedis jedis = null;
        try {
            jedis = pool.getResource();

            jedis.set("name", "lisi");
            String name = jedis.get("name");
            System.out.println(name);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                // 关闭连接
                jedis.close();
            }
        }
    }

 

 二,String类型

/**
     * 1,redis操作字符串
     * 
     * @throws InterruptedException
     */
    @Test
    public void testString() throws InterruptedException {
        jedis.select(1);
        jedis.set("testString", "123"); // 往redis中放入字符串

        System.out.println("1-----从redis中获取刚刚放进去的testString:" + jedis.get("testString"));

        jedis.incr("testString"); // 自增,不存在testInt则自增结果是1,如果不是字符串,自增会报JedisDataException

        System.out.println("2-----从redis中获取自增后的testString:" + jedis.get("testString"));

        jedis.decr("testString"); // 自减,效果同自增

        System.out.println("3-----从redis中获取自减后的testString:" + jedis.get("testString"));

        // incrby方法可以自定要增加多少

        jedis.append("testString", "456abcd"); // 在后面追加

        System.out.println("4-----从redis中获取追加后的testString:" + jedis.get("testString"));

        String sub = jedis.substr("testString", 2, 6); // 切割字符串

        System.out.println("5-----substr方法的返回值:" + sub);

        System.out.println("6-----从redis中获取切割后的testString:" + jedis.get("testString")); // 可以看出,substr方法并不会破坏原有值,只是取出来加工而已

        jedis.rename("testString", "newString"); // 字段改名,值不会变

        System.out.println("7-----testString改名成newString后,值为:" + jedis.get("newString"));

        String type = jedis.type("newString");// 获取其数据类型

        System.out.println("8-----newString的数据类型是:" + type);

        long length = jedis.strlen("newString"); // 获取字符串长度

        System.out.println("9-----newString的字符串长度为:" + length);

        jedis.set("testString6", "哈哈");

        jedis.set("testString7", "呵呵");

        jedis.set("testString8", "helloword");

        jedis.set("testString99", "SMSP");

        Set<String> keys = jedis.keys("*"); // 获取所有符合条件的键

        System.out.println("10-----返回redis中所有的键:" + keys);

        keys = jedis.keys("*String?");

        System.out.println("11-----返回redis中所有正则符合*String?的键:" + keys);

        jedis.del("testString"); // 字符串删除

        System.out.println("12-----从redis删除testInt后,testInt是否还存在:" + jedis.exists("testString"));
        System.out.println("12-----从redis删除testInt后,testInt是否还存在:" + jedis.exists("testString99"));

        jedis.set("testString2", "你好啊!!!");

        jedis.expire("testString2", 2); // 设置有效期,单位是秒

        System.out.println("13-----从redis中获取testString2的值为:" + jedis.get("testString2"));

        Thread.sleep(3000);

        System.out.println("14-----3秒后从redis中获取testString2的值为:" + jedis.get("testString2")); // 过期了,会找不到该字段,返回null

        // ttl方法可以返回剩余有效时间,expire如果方法不指定时间,就是将该字段有效期设为无限
    }

 

 

1-----从redis中获取刚刚放进去的testString:123
2-----从redis中获取自增后的testString:124
3-----从redis中获取自减后的testString:123
4-----从redis中获取追加后的testString:123456abcd
5-----substr方法的返回值:3456a
6-----从redis中获取切割后的testString:123456abcd
7-----testString改名成newString后,值为:123456abcd
8-----newString的数据类型是:string
9-----newString的字符串长度为:10
10-----返回redis中所有的键:[testString99, testString6, testString7, testString8, newString]
11-----返回redis中所有正则符合*String?的键:[testString7, testString8, testString6]
12-----从redis删除testInt后,testInt是否还存在:false
12-----从redis删除testInt后,testInt是否还存在:true
13-----从redis中获取testString2的值为:你好啊!!!
14-----3秒后从redis中获取testString2的值为:null

 

三,list类的基本操作,有序可重复

  @Test
    public void list() {
        jedis.select(2);
        // 列表的插入与获取(可以重复)

        jedis.lpush("testList", "Redis"); // 从左边插入

        jedis.lpush("testList", "Mongodb");

        jedis.lpush("testList", "Mysql");

        jedis.lpush("testList", "Mysql");

        jedis.rpush("testList", "DB2"); // 从右边插入

        List<String> list = jedis.lrange("testList", 0, -1); // 从左到右遍历,3个参数分别是,key,开始位置,结束位置(-1代表到最后)

        for (int i = 0; i < list.size(); i++) {

            System.out.printf("从redis中获取刚刚放进去的testList[%d]: %s\n", i, list.get(i));

        }

        System.out.println();

        String lpop = jedis.lpop("testList"); // 删掉最左边的那个

        String rpop = jedis.rpop("testList"); // 删掉最右边的那个

        System.out.printf("被删的左边元素是:%s,被删的右边元素是:%s\n", lpop, rpop);

        list = jedis.lrange("testList", 0, -1);

        for (int i = 0; i < list.size(); i++) {

            System.out.printf("从redis中获取被删除后的testList[%d]: %s\n", i, list.get(i));

        }

        System.out.println();

        jedis.ltrim("testList", 1, 2); // 裁剪列表,三个参数分别是,key,开始位置,结束位置

        list = jedis.lrange("testList", 0, -1);

        for (int i = 0; i < list.size(); i++) {

            System.out.printf("从redis中获取被裁剪后的testList[%d]: %s\n", i, list.get(i));

        }

        jedis.del("testList"); // 删除列表

        System.out.println("从redis删除testList后,testList是否还存在:" + jedis.exists("testList"));

    }
从redis中获取刚刚放进去的testList[0]: Mysql
从redis中获取刚刚放进去的testList[1]: Mysql
从redis中获取刚刚放进去的testList[2]: Mongodb
从redis中获取刚刚放进去的testList[3]: Redis
从redis中获取刚刚放进去的testList[4]: DB2

被删的左边元素是:Mysql,被删的右边元素是:DB2
从redis中获取被删除后的testList[0]: Mysql
从redis中获取被删除后的testList[1]: Mongodb
从redis中获取被删除后的testList[2]: Redis

从redis中获取被裁剪后的testList[0]: Mongodb
从redis中获取被裁剪后的testList[1]: Redis
从redis删除testList后,testList是否还存在:false

 

三,集合类型的基本操作,无序不重复 

  /**
     * 
     * 3.1,集合类型的基本操作,无序不重复
     */
    @Test
    public void set() {
        jedis.sadd("testSet", "lida", "wch", "chf", "lxl", "wch"); // 添加元素,不可重复
        Set<String> set = jedis.smembers("testSet"); // 获取集合中的全部元素

        System.out.println("从testSet中获取的元素:" + set);

        long length = jedis.scard("testSet"); // 求集合的长度

        System.out.println("\n获取testSet的长度:" + length);

        System.out.println();

        jedis.srem("testSet", "wch"); // 从testSet移除wch

        set = jedis.smembers("testSet");

        System.out.println("从testSet中获取移除后的的元素:" + set);

        System.out.println();

        boolean exist = jedis.sismember("testSet", "lida"); // 判断元素是否包含在该集合中

        System.out.println("检查lida是否包含在testSet中:" + exist);

        System.out.println();

        String spop = jedis.spop("testSet");// 随机的移除spop中的一个元素,并返回它

        System.out.println("testSet中被随机移除的元素是:" + spop);

        System.out.println();

        jedis.del("testSet"); // 删除整个集合

        System.out.println("删除后,testSet是否还是存在:" + jedis.exists("testSet"));

        System.out.println();

        System.out.println();

    }
从testSet中获取的元素:[chf, lxl, lida, wch]

获取testSet的长度:4

从testSet中获取移除后的的元素:[chf, lxl, lida]

检查lida是否包含在testSet中:true

testSet中被随机移除的元素是:lida

删除后,testSet是否还是存在:false

 

补充:集合之间的运算,交集、并集、差集

 

 @Test
    public void sets() {
        jedis.sadd("set1", "a", "b", "c", "d");
        jedis.sadd("set2", "b", "c", "e");
        Set<String> set = jedis.sdiff("set1", "set2"); // 求两个集合的差集(只会返回存在于1,但2不存在的)
        System.out.println("求出两个集合之间的差集:" + set); // 会输出a和d
        // 还有一个sdiffstore的api,可以把sdiff的计算结果赋值到另一个set中,下面的交集和并集也类似
        System.out.println();
        set = jedis.sinter("set1", "set2"); // 求两个集合的交集
        System.out.println("求出两个集合之间的交集:" + set); // 会输出b和c
        System.out.println();
        set = jedis.sunion("set1", "set2"); // 求两个集合的并集
        System.out.println("求出两个集合之间的并集:" + set);
    }
求出两个集合之间的差集:[d, a]

求出两个集合之间的交集:[b, c]

求出两个集合之间的并集:[a, b, c, d, e]

 

四,散列的基本操作,键值对里面还有键值对,经常用来存储多个字段信息,也可以理解为存放一个map,散列是redis的存储原型 

 

 @Test
    public void hash() {
        Map<String, String> map = new HashMap<String, String>();

        map.put("k1", "v1");

        map.put("k2", "v2");

        map.put("k3", "v3");

        map.put("k4", "123");

        jedis.hmset("hash1", map); // 存放一个散列

        Map<String, String> getMap = jedis.hgetAll("hash1"); // 从redis中取回来

        System.out.println("从redis中取回的hash1散列:" + getMap.toString());

        System.out.println();

        List<String> hmget = jedis.hmget("hash1", "k1", "k3"); // 从散列中取回一个或多个字段信息

        System.out.println("从hash1散列中两个字段来看看:" + hmget);

        System.out.println();

        jedis.hdel("hash1", "k1"); // 删除散列中的一个或者多个字段

        getMap = jedis.hgetAll("hash1");

        System.out.println("从redis中取回的被删除后的hash1散列:" + getMap);

        System.out.println();

        long length = jedis.hlen("hash1"); // 求出集合的长度

        System.out.println("散列hash1的长度为:" + length);

        System.out.println();

        boolean exists = jedis.hexists("hash1", "k5"); // 判断某个字段是否存在于散列中

        System.out.println("k5字段是否存在于散列中:" + exists);

        System.out.println();

        Set<String> keys = jedis.hkeys("hash1"); // 获取散列的所有字段名

        System.out.println("hash1的所有字段名:" + keys);

        System.out.println();

        List<String> values = jedis.hvals("hash1"); // 获取散列的所有字段值,实质的方法实现,是用上面的hkeys后再用hmget

        System.out.println("hash1的所有字段值:" + values);

        System.out.println();

        jedis.hincrBy("hash1", "k4", 10); // 给散列的某个字段进行加法运算

        System.out.println("执行加法运行后的hash1散列:" + jedis.hgetAll("hash1"));

        System.out.println();

        jedis.del("hash1"); // 删除散列

        System.out.println("删除hash1后,hash1是否还存在redis中:" + jedis.exists("hash1"));

    }

 

从redis中取回的hash1散列:{k1=v1, k2=v2, k3=v3, k4=123}

从hash1散列中两个字段来看看:[v1, v3]

从redis中取回的被删除后的hash1散列:{k2=v2, k3=v3, k4=123}

散列hash1的长度为:3

k5字段是否存在于散列中:false

hash1的所有字段名:[k3, k4, k2]

hash1的所有字段值:[v3, v2, 123]

执行加法运行后的hash1散列:{k2=v2, k3=v3, k4=133}

删除hash1后,hash1是否还存在redis中:false

 

五,有序集合的基本使用,zset是set的升级版,在无序的基础上,加入了一个权重,使其有序化<br/>另一种理解,zset是hash的特殊版,一样的存放一些键值对,但这里的值只能是数字,不能是字符串<br/>zset广泛应用于排名类的场景

 

 

 @Test
    public void zset() {
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("第二名", 24.3); // 这里以小组成员的年龄来演示

        map.put("第一名", 30.0);

        map.put("第三名", 23.5);

        map.put("第四名", 22.1);

        map.put("第二名", 24.3); // 这个不会被加入,应该重复了

        jedis.zadd("zset1", map); // 添加一个zset

        Set<String> range = jedis.zrange("zset1", 0, -1); // 从小到大排序,返回所有成员,三个参数:键、开始位置、结束位置(-1代表全部)

        // zrange方法还有很多衍生的方法,如zrangeByScore等,只是多了一些参数和筛选范围而已,比较简单,自己看看api就知道了

        System.out.println("zset返回的所有从小大到排序的成员:" + range);

        System.out.println("");

        Set<String> revrange = jedis.zrevrange("zset1", 0, -1); // 从大到小排序,类似上面的range

        System.out.println("zset返回的所有排序的成员:" + revrange);

        System.out.println("");

        long length = jedis.zcard("zset1"); // 求有效长度

        System.out.println("zset1的长度:" + length);

        System.out.println();

        long zcount = jedis.zcount("zset1", 22.1, 30.0); // 求出zset中,两个成员的排名之差,注意不是求长度,

        System.out.println("zset1中,22.1和30.0差了" + zcount + "");

        System.out.println();

        long zrank = jedis.zrank("zset1", "第四名"); // 求出zset中某成员的排位,注意第一是从0开始的

        System.out.println("第四名在zset1中排名:" + zrank);

        System.out.println();

        double zscore = jedis.zscore("zset1", "第二名"); // 获取zset中某成员的值

        System.out.println("zset1中第二名的值为:" + zscore);

        System.out.println();

        jedis.zincrby("zset1", 10, "第三名"); // 给zset中的某成员做加法运算

        System.out.println("zset1中第三名加10后,排名情况为:" + jedis.zrange("zset1", 0, -1));

        System.out.println();

        jedis.zrem("zset1", "第四名"); // 删除zset中某个成员

        // zrem还有衍生的zremByScore和zremByRank,分别是删除某个分数区间和排名区间的成员

        System.out.println("zset1删除第四名后,剩下:" + jedis.zrange("zset1", 0, -1));

        System.out.println();
    }
zset返回的所有从小大到排序的成员:[第四名, 第三名, 第二名, 第一名]

zset返回的所有排序的成员:[第一名, 第二名, 第三名, 第四名]

zset1的长度:4

zset1中,22.1和30.0差了4名

第四名在zset1中排名:0

zset1中第二名的值为:24.3

zset1中第三名加10后,排名情况为:[第四名, 第二名, 第一名, 第三名]

zset1删除第四名后,剩下:[第二名, 第一名, 第三名]

 

补充: 有序集合的运算,交集、并集(最小、最大、总和)

 

  @Test
    public void zsets() {
        Map<String, Double> map1 = new HashMap<String, Double>();

        map1.put("a", 24.3); // 这里以小组成员的年龄来演示

        map1.put("b", 30.0);

        map1.put("c", 23.5);

        map1.put("d", 22.1);

        Map<String, Double> map2 = new HashMap<String, Double>();

        map2.put("a", 24.3);

        map2.put("b", 29.6);

        map2.put("c", 23.5);

        map2.put("d", 21.3);

        jedis.zadd("zset1", map1);

        jedis.zadd("zset2", map2);

        System.out.println("zset1的值有:" + jedis.zrangeWithScores("zset1", 0, -1));
                                 
        System.out.println("zset2的值有:" + jedis.zrangeWithScores("zset2", 0, -1));

        System.out.println();

        jedis.zinterstore("zset_inter", "zset1", "zset2"); // 把两个集合进行交集运算,运算结果赋值到zset_inter中

        System.out.println("看看两个zset交集运算结果:" + jedis.zrangeWithScores("zset_inter", 0, -1));

        jedis.zinterstore ("zset_union", "zset1", "zset2");// 把两个集合进行并集运算,运算结果赋值到zset_union中

        System.out.println("看看两个zset并集运算结果:" + jedis.zrangeWithScores("zset_union", 0, -1));

        System.out.println("可以看出,zset的交集和并集计算,默认会把两个zset的score相加");

        ZParams zParams = new ZParams();

        zParams.aggregate(ZParams.Aggregate.MAX);

        jedis.zinterstore("zset_inter", zParams, "zset1", "zset2"); // 通过指定ZParams来设置集合运算的score处理,有MAX MIN
                                                                    // SUM三个可以选择,默认是SUM

        System.out.println("看看两个zset交集max运算结果:" + jedis.zrangeWithScores("zset_inter", 0, -1));
    }
    
zset1的值有:[[[100],22.1], [[99],23.5], [[97],24.3], [[98],30.0]]
zset2的值有:[[[100],21.3], [[99],23.5], [[97],24.3], [[98],29.6]]

看看两个zset交集运算结果:[[[100],43.400000000000006], [[99],47.0], [[97],48.6], [[98],59.6]]
看看两个zset并集运算结果:[[[100],43.400000000000006], [[99],47.0], [[97],48.6], [[98],59.6]]
可以看出,zset的交集和并集计算,默认会把两个zset的score相加
看看两个zset交集max运算结果:[[[100],22.1], [[99],23.5], [[97],24.3], [[98],30.0]]

 

六,发布订阅模式 

监视着

package com.redis;

import redis.clients.jedis.JedisPubSub;

public class RedisMsgPubSubListener extends JedisPubSub {

    

    @Override

    public void onMessage(String channel, String message) {

        System.out.println("channel:" + channel + "receives message :" + message);

        //this.unsubscribe();//取消订阅

    }

 

    @Override

    public void onSubscribe(String channel, int subscribedChannels) {

        System.out.println("channel:" + channel + "is been subscribed:" + subscribedChannels);

    }

 

    @Override

    public void onUnsubscribe(String channel, int subscribedChannels) {

        System.out.println("channel:" + channel + "is been unsubscribed:" + subscribedChannels);

    }



    @Override
    public void onPMessage(String s, String s1, String s2) {
        // TODO Auto-generated method stub
        
    }



    @Override
    public void onPUnsubscribe(String s, int i) {
        // TODO Auto-generated method stub
        
    }



    @Override
    public void onPSubscribe(String s, int i) {
        // TODO Auto-generated method stub
        
    }

}

 

发布者:

package com.redis;

import redis.clients.jedis.Jedis;

public class TestPublish {
    public static void main(String[] args) throws Exception {
        final Jedis jedis = new Jedis("localhost");
        new Thread() {
            public void run() {
                try {
                    for (int i = 0; i < 10; i++) {
                        jedis.publish("redisChat", "要发送的消息内容" + i); // 每隔一秒推送一条消息
                        System.out.printf("成功向redisChat推送消息:%s\n", i);
                        Thread.sleep(1000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }.start();
        /*
         * jedis.publish("redisChat", "Redis is a great caching technique"); Thread.sleep(5000);
         * jedis.publish("redisChat", "build your dream"); Thread.sleep(5000); jedis.publish("redisChat", "over");
         */
    }
}

 

订阅者:

package com.redis;

import redis.clients.jedis.Jedis;

public class TestSubscribe {

    public  static void main(String[] args){

        Jedis jedis = new Jedis("localhost");

        RedisMsgPubSubListener listener = new RedisMsgPubSubListener();

        /**

         * 注意:subscribe是一个阻塞的方法,在取消订阅该频道前,会一直阻塞在这,只有当取消了订阅才会执行下面的other code,

         * 参考上面代码,我在onMessage里面收到消息后,调用了this.unsubscribe(); 来取消订阅,这样才会执行后面的other code

         */

        jedis.subscribe(listener, "redisChat");

        //如果没有取消订阅,方法将一直堵塞在此处不会向下执行

        

        //to do others

    }
}

先启动订阅者,再启动发布者,控制台打印

发布者控制台:

成功向redisChat推送消息:0
成功向redisChat推送消息:1
成功向redisChat推送消息:2
成功向redisChat推送消息:3
成功向redisChat推送消息:4
成功向redisChat推送消息:5
成功向redisChat推送消息:6
成功向redisChat推送消息:7
成功向redisChat推送消息:8
成功向redisChat推送消息:9

 

订阅者控制台:

channel:redisChatis been subscribed:1
channel:redisChatreceives message :要发送的消息内容0
channel:redisChatreceives message :要发送的消息内容1
channel:redisChatreceives message :要发送的消息内容2
channel:redisChatreceives message :要发送的消息内容3
channel:redisChatreceives message :要发送的消息内容4
channel:redisChatreceives message :要发送的消息内容5
channel:redisChatreceives message :要发送的消息内容6
channel:redisChatreceives message :要发送的消息内容7
channel:redisChatreceives message :要发送的消息内容8
channel:redisChatreceives message :要发送的消息内容9

 假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

kk

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值