别再傻傻写代码,Spring内置神器带你飞

33 阅读14分钟

一、Spring 内置神器的魅力

Spring 作为一款备受开发者青睐的框架,其内置神器为开发带来了诸多便利。这些内置神器不仅提高了开发效率,还增强了代码的可读性和可维护性。

其中,Spring 自带了许多实用的工具类,如 Assert、StringUtils、CollectionUtils 和 ObjectUtils 等。这些工具类在日常开发中发挥着重要作用。

Assert 类用于在代码中进行断言判断。可以断言参数是否为空、集合是否为空以及条件是否满足等。例如,可以使用Assert.notNull方法判断一个对象是否为空,如果为空则抛出异常。同样,Assert.notEmpty方法可以判断集合是否为空,不满足条件时也会抛出异常。

StringUtils 类对字符串操作进行了扩展。它提供了判断字符串是否为空的方法,如hasLength方法可以判断字符串是否有长度。此外,还可以使用trimAllWhitespace方法去除字符串中的空格,包括中间的空格。同时,该类还提供了判断字符串开头或结尾的方法,如startsWithIgnoreCase和endsWithIgnoreCase,可以忽略大小写进行比较。另外,collectionToCommaDelimitedString方法可以将字符串集合拼接成一个以逗号分隔的字符串。

CollectionUtils 工具类专门用于集合的判断。可以使用isEmpty方法判断集合是否为空,使用contains方法判断集合中是否包含某个元素。在判断元素是否存在时,需要先调用集合的iterator方法。

ObjectUtils 工具类提供了强大的对象操作方法。它可以判断对象、字符串、集合、数组、Optional 和 Map 是否为空。例如,可以使用nullSafeEquals方法安全地判断两个对象是否相等,避免了空指针问题。

除了这些工具类,Spring 还内置了其他神器,如 RestTemplate。RestTemplate 作为 Spring 内置的 Http 客户端,提供了访问 HTTP 接口的统一方式,底层允许使用不同的实现,包括 HttpURLConnection、HttpClient、OkHttp 以及自定义的实现。使用 RestTemplate 可以轻松地发送 GET、POST、PUT、DELETE 等请求,并获取响应内容。

总之,Spring 的内置神器为开发者提供了丰富的功能和便利,让开发更加高效和轻松。不再傻傻写代码,快来探索和使用这些神器吧!

二、Spring 内置神器有哪些

1. 断言工具类(Assert)

Assert 类是 Spring 中的断言工具类,通常用于数据合法性检查。它提供了多种方法来判断参数是否满足特定条件,若不满足则抛出异常。

例如,可以使用notNull方法判断一个对象是否为空,如果为空则抛出异常。如Assert.notNull(obj, "对象不能为空"),当obj为null时,会抛出IllegalArgumentException异常,并显示指定的错误信息。

isTrue方法用于判断一个布尔表达式是否为真,如果为假则抛出异常。例如Assert.isTrue(expression, "条件必须为真"),当expression为false时,会抛出异常。

notEmpty方法可以判断集合是否为空,若集合为空则抛出异常。例如对于一个列表List list = null,调用Assert.notEmpty(list, "列表不能为空")会在列表为空时抛出异常。

2. 对象、数组、集合工具类(ObjectUtils)

ObjectUtils 提供了强大的对象操作方法。

获取对象基本信息方面,如nullSafeClassName方法可以在对象为null时返回字符串 "null",否则返回对象的类名。nullSafeHashCode方法在对象为null时返回 0,否则返回对象的哈希码。nullSafeToString方法在对象为null时返回 "null",否则返回对象的字符串表示。

判断工具方面,isEmpty方法可以判断对象、字符串、集合、数组、Optional和Map是否为空。例如,对于一个数组Object[] array = null,调用ObjectUtils.isEmpty(array)会返回true。isArray方法用于判断参数对象是否是数组,返回布尔值。containsElement方法可以判断数组中是否包含指定元素,对于数组Object[] array和元素Object element,如果数组中包含该元素则返回true。nullSafeEquals方法安全地判断两个对象是否相等,避免了空指针问题。

