在Windows端开发连接需要进行配置文件的配置:

在redis.conf配置文件中

将protected-mode yes,修改为protected-mode no;不保护redis

# By default protected mode is enabled. You should disable it only if
# you are sure you want clients from other hosts to connect to Redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
protected-mode no

将bind 127.0.0.1加上注释,(#bind 127.0.0.1),允许出本机外的IP访问redis

# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#bind 0.0.0.0:
#bind 127.0.0.1
将daemonize no,修改为daemonize yes;允许redis服务后台运行
简单来说我们不用看到点心的那个页面
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes

修改防火墙端口号

命令:/sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT

保存防火墙修改命令:/etc/rc.d/init.d/iptables save

修改完成后,需要重新启动redis服务。

redis-server /xxxx/redis.conf

通过iptables 允许指定的外网ip访问

修改 Linux 的防火墙(iptables),开启你的redis服务端口,默认是6379

//只允许127.0.0.1访问6379
iptables -A INPUT -s 127.0.0.1 -p tcp --dport 6379 -j ACCEPT
//其他ip访问全部拒绝
iptables -A INPUT -p TCP --dport 6379 -j REJECT

一些命令的代码测试:

使用maven工程进行

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7..RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.</version>
</dependency>

Redis的使用

1.默认直接使用

    //首次进行册数的测试
@Test
public void testSpeed(){
Jedis jedis = new Jedis("192.168.42.153", 6379);try {
jedis.set("key", "value");
}
} finally {
jedis.close();
}
}

2.使用连接池

    @Test
public void RedisConfigPool(){ JedisPoolConfig pool = new JedisPoolConfig();
//最大空闲数
pool.setMaxIdle();
//连接数
pool.setMaxTotal();
//等待毫秒数
pool.setMaxWaitMillis(); //使用配置的连接池
JedisPool jedisPool = new JedisPool(pool, "192.168.42.153"); //从连接池中获取单个连接
Jedis jedis = jedisPool.getResource(); jedis.set("ts","1234"); }

使用spring:

基本配置条件如下

User类

//对象需要可序列化,实现接口
public class User implements Serializable{ private static final long serialVersionUID = 6977402643848374753L; private long id;
private String name;
  //........
}

spring的配置类

<!-- 连接池 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 空闲数 -->
<property name="maxIdle" value=""></property>
<!-- 连接数 -->
<property name="maxTotal" value=""></property>
<!-- 最大等待时间 -->
<property name="maxWaitMillis" value=""></property>
</bean> <!-- 连接配置 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="192.168.42.153"></property>
<property name="port" value=""></property>
<!-- 连接池 -->
<property name="poolConfig" ref="poolConfig"></property>
</bean> <!-- 配置spring-date-Template -->
<!-- 序列化 -->
<bean id="jdkSerializationRedisSerializer"
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean> <bean id="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
</bean> <bean id="redisTemplate1" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer" ref="stringRedisSerializer"></property>
</bean> <bean id="redisTemplate2" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="defaultSerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer" ref="stringRedisSerializer"></property>
</bean>

1.

    @Test
public void testResisString(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate"); User user = new User();
user.setId(1L);
user.setName("Mr"); //设置键值对
redisTemplate.opsForValue().set("user", user); //获取键值对
User u = (User) redisTemplate.opsForValue().get("user");
System.out.println(u);
}

//以上的使用都是基于 RedisTemplate 基于连接池的操作,换句话说,并不能保
//证每次使用 RedisTemplate 是操作同一个对 Redis 连接

2.

为了使得 操作都来自于同 连接 可以使用 SessionCallback & RedisCallback
RedisCallback是比较底层 封装 使用不是很友好
更多 的时候会使SessionCallback 接口
Redis 同时执行多个命令,那么还是采用 SessionCallback 接口进行操作,从而保证多个命令在同 Redis接操作中。

前后使用的都是同 个连接,对资源消耗小

    @Test
public void testResisString1(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate"); User user = new User();
user.setId(1L);
user.setName("Mr"); SessionCallback callback = new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
//设置 key = user1 值 = user
operations.boundValueOps("user1").set(user);
return (User)operations.boundValueOps("user1").get();
}
};
//获取键值对
User u = (User) redisTemplate.execute(callback);
System.out.println(u);
}

数据类型:

1.String

//注意此时的RedisTemplate的配置序列化
//首先配置 Spring关于 Redis 字符串 运行环境
//这里给 Spring RedisTemplate 的键值序列 器设置为了 String 类型
//所以就是种字符串的操作

