首页 文章 精选 留言 我的

精选列表

搜索[java],共10000篇文章
优秀的个人博客,低调大师

java经常使用16种工具类

一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流、socket、或者selector且不抛出异常,通常放在finally块toString:转换IO流、 Uri、 byte[]为Stringcopy:IO流数据复制,从输入流写到输出流中,最大支持2GBtoByteArray:从输入流、URI获取byte[]write:把字节. 字符等写入输出流toInputStream:把字符转换为输入流readLines:从输入流中读取多行数据,返回List<String copyLarge:同copy,支持 2GB以上数据的复制lineIterator:从输入流返回一个迭代器,根据参数要求读取的数据量,全部读取,如果数据不够,则失败二. org.apache.commons.io.FileUtils deleteDirectory:删除文件夹readFileToString:以字符形式读取文件内容deleteQueitly:删除文件或文件夹且不会抛出异常copyFile:复制文件writeStringToFile:把字符写到目标文件,如果文件不存在,则创建forceMkdir:强制创建文件夹,如果该文件夹父级目录不存在,则创建父级write:把字符写到指定文件中listFiles:列举某个目录下的文件(根据过滤器)copyDirectory:复制文件夹forceDelete:强制删除文件三. org.apache.commons.lang.StringUtils isBlank:字符串是否为空 (trim后判断)isEmpty:字符串是否为空 (不trim并判断)equals:字符串是否相等join:合并数组为单一字符串,可传分隔符split:分割字符串EMPTY:返回空字符串trimToNull:trim后为空字符串则转换为nullreplace:替换字符串四. org.apache.http.util.EntityUtils toString:把Entity转换为字符串consume:确保Entity中的内容全部被消费。可以看到源码里又一次消费了Entity的内容,假如用户没有消费,那调用Entity时候将会把它消费掉toByteArray:把Entity转换为字节流consumeQuietly:和consume一样,但不抛异常getContentCharset:获取内容的编码五. org.apache.commons.lang3.StringUtils isBlank:字符串是否为空 (trim后判断)isEmpty:字符串是否为空 (不trim并判断)equals:字符串是否相等join:合并数组为单一字符串,可传分隔符split:分割字符串EMPTY:返回空字符串replace:替换字符串capitalize:首字符大写六. org.apache.commons.io.FilenameUtils getExtension:返回文件后缀名getBaseName:返回文件名,不包含后缀名getName:返回文件全名concat:按命令行风格组合文件路径(详见方法注释)removeExtension:删除后缀名normalize:使路径正常化wildcardMatch:匹配通配符seperatorToUnix:路径分隔符改成unix系统格式的,即/getFullPath:获取文件路径,不包括文件名isExtension:检查文件后缀名是不是传入参数(List<String )中的一个 七. org.springframework.util.StringUtils hasText:检查字符串中是否包含文本hasLength:检测字符串是否长度大于0isEmpty:检测字符串是否为空(若传入为对象,则判断对象是否为null)commaDelimitedStringToArray:逗号分隔的String转换为数组collectionToDelimitedString:把集合转为CSV格式字符串replace 替换字符串7. delimitedListToStringArray:相当于splituncapitalize:首字母小写collectionToDelimitedCommaString:把集合转为CSV格式字符串tokenizeToStringArray:和split基本一样,但能自动去掉空白的单词八. org.apache.commons.lang.ArrayUtils contains:是否包含某字符串addAll:添加整个数组clone:克隆一个数组isEmpty:是否空数组add:向数组添加元素subarray:截取数组indexOf:查找某个元素的下标isEquals:比较数组是否相等toObject:基础类型数据数组转换为对应的Object数组九. org.apache.commons.lang.StringEscapeUtils 参考十五:org.apache.commons.lang3.StringEscapeUtils十. org.apache.http.client.utils.URLEncodedUtils format:格式化参数,返回一个HTTP POST或者HTTP PUT可用application/x-www-form-urlencoded字符串parse:把String或者URI等转换为List<NameValuePair 十一. org.apache.commons.codec.digest.DigestUtils md5Hex:MD5加密,返回32位字符串sha1Hex:SHA-1加密sha256Hex:SHA-256加密sha512Hex:SHA-512加密md5:MD5加密,返回16位字符串十二. org.apache.commons.collections.CollectionUtils isEmpty:是否为空select:根据条件筛选集合元素transform:根据指定方法处理集合元素,类似List的map()filter:过滤元素,雷瑟List的filter()find:基本和select一样collect:和transform 差不多一样,但是返回新数组forAllDo:调用每个元素的指定方法isEqualCollection:判断两个集合是否一致十三. org.apache.commons.lang3.ArrayUtils contains:是否包含某个字符串addAll:添加整个数组clone:克隆一个数组isEmpty:是否空数组add:向数组添加元素subarray:截取数组indexOf:查找某个元素的下标isEquals:比较数组是否相等toObject:基础类型数据数组转换为对应的Object数组十四. org.apache.commons.beanutils.PropertyUtils getProperty:获取对象属性值setProperty:设置对象属性值getPropertyDiscriptor:获取属性描述器isReadable:检查属性是否可访问copyProperties:复制属性值,从一个对象到另一个对象getPropertyDiscriptors:获取所有属性描述器isWriteable:检查属性是否可写getPropertyType:获取对象属性类型十五. org.apache.commons.lang3.StringEscapeUtils unescapeHtml4:转义htmlescapeHtml4:反转义htmlescapeXml:转义xmlunescapeXml:反转义xmlescapeJava:转义unicode编码escapeEcmaScript:转义EcmaScript字符unescapeJava:反转义unicode编码escapeJson:转义json字符escapeXml10:转义Xml10这个现在已经废弃了,建议使用commons-text包里面的方法。 十六. org.apache.commons.beanutils.BeanUtils copyPeoperties:复制属性值,从一个对象到另一个对象getProperty:获取对象属性值setProperty:设置对象属性值populate:根据Map给属性复制copyPeoperty:复制单个值,从一个对象到另一个对象cloneBean:克隆bean实例