其他工具方法中,addObjectToArray方法可以向参数数组的末尾追加新元素,并返回一个新数组。

3. 字符串工具类(StringUtils)

StringUtils 是 Spring 中功能强大的字符串工具类,扩展了 JDK 对字符串的操作。

字符串判断工具方面,isEmpty方法判断字符串是否为null或空字符串,但该方法已被废弃,可以使用hasLength方法判断字符串是否有长度,即不为null且长度大于 0。endsWithIgnoreCase方法判断字符串是否以指定内容结束,忽略大小写。startsWithIgnoreCase方法判断字符串是否以指定内容开头,忽略大小写。containsWhitespace方法判断字符串是否包含空白符。hasLength方法判断字符串非空且长度不为 0。hasText方法判断字符串是否包含实际内容,即非仅包含空白符。substringMatch方法判断字符串指定索引处是否包含一个子串。countOccurrencesOf方法计算一个字符串中指定子串的出现次数。

字符串操作工具方面,replace方法用于查找并替换指定子串。trimTrailingCharacter方法去除尾部的特定字符。trimLeadingCharacter方法去除头部的特定字符。trimLeadingWhitespace方法去除头部的空白符。trimTrailingWhitespace方法去除尾部的空白符。trimWhitespace方法去除头部和尾部的空白符。trimAllWhitespace方法删除开头、结尾和中间的空白符。delete方法删除指定子串。deleteAny方法删除指定字符(可以是多个)。trimArrayElements方法对数组的每一项执行trim方法。uriDecode方法将 URL 字符串进行解码。

路径相关工具方法中,cleanPath方法解析路径字符串,优化其中的 “..”。getFilename方法解析路径字符串,解析出文件名部分。getFilenameExtension方法解析路径字符串,解析出文件后缀名。pathEquals方法比较两个两个字符串,判断是否是同一个路径,会自动处理路径中的 “..”。stripFilenameExtension方法删除文件路径名中的后缀部分。unqualify方法以指定字符作为分隔符,获取其最后一部分。

4. 集合工具类(CollectionUtils)

CollectionUtils 用于集合的判断和操作。

集合判断工具方面,isEmpty方法可以判断集合是否为空,对于Collection collection,如果集合为空则返回true。isNotEmpty方法与isEmpty方法相反,判断集合是否非空。containsInstance方法判断集合中是否包含某个对象,对于Collection collection和Object element,如果集合中包含该对象则返回true。contains方法以迭代器的方式判断集合中是否包含某个对象,需要先调用集合的iterator方法。containsAny方法判断一个集合中是否包含另一个集合中的任意一个元素。findFirstMatch方法找到第一个匹配源集合和候选集合的元素。select方法根据断言筛选集合中的元素。

集合操作方面,mergeCollection方法可以合并两个集合。transformToList方法将集合中的元素进行转换。

三、Spring 内置神器的优势

1. 请求数据记录

Spring 通过 AbstractRequestLoggingFilter 和 CommonsRequestLoggingFilter 提供了强大的请求数据记录功能。

AbstractRequestLoggingFilter 是一个抽象类,为记录请求提供了基本功能,子类应覆盖 beforeRequest 和 afterRequest 方法来执行实际的日志记录。常用的实现类是 CommonsRequestLoggingFilter,它允许开发者自定义记录请求的参数、请求体、请求头和客户端信息。

启用方式很简单,通过配置可以将其添加到 Spring Boot 应用程序中。例如:

@Configuration
public class RequestLoggingConfig {
    @Bean
    public CommonsRequestLoggingFilter logFilter() {
        CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
        filter.setIncludeQueryString(true);
        filter.setIncludePayload(true);
        filter.setIncludeHeaders(true);
        filter.setIncludeClientInfo(true);
        filter.setAfterMessagePrefix("REQUEST DATA : ");
        return filter;
    }
}