@Test
public void StringTest(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate1"); //设置值
//set key name 设置键值对
redisTemplate.opsForValue().set("k1", "v1");
redisTemplate.opsForValue().set("k2", "v2");
//通过key获取值
//get key 通过键获取值
String value1 = (String) redisTemplate.opsForValue().get("k1");
System.out.println("value1" + value1); //删除键值对
redisTemplate.delete("k1"); //字符串长度
//strlen key
Long length = redisTemplate.opsForValue().size("k2");
System.out.println("length:" + length); //设置新值返回旧值
String oldVal = (String) redisTemplate.opsForValue().getAndSet("k2", "k222333444");
System.out.println("oldVal:"+ oldVal); String value2 = (String) redisTemplate.opsForValue().get("k2");
System.out.println("value2" + value2); //求子串
//getrange key st end [0 ...]
String rangString = redisTemplate.opsForValue().get("k2", , );
System.out.println("rangString:"+rangString); //追加内容在末尾
//append key value 返回新字符串的长度
int newSize = redisTemplate.opsForValue().append("k2", "_new");
System.out.println("newSize:" + newSize); String newVal = (String) redisTemplate.opsForValue().get("k2");
System.out.println("value1" + newVal);
}

//redisTemplate.opsForValu() 所返回的对象可以操作简单的键值对
//可以是字符串,也可以是对象,具体依据你所配置的序列化方案

    //关于运算
@Test
public void StringTestCal(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate1"); //设值
redisTemplate.opsForValue().set("cal", ""); //初始化的值
String initValue = (String) redisTemplate.opsForValue().get("cal");
System.out.println("initValue:" + initValue); //加1
//还可以加其他的数
redisTemplate.opsForValue().increment("cal", );
String AddOneVal = (String) redisTemplate.opsForValue().get("cal");
System.out.println("AddOneVal:" + AddOneVal); //减一
redisTemplate.getConnectionFactory().getConnection().decr(redisTemplate.
getKeySerializer().serialize("cal"));
String MinOneVal = (String) redisTemplate.opsForValue().get("cal");
System.out.println("MinOneVal:" + MinOneVal); //减3
redisTemplate.getConnectionFactory().getConnection().decrBy(
redisTemplate.getKeySerializer().serialize("cal"), );
String MinThreeVal = (String) redisTemplate.opsForValue().get("cal");
System.out.println("MinThreeVal:" + MinThreeVal); //加浮点数
redisTemplate.opsForValue().increment("cal", 4.2);
String floatVal = (String) redisTemplate.opsForValue().get("cal");
System.out.println("floatVal:" + floatVal);
}

// increment 方法可 支持长整形 long 双精度double的加法
//对于减法而言,RedisTemplate 并没有进行支持
//通过获得连接工厂再获得连接从而得到底 Redis 连接对象
//redisTemplate.getConnectionFactory().getConnection().decr(redisTemplate.
// getKeySerializer().serialize("cal"));
//所有关于减法的方法,原有值都必须是整数,否则就会引发异常

2.Set

//集合不是 个线性结构
//它的内部会根据 hash 分子来存储和查找数据
// Redis 集合的插入、删除和查找的复杂度都是 0(1 )
//对于集合而言,它的每 个元素都是不能重复的,当插入相同记录的时候都会失败
//集合是无序的。
//集合的每 个元素都是 String 数据结构类型。

