# Spring 框架中自带的工具类
# Spring 中最常用的四个工具类
- ObjectUtils
- StringUtils
- CollectionUtils
- Assert
略
# PatternMatchUtils
PatternMatchUtils 类来自 org.springframework.util
包 。
它用于进行简单地正则匹配。
判断规则有:xxx*
, *xxx
, *xxx*
和 xxx*yyy
。 *
通配任意个字符。
注意
,正则规则字符串在前。
// 判断字符串是否符合规则。
static boolean simpleMatch(String pattern, String str)
// 判断字符串是否同时满足多个规则。
static boolean simpleMatch(String[] patterns, String str)
# StreamUtils
StreamUtils 类位于 org.springframework.util 包下 。
# 输出
void copy(byte[] in, OutputStream out)
int copy(InputStream in, OutputStream out)
void copy(String in, Charset charset, OutputStream out)
long copyRange(InputStream in, OutputStream out, long start, long end)
# 输入
byte[] copyToByteArray(InputStream in)
String copyToString(InputStream in, Charset charset)
// 舍弃输入流中的内容
int drain(InputStream in)
# 实例化
InputStream emptyInput()
// 所生成的 输入流 close() 方法无效
InputStream nonClosing(InputStream in)
// 所生成的 输出流 close() 方法无效
OutputStream nonClosing(OutputStream out)
# FileCopyUtils
FileCopyUtils 类来自 org.springframework.util 包。它用于文件的拷贝处理工具。
以下方法结尾 static 方法,故不再显示 static 关键字。
# 输出
// 从字节数组到文件
void copy(byte[] in, File out)
// 从文件到文件
int copy(File in, File out)
// 从字节数组到输出流
void copy(byte[] in, OutputStream out)
// 从输入流到输出流
int copy(InputStream in, OutputStream out)
// 从输入流到输出流
int copy(Reader in, Writer out)
// 从字符串到输出流
void copy(String in, Writer out)
# 输入
// 从文件中读入到字节数组中
byte[] copyToByteArray(File in)
// 从输入流中读入到字节数组中
byte[] copyToByteArray(InputStream in)
// 从输入流中读入到字符串中
String copyToString(Reader in)
# 资源(Resource)及相关
# URI 和 URL
在原生 JDK 中,提供了 java.net.URI 和 java.net.URL 类,来标识资源的定位。
# | 说明 |
---|---|
URI | 统一资源标志符(Uniform Resource Identifier) |
URL | 统一资源定位符(uniform Resource Location) |
就像经纬度一样可以表示你在世界的哪个角落。URI 和 URL 代表着资源的位置信息。例如,数据库的 JDBC 连接是一个 URI/URL:
dbc:mysql://127.0.0.1:3306/scott?useSSL=false
它表示这一个资源(scott 数据库)的位置信息。
URI 更宽泛、更高级也更抽象,而 URL 则更具体。在概念上,URI 是 URL 的超集,URL 是 URI 的子集。类似于父类和子类的关系。
URL 并未 URI 唯一的 “子类” 。有一些标识资源的方式,它是 URI ,但不是 URL 。例如 urn:isbn:0-486-27557-4
,这个是一本书的 ISBN ,可以唯一标识这本书,它是 URI 但不是 URL 。
# Resource 及其实现类
在日常项目开发过程中,从 classpath 下加载一个配置文件(并从中读取配置信息)是一个常见需求。
Spring 提炼出 Resource(资源)的概念,并围绕它提供了一系列的工具类,能方便地实现上述功能(及其它功能)。
Resource
├── FileSystemResource
├── FileUrlResource
├── ClassPathResource
├── UrlResource
└── InputStreamResource
└── EncodedResource
InputStreamResource 是 Resource 接口的子接口,其实现类 EncodedResource 支持通过 InputStream 生成 Resource 对象,并且可以设置编码。(其他 Resource 都是使用 ISO-8859-1 编码)
Resource 接口定义了『资源』的概念,其中常用方法有:
实例方法 | 说明 |
---|---|
boolean exists() | 判断资源是否存在 |
File getFile() | 从资源中获得 File 对象 |
URI getURI() | 从资源中获得 URI 对象 |
URL getURL() | 从资源中获得 URI 对象 |
InputStream getInputStream() | 获得资源的 InputStream |
String getDescription() | 获得资源的描述信息 |
Resource 接口的各个实现类中除了上述方法外,还有自己的一些方法。
# Resource 的 getFile() 方法的一个问题
Resource 的 getFile() 方法需要 Resource 对象所代表的那个文件 在文件系统中是独立存在的!
因此,你在 Eclipse/Idea 源码运行中运行,或者是一个 .war 的项目在 tomcat 下运行,.getFile() 方法都是没有任何问题,能正常起作用:获得 File 对象。
但是,在 Spring Boot 中,.getFile() 方法无法获得 File 对象。因为,Spring Boot 的 .jar 包不像一般 Java Web 的 .war 那样会被 tomcat 解压开!
因此,Spring Boot 项目中的资源文件都是 内嵌 在 .jar 包中,而非独立存在的。不满足 .getFile() 的那个前提要求。
Spring Boot 的这种场景下,需要 使用 .getInputStream() 方法来替代 .getFile() 方法 。
简而言之,Resource 的 .getInputStream() 方法比 .getFile() 方法具有更好的普适性。
# ResourceUtils
对于常见的 “new Resource() 对象 + 操作 Resource 对象” 的常见使用方式,Spring 提供了一个 ResourceUtils 类来简化这样的代码。
ResourceUtils 类位于 org.springframework.util 包。它用于处理表达资源字符串前缀描述资源的工具. 如: classpath:、file: 等。
不过,ResourceUtils 类也有上面所说的那个 .getFile() 的问题。因此,如果是 Spring Boot 项目,还是少用/不用 ResourceUtils 的 .getFile() 方法。
ResourceUtils 的常用方法:
// 判断字符串是否是一个合法的 URL 字符串。
static boolean isUrl(String resourceLocation)
static URL getURL(String resourceLocation)
static File getFile(String resourceLocation)
static URI toURI(URL url)
static File getFile(URI resourceUri)
static File getFile(URL resourceUrl)
# PropertiesLoaderUtils
.properties 文件是最常见的资源文件。对此,Spring 框架提供了 PropertiesLoaderUtils 工具类来简化加载 .properties 配置类的工作。
PropertiesLoaderUtils 位于 org.springframework.core.io.support 包下。
以下方法都是 static 方法
// 查找资源,并生成 Properties 对象。使用 ISO-8859-1 编码。
Properties loadProperties(Resource resource)
// 从 classpath 中查找资源,并生成 Properties 对象。使用 ISO-8859-1 编码。
Properties loadAllProperties(String resourceName)
// 查找资源,并生成 Properties 对象。
Properties loadProperties(EncodedResource resource)
// 查找资源,填充参数对象。
void fillProperties(Properties props, Resource resource)
// 查找资源,填充参数对象。
void fillProperties(Properties props, EncodedResource resource)
# Spring ResolvableType
提示
ResolveableType 与 Java 的 Type 类型体系密切相关。请先了解另一篇笔记《虚拟机中的泛型类型信息》 的内容。
# 类型擦除
由于类型擦除,当你在实例化泛型对象时,泛型的信息会受影响,被擦除(替换为 Object 等)。例如:
List<String> stringList = new ArrayList<String>();
上述代码中的 stringList 的泛型类型 String 会被擦除,变量 stringList 的实际类型会变为 ArrayList,而非 ArrayList<String> 。
但是好消息是,类型擦除只影响被实例化的类型参数,如果你使用在类定义中,泛型信息会被保留,在运行时可用。例如:
class StringList extends ArrayList<String> {
...
}
StringList stringList = new StringList();
当你去使用 StringList 类型时,这里的 String 信息你是可以通过反射机制获取到的。
# ResolvableType 简介
ResolvableType 是 Spring 4.0 的 feature 之一。
ResolvableType 为 java Type 体系中的所有类型提供了统一的数据结构以及 API 。
逻辑上,ResolvableType 就是一种特殊的容器,它可以用来包装 Type 类型(Class、ParameterizedType、TypeVariable、WildcardType、GenericArrayType)的数据类型的数据。
这样,你是直接操作 ResolvableType,而间接操作 Class、ParameterizedType、TypeVariable 等类型的数据。好处是无论 ResovableType 中封装的是何种 Type 类型, ResolvableType 有统一 API,且更简便好用。
# 简单使用
以 Class 类型为例,用 ResolvableType 包装 Class 类型的常见方式有:
// 其实本质上是一样的
ResolvableType type1 = ResolvableType.forClass(String.class);
ResolvableType type2 = ResolvableType.forClass("hello".getClass());
ResolvableType type3 = ResolvableType.forClass(Integer.class);
ResolvableType type4 = ResolvableType.forClass(ArrayList.class);
于此同时,ResolvableType 还提供了一个 .resolve()
方法,用于反向从 type 对象再反向求出其封装的 Class 对象。
Class clazz1 = type1.resolve(); // class java.lang.String
Class clazz2 = type2.resolve(); // class java.lang.String
Class clazz3 = type3.resolve(); // class java.lang.Integer
Class clazz4 = type4.resolve(); // class java.util.ArrayList
借助于这个 ResolvabType 对象,可以很方便地求出它(String.class
)的直接父类类型、接口类型、泛型参数类型等类型有关信息。
System.out.println(type1.getSuperType());
System.out.println(Arrays.toString(type1.getInterfaces()));
需要注意的是这些方法的返回值的类型,仍然是 ResolvableType 类型(或 ResolvableType 类型的数组)。
- 包装域的类型
- forField(Field field);
- 包装方法形参的类型
- forMethodParameter(Method method, int parameterIndex)
- 包装方法的返回值类型
- forMethodReturnType(Method method);
- 等等
# 在泛型中的使用
还是曾经的一个例子:
public class StringArrayList extends ArrayList<String> {
...
}
在泛型和反射中,我们最常见的需求就是要去【求】出某个类的父类的泛型实参(ActualTypeArguments)。
通过 ResolvableType 实现这个需求就非常容易了:
ResolvableType resolvableType = ResolvableType.forClass(StringArrayList.class);
System.out.println( resolvableType.getSuperType().getGenerics()[0].resolve() );
# Base64Utils
Base64Utils 类来自 org.springframework.util
包。
Base64 是网络上最常见的用于传输 8 Bit 字节码的编码方式之一,Base64 就是一种基于 64 个可打印字符来表示二进制数据的方法。
Base64 编码是从二进制到字符的过程,可用于在 HTTP 环境下传递较长的标识信息。
采用 Base64 编码具有不可读性,需要解码后才能阅读。
编码方法
static byte[] encode(byte[] src) static String encodeToString(byte[] src) static byte[] encodeUrlSafe(byte[] src) static String encodeToUrlSafeString(byte[] src)
解码方法
static byte[] decode(byte[] src) static byte[] decodeFromString(String src) static byte[] decodeUrlSafe(byte[] src) static byte[] decodeFromUrlSafeString(String src)
BASE64-字母表
字符 | 十进制 | 十六进制 | 字符 | 十进制 | 十六进制 | 字符 | 十进制 | 十六进制 | ||
---|---|---|---|---|---|---|---|---|---|---|
A | 0 | 00 | W | 22 | 16 | s | 44 | 2C | ||
B | 1 | 01 | X | 23 | 17 | t | 45 | 2D | ||
C | 2 | 02 | Y | 24 | 18 | u | 46 | 2E | ||
D | 3 | 03 | Z | 25 | 19 | v | 47 | 2F | ||
E | 4 | 04 | a | 26 | 1A | w | 48 | 30 | ||
F | 5 | 05 | b | 27 | 1B | x | 49 | 31 | ||
G | 6 | 06 | c | 28 | 1C | y | 50 | 32 | ||
H | 7 | 07 | d | 29 | 1D | z | 51 | 33 | ||
I | 8 | 08 | e | 30 | 1E | 0 | 52 | 34 | ||
J | 9 | 09 | f | 31 | 1F | 1 | 53 | 35 | ||
K | 10 | 0A | g | 32 | 20 | 2 | 54 | 36 | ||
L | 11 | 0B | h | 33 | 21 | 3 | 55 | 37 | ||
M | 12 | 0C | i | 34 | 22 | 4 | 56 | 38 | ||
N | 13 | 0D | j | 35 | 23 | 5 | 57 | 39 | ||
O | 14 | 0E | k | 36 | 24 | 6 | 58 | 3A | ||
P | 15 | 0F | l | 37 | 25 | 7 | 59 | 3B | ||
Q | 16 | 10 | m | 38 | 26 | 8 | 60 | 3C | ||
R | 17 | 11 | n | 39 | 27 | 9 | 61 | 3D | ||
S | 18 | 12 | o | 40 | 28 | + | 62 | 3E | ||
T | 19 | 13 | p | 41 | 29 | / | 63 | 3F | ||
U | 20 | 14 | q | 42 | 2A | |||||
V | 21 | 15 | r | 43 | 2B | = | (pad) | (pad) |
在 URL and Filename Safe 字母表中,+
号会被替换成 -
号,进行编解码。同理,/
号会被替换成 _
。
# SerializationUtils
SerializationUtils 类来自 org.springframework.util 包,它用于 java 的序列化与反序列化。
// 序列化方法
static byte[] serialize(Object object)
// 反序列化方法
static Object deserialize(byte[] bytes)