配置完成后,还需要将日志级别设置为 DEBUG,这样就可以详细记录请求信息:

logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG

通过这种方式,可以在日志中获取详尽的请求数据,助力问题排查与性能监控。

2. 请求 / 响应包装器

Spring 的 ContentCachingRequestWrapper 和 ContentCachingResponseWrapper 可以增强 HttpServletRequest 和 HttpServletResponse 的功能。

请求包装器 ContentCachingRequestWrapper 用于缓存请求的输入流,允许多次读取请求体,这在需要多次处理请求数据(如日志记录和业务处理)时非常有用。例如,在处理请求日志记录时,可以使用这个包装器来缓存请求体,并在日志记录完成后继续处理请求。

响应包装器 ContentCachingResponseWrapper 用于缓存响应的输出流,允许开发者在响应提交给客户端之前修改响应体,这在需要对响应内容进行后处理(如添加额外的头部信息、修改响应体)时非常有用。

3. 单次过滤器(OncePerRequestFilter)

OncePerRequestFilter 是 Spring 框架中一个重要的过滤器基类,确保过滤器逻辑在请求的生命周期中只被执行一次。

无论请求如何转发或包含,这种机制都能极大地减少重复处理的风险,确保请求数据处理的高效性。使用场景包括请求日志记录、请求数据修改及安全控制等。例如,在请求日志记录中,可以使用 OncePerRequestFilter 确保日志记录逻辑只执行一次,避免重复记录。

4. AOP 三件套(AopContext、AopUtils、ReflectionUtils)

Spring 框架中的面向切面编程(AOP)提供了强大的功能,AopContext、AopUtils 和 ReflectionUtils 等工具为开发者提供了高效实现事务管理、日志记录以及安全控制等功能的途径。

AopUtils 提供了一系列静态方法来帮助开发者获取目标对象、判断代理类型等操作,为代码的可读性与可维护性提供了极大的便利。例如,可以使用 AopUtils 来判断一个对象是否是代理对象,以及获取目标对象的信息。

ReflectionUtils 广泛用于处理反射相关的操作,例如获取对象的字段、方法等信息,并进行动态的操作。

这些工具的使用使得开发者可以在不修改源代码的情况下,对特定逻辑进行拦截和增强,提高了代码的可维护性和灵活性。

四、如何利用 Spring 内置神器

在实际项目中,Spring 的内置神器可以在多个方面发挥重要作用,极大地提高开发效率。下面结合具体场景展示如何使用 Spring 的内置神器。

1. 请求处理方面

  • 请求数据记录:Spring 通过 AbstractRequestLoggingFilter 和 CommonsRequestLoggingFilter 提供了强大的请求数据记录功能。在配置类中添加 logFilter 方法创建 CommonsRequestLoggingFilter 实例,并设置相关参数,如包含查询字符串、请求体、请求头等信息,以及设置日志前缀。然后将日志级别设置为 DEBUG,就可以详细记录请求信息,助力问题排查与性能监控。
  • 请求 / 响应包装器:ContentCachingRequestWrapper 和 ContentCachingResponseWrapper 可以增强 HttpServletRequest 和 HttpServletResponse 的功能。请求包装器 ContentCachingRequestWrapper 用于缓存请求的输入流,允许多次读取请求体,在处理请求日志记录时,可以使用这个包装器来缓存请求体,并在日志记录完成后继续处理请求。响应包装器 ContentCachingResponseWrapper 用于缓存响应的输出流,允许开发者在响应提交给客户端之前修改响应体,比如添加额外的头部信息、修改响应体等。
  • 单次过滤器(OncePerRequestFilter) :确保过滤器逻辑在请求的生命周期中只被执行一次,避免重复处理的风险。在请求日志记录、请求数据修改及安全控制等场景中非常有用。例如,在请求日志记录中,可以使用 OncePerRequestFilter 确保日志记录逻辑只执行一次,避免重复记录。