@Test
public void test(){ ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate2"); Set set = null; //将元素加入列表
//sadd key menber [menber1 ...] 给键为key的集合添加成员
redisTemplate.boundSetOps("set1").add("v1","v2","v3","v4","v5","v6");
redisTemplate.boundSetOps("set2").add("v0","v5","v6","v7","v8","v9"); //求集合长度
Long size = redisTemplate.opsForSet().size("set1");
System.out.println("size:" + size); //求差集
//sdif key key2
set = redisTemplate.opsForSet().difference("set1", "set2");
System.out.println("差集:" + set); //并集
//sunion key1 [key2] 求两个集合的并集
set =redisTemplate.opsForSet().intersect("set1", "set2");
System.out.println("并集:" + set); //判断集合中的元素
//sismember key menber 判断menber是否为键为key的集合成员
boolean exist = redisTemplate.opsForSet().isMember("set1", "v3");
System.out.println("exist:" + exist); //获取集合所有元素
//smembers key 返回集合所有成员
set =redisTemplate.opsForSet().members("set1");
System.out.println("集合所有元素:" + set); //随机从集合中弹出一个元素
//spop key 随机弹出一个元素
String val = (String)redisTemplate.opsForSet().pop("set1");
System.out.println("随机弹出:" + val); //随机获取一个集合的元素
//srandmember key [count] 随机返回一个或多个
val = (String)redisTemplate.opsForSet().randomMember("set1");
System.out.println("随机返回一个数:" + val); //随机返回两个
List list = redisTemplate.opsForSet().randomMembers("set1", );
System.out.println("随机获取集合中两个数:" + list); //删除一个集合的元素,参数可以是多个
//srem key member[member2 ...] 移除集合中的元素,可以多个
// redisTemplate.opsForSet().remove("set1", "v3","v2"....);
Long e = redisTemplate.opsForSet().remove("set1", "v3");
System.out.println("e:" + e); //并集
//sunion key [key1]
set = redisTemplate.opsForSet().union("set1", "set2");
System.out.println("并集:" + set); //求差集并且保存到新的集合中
//sdiffstore des key1 [key2] 保存到des中
redisTemplate.opsForSet().differenceAndStore("set1",
"set2", "new_set");
System.out.println("new_set"+redisTemplate.opsForSet().members("new_set")); //求两个集合的交集,并保存到集合 inter_set
//sinterstore des key1 key2
redisTemplate.opsForSet().intersectAndStore("set1", "set2", "inter_set");
System.out.println("新集合交集:"+ redisTemplate.opsForSet().members("inter_set")); //求两个集合的并集,并保存到集合 union_set
redisTemplate.opsForSet().unionAndStore("set1", "set2", "union_set");
System.out.println("新并集集合union_set:" + redisTemplate.opsForSet().members("union_set")); }

3.链表

//可以存储多个字符串
//它是有序的
//Redis 链表是双向的
//使用链表结构就意味着读性能的丧失
//链表结构的优势在于插入和删除的便利:,因为链表的数据节点是分配在不同的内存域的,并不连续

//由此可见,链表结构的使用是需要注意场景的,对于那些经常需要对数据进行插入和
//删除的列表数据使用它是十分方便的,因为它可以在不移动其他节点的情况下完成插入和
//删除。而对于需要经常查找的,使用它性能并不佳,它只能从左到右或者从右到左的查找
//和比对。

@Test
public void test() throws Exception{
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate2"); //删除链表
redisTemplate.delete("list"); //创建新的链表
//lpush key node1[node2...] 把节点从左边插入 此时单个节点插入
redisTemplate.opsForList().leftPush("list","node3"); //测试同时插入多个节点
List<String> nodeList = new ArrayList<String>();
for(int i = ;i >=;i--){
nodeList.add("node"+i);
} //lpush key node1[node2...] 此时同时插入多个节点 从左边插入到key中
redisTemplate.opsForList().leftPushAll("list", nodeList); //rpush key node1[node2...]
//从右侧插入节点可一个或多个
redisTemplate.opsForList().rightPush("list", "node4"); //获取链表的长度
Long size = redisTemplate.opsForList().size("list");
System.out.println("size:" + size); List listValue = redisTemplate.opsForList().range("list", , size);
System.out.println("listValue:" + listValue); //获取下表为0的节点
//index key index index从0开始,返回节点的字符串,读取下表为index的节点
String indexZero = (String)redisTemplate.opsForList().index("list", );
System.out.println("下表为0的节点:" + indexZero); //从左边弹出一个节点
//lpop key 删除左边的一个节点,并且返回给节点
String leftPop = (String)redisTemplate.opsForList().leftPop("list");
System.out.println("leftpop:" + leftPop); //从右边弹出一个节点
//rpop key 删除左边的一个节点,并且返回给节点
String rightPop = (String)redisTemplate.opsForList().rightPop("list");
System.out.println("rightPop:" + rightPop); //插入节点
//linsert key before | after pivot node 插入一个节点,并且可以指定在职位pivot的前面或者后面
//若list不存在,则报错,没有对应的pivot值,也会插入失败返回 -1 //在node2的前后各插入一个节点
//注意,需要使用更为底层的命令才能操 linsert 命令
//redisTemplate.getConnectionFactory().getConnection().lInsert(key, where, pivot, value);
redisTemplate.getConnectionFactory().getConnection().lInsert(
"list".getBytes("utf-8"), RedisListCommands.Position.BEFORE, "node2".getBytes("utf-8"),
"before_node2".getBytes("utf-8")); redisTemplate.getConnectionFactory().getConnection().lInsert(
"list".getBytes("utf-8"), RedisListCommands.Position.AFTER, "node2".getBytes("utf-8"),
"after_node2".getBytes("utf-8")); //lpushx list node 若存在key为list的链表, 则插入节点node 否则失败 从左边插入
redisTemplate.opsForList().leftPushIfPresent("list", "head"); //rpushx list node 若存在key为list的链表, 则插入节点node 否则失败 从右边插入
redisTemplate.opsForList().rightPushIfPresent("list", "end"); //lrange list start end 获取从start-end下边的节点值 [start ,end]
listValue = redisTemplate.opsForList().range("list", , );
System.out.println("listValue:" + listValue); //lrem list count value count=0删除所有的值为value的节点,否则删除绝对值为count个value的节点值
nodeList.clear();
for(int i = ;i <= ;i++){
nodeList.add("node");
}
//左边插入nodeList
redisTemplate.opsForList().leftPushAll("list", nodeList);
System.out.println("删除node节点之前的list:");
size = redisTemplate.opsForList().size("list");
listValue = redisTemplate.opsForList().range("list", , size);
System.out.println("listValue:" + listValue); //从左到右删除6个node节点
redisTemplate.opsForList().remove("list", , "node");
System.out.println("");
System.out.println("删除node节点之后的list:");
size = redisTemplate.opsForList().size("list");
listValue = redisTemplate.opsForList().range("list", , size);
System.out.println("listValue:" + listValue); //修改下表指定节点的值,设置新值
//lset key index value 设置index节点处的新值,设为value
redisTemplate.opsForList().set("list", , "new_head");
indexZero = (String)redisTemplate.opsForList().index("list", );
System.out.println("index=0处的新值:" + indexZero);
}