优秀的个人博客,低调大师

Java中使用redisTemplate操作缓存

背景 在最近的项目中,有一个需求是对一个很大的数据库进行查询,数据量大概在几千万条。但同时对查询速度的要求也比较高。 这个数据库之前在没有使用Presto的情况下,使用的是Hive,使用Hive进行一个简单的查询,速度可能在几分钟。当然几分钟也并不完全是跑SQL的时间,这里面包含发请求,查询数据并且返回数据的时间的总和。但是即使这样,这样的速度明显不能满足交互式的查询需求。 我们的下一个解决方案就是Presto,在使用了Presto之后,查询速度降到了秒级。但是对于一个前端查询界面的交互式查询来说,十几秒仍然是一个不能接受的时间。 虽然Presto相比Hive已经快了很多(FaceBook官方宣称的是10倍),但是对分页的支持不是很友好。我在使用的时候是自己在后端实现的分页。 在这种情况下应用缓存实属无奈之举。讲道理,优化应从底层开始,自底而上。上层优化的方式和效率感觉都很有局限。 为什么要使用缓存 前端查询中,单次查询的匹配数据量有可能会达到上百甚至上千条,在前端中肯定是需要分页展示的。就算每次查询10条数据,整个查询也要耗时6-8s的时间。想象一下,每翻一页等10s的场景。 所以,此时使用redis缓存。减少请求数据库的次数。将匹配的数据一并存入数据库。这样只有在第一次查询时耗费长一点,一旦查询完成,用户点击下一页就是毫秒级别的操作了。 使用redisTemplate Spring封装了一个比较强大的模板,也就是redisTemplate,方便在开发的时候操作Redis缓存。在Redis中可以存储String、List、Set、Hash、Zset。下面将针对List和Hash分别介绍。 List Redis中的List为简单的字符串列表,常见的有下面几种操作。 hasKey 判断一个键是否存在,只需要调用hasKey就可以了。假设这个Key是test,具体用法如下。 if (redisTemplate.hasKey("test")) { System.out.println("存在"); } else { System.out.println("不存在"); } range 该函数用于从redis缓存中获取指定区间的数据。具体用法如下。 if (redisTemplate.hasKey("test")) { // 该键的值为 [4, 3, 2, 1] System.out.println(redisTemplate.opsForList().range("test", 0, 0)); // [4] System.out.println(redisTemplate.opsForList().range("test", 0, 1)); // [4, 3] System.out.println(redisTemplate.opsForList().range("test", 0, 2)); // [4, 3, 2] System.out.println(redisTemplate.opsForList().range("test", 0, 3)); // [4, 3, 2, 1] System.out.println(redisTemplate.opsForList().range("test", 0, 4)); // [4, 3, 2, 1] System.out.println(redisTemplate.opsForList().range("test", 0, 5)); // [4, 3, 2, 1] System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [4, 3, 2, 1] 如果结束位是-1, 则表示取所有的值 } delete 删除某个键。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [1, 2, 3, 4] redisTemplate.delete("test"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [] size 获取该键的集合长度。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); System.out.println(redisTemplate.opsForList().size("test")); // 4 leftPush 我们把存放这个值的地方想象成如图所示的容器。 并且取数据总是从左边取,但是存数据可以从左也可以从右。左就是leftPush,右就是rightPush。leftPush如下图所示。 用法如下。 for (int i = 0; i < 4; i++) { Integer value = i + 1; redisTemplate.opsForList().leftPush("test", value.toString()); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); } 控制台输出的结果如下。 [1] [2, 1] [3, 2, 1] [4, 3, 2, 1] leftPushAll 基本和leftPush一样,只不过是一次性的将List入栈。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().leftPushAll("test", test); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [4, 3, 2, 1] 当然你也可以这样 redisTemplate.opsForList().leftPushAll("test", t"1", "2", "3", "4"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [4, 3, 2, 1] leftPushIfPresent 跟leftPush是同样的操作,唯一的不同是,当且仅当key存在时,才会更新key的值。如果key不存在则不会对数据进行任何操作。 redisTemplate.delete("test"); redisTemplate.opsForList().leftPushIfPresent("test", "1"); redisTemplate.opsForList().leftPushIfPresent("test", "2"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [] leftPop 该函数用于移除上面我们抽象的容器中的最左边的一个元素。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); redisTemplate.opsForList().leftPop("test"); // [2, 3, 4] redisTemplate.opsForList().leftPop("test"); // [3, 4] redisTemplate.opsForList().leftPop("test"); // [4] redisTemplate.opsForList().leftPop("test"); // [] redisTemplate.opsForList().leftPop("test"); // [] 值得注意的是,当返回为空后,在redis中这个key也不复存在了。如果此时再调用leftPushIfPresent,是无法再添加数据的。有代码有真相。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); redisTemplate.opsForList().leftPop("test"); // [2, 3, 4] redisTemplate.opsForList().leftPop("test"); // [3, 4] redisTemplate.opsForList().leftPop("test"); // [4] redisTemplate.opsForList().leftPop("test"); // [] redisTemplate.opsForList().leftPop("test"); // [] redisTemplate.opsForList().leftPushIfPresent("test", "1"); // [] redisTemplate.opsForList().leftPushIfPresent("test", "1"); // [] rightPush rightPush如下图所示。 用法如下。 for (int i = 0; i < 4; i++) { Integer value = i + 1; redisTemplate.opsForList().leftPush("test", value.toString()); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); } 控制台输出的结果如下。 [1] [1, 2] [1, 2, 3] [1, 2, 3, 4] rightPushAll 同rightPush,一次性将List存入。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [1, 2, 3, 4] 当然你也可以这样。 redisTemplate.opsForList().rightPushAll("test", "1", "2", "3", "4"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [1, 2, 3, 4] rightPushIfPresent 跟rightPush是同样的操作,唯一的不同是,当且仅当key存在时,才会更新key的值。如果key不存在则不会对数据进行任何操作。 redisTemplate.delete("test"); redisTemplate.opsForList().rightPushIfPresent("test", "1"); redisTemplate.opsForList().rightPushIfPresent("test", "2"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [] rightPop 该函数用于移除上面我们抽象的容器中的最右边的一个元素。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); redisTemplate.opsForList().rightPop("test"); // [1, 2, 3] redisTemplate.opsForList().rightPop("test"); // [1, 2] redisTemplate.opsForList().rightPop("test"); // [1] redisTemplate.opsForList().rightPop("test"); // [] redisTemplate.opsForList().rightPop("test"); // [] 与leftPop一样,返回空之后,再调用rightPushIfPresent,是无法再添加数据的。 index 获取list中指定位置的元素。 if (redisTemplate.hasKey("test")) { // 该键的值为 [1, 2, 3, 4] System.out.println(redisTemplate.opsForList().index("test", -1)); // 4 System.out.println(redisTemplate.opsForList().index("test", 0)); // 1 System.out.println(redisTemplate.opsForList().index("test", 1)); // 2 System.out.println(redisTemplate.opsForList().index("test", 2)); // 3 System.out.println(redisTemplate.opsForList().index("test", 3)); // 4 System.out.println(redisTemplate.opsForList().index("test", 4)); // null System.out.println(redisTemplate.opsForList().index("test", 5)); // null } 值得注意的有两点。一个是如果下标是-1的话,则会返回List最后一个元素,另一个如果数组下标越界,则会返回null。 trim 用于截取指定区间的元素,可能你会理解成与range是一样的作用。看了下面的代码之后应该就会立刻理解。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); redisTemplate.opsForList().rightPushAll("test", test); // [1, 2, 3, 4] redisTemplate.opsForList().trim("test", 0, 2); // [1, 2, 3] 其实作用完全不一样。range是获取指定区间内的数据,而trim是留下指定区间的数据,删除不在区间的所有数据。trim是void,不会返回任何数据。 remove 用于移除键中指定的元素。接受3个参数,分别是缓存的键名,计数事件,要移除的值。计数事件可以传入的有三个值,分别是-1、0、1。 -1代表从存储容器的最右边开始,删除一个与要移除的值匹配的数据;0代表删除所有与传入值匹配的数据;1代表从存储容器的最左边开始,删除一个与要移除的值匹配的数据。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); test.add("4"); test.add("3"); test.add("2"); test.add("1"); redisTemplate.opsForList().rightPushAll("test", test); // [1, 2, 3, 4, 4, 3, 2, 1] // 当计数事件是-1、传入值是1时 redisTemplate.opsForList().remove("test", -1, "1"); // [1, 2, 3, 4, 4, 3, 2] // 当计数事件是1,传入值是1时 redisTemplate.opsForList().remove("test", 1, "1"); // [2, 3, 4, 4, 3, 2] // 当计数事件是0,传入值是4时 redisTemplate.opsForList().remove("test", 0, "4"); // [2, 3, 3, 2] rightPopAndLeftPush 该函数用于操作两个键之间的数据,接受两个参数,分别是源key、目标key。该函数会将源key进行rightPop,再将返回的值,作为输入参数,在目标key上进行leftPush。具体代码如下。 List<String> test = new ArrayList<>(); test.add("1"); test.add("2"); test.add("3"); test.add("4"); List<String> test2 = new ArrayList<>(); test2.add("1"); test2.add("2"); test2.add("3"); redisTemplate.opsForList().rightPushAll("test", test); // [1, 2, 3, 4] redisTemplate.opsForList().rightPushAll("test2", test2); // [1, 2, 3] redisTemplate.opsForList().rightPopAndLeftPush("test", "test2"); System.out.println(redisTemplate.opsForList().range("test", 0, -1)); // [1, 2, 3] System.out.println(redisTemplate.opsForList().range("test2", 0, -1)); // [4, 1, 2, 3] Hash 存储类型为hash其实很好理解。在上述的List中,一个redis的Key可以理解为一个List,而在Hash中,一个redis的Key可以理解为一个HashMap。 put 用于写入数据。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); // [1, 2, 3, 4] redisTemplate.opsForHash().put("test", "isAdmin", true); // true putALl 用于一次性向一个Hash键中添加多个key。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); List<String> list2 = new ArrayList<>(); list2.add("5"); list2.add("6"); list2.add("7"); list2.add("8"); Map<String, String> valueMap = new HashMap<>(); valueMap.put("map1", list.toString()); valueMap.put("map2", list2.toString()); redisTemplate.opsForHash().putAll("test", valueMap); // {map2=[5, 6, 7, 8], map1=[1, 2, 3, 4]} putIfAbsent 用于向一个Hash键中写入数据。当key在Hash键中已经存在时,则不会写入任何数据,只有在Hash键中不存在这个key时,才会写入数据。 同时,如果连这个Hash键都不存在,redisTemplate会新建一个Hash键,再写入key。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().putIfAbsent("test", "map", list.toString()); System.out.println(redisTemplate.opsForHash().entries("test")); // {map=[1, 2, 3, 4]} get 用于获取数据。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); System.out.println(redisTemplate.opsForHash().get("test", "map")); // [1, 2, 3, 4] System.out.println(redisTemplate.opsForHash().get("test", "isAdmin")); // true Boolean bool = (Boolean) redisTemplate.opsForHash().get("test", "isAdmin"); System.out.println(bool); // true String str = redisTemplate.opsForHash().get("test", "map").toString(); List<String> array = JSONArray.parseArray(str, String.class); System.out.println(array.size()); // 4 值得注意的是,使用get函数获取的数据都是Object类型。 所以需要使用类型与上述例子中的布尔类型的话,则需要强制转换一次。List类型则可以使用fastjson这种工具来进行转换。转换的例子已列举在上述代码中。 delete 用于删除一个Hash键中的key。可以理解为删除一个map中的某个key。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); List<String> list2 = new ArrayList<>(); list2.add("5"); list2.add("6"); list2.add("7"); list2.add("8"); Map<String, String> valueMap = new HashMap<>(); valueMap.put("map1", list.toString()); valueMap.put("map2", list2.toString()); redisTemplate.opsForHash().putAll("test", valueMap); // {map2=[5, 6, 7, 8], map1=[1, 2, 3, 4]} redisTemplate.opsForHash().delete("test", "map1"); // {map2=[5, 6, 7, 8]} values 用于获取一个Hash类型的键的所有值。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); System.out.println(redisTemplate.opsForHash().values("test")); // [[1, 2, 3, 4], true] entries 用于以Map的格式获取一个Hash键的所有值。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); Map<String, String> map = redisTemplate.opsForHash().entries("test"); System.out.println(map.get("map")); // [1, 2, 3, 4] System.out.println(map.get("map") instanceof String); // true System.out.println(redisTemplate.opsForHash().entries("test")); // {a=[1, 2, 3, 4], isAdmin=true} hasKey 用于获取一个Hash键中是否含有某个键。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); System.out.println(redisTemplate.opsForHash().hasKey("test", "map")); // true System.out.println(redisTemplate.opsForHash().hasKey("test", "b")); // false System.out.println(redisTemplate.opsForHash().hasKey("test", "isAdmin")); // true keys 用于获取一个Hash键中所有的键。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); System.out.println(redisTemplate.opsForHash().keys("test")); // [a, isAdmin] size 用于获取一个Hash键中包含的键的数量。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); redisTemplate.opsForHash().put("test", "map", list.toString()); redisTemplate.opsForHash().put("test", "isAdmin", true); System.out.println(redisTemplate.opsForHash().size("test")); // 2 increment 用于让一个Hash键中的某个key,根据传入的值进行累加。传入的数值只能是double或者long,不接受浮点型 redisTemplate.opsForHash().increment("test", "a", 3); redisTemplate.opsForHash().increment("test", "a", -3); redisTemplate.opsForHash().increment("test", "a", 1); redisTemplate.opsForHash().increment("test", "a", 0); System.out.println(redisTemplate.opsForHash().entries("test")); // {a=1} multiGet 用于批量的获取一个Hash键中多个key的值。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); List<String> list2 = new ArrayList<>(); list2.add("5"); list2.add("6"); list2.add("7"); list2.add("8"); redisTemplate.opsForHash().put("test", "map1", list.toString()); // [1, 2, 3, 4] redisTemplate.opsForHash().put("test", "map2", list2.toString()); // [5, 6, 7, 8] List<String> keys = new ArrayList<>(); keys.add("map1"); keys.add("map2"); System.out.println(redisTemplate.opsForHash().multiGet("test", keys)); // [[1, 2, 3, 4], [5, 6, 7, 8]] System.out.println(redisTemplate.opsForHash().multiGet("test", keys) instanceof List); // true scan 获取所以匹配条件的Hash键中key的值。我查过一些资料,大部分写的是无法模糊匹配,我自己尝试了一下,其实是可以的。如下,使用scan模糊匹配hash键的key中,带SCAN的key。 List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); List<String> list2 = new ArrayList<>(); list2.add("5"); list2.add("6"); list2.add("7"); list2.add("8"); List<String> list3 = new ArrayList<>(); list3.add("9"); list3.add("10"); list3.add("11"); list3.add("12"); Map<String, String> valueMap = new HashMap<>(); valueMap.put("map1", list.toString()); valueMap.put("SCAN_map2", list2.toString()); valueMap.put("map3", list3.toString()); redisTemplate.opsForHash().putAll("test", valueMap); // {SCAN_map2=[5, 6, 7, 8], map3=[9, 10, 11, 12], map1=[1, 2, 3, 4]} Cursor<Map.Entry<String, String>> cursor = redisTemplate.opsForHash().scan("test", ScanOptions.scanOptions().match("*SCAN*").build()); if (cursor.hasNext()) { while (cursor.hasNext()) { Map.Entry<String, String> entry = cursor.next(); System.out.println(entry.getValue()); // [5, 6, 7, 8] } } 引入redisTemplate 如果大家看懂了怎么用,就可以将redisTemplate引入项目中了。 引入pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.0.5.RELEASE</version> </dependency> 新建配置文件 然后需要新建一个RedisConfig配置文件。 package com.detectivehlh; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; /** * RedisConfig * * @author Lunhao Hu * @date 2019-01-17 15:12 **/ @Configuration public class RedisConfig { @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //redis序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisTemplate template = new StringRedisTemplate(factory); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashKeySerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } } 注入 将redisTemplate注入到需要使用的地方。 @Autowired private RedisTemplate redisTemplate; 写在后面 Github

优秀的个人博客,低调大师

java EasyExcel集成及工具类使用

EasyExcel简介 easyExcel是阿里巴巴开源poi插件之一,当前最新版本1.1.2-beta5,poi版本3.17,因此,集成时老版本poi需要提升poi版本,或者做版本隔离。 吐槽一下这个版本没有RELEASE版本 主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错 主要解决方式:通过解压文件的方式加载,一行一行的加载,并且抛弃样式字体等不重要的数据,降低内存的占用 具体实现原理,建议看github上的readme EasyExcel优势 注解式自定义操作。 输入输出简单,提供输入输出过程的接口 支持一定程度的单元格合并等灵活化操作 EasyExcel劣势 框架不成熟,1.1.0版本后提供灵活接口的只剩beta版本 依然存在一些bug 没有一套完整的api ExcelUtil快速使用 maven引用(版本控制内若存在低版本POI,请升级版本和代码,官方POI版本3.17): <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>1.1.2-beta5</version> </dependency> 工具类:详见底部附带的github地址 实体类继承BaseRowModel ,对需要导出或者导入的字段增加@ExcelProperty注解,index值为对应excel中的列,value为表头,format为日期格式化 public class PersonDto extends BaseRowModel{ /** id */ @ExcelProperty(index = 0 , value = "id") private String id; /** 姓名 **/ @ExcelProperty(index = 1 , value = "姓名") private String name; /** 生日 **/ @ExcelProperty(index = 2 , value = "生日" , format = "yyyy-MM-dd") private String birth; } 导出: ExcelUtil.writeExcel(response,exportVoList,"导出文件名","sheet1", ExcelTypeEnum.XLSX , PersonDto .class); 导入: List<FundDto> importDtoList = ExcelUtil.readExcel(excelFile,PersonDto .class); 自定义样式注解: 在对应列上增加注解,修改对应的列上的参数,例 public class PersonDto extends BaseRowModel{ /** id */ @ExcelProperty(index = 0 , value = "id") private String id; /** 姓名 **/ @ExcelProperty(index = 1 , value = "姓名") private String name; /** 生日 **/ @ExcelProperty(index = 2 , value = "生日" , format = "yyyy-MM-dd") @CellStyleFormat(fillBackgroundColor= IndexedColors.LIGHT_YELLOW) @CellFontFormat(fontColor=IndexedColors.BLACK) private String birth; } Ps. 后续有新的需要,可以就自定义注解的修改增加新的功能 目前已知存在问题: 自定义注解目前未经过多种场景的测试,出现问题,需要再修改 导入的实体类中配置了注解的属性为基本类型时,可能会读到一部分空行,这个问题目前需要EasyExcel的看看后续版本处理 EasyExcel github地址:https://github.com/alibaba/easyexcel EasyExcelUtils github项目地址:https://github.com/wangxiaoxiongjuly/easyExcelUtils

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册