2. 数据格式化方面

  • 内置数据格式化器:SpringMVC 内置了许多数据格式化器,如 DateFormatter 用于将日期字符串转换为日期对象或进行反向格式化,NumberFormatter 用于将数字字符串转换为数字对象或进行格式化,CurrencyFormatter 用于将数字对象格式化为货币字符串等。在 SpringMVC 的配置文件中可以配置这些格式化器,并在控制器的方法参数中使用相应的注解,如 @RequestParam 和 @DateTimeFormat、@NumberFormat 等注解来指定数据格式化方式。
  • 自定义格式化器:可以实现 Formatter 接口,编写自定义的格式化器类。例如,创建一个实现 Formatter 接口的自定义格式化器类,重写 parse 和 print 方法,分别用于将字符串转换为日期对象和将日期对象格式化为字符串。然后在配置文件中注册格式化转换器,通过 ConversionServiceFactoryBean 将自定义格式化器添加到转换服务中。

3. 集合操作方面

  • CollectionUtils 工具类:Spring 的 CollectionUtils 工具类提供了一系列集合操作的方法。
    • 集合判断工具:可以使用 isEmpty 方法判断集合是否为空,对于 List、Set 和 Map 都有相应的判断方法。但是需要注意,hasUniqueObject 和 containsInstance 方法存在问题,不建议使用,因为它们在判断对象是否相等时使用了 == 而不是 equals 方法,对于普通引用对象可能得不到正确结果。而 containsAny 方法在判断集合是否包含另一个集合中的任意一个元素时,会调用集合内对象的 equals 方法,所以比较的对象要重写 hashCode() 和 equals() 方法才能得到正确结果。
    • 集合操作:mergeArrayIntoCollection 方法可以将数组中的元素添加到集合中,mergePropertiesIntoMap 方法可以将 Properties 中的键值对添加到 Map 中,lastElement 和 firstElement 方法分别返回集合中的最后一个和第一个元素,arrayToList 方法可以将数组转换成集合。

4. 内置作用域的应用

  • Spring 内置了六种作用域:singleton(单例作用域,在 IOC 容器中对应 Bean 只有一个实例)、prototype(每次请求都会创建一个新的 Bean 实例)、request(在 Web 应用中为每个 HTTP 请求创建一个 Bean 实例)、session(在 Web 应用中为每个 HTTP 会话创建一个 Bean 实例)、application(在整个 Web 应用期间创建一个 Bean 实例)、websocket(在每个 WebSocket 会话中创建一个 Bean 实例)。在实际项目中,可以根据不同的需求选择合适的作用域。例如,对于无状态的工具类或服务类,可以使用 singleton 作用域,避免对象的频繁创建与销毁,提高性能;对于需要维护状态的 Bean,可以使用 prototype 作用域。

通过合理地利用 Spring 的内置神器,可以极大地提高开发效率,增强代码的可读性和可维护性。

五、结语

Spring 的内置神器为开发者提供了强有力的技术支撑,掌握这些工具不仅有助于提升个人技能,也能为团队的成功贡献一份力量。

Spring 框架中的内置神器,如断言工具类、对象和数组工具类、字符串工具类、集合工具类等,为开发带来了诸多便利。这些工具类在日常开发中发挥着重要作用,提高了开发效率,增强了代码的可读性和可维护性。

同时,Spring 内置的请求数据记录、请求 / 响应包装器、单次过滤器以及 AOP 三件套等功能,为开发者提供了强大的技术支持,使得开发者可以更加高效地处理请求,增强代码的可维护性和灵活性。

在实际项目中,合理利用 Spring 的内置神器,可以极大地提高开发效率。例如,在请求处理方面,利用请求数据记录功能可以助力问题排查与性能监控;在数据格式化方面,使用内置数据格式化器和自定义格式化器可以方便地进行数据转换;在集合操作方面,CollectionUtils 工具类提供了丰富的集合操作方法;在内置作用域的应用方面,可以根据不同的需求选择合适的作用域,提高性能和代码的可维护性。

呼吁大家