//上面这些操作链表的命令都是进程不安全的,因为 我们操作这些命令的时候,
//其他 Redis 的客户端也可能操作同 个链表,这样就会造成并发数据安全和一致性的问题
//Redis 提供了链表的阻塞命令,它 在运行的时候 会给链表加锁,以保证操作链表的命令安全性
//加锁的结果就是其他的进程不能再读取或者写入该链 ,只能等待命令结束

@Test
public void testBlock(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate2"); //清空数据
//redisTemplate.delete("list1");
//redisTemplate.delete("list2"); List<String> nodeList = new ArrayList<String>();
for(int i = ;i <= ;i++){
nodeList.add("node"+i);
} //放入数据
redisTemplate.opsForList().leftPushAll("list1", nodeList); //blpop移除并获取列表的第一个元素,如果没有元素会阻塞列表直到等待超时或者发现可弹出元素
//Spring 使用参数超时时间作为阻塞命令区分,等价于 blpop 命令,并且可以设置时间参数
//redisTemplate.opsForList().leftPop(key, timeout, unit)
redisTemplate.opsForList().leftPop("list1", , TimeUnit.SECONDS); //Spring 使用参数超时时间作为阻塞命令区分,等价于 brpop 命令,并且可以设置时间参数
redisTemplate.opsForList().rightPop("list1", , TimeUnit.SECONDS); Long size = redisTemplate.opsForList().size("list1");
List listValue = redisTemplate.opsForList().range("list1", , size);
System.out.println("listValue:" + listValue);
System.out.println(""); nodeList.clear();
for(int i = ;i <= ;i++){
nodeList.add("date"+i);
} redisTemplate.opsForList() .leftPushAll ("list2", nodeList); //rpoplpush key src dest 将src的最右边的删除,然后将src追加在dest后面
//不可设置时间
//相当于 rpoplpush 命令,弹出 listl 最右边的节点,插入到 list2 最左边
redisTemplate .opsForList().rightPopAndLeftPush("list1", "list2"); size = redisTemplate.opsForList().size("list2");
listValue = redisTemplate.opsForList().range("list2", , size);
System.out.println("listValue:" + listValue); //brpoplpush key src dest timeout
//相当于 brpoplpush 命令,注意在 Spring 中使用超时参数区分
redisTemplate.opsForList().rightPopAndLeftPush("list1",
"list2", , TimeUnit.SECONDS);
size = redisTemplate.opsForList().size("list2");
listValue = redisTemplate.opsForList().range("list2", , size);
System.out.println("listValue:" + listValue); }

4.Hash

//Redis中哈希结构就如同 Java的 map 一样
//一个对象里面有许多键值对
//特别适合存储对象的
// 要对 RedisTemplate 的配置项进行修改

//Spring 提供的RedisTemplate 序列 defaultSerializer的默认修改为了字符串序列 器
//因为在 Spring对hash结构的 作中会涉及 map 等其 类的操作 所以需要明确它的规则

