背景:手下新人在初次使用springboot整合redis,大部分人习惯从网上检索到一份配置,然后不知其所以然的复制粘贴到项目中,网上搜索到的配置良莠不齐但又万变不离其宗。由于springboot最大化地简化了整合redis需要的配置,在用户只需要在配置文件(application.*)中配置少量参数就可以使用官方默认提供的RedisTemplate和StringRedisTemplate来操作redis。由于官方提供的*RedisTemplate提供的功能有限,难以针对java的复杂数据类型进行序列化,且采用直连的方式以及没有对连接数进行限制等诸多因素在现代引用中制约较大,所以项目中一般需要提供一个RedisConfig类来针对redisTemplate做进一步配置。在此把自己之前项目中用到的一份基于redis的配置和封装类贴出来,以便抛砖引玉!

  1. 假定熟悉springboot的常见用法和配置;
  2. 假定你熟悉并掌握redis的六种数据结构和相关命令,否则难以理解redisTemplate API中方法和redis命令的对应关系
  3. 本篇博客以下内容,本人亲测可用,有需要的小伙伴直接复制粘贴即可。

下面开始编码:

1、新建一个springboot项目,pom.xml做如下依赖,注意jedis版本与spring-boot-starter-data-redis版本对应,一般来说2.1.x对应jedis 2.9.x,2.2.x对应jedis 3.x,切记,否则可能出现莫名其妙的错误。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>thinking-in-spring-boot</groupId><artifactId>first-app-by-gui</artifactId><version>0.0.1-SNAPSHOT</version><name>first-app-by-gui</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

新建的项目结构如下:

2、在application.yml配置文件中新增关于redis配置,内容如下:

spring:redis:database: 0host: 127.0.0.1port: 6379password: # 如果未单独配置默认为空即可timeout: 1000jedis:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0

3、编写redis配置类,内容如下,在该类中完成Jedis池、Redis连接和RedisTemplate序列化三个配置完成springboot整合redis的进一步配置。其中RedisTemplate对key和value的序列化类,各人结合自己项目情况进行选择即可。

package com.dongnao.config;import com.dongnao.cache.IGlobalCache;
import com.dongnao.cache.impl.AppRedisCacheManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;@EnableCaching
@Configuration
public class RedisConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.database}")private Integer database;@Value("${spring.redis.port}")private Integer port;@Value("${spring.redis.password}")private String pwd;@Primary@Bean(name = "jedisPoolConfig")@ConfigurationProperties(prefix = "spring.redis.pool")public JedisPoolConfig jedisPoolConfig() {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxWaitMillis(10000);return jedisPoolConfig;}@Beanpublic RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();redisStandaloneConfiguration.setHostName(host);redisStandaloneConfiguration.setDatabase(database);redisStandaloneConfiguration.setPassword(pwd);redisStandaloneConfiguration.setPort(port);JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();jpcb.poolConfig(jedisPoolConfig);JedisClientConfiguration jedisClientConfiguration = jpcb.build();return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);}/*** 配置redisTemplate针对不同key和value场景下不同序列化的方式** @param factory Redis连接工厂* @return*/@Primary@Bean(name = "redisTemplate")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();template.setKeySerializer(stringRedisSerializer);template.setHashKeySerializer(stringRedisSerializer);Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer(Object.class);template.setValueSerializer(redisSerializer);template.setHashValueSerializer(redisSerializer);template.afterPropertiesSet();return template;}@BeanIGlobalCache cache(RedisTemplate redisTemplate) {return new AppRedisCacheManager(redisTemplate);}}

4、网络上大部分配置都到此为止,但在实际使用redis缓存的场景,一般由于redisTemplate使用不便、需要解决将java数据类型和redis六种数据结构命令的对应以及不应该直接暴露redisTemplate给service等因素考虑,需要进行进一步对redisTemplate进行封装,封装后代码如下:

package com.dongnao.cache;import org.springframework.data.redis.core.RedisTemplate;import java.util.List;
import java.util.Map;
import java.util.Set;/*** 系统全局Cache接口,具体缓存方式需要实现该接口** @author YuXD* @date 2021-01-05 10:38* @since v1.0*/
public interface IGlobalCache {/*** 指定缓存失效时间** @param key  键* @param time 时间(秒)* @return*/boolean expire(String key, long time);/*** @param key 键 不能为null* @return 时间(秒) 返回0代表为永久有效*/long getExpire(String key);/*** 判断key是否存在** @param key 键* @return true 存在 false不存在*/boolean hasKey(String key);/*** 删除缓存** @param key 可以传一个值 或多个*/void del(String... key);
// ============================String=============================/*** 普通缓存获取** @param key 键* @return 值*/Object get(String key);/*** 普通缓存放入** @param key   键* @param value 值* @return true成功 false失败*/boolean set(String key, Object value);/*** 普通缓存放入并设置时间** @param key   键* @param value 值* @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期* @return true成功 false 失败*/boolean set(String key, Object value, long time);/*** 递增** @param key   键* @param delta 要增加几(大于0)* @return*/long incr(String key, long delta);/*** 递减** @param key   键* @param delta 要减少几(小于0)* @return*/long decr(String key, long delta);/*** HashGet** @param key  键 不能为null* @param item 项 不能为null* @return 值*/Object hget(String key, String item);/*** 获取hashKey对应的所有键值** @param key 键* @return 对应的多个键值*/Map<Object, Object> hmget(String key);/*** HashSet** @param key 键* @param map 对应多个键值* @return true 成功 false 失败*/boolean hmset(String key, Map<String, Object> map);/*** HashSet 并设置时间** @param key  键* @param map  对应多个键值* @param time 时间(秒)* @return true成功 false失败*/boolean hmset(String key, Map<String, Object> map, long time);/*** 向一张hash表中放入数据,如果不存在将创建** @param key   键* @param item  项* @param value 值* @return true 成功 false失败*/boolean hset(String key, String item, Object value);/*** 向一张hash表中放入数据,如果不存在将创建** @param key   键* @param item  项* @param value 值* @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间* @return true 成功 false失败*/boolean hset(String key, String item, Object value, long time);/*** 删除hash表中的值** @param key  键 不能为null* @param item 项 可以使多个 不能为null*/void hdel(String key, Object... item);/*** 判断hash表中是否有该项的值** @param key  键 不能为null* @param item 项 不能为null* @return true 存在 false不存在*/boolean hHasKey(String key, String item);/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回** @param key  键* @param item 项* @param by   要增加几(大于0)* @return*/double hincr(String key, String item, double by);/*** hash递减** @param key  键* @param item 项* @param by   要减少记(小于0)* @return*/double hdecr(String key, String item, double by);/*** 根据key获取Set中的所有值** @param key 键* @return*/Set<Object> sGet(String key);/*** 根据value从一个set中查询,是否存在** @param key   键* @param value 值* @return true 存在 false不存在*/boolean sHasKey(String key, Object value);/*** 将数据放入set缓存** @param key    键* @param values 值 可以是多个* @return 成功个数*/long sSet(String key, Object... values);/*** 将set数据放入缓存** @param key    键* @param time   时间(秒)* @param values 值 可以是多个* @return 成功个数*/long sSetAndTime(String key, long time, Object... values);/*** 获取set缓存的长度** @param key 键* @return*/long sGetSetSize(String key);/*** 移除值为value的** @param key    键* @param values 值 可以是多个* @return 移除的个数*/long setRemove(String key, Object... values);/*** 获取list缓存的内容** @param key   键* @param start 开始* @param end   结束 0 到 -1代表所有值* @return*/List<Object> lGet(String key, long start, long end);/*** 获取list缓存的长度** @param key 键* @return*/long lGetListSize(String key);/*** 通过索引 获取list中的值** @param key   键* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推* @return*/Object lGetIndex(String key, long index);/*** 将list放入缓存** @param key   键* @param value 值* @return*/boolean lSet(String key, Object value);/*** 将list放入缓存** @param key   键* @param value 值* @return*/boolean lSet(String key, Object value, long time);/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/boolean lSetAll(String key, List<Object> value);/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/boolean lSetAll(String key, List<Object> value, long time);/*** 将list放入缓存** @param key   键* @param value 值* @return*/boolean rSet(String key, Object value);/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/boolean rSet(String key, Object value, long time);/*** 将list放入缓存** @param key   键* @param value 值* @return*/boolean rSetAll(String key, List<Object> value);/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/boolean rSetAll(String key, List<Object> value, long time);/*** 根据索引修改list中的某条数据** @param key   键* @param index 索引* @param value 值* @return*/boolean lUpdateIndex(String key, long index, Object value);/*** 移除N个值为value** @param key   键* @param count 移除多少个* @param value 值* @return 移除的个数*/long lRemove(String key, long count, Object value);/*** 从redis集合中移除[start,end]之间的元素** @param key* @param stard* @param end* @return*/void rangeRemove(String key, Long stard, Long end);/*** 返回当前redisTemplate** @return*/RedisTemplate getRedisTemplate();
}
package com.dongnao.cache.impl;import com.dongnao.cache.IGlobalCache;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** @description: 移动端Redis缓存实现类* @author: YuXD* @create: 2021-01-05 10:40**/
@Getter
@AllArgsConstructor
public final class AppRedisCacheManager implements IGlobalCache {private RedisTemplate<String, Object> redisTemplate;@Overridepublic boolean expire(String key, long time) {try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}@Overridepublic boolean hasKey(String key) {try {return redisTemplate.hasKey(key);} catch (Exception e) {e.printStackTrace();return false;}}@Override@SuppressWarnings("unchecked")public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete(CollectionUtils.arrayToList(key));}}}@Overridepublic Object get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);}@Overridepublic boolean set(String key, Object value) {try {redisTemplate.opsForValue().set(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean set(String key, Object value, long time) {try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic long incr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递增因子必须大于0");}return redisTemplate.opsForValue().increment(key, delta);}@Overridepublic long decr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递减因子必须大于0");}return redisTemplate.opsForValue().increment(key, -delta);}@Overridepublic Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);}@Overridepublic Map<Object, Object> hmget(String key) {return redisTemplate.opsForHash().entries(key);}@Overridepublic boolean hmset(String key, Map<String, Object> map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean hmset(String key, Map<String, Object> map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean hset(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean hset(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic void hdel(String key, Object... item) {redisTemplate.opsForHash().delete(key, item);}@Overridepublic boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);}@Overridepublic double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);}@Overridepublic double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);}@Overridepublic Set<Object> sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();return null;}}@Overridepublic boolean sHasKey(String key, Object value) {try {return redisTemplate.opsForSet().isMember(key, value);} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic long sSet(String key, Object... values) {try {return redisTemplate.opsForSet().add(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic long sSetAndTime(String key, long time, Object... values) {try {Long count = redisTemplate.opsForSet().add(key, values);if (time > 0) {expire(key, time);}return count;} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic long setRemove(String key, Object... values) {try {Long count = redisTemplate.opsForSet().remove(key, values);return count;} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic List<Object> lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}@Overridepublic long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();return null;}}@Overridepublic boolean lSetAll(String key, List<Object> value) {try {redisTemplate.opsForList().leftPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean lSet(String key, Object value) {try {redisTemplate.opsForList().leftPushIfPresent(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean lSet(String key, Object value, long time) {try {redisTemplate.opsForList().leftPush(key, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean lSetAll(String key, List<Object> value, long time) {try {redisTemplate.opsForList().leftPushAll(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean rSet(String key, Object value) {try {redisTemplate.opsForList().rightPush(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean rSet(String key, Object value, long time) {try {redisTemplate.opsForList().rightPush(key, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean rSetAll(String key, List<Object> value) {try {redisTemplate.opsForList().rightPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean rSetAll(String key, List<Object> value, long time) {try {redisTemplate.opsForList().rightPushAll(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic boolean lUpdateIndex(String key, long index, Object value) {try {redisTemplate.opsForList().set(key, index, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}@Overridepublic long lRemove(String key, long count, Object value) {try {Long remove = redisTemplate.opsForList().remove(key, count, value);return remove;} catch (Exception e) {e.printStackTrace();return 0;}}@Overridepublic void rangeRemove(String key, Long stard, Long end) {try {redisTemplate.opsForList().trim(key, stard, end);} catch (Exception e) {e.printStackTrace();}}}

5、下面是简单使用的例子,其它结合实际情况使用即可。

package com.dongnao;import com.dongnao.cache.IGlobalCache;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays;
import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest
public class FirstAppByGuiApplicationTests {@Autowiredprivate IGlobalCache globalCache;@Testpublic void test() {globalCache.set("key2", "value3");globalCache.lSetAll("list", Arrays.asList("hello", "redis"));List<Object> list = globalCache.lGet("list", 0, -1);System.out.println(globalCache.get("key2"));}}

以上,完了!

博客整理不易,路过的小伙伴点赞评论下~

springboot整合redis,推荐整合和使用案例(2021版)相关推荐

  1. Redis入门(3): 数据新类型(BitmapsHyperLogLog,GeoSpatial),Jredis,springboot与redis的整合

    Redis新数据类型 Bitmaps 简介 现代计算机用二进制(位) 作为信息的基础单位, 1个字节等于8位, 例如"abc"字符串是由3个字节组成, 但实际在计算机存储时将其用二 ...

  2. springboot+shiro+redis项目整合

    介绍: Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最 ...

  3. springboot整合redis后整合es,报错Failed to instantiate [org.elasticsearch.client.transport.TransportClient]

    之前springboot项目整合了redis,现在整个es,启动项目后 发现报这个错误 [ERROR]Failed to instantiate [org.elasticsearch.client.t ...

  4. java整合redis集群_SpringBoot2.X整合Redis(单机+集群+多数据源)-Lettuce版

    最近项目尝试从SpringBoot1.X升级到SpringBoot2.X, 但是 Spring Boot 2.0中 Redis 客户端驱动现在由 Jedis变为了 Lettuce, 所以尝试测试一下L ...

  5. Springboot应用中线程池配置教程(2021版)

    前言:日常开发中我们常用ThreadPoolExecutor提供的线程池服务帮我们管理线程,在Springboot中更是提供了@Async注解来简化业务逻辑提交到线程池中执行的过程.由于Springb ...

  6. spring boot连接redis配置127.0.0.1_Java技术分享——Springboot整合redis

    springboot提供了spring-data-redis的框架来整合redis的操作.下面主要介绍,springboot整合redis的配置,以及spring-data-redis是如何提供便捷的 ...

  7. SpringBoot整合redis实现简单的操作demo

    SpringBoot中整合Redis 将用户频繁访问的内容存放在离用户最近,访问速度最快的地方,提高用户的响应速度,今天先来讲下在springboot中整合redis的详细步骤. 1.安装步骤 安装步 ...

  8. redis05_springboot+mybatis整合redis cluster

    一.springboot+mybatis整合redis cluster整合流程图 二.springboot+mybatis整合redis cluster具体实现 2.1   创建springboot+ ...

  9. springboot整合redis案例——点赞取消点赞

    目录 springboot与缓存 JSR-107 Spring缓存抽象 重要概念和缓存注解 springboot整合redis 案例一:Redis是实现点赞.取消点赞 一.Redis 缓存设计及实现 ...

最新文章

  1. 沫沫金:2014最新全浏览器兼容左列固定右列自适应宽度技巧大公开
  2. 对CAN、USART、SPI、SCI等常见总线的简单介绍
  3. 分布式定时任务框架Elastic-Job的使用
  4. 无法从套接字中获取更多数据_数据科学中应引起更多关注的一个组成部分
  5. python比较时间的最大值_时间戳的最大值
  6. OpenTelemetry-可观察性的新时代
  7. 总结 | 深度学习PyTorch神经网络箱使用
  8. mysql关闭12260端口_windows 如何查看端口占用情况?
  9. 从今天起,TensorFlow 1.9开始支持树莓派了
  10. 《算法图解》之散列表
  11. CSS3 ---奔跑的小人
  12. 基于 Roslyn 实现代码动态编译
  13. Python 爬虫 爬取视频
  14. img 标签的 height 和 width 属性设置图像的尺寸。
  15. Android-adb获取当前前台进程
  16. 7行代码让B站崩溃3小时,竟因“一个诡计多端的0”
  17. Calc3: Partial Derivative
  18. FRED应用: LED混合准直透镜模拟
  19. 大数据毕设/课设 - 水质情况实时监测预警可视化设计与实现
  20. 【自学Python】Python布尔型(bool)

热门文章

  1. Hibernate 学习-1
  2. iOS : 静态库(.framework)合并
  3. 《Windows via C/C++》学习笔记(二):Working with Characters and String
  4. http :请求响应报文-web服务-ajax-cors跨域
  5. LeetCode--95. 不同的二叉树搜索Ⅱ(动态规划)
  6. oracle signed类型,char、signed char 和 unsigned char 的区别
  7. 连接oracle配置文件参数,Hibernate3 +Oracle10g 集群,hibernate配置文件中如何编写连接参数...
  8. Dart 13-Day
  9. 7-42 关于堆的判断 (25 分)
  10. 7-1 打印沙漏 (20 分)