//如果想为 hash 结构指定序列化器,可以使用 di mplate 提供的两个
//属性 hashKeySerializer和hashValueSerializer ,来为 hash 结构的 field和value 指定序列化器。

@Test
public void testHash(){
ApplicationContext app = new
ClassPathXmlApplicationContext("classpath:/applicationContext.xml"); RedisTemplate redisTemplate = (RedisTemplate) app.getBean("redisTemplate2"); //设置key
String key = "hash"; Map<String,String> map = new HashMap<String,String>();
map.put("name", "MrChengs");
map.put("age",""); //hmset 设置键值对(可多个)
//hmset key filed1[filed2....]
redisTemplate.opsForHash().putAll(key, map); //hset 在结构体中键值对
//hset key filed
redisTemplate.opsForHash().put(key, "hobby", "game");
pringtValehash(redisTemplate, key, "hobby"); //hexists key field
//判断是否存在field字段
boolean exists = redisTemplate.opsForHash().hasKey(key, "hobby");
System.out.println("exitsts:" + exists); //hgetall key
//获取key中的所有字段
map=redisTemplate.opsForHash().entries(key);
System.out.println("hgetall:" + map); //hincrby key field increment
//给某一字段加以整数
//还可以double
redisTemplate.opsForHash().increment(key, "age", );
pringtValehash(redisTemplate, key, "age"); //hvals key
//获取hash结构中的所有值
List keyList = new ArrayList();
keyList = redisTemplate.opsForHash().values(key);
System.out.println("value:"+ keyList); //hkeys key 返回key中的所有键
Set set = redisTemplate.opsForHash().keys(key);
System.out.println("keys:" + set); //hmget key filed1[2...]
//返回指定键中的值
List listVal = redisTemplate.opsForHash().multiGet(key, set);
System.out.println("listVal:" + listVal); //hmsetnx key field value
//设置键值对,在不存在field时才进行设置
boolean su = redisTemplate.opsForHash().putIfAbsent(key, "wight", "");
System.out.println(su); pringtValehash(redisTemplate, key, "wight"); //hdel
Long size = redisTemplate.opsForHash().delete(key, "age");
System.out.println("size" + size);
} private static void pringtValehash(RedisTemplate redisTemplate , String key
,String field){
//hget 获取属性值 单个
Object value = redisTemplate.opsForHash().get(key, field);
System.out.println(value);
}

//hmset在 JavaAPI中,是使用 map保存多个键值对在先的。
//getall 命令会返回所有的键值对,并保存到 map 对象中,如果 hash 结构很大,那么要考虑它对JVM 的内存影响。
// hincrby hincrbyFloat 令都采用 ncrement 方法, Spring 会识别它具体使用何种方法。

最新文章

  1. [转] Jenkins实战演练之Windows系统节点管理
  2. DSP using MATLAB 随书示例Example2.8
  3. python - socket - server
  4. Sublime Text 2 - 性感无比的代码编辑器!程序员必备神器!跨平台支持Win/Mac/Linux
  5. ffmpeg 2.8.1 最新版本 VS2013 可调式动态库
  6. C++常量指针与常量数据
  7. Linux用户管理(笔记)
  8. DELL服务器硬件信息采集SHELL脚本
  9. 源码浅谈(二):java中的 Integer.parseInt(String str)方法
  10. SVG初尝试(一)
  11. GenericServlet 、Servlet和httpServler
  12. C# TCP与UDP
  13. vue项目两级全选(多级原理也一样),感觉有点意思,随手一记
  14. rbac(基于角色权限控制)-------权限管理
  15. 几种流行的AJAX框架jQuery,Mootools,Dojo,Ext JS的对比
  16. vue下载和上传excle数据文件,解析excel文件数据并存在数据库中
  17. UIDatePicker 时间选择器
  18. 【14】代理模式(Proxy Pattern)
  19. 关于winform窗体关闭时弹出提示框,选择否时窗体也关闭的问题
  20. 理解flex布局

热门文章

  1. Java - 用builder代替构造器
  2. java导入excle表格,并且对表格进行相应的修改,并对表格数据进行整理,最后导出本地表格等一系列操作
  3. JFrame自适应大小
  4. 4、springboot之全局异常捕获
  5. linux设置静态获取ip
  6. UNIX 5种I/O模型
  7. Java接口和抽象类理解(New)
  8. java设计模式之工厂模式学习
  9. JavaScript实现邮箱后缀提示功能
  10. 原生JS的轮播图