spring boot 常用工具类集成详解groupId

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
在 Spring Boot 中,SnakeYAML 是一个常用的 YAML 解析库,主要用于处理 YAML 格式的配置文件(如 application.yml)。Spring Boot 内部默认集成了 SnakeYAML,用于加载和解析 YAML 配置,将其转换为 Java 对象供应用使用。

一、SnakeYAML 在 Spring Boot 中的作用

  1. 解析 YAML 配置文件:Spring Boot 的核心配置文件(application.yml 或 application.yaml)默认通过 SnakeYAML 解析,将配置项绑定到 Environment 或自定义配置类中。
    示例 application.yml
    yaml
     
     
    server:
      port: 8080
    app:
      name: my-springboot-app
      timeout: 3000
    
     
  2. 对象与 YAML 互转:除了配置解析,SnakeYAML 还可用于在业务代码中实现 Java 对象与 YAML 字符串的相互转换(序列化 / 反序列化)。

二、Spring Boot 中使用 SnakeYAML 的两种场景

1. 配置文件解析(自动集成)

Spring Boot 已内置 SnakeYAML 依赖(通过 spring-boot-starter 间接引入),无需额外配置即可解析 YAML 配置。

将 YAML 配置绑定到 Java 类:

java
 
运行
 
 
 
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "app") // 绑定前缀为 "app" 的配置
public class AppConfig {
    private String name;
    private int timeout;

    // getter 和 setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getTimeout() { return timeout; }
    public void setTimeout(int timeout) { this.timeout = timeout; }
}
 

在业务中使用:

java
 
运行
 
 
 
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AppController {
    @Autowired
    private AppConfig appConfig;

    @GetMapping("/config")
    public String getConfig() {
        return "App Name: " + appConfig.getName() + ", Timeout: " + appConfig.getTimeout();
    }
}
 

2. 手动处理 YAML 与对象互转(业务场景)

若需在代码中手动序列化 / 反序列化 YAML(如读取自定义 YAML 文件),可直接使用 SnakeYAML 的 API。

步骤 1:确认依赖
Spring Boot 已默认包含 SnakeYAML,若需单独引入(非 Spring Boot 项目):

xml
 
 
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.33</version> <!-- 版本号可根据需要调整 -->
</dependency>
 

步骤 2:Java 对象与 YAML 互转示例

java
 
运行
 
 
 
 
import org.yaml.snakeyaml.Yaml;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Map;

public class YamlUtils {
    // YAML 字符串转 Java 对象(Map)
    public static Map<String, Object> yamlToMap(String yamlStr) {
        Yaml yaml = new Yaml();
        return yaml.load(yamlStr);
    }

    // Java 对象转 YAML 字符串
    public static String objectToYaml(Object obj) {
        Yaml yaml = new Yaml();
        return yaml.dump(obj);
    }

    // 从文件读取 YAML 并转换为对象
    public static <T> T loadFromFile(String filePath, Class<T> clazz) throws Exception {
        Yaml yaml = new Yaml();
        try (FileReader reader = new FileReader(filePath)) {
            return yaml.loadAs(reader, clazz);
        }
    }

    // 将对象写入 YAML 文件
    public static void dumpToFile(Object obj, String filePath) throws Exception {
        Yaml yaml = new Yaml();
        try (FileWriter writer = new FileWriter(filePath)) {
            yaml.dump(obj, writer);
        }
    }
}
 

使用示例:

java
 
运行
 
 
 
 
// 1. 对象转 YAML
AppConfig config = new AppConfig();
config.setName("test-app");
config.setTimeout(5000);
String yamlStr = YamlUtils.objectToYaml(config);
System.out.println("YAML:\n" + yamlStr);

// 2. YAML 转对象
AppConfig parsedConfig = YamlUtils.loadFromFile("config.yaml", AppConfig.class);
 

三、注意事项

  1. 数据类型匹配:YAML 中的类型(如 nulltrue/false、数字)需与 Java 类字段类型匹配,否则可能抛出 YAMLException
  2. 复杂对象处理:对于包含集合、嵌套对象的 YAML,SnakeYAML 会自动解析,但建议使用 TypeDescription 或 Constructor 明确类型,避免类型擦除问题。
    示例(处理泛型):
    java
     
    运行
     
     
     
     
    import org.yaml.snakeyaml.constructor.Constructor;
    import org.yaml.snakeyaml.nodes.Tag;
    import org.yaml.snakeyaml.representer.Representer;
    
    // 解析包含 List<AppConfig> 的 YAML
    Representer representer = new Representer();
    representer.addClassTag(AppConfig.class, Tag.MAP); // 指定自定义类的标签
    Yaml yaml = new Yaml(new Constructor(List.class), representer);
    List<AppConfig> configs = yaml.load(yamlStr);
    
     
  3. 安全问题:SnakeYAML 的默认配置允许解析任意类(可能存在安全风险,如反序列化漏洞)。若处理不可信的 YAML 数据,需限制可解析的类:
    java
     
    运行
     
     
     
     
    // 限制只能解析 AppConfig 类
    Constructor constructor = new Constructor(AppConfig.class);
    Yaml safeYaml = new Yaml(constructor);
    
     

总结

SnakeYAML 是 Spring Boot 处理 YAML 配置的核心依赖,既支持自动解析配置文件,也可手动用于 YAML 与 Java 对象的转换。在使用时需注意类型匹配和安全问题,尤其是处理外部来源的 YAML 数据时。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-autoconfigure</artifactId>
</dependency>
com.github.xiaoymin 是国产开发者 xiaoymin(肖 ym)在 Maven 仓库中发布开源项目的 Group ID,其最知名的项目是 Knife4j(前身是 swagger-bootstrap-ui)—— 一款基于 Swagger 的增强型 API 文档工具,广泛用于 Spring Boot 项目中生成和展示 API 文档。

主要项目:Knife4j

Knife4j 是对 Swagger UI 的二次封装,提供了更美观的界面、更丰富的交互功能,同时简化了 Spring Boot 项目的集成步骤。

1. 核心功能

  • 美化 Swagger 文档界面,支持黑暗模式、接口搜索、在线调试
  • 增强接口管理能力(如接口排序、分组、权限控制)
  • 支持导出 API 文档为 Markdown、HTML、Word 等格式
  • 兼容 Swagger 2.x 和 OpenAPI 3.x 规范

2. 在 Spring Boot 中集成

步骤 1:引入依赖
在 pom.xml 中添加:

xml
 
 
<!-- Knife4j Spring Boot 2.x 依赖 -->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version> <!-- 版本号可根据需要更新 -->
</dependency>
 

步骤 2:配置 Swagger/OpenAPI
创建配置类启用 API 文档:

java
 
运行
 
 
 
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class Knife4jConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                        .title("API 文档")
                        .description("项目接口文档")
                        .version("1.0")
                        .build())
                .select()
                // 指定扫描的控制器包路径
                .apis(RequestHandlerSelectors.basePackage("com.example.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}
 

步骤 3:访问文档
启动项目后,通过以下地址访问 Knife4j 文档界面:

plaintext
 
 
http://localhost:8080/doc.html
 

3. 其他相关项目

除了 Knife4j,com.github.xiaoymin 下还有一些辅助工具:

  • knife4j-extension:Knife4j 扩展模块(如接口签名、加密等)
  • swagger-bootstrap-ui:Knife4j 的早期版本(已停止维护,建议使用 Knife4j)

总结

com.github.xiaoymin 主要关联的是 Knife4j 系列项目,该工具已成为国内 Spring Boot 开发者生成 API 文档的主流选择,相比原生 Swagger UI 更符合中文用户的使用习惯,界面更友好,功能更丰富。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
com.google.guava 是 Google 开发的 Java 核心库(Guava)的 Maven 坐标,它提供了大量实用的工具类和增强功能,弥补了 Java 标准库的不足,广泛应用于 Java 项目中。

一、Guava 核心价值

Guava 旨在解决以下问题:

  1. 简化集合操作(提供更强大的集合类型和工具方法)
  2. 增强字符串处理、缓存、并发编程等能力
  3. 提供更优雅的异常处理、I/O 操作等工具
  4. 减少样板代码,提升开发效率

二、主要功能模块与常用类

1. 集合工具(com.google.common.collect

Guava 扩展了 Java 集合框架,提供了更灵活的集合类型和操作工具:

类 / 接口功能说明
ImmutableList 不可变列表(线程安全,创建后不可修改)
Multimap 支持一个键映射多个值的集合(类似 Map<K, Collection<V>> 的简化版)
BiMap 双向映射(可通过值反向查找键,如 HashBiMap
Table 二维表结构(类似 Map<R, Map<C, V>>,支持行、列双向访问)
Lists/Sets/Maps 集合工具类(提供 newArrayList()transform()filter() 等便捷方法)

示例:

java
 
运行
 
 
 
 
// 创建不可变列表
List<String> immutableList = ImmutableList.of("a", "b", "c");

// Multimap 示例(一个键对应多个值)
Multimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.put("score", 90);
multimap.put("score", 85);
Collection<Integer> scores = multimap.get("score"); // [90, 85]

// 集合转换
List<Integer> numbers = Lists.newArrayList(1, 2, 3);
List<String> numberStrs = Lists.transform(numbers, n -> "num:" + n); // [num:1, num:2, num:3]
 

2. 字符串处理(com.google.common.base

提供比 java.lang.String 更丰富的字符串工具:

类 / 方法功能说明
Strings 字符串工具(isNullOrEmpty()padStart()repeat() 等)
Splitter 灵活的字符串拆分器(支持按正则、固定长度拆分,忽略空值等)
Joiner 字符串拼接器(支持连接集合、处理 null 值)
CharMatcher 字符匹配工具(判断字符类型、过滤字符串等)

示例:

java
 
运行
 
 
 
 
// 字符串拼接(自动处理 null)
String joined = Joiner.on(",").skipNulls().join("a", null, "b"); // "a,b"

// 字符串拆分(忽略空字符串)
List<String> parts = Splitter.on(",")
    .trimResults()
    .omitEmptyStrings()
    .splitToList("  a, , b  "); // ["a", "b"]

// 字符匹配(保留数字)
String numbers = CharMatcher.digits().retainFrom("abc123def456"); // "123456"
 

3. 缓存(com.google.common.cache

提供轻量级本地缓存实现,比 ConcurrentHashMap 更强大:

类 / 接口功能说明
Cache/LoadingCache 缓存接口,支持自动加载、过期策略、最大容量限制
CacheBuilder 缓存构建器(配置过期时间、并发级别、移除监听器等)

示例:

java
 
运行
 
 
 
 
// 构建一个具有过期策略的缓存
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
    .maximumSize(100) // 最大缓存项数
    .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期
    .build(new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            // 缓存未命中时的加载逻辑(如查数据库)
            return "value for " + key;
        }
    });

// 使用缓存
String value = cache.get("key1"); // 首次加载,后续直接从缓存获取
 

4. 并发编程(com.google.common.util.concurrent

增强 Java 并发工具,简化线程管理:

类 / 接口功能说明
ListenableFuture 可监听的 Future(支持注册回调,避免阻塞等待)
Futures 异步任务工具类(处理 ListenableFuture 链、合并结果等)
RateLimiter 限流器(控制接口调用频率,如每秒最多 100 次请求)

示例:

java
 
运行
 
 
 
 
// 限流器(每秒允许5个请求)
RateLimiter limiter = RateLimiter.create(5.0);

// 尝试获取令牌,未获取到则等待
limiter.acquire(); // 阻塞直到获取令牌
doSomething(); // 执行受限制的操作
 

5. 其他实用工具

  • I/O 操作:com.google.common.io 提供 FilesResources 等工具,简化文件读写、资源加载。
  • 数学工具:com.google.common.math 提供 IntMathLongMath 等,支持溢出检查、最大公约数计算。
  • 前置条件检查:com.google.common.base.Preconditions 提供 checkNotNull()checkArgument() 等,简化参数校验。

示例:

java
 
运行
 
 
 
 
// 参数校验
Preconditions.checkNotNull(user, "用户不能为空");
Preconditions.checkArgument(age > 0, "年龄必须为正数");

// 文件操作
File file = new File("test.txt");
String content = Files.asCharSource(file, Charsets.UTF_8).read(); // 读取文件内容
 

三、在项目中引入 Guava

Maven 依赖

xml
 
 
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version> <!-- 版本号可根据需要更新 -->
</dependency>
 

  • 版本说明:-jre 后缀版本依赖 Java 8+ 标准库,-android 版本适用于 Android 环境。

四、使用注意事项

  1. 版本兼容性:Guava 部分版本(如 21.0+)要求 Java 8+,需根据项目 JDK 版本选择合适版本。
  2. 避免过度依赖:优先使用 JDK 自带功能(如 Java 8 的 Stream 可替代部分 Guava 集合工具)。
  3. 了解实现细节:例如 ImmutableList 是不可变的,避免在需要修改的场景中使用。

总结

Guava 是 Java 开发中的 “瑞士军刀”,其集合增强、字符串处理、缓存等功能大幅简化了开发工作。掌握 Guava 能有效减少样板代码,提升代码可读性和效率,是中大型 Java 项目的常用依赖。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
org.mapstruct 是 MapStruct 框架的 Maven 坐标,MapStruct 是一个类型安全的 Java Bean 映射工具,通过注解处理器在编译时生成映射代码,解决了手动编写对象转换逻辑(如 DO 与 DTO 互转)的繁琐问题。

一、MapStruct 核心优势

  1. 类型安全:编译时检查属性映射是否匹配,避免运行时类型转换错误。
  2. 高性能:生成的代码是直接调用 getter/setter 的普通 Java 代码,比反射(如 BeanUtils)效率更高。
  3. 可维护性:映射规则集中在注解中,无需手动编写转换工具类。
  4. 灵活性:支持复杂映射场景(如嵌套对象、集合转换、自定义转换逻辑)。

二、核心依赖与配置

在 Maven 项目中引入 MapStruct 依赖:

xml
 
 
<!-- 核心依赖 -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version> <!-- 稳定版本,可按需更新 -->
</dependency>

<!-- 注解处理器(编译时生成代码) -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope> <!-- 仅编译时需要 -->
</dependency>
 

三、核心注解与使用示例

MapStruct 的核心能力通过注解实现,最常用的包括 @Mapper@Mapping 等。

1. 基础对象映射

场景:将 User(数据实体)转换为 UserDTO(数据传输对象)。

java
 
运行
 
 
 
 
// 数据实体
public class User {
    private Long id;
    private String userName;
    private LocalDate birthDate;
    // getter/setter
}

// DTO
public class UserDTO {
    private Long userId;
    private String name;
    private String birthDate; // 日期以字符串形式展示
    // getter/setter
}

// 映射器接口(MapStruct 会生成实现类)
@Mapper(componentModel = "spring") // 生成 Spring 管理的 Bean
public interface UserMapper {
    // 单例实例(MapStruct 自动生成)
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 自定义映射规则
    @Mapping(source = "id", target = "userId") // 字段名不同
    @Mapping(source = "userName", target = "name") // 字段名不同
    @Mapping(source = "birthDate", target = "birthDate", dateFormat = "yyyy-MM-dd") // 日期格式化
    UserDTO toDTO(User user);

    // 反向映射(DTO 转实体)
    @Mapping(source = "userId", target = "id")
    @Mapping(source = "name", target = "userName")
    @Mapping(source = "birthDate", target = "birthDate", dateFormat = "yyyy-MM-dd")
    User toEntity(UserDTO dto);
}
 

使用映射器:

java
 
运行
 
 
 
 
// 转换实体为 DTO
User user = new User(1L, "张三", LocalDate.of(1990, 1, 1));
UserDTO dto = UserMapper.INSTANCE.toDTO(user);
// dto 结果:userId=1, name="张三", birthDate="1990-01-01"
 

2. 集合映射

MapStruct 支持 ListSet 等集合类型的自动转换,只需定义单个对象的映射方法,集合映射会自动生成。

java
 
运行
 
 
 
 
@Mapper(componentModel = "spring")
public interface UserMapper {
    // 单个对象映射(集合映射依赖此方法)
    UserDTO toDTO(User user);

    // 集合映射(MapStruct 自动生成循环调用 toDTO 的代码)
    List<UserDTO> toDTOList(List<User> users);
}
 

3. 自定义转换逻辑

当默认转换无法满足需求时(如枚举转换、复杂计算),可通过 qualifiedByName 引用自定义方法。

java
 
运行
 
 
 
 
@Mapper(componentModel = "spring")
public interface OrderMapper {
    @Mapping(source = "status", target = "statusDesc", qualifiedByName = "orderStatusConverter")
    OrderDTO toDTO(Order order);

    // 自定义转换方法(通过 @Named 标记)
    @Named("orderStatusConverter")
    default String convertStatus(Integer status) {
        if (status == 0) return "未支付";
        if (status == 1) return "已支付";
        return "未知状态";
    }
}
 

四、生成代码的特点

MapStruct 在编译时生成的映射实现类具有以下特点:

  • 代码透明:可在 target/generated-sources/annotations 目录查看生成的代码。
  • 无反射:直接调用 getter/setter,性能接近手写代码。
  • 空值安全:默认处理 null 值(不会因源对象为 null 抛出异常)。

五、与其他映射工具的对比

工具实现方式性能类型安全灵活性
MapStruct 编译时生成代码 极高 编译时检查 支持复杂映射
Apache BeanUtils 反射 运行时检查 简单映射
ModelMapper 反射 + 智能匹配 运行时检查 自动推断映射

结论:MapStruct 在性能和类型安全上优势显著,适合对可靠性和效率要求高的场景。

总结

org.mapstruct 对应的 MapStruct 框架是 Java 项目中对象转换的最佳实践之一,通过编译时代码生成实现了类型安全、高性能的映射逻辑,大幅减少了手动编写转换代码的工作量。其核心注解 @Mapper 和 @Mapping 提供了灵活的映射规则配置,支持从简单字段映射到复杂自定义转换的全场景需求。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
</dependency>
cn.hutool 是国产 Java 工具库 Hutool 的 Maven 坐标,它是一个功能全面、开箱即用的工具类集合,旨在简化 Java 开发中的常见操作,减少重复代码。Hutool 涵盖了字符串处理、日期时间、集合操作、IO 流、加密解密等近百个工具类,被广泛应用于国内 Java 项目中。

一、Hutool 的核心优势

  1. 功能全面:覆盖开发中 80% 以上的工具类需求,避免引入多个零散库。
  2. 零依赖:纯 Java 实现,不依赖其他第三方库,体积小巧(约 1.5MB)。
  3. 易用性强:API 设计简洁直观,方法命名符合中文开发者习惯。
  4. 兼容性好:支持 JDK 8+,适配主流框架(Spring Boot、MyBatis 等)。

二、主要功能模块与常用工具类

Hutool 按功能划分为多个模块,以下是最常用的核心模块:

1. 核心工具类(cn.hutool.core

包含 Java 基础类型、集合、字符串等核心操作工具。

工具类功能说明
StrUtil 字符串工具(判空、拼接、截取、替换等,替代 StringUtils
CollectionUtil 集合工具(创建集合、判断空、合并、过滤等)
ObjectUtil 对象工具(判空、克隆、比较等)
NumberUtil 数字工具(加减乘除、四舍五入、数字转换等)

示例:

java
 
运行
 
 
 
 
// 字符串判空(比 StringUtils 更直观)
StrUtil.isEmpty(""); // true
StrUtil.isNotEmpty("hutool"); // true

// 字符串拼接
String str = StrUtil.format("Hello, {}!", "Hutool"); // "Hello, Hutool!"

// 集合操作
List<String> list = CollectionUtil.newArrayList("a", "b");
CollectionUtil.addIfAbsent(list, "c"); // 仅添加不存在的元素
 

2. 日期时间工具(cn.hutool.core.date

简化日期时间处理,支持 JDK 8+ 的 LocalDateTime 及传统 Date

工具类 / 常量功能说明
DateUtil 日期工具(解析、格式化、加减、比较等)
LocalDateTimeUtil JDK 8+ 日期工具(处理 LocalDateTime
DatePattern 常用日期格式常量(如 yyyy-MM-dd HH:mm:ss

示例:

java
 
运行
 
 
 
 
// 解析字符串为日期
Date date = DateUtil.parse("2023-01-01", "yyyy-MM-dd");

// 计算两个日期差(天)
long days = DateUtil.between(DateUtil.parse("2023-01-01"), DateUtil.parse("2023-01-10"), DateUnit.DAY); // 9

// LocalDateTime 操作
LocalDateTime now = LocalDateTimeUtil.now();
LocalDateTime tomorrow = LocalDateTimeUtil.plusDays(now, 1); // 加1天
 

3. IO 工具(cn.hutool.core.io

简化文件读写、流操作,自动处理资源关闭。

工具类功能说明
FileUtil 文件工具(创建文件、复制、移动、删除、读取内容等)
IoUtil 流工具(读取流内容、复制流、关闭流等)
ResourceUtil 资源工具(读取 classpath 下的资源文件)

示例:

java
 
运行
 
 
 
 
// 读取文件内容(自动处理编码和流关闭)
String content = FileUtil.readString("test.txt", CharsetUtil.UTF_8);

// 写入文件
FileUtil.writeString("Hello Hutool", "output.txt", CharsetUtil.UTF_8);

// 读取 classpath 资源
String config = ResourceUtil.readUtf8Str("config.properties");
 

4. 加密解密(cn.hutool.crypto

支持 MD5、SHA、AES、RSA 等主流加密算法,使用简单。

工具类功能说明
SecureUtil 加密工具入口(简化 MD5、SHA、AES 等调用)
SymmetricCrypto 对称加密(AES、DES 等)
AsymmetricCrypto 非对称加密(RSA、DSA 等)

示例:

java
 
运行
 
 
 
 
// MD5 加密
String md5 = SecureUtil.md5("123456"); // 输出 123456 的 MD5 哈希值

// AES 加密解密
SymmetricCrypto aes = SecureUtil.aes("myKey1234567890".getBytes()); // 密钥长度 16/24/32 字节
String encrypt = aes.encryptBase64("secret"); // 加密
String decrypt = aes.decryptStr(encrypt); // 解密,结果为 "secret"
 

5. 其他实用模块

  • HTTP 客户端(cn.hutool.http):HttpUtil 简化 HTTP 请求(GET/POST、文件上传等),无需依赖 OkHttp 或 HttpClient。
    java
     
    运行
     
     
     
     
    // 发送 GET 请求
    String result = HttpUtil.get("https://www.baidu.com");
    
     
  • JSON 处理(cn.hutool.json):JSONUtil 支持 JSON 字符串与对象互转,兼容 FastJSON 语法。
    java
     
    运行
     
     
     
     
    // JSON 字符串转对象
    User user = JSONUtil.toBean("{\"name\":\"张三\"}", User.class);
    
     
  • 验证码生成(cn.hutool.captcha):LineCaptchaCircleCaptcha 快速生成图形验证码。
    java
     
    运行
     
     
     
     
    // 生成 100x50 的验证码
    LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 50);
    captcha.write("captcha.png"); // 写入文件
    String code = captcha.getCode(); // 验证码文本
    
     

三、在项目中引入 Hutool

Maven 依赖

xml
 
 
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.22</version> <!-- 最新稳定版,可按需更新 -->
</dependency>
 

  • hutool-all 包含所有模块,若需按需引入(如仅用 IO 工具),可单独引入子模块(如 hutool-corehutool-io)。

四、使用建议

  1. 按需学习:无需记忆所有工具类,用时查阅 官方文档 即可。
  2. 避免过度封装:Hutool 已足够简洁,无需再二次封装工具类。
  3. 版本选择:优先使用最新稳定版,修复了旧版本的 Bug 并增强了功能。

总结

cn.hutool 对应的 Hutool 是国产 Java 工具库的优秀代表,其设计理念贴合国内开发者习惯,功能覆盖全面,极大简化了日常开发中的重复工作。无论是字符串处理、日期操作,还是加密解密、HTTP 请求,Hutool 都能提供简洁高效的解决方案,是 Java 项目的 “必备工具库” 之一。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
</dependency>
com.github.dozermapper 是 Dozer 框架的 Maven 坐标,Dozer 是一个经典的 Java Bean 映射工具,用于实现不同对象之间的属性转换(如 DO 与 DTOVO 之间的映射)。它通过 XML 配置或注解定义映射规则,自动处理字段名匹配、类型转换等逻辑,曾广泛应用于 Java 项目中。

一、Dozer 的核心特点

  1. 自动映射:默认按字段名匹配(忽略大小写),无需手动编写 getter/setter 转换代码。
  2. 灵活配置:支持 XML 配置文件、注解、API 三种方式定义映射规则,应对复杂场景。
  3. 类型转换:内置常用类型转换器(如 String 与 DateLong 与 String 等),也支持自定义转换器。
  4. 嵌套对象映射:自动处理嵌套对象的属性转换(如 User.addr.city 映射到 UserDTO.address.cityName)。

二、核心依赖与配置

Maven 依赖

xml
 
 
<dependency>
    <groupId>com.github.dozermapper</groupId>
    <artifactId>dozer-core</artifactId>
    <version>6.5.0</version> <!-- 最新稳定版,需注意兼容性 -->
</dependency>
 

  • 注意:Dozer 自 2020 年后更新缓慢,部分新特性(如 Java 8+ 类型支持)需谨慎使用。

三、基本使用方式

1. 基础映射(默认按字段名匹配)

场景:将 User 转换为 UserDTO,字段名一致时自动映射。

java
 
运行
 
 
 
 
// 源对象
public class User {
    private Long id;
    private String userName;
    private Date birthDate;
    // getter/setter
}

// 目标对象
public class UserDTO {
    private Long id; // 与源字段名一致
    private String userName; // 与源字段名一致
    private String birthDate; // 类型不同(Date → String)
    // getter/setter
}

// 映射工具类(单例模式)
public class DozerMapperUtil {
    private static final Mapper mapper = DozerBeanMapperBuilder.buildDefault();
    
    public static <T> T map(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        return mapper.map(source, targetClass);
    }
}

// 使用示例
User user = new User(1L, "张三", new Date());
UserDTO dto = DozerMapperUtil.map(user, UserDTO.class);
 

2. 自定义映射规则(XML 配置)

当字段名或类型不匹配时,通过 XML 配置映射关系(推荐放在 src/main/resources/dozer/ 目录)。

步骤 1:创建映射文件 user-mapping.xml

xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd">

    <!-- User 与 UserDTO 的映射规则 -->
    <mapping>
        <class-a>com.example.User</class-a>
        <class-b>com.example.UserDTO</class-b>
        
        <!-- 字段名不同时映射 -->
        <field>
            <a>userName</a> <!-- 源字段 -->
            <b>name</b>     <!-- 目标字段 -->
        </field>
        
        <!-- 日期类型转换(指定格式) -->
        <field>
            <a>birthDate</a>
            <b>birthDate</b>
            <a-hint>java.util.Date</a-hint>
            <b-hint>java.lang.String</b-hint>
            <field-exclude>false</field-exclude>
            <format>yyyy-MM-dd</format> <!-- 日期格式化 -->
        </field>
    </mapping>
</mappings>
 

步骤 2:加载配置文件

java
 
运行
 
 
 
 
// 自定义映射器(加载 XML 配置)
public class CustomDozerMapper {
    private static final Mapper mapper;
    static {
        List<String> mappingFiles = new ArrayList<>();
        mappingFiles.add("dozer/user-mapping.xml"); // 加载自定义配置
        mapper = DozerBeanMapperBuilder.create()
                .withMappingFiles(mappingFiles)
                .build();
    }
    
    public static <T> T map(Object source, Class<T> targetClass) {
        return mapper.map(source, targetClass);
    }
}
 

3. 注解方式配置(简化 XML)

Dozer 也支持通过注解 @Mapping 直接在类上定义映射规则:

java
 
运行
 
 
 
 
import org.dozer.Mapping;

public class UserDTO {
    @Mapping("id") // 对应源对象的 id 字段
    private Long userId;
    
    @Mapping("userName") // 对应源对象的 userName 字段
    private String name;
    
    @Mapping(value = "birthDate", dateFormat = "yyyy-MM-dd") // 日期格式化
    private String birthDate;
    // getter/setter
}
 

四、与 MapStruct 的对比

Dozer 曾是对象映射的主流工具,但近年来逐渐被 MapStruct 替代,核心差异如下:

特性DozerMapStruct
实现方式 运行时通过反射实现 编译时生成 Java 代码
性能 较低(反射开销) 极高(直接调用 getter/setter)
类型安全 运行时检查(易出错) 编译时检查(更可靠)
灵活性 配置复杂(依赖 XML) 注解驱动(更简洁)
维护状态 更新缓慢(几乎停滞) 活跃更新(支持新特性)

五、使用建议

  1. 新项目谨慎选择:Dozer 已进入维护模式,功能更新停滞,且性能不如 MapStruct,新项目建议优先使用 MapStruct。
  2. 老项目迁移:若已有项目使用 Dozer,可逐步迁移到 MapStruct(二者 API 风格相似,迁移成本较低)。
  3. 特殊场景:若需动态映射(运行时动态修改映射规则),Dozer 的反射机制可能更适合(但需权衡性能)。

总结

com.github.dozermapper 对应的 Dozer 是一款经典的对象映射工具,通过 XML 或注解实现属性转换,曾广泛用于 Java 项目。但由于其基于反射的实现导致性能较差,且维护活跃度低,目前已逐渐被编译时生成代码的 MapStruct 取代。对于新项目,建议优先选择 MapStruct;对于老项目,可根据性能需求决定是否迁移。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
org.projectlombok 是 Lombok 库的 Maven 坐标,Lombok 是一款 Java 开发工具,通过注解简化 Java 类的代码编写,自动生成 getter/setter、构造方法、toString 等样板代码,显著减少代码冗余。

一、Lombok 核心价值

  1. 消除样板代码:自动生成常用方法(如 getter/settertoString()equals() 等),减少手动编写。
  2. 提升开发效率:修改字段时无需同步修改相关方法,降低维护成本。
  3. 代码更简洁:聚焦业务逻辑,类结构更清晰。

二、核心依赖与安装

1. Maven 依赖

xml
 
 
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version> <!-- 最新稳定版,兼容 JDK 8+ -->
    <scope>provided</scope> <!-- 仅编译时需要,运行时不依赖 -->
</dependency>
 

2. IDE 插件安装

Lombok 通过注解处理器在编译时生成代码,需在 IDE 中安装插件才能正常识别:

  • IntelliJ IDEA:File → Settings → Plugins,搜索 Lombok 安装并重启。
  • Eclipse:通过 Eclipse Marketplace 搜索 Lombok 安装,或手动执行 Lombok Jar 包的安装程序。

三、常用注解详解

1. @Data(最常用)

  • 作用:组合注解,自动生成 gettersettertoString()equals()hashCode() 方法。
  • 适用场景:普通 Java Bean(如 DTO、VO)。

java
 
运行
 
 
 
 
import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    // 无需手动编写 getter/setter 等方法
}
 

2. @Getter / @Setter

  • 作用:为类或字段生成 getter / setter 方法。
  • 灵活使用:可标注在类上(所有字段生效)或单个字段上(仅该字段生效)。

java
 
运行
 
 
 
 
import lombok.Getter;
import lombok.Setter;

public class User {
    @Getter @Setter private Long id; // 仅为 id 生成 get/set
    private String name; // 无 get/set
}
 

3. @NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor

  • 作用:生成构造方法:
    • @NoArgsConstructor:无参构造方法。
    • @AllArgsConstructor:全参构造方法(包含所有字段)。
    • @RequiredArgsConstructor:必需参数构造方法(仅包含被 @NonNull 标注或 final 修饰的字段)。

java
 
运行
 
 
 
 
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

@NoArgsConstructor // 无参构造
@AllArgsConstructor // 全参构造
@RequiredArgsConstructor // 必需参数构造
public class User {
    private final Long id; // final 字段,属于必需参数
    @NonNull private String name; // @NonNull 标注,属于必需参数
    private Integer age; // 普通字段,非必需
}
 

4. @ToString

  • 作用:生成 toString() 方法,默认包含所有字段。
  • 常用属性:
    • exclude:排除指定字段(如 @ToString(exclude = "password"))。
    • of:仅包含指定字段(如 @ToString(of = {"id", "name"}))。

java
 
运行
 
 
 
 
import lombok.ToString;

@ToString(exclude = "password") // toString 中不包含 password
public class User {
    private Long id;
    private String name;
    private String password;
}
 

5. @EqualsAndHashCode

  • 作用:生成 equals() 和 hashCode() 方法,默认基于所有非静态字段。
  • 常用属性:exclude(排除字段)、of(包含字段),用法同 @ToString

6. @Slf4j / @Log

  • 作用:自动生成日志对象(如 private static final Logger log = LoggerFactory.getLogger(XXX.class);)。
  • 适用场景:需要日志输出的类(Service、Controller 等)。

java
 
运行
 
 
 
 
import lombok.extern.slf4j.Slf4j;

@Slf4j // 生成 log 日志对象(基于 SLF4J)
@RestController
public class UserController {
    public void getuser() {
        log.info("查询用户信息"); // 直接使用 log 对象
    }
}
 

7. @Builder

  • 作用:生成建造者模式代码,支持链式调用创建对象。
  • 适用场景:字段较多的类,创建对象时更简洁。

java
 
运行
 
 
 
 
import lombok.Builder;
import lombok.Data;

@Data
@Builder // 生成建造者模式
public class User {
    private Long id;
    private String name;
    private Integer age;
}

// 使用示例
User user = User.builder()
    .id(1L)
    .name("张三")
    .age(20)
    .build();
 

8. @NonNull

  • 作用:标记字段或方法参数不可为 null,生成 null 校验代码。
  • 效果:若传入 null,会抛出 NullPointerException

java
 
运行
 
 
 
 
import lombok.NonNull;

public class User {
    private String name;
    
    public void setName(@NonNull String name) { // 参数不可为 null
        this.name = name;
    }
}
 

四、工作原理

Lombok 在 编译阶段 通过注解处理器(Annotation Processor)解析注解,动态生成 Java 代码(如 getter、构造方法等),并将生成的代码合并到字节码中。因此:

  • 运行时无需依赖 Lombok 库(scope=provided)。
  • 反编译 class 文件可看到生成的完整代码。

五、注意事项

  1. 调试问题:直接调试时可能无法查看自动生成的方法,需通过反编译 class 文件确认。
  2. 继承场景:@Data 生成的 equals()/hashCode() 不会考虑父类字段,需结合 @EqualsAndHashCode(callSuper = true) 使用。
  3. 与 IDE 配合:必须安装 Lombok 插件,否则 IDE 会提示 “方法不存在”(不影响编译)。
  4. 代码可读性:过度使用可能导致团队新成员理解成本增加,建议团队统一规范。

总结

org.projectlombok 对应的 Lombok 是 Java 开发的 “减负工具”,通过注解自动生成样板代码,大幅提升开发效率。其核心注解 @Data@Getter@Setter@Slf4j 等已成为主流项目的标配,但需注意与 IDE 配合及团队规范,平衡代码简洁性与可读性。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>

org.apache.poi 是 Apache 软件基金会旗下 POI 项目的 Maven 坐标,POI(Poor Obfuscation Implementation)是 Java 领域处理 Microsoft Office 文档的核心库,支持读写 Excel、Word、PowerPoint 等格式文件,尤其在 Excel 处理方面应用广泛。

一、POI 核心功能

POI 提供了对 Office 格式的底层解析和生成能力,主要支持:

  • Excel:.xls(BIFF8 格式,Excel 97-2003)和 .xlsx(OOXML 格式,Excel 2007+)。
  • Word:.doc 和 .docx 格式(主要通过 HWPF 和 XWPF 模块)。
  • PowerPoint:.ppt 和 .pptx 格式(主要通过 HSLF 和 XSLF 模块)。

其中,Excel 处理是 POI 最常用的功能,下面重点介绍。

二、核心模块与依赖

POI 按功能拆分多个模块,可按需引入:

模块功能说明Maven 依赖坐标
poi 处理 .xls 格式(Excel 97-2003) <artifactId>poi</artifactId>
poi-ooxml 处理 .xlsx 格式(Excel 2007+) <artifactId>poi-ooxml</artifactId>
poi-ooxml-schemas OOXML 格式的 XML Schema 定义(依赖) <artifactId>poi-ooxml-schemas</artifactId>
poi-scratchpad 处理 Word(.doc)、PowerPoint(.ppt)等 <artifactId>poi-scratchpad</artifactId>

常用依赖配置(以 Excel 处理为例):

xml
 
 
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.4</version> <!-- 最新稳定版,兼容 Java 8+ -->
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.4</version>
</dependency>
 

三、Excel 处理核心类与示例

1. 处理 .xlsx 格式(Excel 2007+)

使用 XSSF 相关类(XSSFWorkbookXSSFSheet 等):

示例 1:创建并写入 Excel 文件

java
 
运行
 
 
 
 
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelWriter {
    public static void main(String[] args) {
        // 创建工作簿(Workbook)
        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
            // 创建工作表(Sheet)
            XSSFSheet sheet = workbook.createSheet("用户列表");
            
            // 创建表头行(Row)
            XSSFRow headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("ID");
            headerRow.createCell(1).setCellValue("姓名");
            headerRow.createCell(2).setCellValue("年龄");
            
            // 写入数据行
            Object[][] data = {{1, "张三", 20}, {2, "李四", 25}};
            for (int i = 0; i < data.length; i++) {
                XSSFRow row = sheet.createRow(i + 1); // 从第1行开始(0是表头)
                row.createCell(0).setCellValue((Integer) data[i][0]);
                row.createCell(1).setCellValue((String) data[i][1]);
                row.createCell(2).setCellValue((Integer) data[i][2]);
            }
            
            // 调整列宽(自适应内容)
            sheet.autoSizeColumn(0);
            sheet.autoSizeColumn(1);
            sheet.autoSizeColumn(2);
            
            // 写入文件
            try (FileOutputStream fos = new FileOutputStream("users.xlsx")) {
                workbook.write(fos);
            }
            System.out.println("Excel 创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 

示例 2:读取 Excel 文件内容

java
 
运行
 
 
 
 
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import java.io.FileInputStream;
import java.io.IOException;

public class ExcelReader {
    public static void main(String[] args) {
        try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("users.xlsx"))) {
            // 获取第一个工作表(索引从0开始)
            XSSFSheet sheet = workbook.getSheetAt(0);
            
            // 遍历行(从第1行开始,跳过表头)
            for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
                XSSFRow row = sheet.getRow(rowNum);
                if (row == null) continue;
                
                // 读取单元格内容
                int id = (int) row.getCell(0).getNumericCellValue();
                String name = row.getCell(1).getStringCellValue();
                int age = (int) row.getCell(2).getNumericCellValue();
                
                System.out.printf("ID: %d, 姓名: %s, 年龄: %d%n", id, name, age);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 

2. 处理 .xls 格式(Excel 97-2003)

使用 HSSF 相关类(HSSFWorkbookHSSFSheet 等),API 与 XSSF 类似,仅类名不同:

java
 
运行
 
 
 
 
// 示例:创建 .xls 文件
try (HSSFWorkbook workbook = new HSSFWorkbook()) {
    HSSFSheet sheet = workbook.createSheet("旧版Excel");
    // 后续操作与 XSSF 一致
}
 

3. 通用处理(兼容两种格式)

通过 Workbook 接口实现通用读写(自动识别格式):

java
 
运行
 
 
 
 
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

// 自动识别 .xls 或 .xlsx
try (Workbook workbook = WorkbookFactory.create(new FileInputStream("file.xls"))) {
    // 通用操作(不依赖具体实现类)
}
 

四、高级功能

  1. 单元格样式:设置字体、颜色、边框、对齐方式等:
    java
     
    运行
     
     
     
     
    // 创建单元格样式
    CellStyle style = workbook.createCellStyle();
    Font font = workbook.createFont();
    font.setBold(true); // 加粗
    font.setColor(Font.COLOR_RED); // 红色
    style.setFont(font);
    cell.setCellStyle(style); // 应用到单元格
    
     
  2. 公式计算:支持 Excel 公式(如求和、平均值):
    java
     
    运行
     
     
     
     
    cell.setCellFormula("SUM(C2:C3)"); // 计算 C2 到 C3 的和
    workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); // 触发计算
    
     
  3. 大数据量处理:
    • 对于 .xlsx 大文件(超过 10 万行),使用 SXSSFWorkbook 替代 XSSFWorkbook,通过内存优化减少 OOM:
      java
       
      运行
       
       
       
       
      try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) { // 仅保留100行在内存
          // 操作与 XSSF 类似,但会临时写入磁盘
      }
      
       

五、注意事项

  1. 版本兼容性:POI 5.x 要求 Java 8+,若使用 Java 7 需选择 4.x 版本。
  2. 内存占用:处理大文件时易发生 OOM,推荐使用 SXSSFWorkbook 或分页读取。
  3. 格式支持:.xlsx 功能更丰富(如更多行数、列数),建议优先使用。
  4. 依赖冲突:poi-ooxml 依赖 poi 和 poi-ooxml-schemas,需确保版本一致。

总结

org.apache.poi 对应的 POI 库是 Java 处理 Office 文档的行业标准,尤其在 Excel 读写方面功能全面。通过 XSSF(.xlsx)和 HSSF(.xls)模块,可实现从简单数据读写到复杂样式、公式计算的全场景需求,是企业级应用中导出报表、解析 Excel 数据的必备工具。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
commons-beanutils 是 Apache Commons 工具集下的一个子项目,提供了一套用于操作 Java Bean 的工具类,主要用于简化 Java 对象的属性访问、复制、转换等操作。它是早期 Java 开发中处理 Bean 映射的常用库,但随着更高效工具(如 MapStruct)的出现,其使用场景逐渐减少。

一、核心功能

commons-beanutils 主要解决以下问题:

  1. 简化 Java Bean 的属性读写(通过属性名动态访问)。
  2. 实现对象之间的属性复制(如 DO 到 DTO 的转换)。
  3. 提供类型转换工具(如字符串转日期、数字等)。

二、依赖配置

在 Maven 项目中引入依赖:

xml
 
 
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version> <!-- 稳定版本,需注意安全漏洞 -->
</dependency>
 

注意:该库存在一些历史安全漏洞(如 CVE-2019-10086),高版本已修复,建议使用 1.9.4+ 版本。

三、核心工具类与用法

1. BeanUtils:核心工具类

提供对象属性复制、属性访问等核心功能。
(1)对象属性复制
将一个对象的属性值复制到另一个对象(要求属性名相同):

java
 
运行
 
 
 
 
import org.apache.commons.beanutils.BeanUtils;

public class User {
    private Long id;
    private String name;
    private Integer age;
    // getter/setter
}

public class UserDTO {
    private Long id;
    private String name;
    private Integer age;
    // getter/setter
}

// 使用示例
User user = new User(1L, "张三", 20);
UserDTO dto = new UserDTO();
try {
    // 复制属性(仅复制名和类型都匹配的属性)
    BeanUtils.copyProperties(dto, user);
    System.out.println(dto.getName()); // 输出 "张三"
} catch (Exception e) {
    e.printStackTrace();
}
 
(2)动态读写属性
通过属性名字符串访问对象属性:

java
 
运行
 
 
 
 
try {
    User user = new User();
    // 设置属性值(支持字符串自动转换为目标类型)
    BeanUtils.setProperty(user, "name", "李四");
    BeanUtils.setProperty(user, "age", "25"); // 字符串 "25" 自动转为 Integer
    
    // 获取属性值
    String name = BeanUtils.getProperty(user, "name"); // "李四"
    String age = BeanUtils.getProperty(user, "age");   // "25"
} catch (Exception e) {
    e.printStackTrace();
}
 

2. PropertyUtils:属性操作工具

与 BeanUtils 类似,但不进行类型转换,要求值的类型与属性类型严格匹配:

java
 
运行
 
 
 
 
import org.apache.commons.beanutils.PropertyUtils;

try {
    User user = new User();
    // 必须传入 Integer 类型,否则报错
    PropertyUtils.setProperty(user, "age", 25); 
    Integer age = (Integer) PropertyUtils.getProperty(user, "age"); // 25
} catch (Exception e) {
    e.printStackTrace();
}
 

3. ConvertUtils:类型转换工具

提供常见数据类型的转换(如 String 转 DateString 转 Integer 等):

java
 
运行
 
 
 
 
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;

// 注册日期转换器(默认不支持 String 转 Date,需手动配置)
DateConverter dateConverter = new DateConverter(null);
dateConverter.setPatterns(new String[]{"yyyy-MM-dd", "yyyy/MM/dd"});
ConvertUtils.register(dateConverter, java.util.Date.class);

// 使用转换
try {
    String dateStr = "2023-01-01";
    Date date = (Date) ConvertUtils.convert(dateStr, java.util.Date.class);
} catch (Exception e) {
    e.printStackTrace();
}
 

四、优缺点分析

优点:

  1. 简化代码:无需手动编写大量 getter/setter 复制逻辑。
  2. 动态性:支持通过字符串名称访问属性,适合反射场景。

缺点:

  1. 性能较差:基于反射实现,比 MapStruct 等编译时生成代码的工具慢 10-100 倍。
  2. 类型转换局限:默认转换能力有限,复杂类型需手动注册转换器。
  3. 异常处理繁琐:所有方法抛出受检异常(Exception),需强制捕获。
  4. 安全漏洞:历史版本存在安全风险(如反序列化漏洞)。

五、替代方案

由于 commons-beanutils 的性能和安全性问题,目前更推荐以下替代工具:

  1. MapStruct:编译时生成代码,性能优异,类型安全(推荐)。
  2. Spring BeanUtils:Spring 框架内置的简化版工具,避免引入额外依赖。
  3. Apache Commons BeanUtils2:commons-beanutils 的改进版,修复了部分问题,但使用较少。

总结

commons-beanutils 是早期 Java 开发中处理 Bean 操作的经典工具,提供了属性复制、动态访问等功能。但其基于反射的实现导致性能较差,且存在安全隐患,目前已逐渐被 MapStruct 等现代工具替代。对于新项目,建议优先选择编译时生成代码的映射工具;若维护老项目需使用,需注意版本安全和性能瓶颈。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
org.springdoc 是 SpringDoc 框架的 Maven 坐标,SpringDoc 是一款基于 OpenAPI 规范(曾用名 Swagger)的 API 文档生成工具,专为 Spring 生态(尤其是 Spring Boot)设计,能够自动生成 RESTful API 文档,并提供交互式 UI 供开发者查阅和调试接口。

一、SpringDoc 核心价值

  1. 自动生成文档:通过解析 Spring 控制器(@RestController)、请求映射(@GetMapping 等)、参数注解(@RequestParam 等),自动生成符合 OpenAPI 3.0 规范的 API 文档。
  2. 交互式 UI:集成 Swagger UI 和 ReDoc 等可视化界面,支持在线接口调试(类似 Postman)。
  3. 零侵入性:无需额外编写文档注解(或仅需少量注解),完全基于 Spring 原生注解生成文档。
  4. 适配 Spring 生态:完美支持 Spring Boot、Spring Cloud、Spring WebFlux 等,兼容主流框架版本。

二、核心依赖与配置

1. 基础依赖(Spring Boot Web 项目)

xml
 
 
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.1.0</version> <!-- 最新稳定版,适配 Spring Boot 3.x;若用 Spring Boot 2.x 需选 1.x 版本 -->
</dependency>
 

  • 该依赖包含:
    • OpenAPI 核心功能(生成 API 元数据)。
    • Swagger UI(交互式文档界面)。
    • 自动适配 Spring MVC 的配置。

2. 其他场景依赖

  • Spring WebFlux 项目:
    xml
     
     
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
        <version>2.1.0</version>
    </dependency>
    
     
  • 仅需 OpenAPI 规范(无需 UI):
    xml
     
     
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
        <version>2.1.0</version>
    </dependency>
    
     

三、基本使用与文档增强

SpringDoc 零配置即可生成基础文档,通过注解可增强文档信息。

1. 基础文档生成

创建一个简单的控制器:

java
 
运行
 
 
 
 
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id, @RequestParam(required = false) String name) {
        return new User(id, name, 20);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return user;
    }

    // User 实体类
    public record User(Long id, String name, Integer age) {}
}
 

启动项目后,访问以下地址查看文档:

  • Swagger UI:http://localhost:8080/swagger-ui/index.html(交互式界面,支持调试)。
  • OpenAPI 规范 JSON:http://localhost:8080/v3/api-docs(机器可读的 API 元数据)。

2. 文档增强注解

通过 OpenAPI 注解补充接口描述、参数说明等信息(需引入 jakarta.validation 相关依赖支持):

java
 
运行
 
 
 
 
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;

@RestController
@RequestMapping("/users")
public class UserController {

    @Operation(
        summary = "获取用户信息",
        description = "根据用户ID查询用户详情,支持按姓名过滤",
        responses = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "404", description = "用户不存在")
        }
    )
    @GetMapping("/{id}")
    public User getUser(
        @Parameter(description = "用户ID", required = true, example = "1") 
        @PathVariable Long id,
        
        @Parameter(description = "用户姓名(可选)", example = "张三") 
        @RequestParam(required = false) String name
    ) {
        return new User(id, name, 20);
    }

    @Operation(summary = "创建用户", description = "新增用户信息")
    @PostMapping
    public User createUser(
        @Parameter(description = "用户信息", required = true)
        @RequestBody User user
    ) {
        return user;
    }

    // 实体类增强
    @Schema(description = "用户实体")
    public record User(
        @Schema(description = "用户ID", example = "1") Long id,
        @Schema(description = "用户姓名", example = "张三") String name,
        @Schema(description = "用户年龄", example = "20", minimum = "0") Integer age
    ) {}
}
 

3. 全局配置

通过 application.yml 或配置类自定义文档全局信息(如标题、版本、联系人):

yaml
 
 
springdoc:
  api-docs:
    path: /api-docs  # 自定义 OpenAPI JSON 路径
  swagger-ui:
    path: /swagger-ui.html  # 自定义 Swagger UI 路径
  info:
    title: 用户管理 API
    version: 1.0.0
    description: 用于演示 SpringDoc 的用户管理接口文档
    contact:
      name: 开发团队
      email: dev@example.com
 

四、核心特性

  1. 接口调试:Swagger UI 支持在线填写参数、发送请求、查看响应,无需依赖 Postman 等工具。
  2. 文档导出:支持导出 API 文档为 JSON、YAML 格式,可导入到其他工具(如 Postman、Insomnia)。
  3. 分组管理:当项目接口较多时,可通过 @Tag 注解分组,便于文档浏览:
    java
     
    运行
     
     
     
     
    @Tag(name = "用户管理", description = "用户CRUD接口")
    @RestController
    @RequestMapping("/users")
    public class UserController { ... }
    
     
  4. 安全认证:支持配置 API 访问的认证方式(如 JWT、Basic Auth),在 Swagger UI 中可一键添加认证信息。

五、与 Swagger 2.x 的对比

SpringDoc 是 Swagger 2.x(io.springfox)的替代方案,二者核心差异:

特性Swagger 2.x(SpringFox)SpringDoc(OpenAPI 3.0)
规范版本 基于 Swagger 2.0 规范 基于 OpenAPI 3.0 规范(更先进)
Spring 兼容性 对 Spring Boot 3.x 支持差 完美支持 Spring Boot 3.x
维护状态 几乎停滞(最后更新 2020 年) 活跃更新(2024 年仍有新版本)
注解包 io.swagger.annotations io.swagger.v3.oas.annotations
零配置支持 较弱,需较多配置 强,开箱即用

结论:新项目优先选择 SpringDoc,尤其是使用 Spring Boot 3.x 的场景;老项目若已使用 SpringFox 且稳定运行,可暂不迁移。

总结

org.springdoc 对应的 SpringDoc 是 Spring 生态中生成 API 文档的最佳选择,基于 OpenAPI 3.0 规范,支持自动生成文档和交互式调试,配置简单且兼容性强。通过少量注解即可增强文档可读性,大幅降低 API 文档维护成本,是前后端分离开发中的必备工具。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
org.dom4j 是 Dom4j 框架的 Maven 坐标,Dom4j 是一款高效、灵活的 Java XML 解析库,基于 W3C DOM 规范实现,同时融合了 SAX 解析的优点,是 Java 领域处理 XML 文档的主流工具之一(尤其在传统企业级项目中应用广泛)。

一、Dom4j 核心价值

  1. API 简洁易用:提供直观的面向对象 API,比 JDK 原生的 org.w3c.dom 或 org.xml.sax 更易上手。
  2. 解析效率高:兼顾 DOM 树的随机访问能力和 SAX 的流解析效率,支持大文件的增量解析。
  3. 功能丰富:支持 XML 文档的创建、读取、修改、查询(如 XPath 语法)、格式化输出等全场景操作。
  4. 扩展性强:可自定义解析器、注册事件监听器,适配复杂 XML 处理需求。

二、核心依赖配置

在 Maven 项目中引入 Dom4j 依赖:

xml
 
 
<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version> <!-- 最新稳定版,兼容 Java 8+ -->
</dependency>
 

  • 注意:Dom4j 早期版本(如 1.6.x)存在安全漏洞(如 XML 外部实体注入 XXE),强烈建议使用 2.1.0+ 版本,该版本已修复相关漏洞。

三、核心 API 与使用示例

Dom4j 的核心操作围绕 Document(XML 文档对象)、Element(XML 元素)、Attribute(XML 属性)等类展开,以下是常见场景的实现。

1. 读取并解析 XML 文件

示例 XML(users.xml):

xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user id="1">
        <name>张三</name>
        <age>20</age>
    </user>
    <user id="2">
        <name>李四</name>
        <age>25</age>
    </user>
</users>
 

解析代码:

java
 
运行
 
 
 
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;

public class XmlReader {
    public static void main(String[] args) {
        // 1. 创建 SAX 解析器(Dom4j 推荐使用 SAXReader,兼顾效率和内存)
        SAXReader reader = new SAXReader();
        
        try {
            // 2. 读取 XML 文件,生成 Document 对象(XML 文档树的根)
            Document document = reader.read(new File("users.xml"));
            
            // 3. 获取 XML 根元素(<users>)
            Element rootElement = document.getRootElement();
            
            // 4. 遍历根元素下的子元素(<user>)
            List<Element> userElements = rootElement.elements("user");
            for (Element userElem : userElements) {
                // 4.1 获取属性值(id)
                String userId = userElem.attributeValue("id");
                
                // 4.2 获取子元素值(name、age)
                String name = userElem.elementText("name"); // 直接获取文本内容
                String age = userElem.element("age").getText(); // 先获取元素再获取文本
                
                System.out.printf("用户ID:%s,姓名:%s,年龄:%s%n", userId, name, age);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
 

输出结果:

plaintext
 
 
用户ID:1,姓名:张三,年龄:20
用户ID:2,姓名:李四,年龄:25
 

2. 创建并写入 XML 文件

通过 Dom4j 手动构建 XML 文档树,并写入文件:

java
 
运行
 
 
 
 
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.FileWriter;
import java.io.IOException;

public class XmlWriter {
    public static void main(String[] args) {
        try {
            // 1. 创建空的 Document 对象
            Document document = DocumentHelper.createDocument();
            
            // 2. 创建根元素(<users>)并添加到 Document
            Element rootElement = DocumentHelper.createElement("users");
            document.setRootElement(rootElement);
            
            // 3. 构建第一个 <user> 元素
            Element user1 = rootElement.addElement("user");
            user1.addAttribute("id", "3"); // 添加属性
            user1.addElement("name").setText("王五"); // 添加子元素并设置文本
            user1.addElement("age").setText("30");
            
            // 4. 构建第二个 <user> 元素
            Element user2 = rootElement.addElement("user");
            user2.addAttribute("id", "4");
            user2.addElement("name").setText("赵六");
            user2.addElement("age").setText("35");
            
            // 5. 格式化 XML 输出(缩进、换行,便于阅读)
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8"); // 设置编码
            
            // 6. 写入文件
            try (XMLWriter writer = new XMLWriter(new FileWriter("new_users.xml"), format)) {
                writer.write(document);
            }
            System.out.println("XML 文件创建成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 

生成的 new_users.xml

xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<users>
  <user id="3">
    <name>王五</name>
    <age>30</age>
  </user>
  <user id="4">
    <name>赵六</name>
    <age>35</age>
  </user>
</users>
 

3. 使用 XPath 快速查询 XML

Dom4j 支持 XPath 语法,可直接定位到目标元素,避免遍历整个文档树,适合复杂 XML 的查询:

java
 
运行
 
 
 
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.xpath.DefaultXPath;
import java.util.List;

public class XmlXPathQuery {
    public static void main(String[] args) {
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(new File("users.xml"));
            
            // 1. 定义 XPath 表达式(查询 id="2" 的 user 元素下的 name)
            DefaultXPath xpath = new DefaultXPath("//user[@id='2']/name");
            Element nameElem = (Element) xpath.selectSingleNode(document);
            System.out.println("ID=2 的用户姓名:" + nameElem.getText()); // 输出 "李四"
            
            // 2. 批量查询(所有 age > 20 的 user 元素的 id)
            DefaultXPath xpath2 = new DefaultXPath("//user[age>20]/@id");
            List<?> idAttributes = xpath2.selectNodes(document);
            for (Object attr : idAttributes) {
                System.out.println("年龄>20 的用户ID:" + ((org.dom4j.Attribute) attr).getValue()); // 输出 "2"
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
 

4. 修改 XML 文档

修改已有的 XML 元素或属性,并覆盖原文件:

java
 
运行
 
 
 
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class XmlModifier {
    public static void main(String[] args) {
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(new File("users.xml"));
            Element root = document.getRootElement();
            
            // 1. 修改 id="1" 的 user 的 age 为 22
            Element user1 = (Element) new DefaultXPath("//user[@id='1']").selectSingleNode(document);
            user1.element("age").setText("22");
            
            // 2. 新增一个属性(如 gender)
            user1.addAttribute("gender", "男");
            
            // 3. 覆盖原文件
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("UTF-8");
            try (XMLWriter writer = new XMLWriter(new FileWriter("users.xml"), format)) {
                writer.write(document);
            }
            System.out.println("XML 文件修改成功!");
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }
}
 

四、关键注意事项

  1. 安全问题(XXE 防护):
    早期 Dom4j 版本默认支持 XML 外部实体(XXE),可能导致文件泄露等安全风险。2.1.0+ 版本已默认禁用 XXE,若需手动配置,可通过 SAXReader 禁用:
    java
     
    运行
     
     
     
     
    SAXReader reader = new SAXReader();
    // 禁用 XXE(手动配置,确保安全)
    reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    
     
  2. 大文件处理:
    若 XML 文件过大(如超过 100MB),直接使用 SAXReader.read() 会加载整个文档树到内存,可能导致 OOM。此时需使用 SAX 事件驱动模式,通过 ContentHandler 逐行解析:
    java
     
    运行
     
     
     
     
    // 大文件 SAX 解析示例
    SAXReader reader = new SAXReader();
    reader.setContentHandler(new org.xml.sax.helpers.DefaultHandler() {
        @Override
        public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes) {
            // 开始解析元素时触发
            if ("user".equals(qName)) {
                System.out.println("用户ID:" + attributes.getValue("id"));
            }
        }
    });
    reader.read(new File("large_users.xml"));
    
     
  3. 编码一致性:
    读取和写入 XML 时,需确保编码格式(如 UTF-8)一致,避免中文乱码。通过 OutputFormat.setEncoding() 和 SAXReader 的编码参数(如 reader.read(new FileInputStream(file), "UTF-8"))控制。

五、与其他 XML 解析库的对比

解析库核心特点适用场景缺点
Dom4j API 友好、支持 XPath、兼顾效率 大多数 XML 处理场景(推荐) 大文件解析需手动适配 SAX 模式
JDK DOM 原生支持、标准 API 简单 XML 场景,无需额外依赖 API 繁琐、效率低
JDK SAX 流解析、内存占用低 超大 XML 文件(GB 级) 无文档树,无法随机访问,编程复杂
Jackson XML 基于 Jackson 生态、支持 POJO 映射 XML 与 Java 对象互转(类似 JSON) 不适合复杂 XML 结构的手动修改

总结

org.dom4j 对应的 Dom4j 是 Java 领域 XML 解析的 “瑞士军刀”,兼具易用性和效率,支持从简单读取到复杂 XPath 查询、文档修改的全场景需求。尽管在 XML 与 POJO 互转场景下可被 Jackson XML 替代,但在传统企业级项目(如解析配置文件、SOAP 协议数据)中仍被广泛使用,是处理 XML 文档的必备工具之一。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</dependency>
在 Maven 项目中,<groupId>jaxen</groupId> 对应的是 Jaxen 库,这是一个用于 XPath 表达式解析和计算的 Java 开源库。它主要用于在各种 XML 文档模型(如 DOM、SAX、JDOM 等)上执行 XPath 查询。

常用的 Jaxen 依赖配置

在 pom.xml 中引入 Jaxen 依赖的典型配置如下:

xml
 
 
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.2.0</version> <!-- 版本号可根据需要调整 -->
</dependency>
 

主要用途

  1. 解析和执行 XPath 表达式,从 XML 文档中提取特定数据
  2. 支持多种 XML 解析模型,提供统一的 XPath 操作接口
  3. 常用于需要处理 XML 数据的场景,如配置文件解析、数据转换等

注意事项

  • 版本选择:建议使用较新的稳定版本(如 1.2.0 或更高),以获得更好的兼容性和安全性
  • 依赖冲突:Jaxen 可能与其他 XML 处理库(如 Xalan、Saxon 等)存在依赖冲突,需注意版本兼容性
  • 替代方案:在 Java 8+ 环境中,也可考虑使用 JDK 内置的 XPath 处理能力(javax.xml.xpath 包)

如果需要使用 Jaxen 处理特定的 XML 模型(如 JDOM、DOM4J 等),可能还需要额外引入相应的适配器依赖。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office</artifactId>
</dependency>
e-iceblue 是国产公司 Iceblue 开发的 Java 文档处理库(Spire 系列)的 Maven 坐标,主要用于处理 Office 文档(Excel、Word、PowerPoint、PDF 等),提供比 Apache POI 更丰富的格式控制和高级功能,尤其适合需要生成复杂样式文档的场景。

一、核心产品与功能

e-iceblue 下的主要产品是 Spire 系列组件,按文档类型分为多个模块:

模块名称功能说明
spire.xls 处理 Excel 文档(.xls、.xlsx),支持复杂公式、图表、数据透视表等
spire.doc 处理 Word 文档(.doc、.docx),支持页眉页脚、样式、表格、图片等
spire.pdf 处理 PDF 文档(生成、编辑、转换、加密等)
spire.presentation 处理 PowerPoint 文档(.ppt、.pptx),支持幻灯片编辑、转换等

二、依赖配置

以处理 Excel 为例,在 Maven 项目中引入依赖:

xml
 
 
<dependency>
    <groupId>e-iceblue</groupId>
    <artifactId>spire.xls</artifactId>
    <version>14.5.0</version> <!-- 版本号可按需更新 -->
</dependency>
 

注意:Spire 系列有免费版和商业版,免费版对文档大小和页数有限制(如 Excel 最多 5 sheets,PDF 最多 10 页),商业版需购买授权。

三、典型使用示例(以 Excel 处理为例)

1. 创建复杂样式的 Excel 文档

java
 
运行
 
 
 
 
import com.spire.xls.*;
import java.awt.*;

public class ExcelDemo {
    public static void main(String[] args) {
        // 创建工作簿
        Workbook workbook = new Workbook();
        // 获取第一个工作表
        Worksheet sheet = workbook.getWorksheets().get(0);
        sheet.setName("销售报表");

        // 合并单元格并设置标题
        sheet.getRange().get("A1:E1").merge();
        CellRange titleRange = sheet.getRange().get("A1");
        titleRange.setValue("2023年销售数据");
        titleRange.getStyle().getFont().setSize(16);
        titleRange.getStyle().getFont().setColor(Color.BLUE);
        titleRange.getStyle().setHorizontalAlignment(HorizontalAlignType.Center);

        // 设置表头
        String[] headers = {"产品", "一季度", "二季度", "三季度", "四季度"};
        for (int i = 0; i < headers.length; i++) {
            CellRange headerCell = sheet.getRange().get(2, i + 1);
            headerCell.setValue(headers[i]);
            headerCell.getStyle().getFont().setIsBold(true);
            headerCell.getStyle().setBackgroundColor(Color.LIGHT_GRAY);
        }

        // 填充数据
        Object[][] data = {
            {"产品A", 120, 150, 180, 200},
            {"产品B", 90, 110, 130, 150},
            {"产品C", 80, 95, 105, 120}
        };
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                sheet.getRange().get(i + 3, j + 1).setValue(data[i][j]);
            }
        }

        // 添加图表(柱状图)
        Chart chart = sheet.getCharts().add(ExcelChartType.ColumnClustered);
        chart.setDataRange(sheet.getRange().get("B3:E5"));
        chart.setSeriesDataFromRange(false);
        chart.setPosition(5, 1, 10, 8); // 位置和大小
        chart.setTitle("季度销售对比");

        // 保存文件
        workbook.saveToFile("销售报表.xlsx", ExcelVersion.Version2016);
        workbook.dispose();
    }
}
 

2. PDF 文档操作示例

java
 
运行
 
 
 
 
import com.spire.pdf.*;
import com.spire.pdf.graphics.PdfBrushes;
import com.spire.pdf.graphics.PdfFont;
import com.spire.pdf.graphics.PdfFontFamily;
import com.spire.pdf.graphics.PdfStringFormat;

import java.awt.*;
import java.awt.geom.Point2D;

public class PdfDemo {
    public static void main(String[] args) {
        // 创建PDF文档
        PdfDocument pdf = new PdfDocument();
        PdfPageBase page = pdf.getPages().add();

        // 设置字体
        PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 12);

        // 绘制文本
        String text = "Hello, Spire.PDF!";
        page.getCanvas().drawString(text, font, PdfBrushes.getBlack(), 
                new Point2D.Float(100, 100), PdfStringFormat.getDefault());

        // 保存文档
        pdf.saveToFile("output.pdf");
        pdf.close();
    }
}
 

四、核心优势

  1. 功能丰富:支持更多高级格式(如 Excel 复杂图表、Word 样式模板、PDF 电子签名)。
  2. 易用性强:API 设计简洁,比 POI 更易实现复杂样式。
  3. 格式兼容性好:对 Office 新版本格式(如 .xlsx、.docx)支持更完善。
  4. 转换能力强:支持跨格式转换(如 Excel 转 PDF、Word 转 HTML 等)。

五、注意事项

  1. 授权限制:免费版有功能和页数限制,商业使用需购买 license,否则文档会添加水印。
  2. 依赖体积:Spire 系列 JAR 包较大(单个模块约 50-100MB),可能增加项目体积。
  3. 替代方案:简单场景可使用 Apache POI(免费开源),复杂格式需求可考虑 Spire。

总结

e-iceblue 对应的 Spire 系列组件是处理 Office 文档的商业解决方案,适合需要生成复杂样式文档的企业级应用。其 API 简洁、功能强大,但需注意授权限制。若项目对文档格式要求较高且可接受商业授权,Spire 是高效选择;若为简单场景或开源项目,Apache POI 等免费库更合适。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
</dependency>
在 Maven 中,<groupId>org.mvel</groupId> 对应的是 MVEL(MVFLEX Expression Language) 库,它是一种高性能的表达式语言,主要用于 Java 应用程序中执行动态表达式计算。MVEL 语法简洁,功能强大,广泛应用于规则引擎、数据绑定、动态配置等场景。

一、MVEL 核心依赖配置

在 pom.xml 中引入 MVEL 依赖的典型配置如下:

xml
 
 
<dependency>
    <groupId>org.mvel</groupId>
    <artifactId>mvel2</artifactId> <!-- MVEL 2.x 版本的 artifactId 为 mvel2 -->
    <version>2.4.14.Final</version> <!-- 版本号可根据需要调整,建议使用稳定版 -->
</dependency>
 

  • MVEL 目前主要维护 2.x 版本,1.x 已停止更新。
  • 最新版本可在 Maven 中央仓库 查询。

二、MVEL 的核心特性

  1. 简洁的语法
    类似 Java,但更灵活,支持省略分号、类型声明等,例如:
    java
     
    运行
     
     
     
     
    // MVEL 表达式示例
    "Hello, " + name + "! Age: " + (age > 18 ? "Adult" : "Minor")
    
     
  2. 动态计算能力
    可以在运行时解析并执行字符串形式的表达式,无需预编译:
    java
     
    运行
     
     
     
     
    String expression = "a + b * c";
    Map<String, Integer> variables = new HashMap<>();
    variables.put("a", 2);
    variables.put("b", 3);
    variables.put("c", 4);
    
    // 执行表达式
    Integer result = (Integer) MVEL.eval(expression, variables); // 结果为 14(2 + 3*4)
    
     
  3. 丰富的数据操作
    • 支持集合、数组的遍历和过滤(类似 Lambda 表达式):
      java
       
      运行
       
       
       
       
      // 过滤列表中大于 10 的元素
      String expr = "list.filter(item -> item > 10)";
      List<Integer> list = Arrays.asList(5, 12, 8, 15);
      List<Integer> result = (List<Integer>) MVEL.eval(expr, Collections.singletonMap("list", list));
      
       
    • 支持 Map、POJO 的属性访问,自动处理 getter/setter。
  4. 高性能
    采用编译型执行(将表达式编译为字节码),执行效率接近原生 Java 代码。
  5. 扩展性
    支持自定义函数、类型转换器和变量解析器,适应复杂场景。

三、典型应用场景

  1. 规则引擎
    动态定义业务规则(如风控规则、工作流条件),无需修改代码即可更新规则。
  2. 动态配置
    在配置文件中使用 MVEL 表达式定义动态逻辑(如计算字段、条件判断)。
  3. 数据绑定与转换
    简化对象属性的赋值、映射和转换操作。
  4. 模板引擎
    结合文本模板生成动态内容(如动态 SQL、邮件模板)。

四、注意事项

  1. 安全风险
    动态执行表达式可能存在代码注入风险,避免直接使用用户输入作为表达式。
  2. 版本兼容性
    MVEL 2.x 与 1.x 语法存在差异,迁移时需注意调整。
  3. 调试难度
    动态表达式的错误排查相对复杂,建议做好日志记录和异常处理。

五、简单示例代码

java
 
运行
 
 
 
 
import org.mvel2.MVEL;
import java.util.HashMap;
import java.util.Map;

public class MvelExample {
    public static void main(String[] args) {
        // 定义表达式
        String expression = "user.name + ' is ' + (user.age >= 18 ? 'adult' : 'minor')";
        
        // 准备变量
        Map<String, Object> variables = new HashMap<>();
        User user = new User("Alice", 20);
        variables.put("user", user);
        
        // 执行表达式
        String result = (String) MVEL.eval(expression, variables);
        System.out.println(result); // 输出:Alice is adult
    }
    
    static class User {
        private String name;
        private int age;
        
        // 构造函数、getter/setter 省略
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() { return name; }
        public int getAge() { return age; }
    }
}
 

通过 MVEL,开发者可以快速实现动态逻辑,减少硬编码,提升系统的灵活性。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
</dependency>
在 Maven 中,<groupId>com.belerweb</groupId> 对应的是一系列与中国特色功能相关的 Java 工具库,主要由国内开发者维护,专注于解决中文处理、短信服务、身份证验证等本地化需求场景。

其中最具代表性的是 pinyin4j 库(虽然其官方 groupId 实际为com.belerweb,但常被误认为是其他分组),这是一个广泛使用的汉字转拼音工具库。

一、核心依赖:pinyin4j

pinyin4j 是处理中文转拼音的经典库,支持多种拼音输出格式(如带声调、不带声调、首字母等)。

Maven 依赖配置:

xml
 
 
<dependency>
    <groupId>com.belerweb</groupId>
    <artifactId>pinyin4j</artifactId>
    <version>2.5.1</version> <!-- 稳定版本,目前无更新 -->
</dependency>
 

二、pinyin4j 的核心功能

  1. 汉字转全拼
    支持将汉字转换为带声调或不带声调的拼音,例如:
    java
     
    运行
     
     
     
     
    import net.sourceforge.pinyin4j.PinyinHelper;
    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
    import net.sourceforge.pinyin4j.format.style.HanyuPinyinToneType;
    
    public class PinyinExample {
        public static void main(String[] args) throws Exception {
            HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
            format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 不带声调
            
            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray('中', format);
            System.out.println(pinyinArray[0]); // 输出:zhong
        }
    }
    
     
  2. 支持多音字处理
    对于多音字,会返回所有可能的拼音组合,需根据上下文自行处理。
  3. 格式灵活配置
    可通过 HanyuPinyinOutputFormat 配置:
    • 声调类型(带声调、数字表示声调、无声调)
    • 字母大小写
    • 韵母 ü 的显示方式(如替换为 v)

三、其他可能的库

除了 pinyin4j,com.belerweb 分组下还有一些小众库,主要用于:

  • 中文分词
  • 身份证号码验证
  • 国内短信接口集成

但这些库更新频率较低,使用范围较窄,建议优先选择更活跃的替代方案(如中文分词可用 HanLP、IKAnalyzer 等)。

四、注意事项

  1. 版本问题
    pinyin4j 2.5.1 是最后一个稳定版本,发布于 2012 年,长期未更新,但功能稳定,足以满足基础需求。
  2. 替代方案
    若需要更现代的中文转拼音功能,可考虑:
    • org.apache.commons:commons-text(提供拼音转换工具)
    • 基于机器学习的分词 + 拼音工具(如 HanLP)
  3. 使用场景
    适用于中文检索、排序、注音等场景,如通讯录按拼音首字母排序、中文内容转拼音索引等。

如果需要处理中文相关的功能,pinyin4j 是一个轻量且可靠的选择,尤其适合对稳定性要求高、功能需求简单的场景。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
</dependency>
spring-mock 是 Spring 框架早期提供的一个测试辅助模块,主要用于在单元测试中模拟(Mock)Spring 容器中的依赖组件,帮助开发者脱离实际容器环境进行独立测试。不过需要注意的是,该模块目前已被更现代的测试工具替代,实际开发中已很少直接使用。

一、历史背景与定位

spring-mock 最初是 Spring 框架的一部分(主要存在于 Spring 2.x 及更早版本),其设计目标是:

  1. 提供对 Spring 核心组件(如 ApplicationContextBeanFactory)的模拟实现。
  2. 简化依赖注入(DI)场景下的单元测试,避免测试依赖真实的 Spring 容器启动。
  3. 支持对 Spring MVC 中的 HttpRequestHttpResponse 等 Web 组件进行模拟。

随着 Spring 版本迭代,spring-mock 的功能已被拆分和替代:

  • 核心容器模拟功能被 spring-test 模块中的 MockApplicationContext 等类取代。
  • Web 组件模拟功能被 spring-test 中的 MockMvc 及第三方库(如 Mockito)替代。
  • 目前 spring-mock 已不再作为独立模块维护,在 Spring 3.0 之后的版本中逐渐被移除。

二、Maven 依赖(仅历史版本)

在早期 Spring 项目中,spring-mock 的依赖配置如下:

xml
 
 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-mock</artifactId>
    <version>2.0.8</version> <!-- 仅旧版本存在,如 2.x 系列 -->
    <scope>test</scope>
</dependency>
 

注意:Spring 3.0 及以上版本已不再提供该依赖,若强行引入会导致版本冲突。

三、核心功能与示例(历史用法)

1. 模拟 Spring 容器

java
 
运行
 
 
 
 
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class MockContainerTest {
    public void testMockContext() {
        // 模拟 Servlet 上下文
        MockServletContext servletContext = new MockServletContext();
        // 模拟 Spring Web 容器
        XmlWebApplicationContext context = new XmlWebApplicationContext();
        context.setServletContext(servletContext);
        context.setConfigLocations(new String[]{"classpath:applicationContext.xml"});
        context.refresh();
        
        // 从模拟容器中获取 Bean 进行测试
        UserService userService = (UserService) context.getBean("userService");
        // ... 执行测试逻辑
    }
}
 

2. 模拟 Web 请求

java
 
运行
 
 
 
 
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class MockWebTest {
    public void testController() {
        // 模拟 HTTP 请求和响应
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("id", "1");
        MockHttpServletResponse response = new MockHttpServletResponse();
        
        // 测试控制器逻辑(伪代码)
        UserController controller = new UserController();
        controller.getUser(request, response);
        
        // 验证响应
        System.out.println(response.getContentAsString());
    }
}
 

四、现代替代方案

由于 spring-mock 已过时,目前 Spring 项目的测试推荐使用以下工具:

1. spring-test 模块(官方推荐)

Spring 核心测试模块,包含 spring-mock 的所有功能并增强:

  • 提供 @SpringBootTest@WebMvcTest 等注解,简化容器启动。
  • 内置 MockMvc 用于测试 Spring MVC 控制器:
    java
     
    运行
     
     
     
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.test.web.servlet.MockMvc;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    
    @WebMvcTest(UserController.class)
    public class UserControllerTest {
        @Autowired
        private MockMvc mockMvc;
        
        public void testGetUser() throws Exception {
            mockMvc.perform(get("/users/1"))
                   .andExpect(content().string("user1"));
        }
    }
    
     

2. Mockito(第三方 Mock 框架)

用于模拟依赖对象,替代 spring-mock 的组件模拟功能:

java
 
运行
 
 
 
 
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
    @Mock // 模拟依赖
    private UserDao userDao;
    
    @InjectMocks // 注入到测试对象
    private UserService userService;
    
    @Test
    public void testQueryUser() {
        // 定义 Mock 行为
        when(userDao.getById(1L)).thenReturn(new User(1L, "test"));
        // 测试业务逻辑
        User user = userService.queryUser(1L);
        // 验证结果
        assertEquals("test", user.getName());
    }
}
 

五、总结

spring-mock 是 Spring 早期的测试辅助模块,主要用于模拟容器和 Web 组件,但目前已被 spring-test 和 Mockito 等现代工具完全替代。在当前 Spring Boot 项目中,无需再关注 spring-mock,而是通过 spring-test 结合 Mockito 实现高效的单元测试和集成测试,这些工具提供了更简洁的 API 和更强大的功能。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
在 Maven 中,<groupId>com.xuxueli</groupId> 对应的是国内开发者徐雪里(xuxueli)维护的一系列 Java 工具库和框架,主要聚焦于任务调度、分布式系统等领域,其中最知名的是 XXL-Job 分布式任务调度平台。

一、核心项目:XXL-Job

XXL-Job 是一个轻量级、分布式的任务调度框架,广泛应用于企业级系统中,用于实现定时任务的调度、监控和管理。

1. Maven 依赖配置

XXL-Job 分为调度中心(admin)和执行器(core)两个核心模块,根据角色引入不同依赖:

执行器依赖(业务系统集成):

xml
 
 
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.0</version> <!-- 版本号可根据最新稳定版调整 -->
</dependency>
 

调度中心依赖(独立部署):
调度中心通常作为独立服务部署,需下载源码编译或直接使用官方提供的部署包,无需在业务系统中引入。

2. XXL-Job 核心特性

  • 分布式调度:支持集群部署,解决单点问题,提高可用性。
  • 弹性扩容:执行器可动态增减,调度中心自动感知。
  • 丰富的任务类型:支持 Bean 模式、GLUE 模式(Java/Shell/Python/PHP 等)、父子任务等。
  • 调度策略:支持 cron 表达式、固定间隔、固定延迟等调度方式。
  • 监控与告警:提供任务执行日志、失败重试、邮件告警等功能。
  • 失败处理:支持失败重试、失败降级等策略。

3. 简单使用示例

Step 1:配置执行器

java
 
运行
 
 
 
 
@Configuration
public class XxlJobConfig {
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
        executor.setAdminAddresses(adminAddresses);
        executor.setAppname(appname);
        return executor;
    }
}
 

Step 2:定义任务

java
 
运行
 
 
 
 
@Component
public class SampleXxlJob {
    // 任务注解:指定任务ID和描述
    @XxlJob("demoJobHandler")
    public void demoJobHandler() throws Exception {
        XxlJobHelper.log("XXL-Job 任务执行中...");
        // 业务逻辑
        System.out.println("执行定时任务:" + new Date());
    }
}
 

二、其他项目

除了 XXL-Job,com.xuxueli 下还有一些其他实用工具:

  1. xxl-conf:分布式配置中心,用于集中管理应用配置。
  2. xxl-mq:轻量级消息队列,支持本地消息表、事务消息等特性。
  3. xxl-sso:分布式单点登录系统,支持多系统统一认证。

这些项目风格统一,文档完善,均遵循 "简单易用、开箱即用" 的设计理念,适合中小型项目快速集成。

三、特点与优势

  1. 本土化支持:由国内开发者维护,文档和社区支持均为中文,对国内开发者友好。
  2. 开箱即用:配置简单,集成成本低,提供完整的管理界面。
  3. 稳定性:经过大量企业实践验证,迭代活跃,bug 修复及时。
  4. 扩展性:架构设计灵活,支持自定义插件和扩展。

四、注意事项

  1. 版本兼容性:XXL-Job 各版本间可能存在配置或 API 差异,升级时需参考官方升级指南。
  2. 部署方式:调度中心建议独立部署,执行器嵌入业务系统,两者通过 HTTP 通信。
  3. 社区资源:官方文档(XXL-Job 文档)和 GitHub 仓库提供了详细的使用示例和问题解答。

如果需要在分布式系统中实现任务调度功能,XXL-Job 是一个成熟且可靠的选择,广泛应用于电商、金融、物流等领域。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
在 Maven 中,<groupId>ch.qos.logback</groupId> 对应的是 Logback 日志框架,它是由 log4j 创始人 Ceki Gülcü 设计的开源日志组件,是 log4j 的继任者,也是目前 Java 生态中最常用的日志框架之一。Logback 以高性能、灵活性和强大的配置能力著称,通常与 SLF4J(Simple Logging Facade for Java)配合使用,提供统一的日志接口。

一、Logback 的核心模块

Logback 由三个核心模块组成,分别对应不同的功能:

  1. logback-core
    核心模块,提供基础功能,是另外两个模块的依赖。
  2. logback-classic
    实现了 SLF4J 接口,可直接替代 log4j,支持与 SLF4J 无缝集成,允许切换其他日志框架(如 log4j2)。
  3. logback-access
    与 Servlet 容器集成,提供 HTTP 访问日志功能(如记录请求、响应等信息)。

二、Maven 依赖配置

通常只需引入 logback-classic(会自动依赖 logback-core 和 SLF4J API):

xml
 
 
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.8</version> <!-- 版本号可根据最新稳定版调整 -->
</dependency>
 

如果需要使用 logback-access,需额外引入:

xml
 
 
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>1.4.8</version>
</dependency>
 

三、Logback 的核心特性

  1. 高性能
    比 log4j 更快,内存占用更低,内部优化了日志输出的性能(如异步日志、缓冲机制)。
  2. 灵活的配置方式
    支持 XML、Groovy 两种配置文件格式,可通过配置文件定义日志输出格式、级别、目的地等。
  3. 强大的日志过滤
    支持按日志级别(DEBUG、INFO、WARN、ERROR)、 logger 名称、MDC(Mapped Diagnostic Context)等条件过滤日志。
  4. 自动重新加载配置
    配置文件修改后无需重启应用,Logback 会自动检测并应用新配置。
  5. 丰富的输出目的地
    支持控制台、文件、数据库、远程服务器(如 Socket)等多种输出目标,还可按时间或文件大小分割日志文件。
  6. 与 SLF4J 无缝集成
    遵循 SLF4J 规范,可通过 SLF4J 接口调用,轻松切换底层日志实现。

四、典型配置示例(logback.xml)

在 src/main/resources 下创建 logback.xml 配置文件,示例如下:

xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志格式:时间 [线程名] 级别 logger名 - 消息 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 文件输出(按时间分割) -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/app.log</file> <!-- 日志文件路径 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 按天分割 -->
            <maxHistory>30</maxHistory> <!-- 保留30天日志 -->
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 根日志配置:级别为INFO,输出到控制台和文件 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>

    <!-- 自定义logger:指定特定包的日志级别 -->
    <logger name="com.example" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
</configuration>
 

五、基本使用示例

结合 SLF4J 接口使用 Logback:

java
 
运行
 
 
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogbackExample {
    // 获取logger实例(通常以类名作为logger名称)
    private static final Logger logger = LoggerFactory.getLogger(LogbackExample.class);

    public static void main(String[] args) {
        // 不同级别的日志输出
        logger.debug("这是DEBUG级别的日志"); // 仅当级别为DEBUG及以下时输出
        logger.info("这是INFO级别的日志");   // 级别为INFO及以下时输出
        logger.warn("这是WARN级别的日志");
        logger.error("这是ERROR级别的日志", new Exception("示例异常")); // 可携带异常信息
    }
}
 

六、优势与注意事项

  1. 优势
    • 性能优于 log4j,资源占用低。
    • 配置灵活,支持动态更新。
    • 原生支持 SLF4J,便于日志框架迁移。
    • 内置多种日志滚动策略,适合生产环境。
  2. 注意事项
    • 避免日志级别滥用(如生产环境使用 DEBUG 级别可能导致性能问题和日志爆炸)。
    • 配置文件路径:默认在 classpath 下查找 logback.xml 或 logback-test.xml(测试环境)。
    • 版本兼容性:需与 SLF4J 版本匹配(通常 logback-classic 会自带兼容的 SLF4J 版本)。

Logback 是 Java 项目中日志组件的首选之一,广泛应用于各类系统,从简单应用到大型分布式系统均能胜任

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
</dependency>
com.github.ulisesbocchio 是 GitHub 开发者 Ulises Bocchio 发布的一系列 Spring 生态相关开源项目的 Maven 坐标,其中最知名的是 jasypt-spring-boot—— 一款基于 Spring Boot 集成 Jasypt(Java Simplified Encryption)的工具,用于对配置文件中的敏感信息(如数据库密码、API 密钥)进行加密解密,避免明文泄露。

一、核心项目:jasypt-spring-boot

jasypt-spring-boot 是该坐标下的旗舰项目,它简化了 Jasypt 在 Spring Boot 中的集成,通过自动配置实现对 application.properties 或 application.yml 中加密内容的透明解密。

1. 核心价值

  • 敏感配置加密:将配置文件中的明文密码(如 spring.datasource.password=123456)加密为密文,防止代码泄露时敏感信息暴露。
  • 透明解密:应用启动时自动解密加密的配置项,业务代码无需修改即可使用。
  • 集成简单:通过少量配置即可与 Spring Boot 无缝集成,支持自定义加密算法和密钥管理。

2. 依赖配置

在 Maven 项目中引入 jasypt-spring-boot 依赖:

xml
 
 
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version> <!-- 最新稳定版,适配 Spring Boot 2.x/3.x -->
</dependency>
 

  • starter 版本已包含自动配置,无需额外配置类。

3. 基本使用步骤

(1)生成加密后的密文
使用 Jasypt 提供的工具类或命令行生成密文(以数据库密码 123456 为例):

方式 1:代码生成

java
 
运行
 
 
 
 
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;

public class JasyptEncryptor {
    public static void main(String[] args) {
        // 加密配置
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("my-secret-key"); // 加密密钥(生产环境需妥善保管)
        config.setAlgorithm("PBEWithMD5AndDES"); // 加密算法(默认)
        
        // 初始化加密器
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setConfig(config);
        
        // 加密明文
        String plaintext = "123456"; // 明文密码
        String ciphertext = encryptor.encrypt(plaintext);
        System.out.println("加密后的密文:" + ciphertext); // 输出类似:+pQx4y5z...
    }
}
 

方式 2:命令行生成
通过 Jasypt jar 包直接生成(需下载 jasypt-1.9.3.jar):

bash
 
 
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
  input="123456" \
  password=my-secret-key \
  algorithm=PBEWithMD5AndDES
 
(2)在配置文件中使用密文
将生成的密文用 ENC() 包裹,写入 application.yml 或 application.properties

yaml
 
 
# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: ENC(+pQx4y5z...) # 加密后的密文,用 ENC() 标记
 
(3)配置解密密钥
应用启动时需要提供加密时使用的密钥(my-secret-key),有以下几种方式:

  • 方式 1:配置文件(不推荐,仍有泄露风险)
    yaml
     
     
    jasypt:
      encryptor:
        password: my-secret-key # 解密密钥
    
     
  • 方式 2:启动参数(推荐)
    bash
     
     
    java -jar myapp.jar --jasypt.encryptor.password=my-secret-key
    
     
  • 方式 3:环境变量(更安全)
    bash
     
     
    # 先设置环境变量
    export JASYPT_ENCRYPTOR_PASSWORD=my-secret-key
    # 启动应用
    java -jar myapp.jar
    
     

    配置文件中对应:
    yaml
     
     
    jasypt:
      encryptor:
        password: ${JASYPT_ENCRYPTOR_PASSWORD}
    
     
(4)应用启动与验证
启动 Spring Boot 应用后,jasypt-spring-boot 会自动识别 ENC() 包裹的密文,使用配置的密钥解密,并将解密后的明文注入到对应的配置项中,业务代码无需任何修改即可使用。

4. 高级配置

  • 自定义加密算法:默认使用 PBEWithMD5AndDES,可配置更安全的算法(如 PBEWITHHMACSHA512ANDAES_256):
    yaml
     
     
    jasypt:
      encryptor:
        password: my-secret-key
        algorithm: PBEWITHHMACSHA512ANDAES_256
        key-obtention-iterations: 1000 # 密钥迭代次数
    
     
  • 自定义加密前缀 / 后缀:默认用 ENC() 标记密文,可自定义:
    yaml
     
     
    jasypt:
      encryptor:
        property:
          prefix: "CRYPT("
          suffix: ")"
    
     

    配置文件中密文格式变为:password: CRYPT(+pQx4y5z...)

二、其他相关项目

com.github.ulisesbocchio 下还有一些 Spring 生态的辅助工具:

  • spring-boot-route:Spring Boot 路由和动态配置相关工具。
  • jasypt-spring-boot-docsjasypt-spring-boot 的官方文档和示例。

三、注意事项

  1. 密钥管理:加密密钥是安全的核心,生产环境中绝对不能硬编码在配置文件中,应通过环境变量、密钥管理服务(如 AWS KMS、Vault)等方式安全存储。
  2. 算法安全性:默认的 PBEWithMD5AndDES 算法安全性较低,建议使用 PBEWITHHMACSHA512ANDAES_256 等强加密算法(需 JDK 支持无限制加密策略)。
  3. 性能影响:解密过程在应用启动时执行,对运行时性能无影响,但会略微增加启动时间。

总结

com.github.ulisesbocchio 最核心的项目是 jasypt-spring-boot,它为 Spring Boot 应用提供了简单高效的敏感配置加密方案,通过自动解密实现透明化使用,是保护配置文件中敏感信息的最佳实践之一。使用时需重点关注密钥的安全管理和加密算法的选择,以确保敏感信息不被泄露。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
</dependency>
在 Maven 中,<groupId>co.elastic.clients</groupId> 对应的是 Elasticsearch Java Client(简称 Elasticsearch Java 客户端),这是 Elastic 官方推出的用于与 Elasticsearch 搜索引擎交互的新一代 Java 客户端。它替代了旧版的 org.elasticsearch.client 客户端,提供了更现代的 API 设计和更好的类型安全性。

一、核心依赖与版本

Elasticsearch Java Client 主要包含客户端核心库和 JSON 处理依赖,典型的 Maven 配置如下:

xml
 
 
<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.11.0</version> <!-- 版本需与 Elasticsearch 服务器版本兼容 -->
</dependency>

<!-- JSON 处理依赖(必须),这里以 Jackson 为例 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>
 

  • 版本兼容性:客户端版本必须与 Elasticsearch 服务器版本保持一致(如客户端 8.11.0 对应服务器 8.11.0),否则可能出现兼容性问题。
  • JSON 处理器:客户端需要 JSON 库支持,除了 Jackson,还支持 Gson 等,需显式引入。

二、核心特性

  1. 类型安全的 API
    基于 Elasticsearch 的 JSON 结构生成强类型 Java 类,避免手动拼接 JSON 字符串,减少错误。
  2. 响应式与同步支持
    同时提供同步(ElasticsearchClient)和异步(ElasticsearchAsyncClient)两种调用方式,适应不同场景。
  3. 完整覆盖 Elasticsearch API
    支持索引、搜索、聚合、更新、删除等所有 Elasticsearch 核心操作,包括最新功能。
  4. 自动请求 / 响应转换
    自动处理 Java 对象与 Elasticsearch JSON 格式的相互转换,简化开发。
  5. 支持 Elastic Cloud
    内置对 Elastic Cloud 服务的支持,便于云环境集成。

三、基本使用示例

1. 初始化客户端

java
 
运行
 
 
 
 
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;

// 创建 REST 客户端
RestClient restClient = RestClient.builder(
    new HttpHost("localhost", 9200) // Elasticsearch 服务器地址和端口
).build();

// 创建传输层(结合 JSON 处理器)
ElasticsearchTransport transport = new RestClientTransport(
    restClient, new JacksonJsonpMapper()
);

// 创建 Elasticsearch 客户端
ElasticsearchClient client = new ElasticsearchClient(transport);
 

2. 索引文档

java
 
运行
 
 
 
 
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.core.indexing.IndexResult;

// 定义文档实体类
class Product {
    private String id;
    private String name;
    private double price;
    // 构造函数、getter/setter 省略
}

// 索引文档
Product product = new Product("1", "笔记本电脑", 5999.99);
IndexRequest<Product> request = IndexRequest.of(i -> i
    .index("products") // 指定索引名
    .id(product.getId()) // 文档 ID
    .document(product) // 文档内容
);

IndexResponse response = client.index(request);
if (response.result() == IndexResult.Created) {
    System.out.println("文档创建成功");
}
 

3. 搜索文档

java
 
运行
 
 
 
 
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;

// 搜索价格小于 6000 的产品
SearchRequest request = SearchRequest.of(s -> s
    .index("products")
    .query(q -> q
        .range(r -> r
            .field("price")
            .lt(6000.0)
        )
    )
);

SearchResponse<Product> response = client.search(request, Product.class);
for (Hit<Product> hit : response.hits().hits()) {
    Product product = hit.source();
    System.out.println("找到产品: " + product.getName() + ", 价格: " + product.getPrice());
}
 

4. 关闭客户端

java
 
运行
 
 
 
 
// 使用完毕后关闭资源
transport.close();
restClient.close();
 

四、与旧版客户端的区别

特性旧版客户端(org.elasticsearch.client)新版客户端(co.elastic.clients)
API 风格 基于 Builder 模式,弱类型 基于 Lambda 表达式,强类型
依赖 依赖 Elasticsearch 核心库 轻量级,仅依赖传输层和 JSON 库
兼容性 跨小版本兼容性差 严格要求版本匹配,但 API 更稳定
异步支持 基于 ListenableFuture 支持 CompletableFuture,更符合现代 Java

五、注意事项

  1. 版本匹配:客户端版本必须与 Elasticsearch 服务器版本完全一致,否则可能导致请求失败。
  2. 依赖冲突:避免同时引入旧版客户端,可能引发类冲突。
  3. 性能优化:客户端默认是线程安全的,建议全局共享一个实例,而非频繁创建。
  4. 认证配置:如果 Elasticsearch 启用了安全认证(如用户名密码),需在初始化 RestClient 时配置认证信息。

Elasticsearch Java Client 是连接 Java 应用与 Elasticsearch 的官方推荐工具,适用于所有需要与 Elasticsearch 交互的场景,如日志分析、全文检索、数据聚合等。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
</dependency>
在 Maven 中,<groupId>jakarta.json</groupId> 对应的是 Jakarta JSON Processing API(简称 JSON-P),它是一套用于处理 JSON 数据的 Java 标准 API。JSON-P 提供了解析、生成、查询和转换 JSON 数据的规范,旨在为 Java 应用程序提供统一的 JSON 处理接口,避免因使用不同 JSON 库而导致的兼容性问题。

一、核心组件与依赖

JSON-P 包含 API 规范和实现两个部分,通常需要引入 API 包和具体实现(如 GlassFish 或 Apache 的实现)。

1. Maven 依赖配置

API 依赖(规范定义):

xml
 
 
<dependency>
    <groupId>jakarta.json</groupId>
    <artifactId>jakarta.json-api</artifactId>
    <version>2.1.2</version> <!-- 最新稳定版,支持 Jakarta EE 10+ -->
</dependency>
 

实现依赖(以 GlassFish 实现为例):

xml
 
 
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.json</artifactId>
    <version>2.0.1</version> <!-- 需与 API 版本兼容 -->
    <scope>runtime</scope>
</dependency>
 

  • 版本说明:jakarta.json-api 1.x 对应 Java EE 环境,2.x 对应 Jakarta EE 9+(包名从 javax.json 迁移为 jakarta.json)。
  • 实现选择:除了 GlassFish,还有 Apache Johnzon 等实现,可根据项目需求选择。

二、核心功能与 API

JSON-P 提供了两套主要 API:

  1. 流式 API(JsonParser/JsonGenerator):高效处理大型 JSON 数据,内存占用低。
  2. 对象模型 API(JsonObject/JsonArray 等):将 JSON 数据解析为内存中的对象树,便于随机访问和修改。

1. 生成 JSON 数据(对象模型)

java
 
运行
 
 
 
 
import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonWriter;
import java.io.StringWriter;

public class JsonGenerationExample {
    public static void main(String[] args) {
        // 创建 JSON 对象
        JsonObject user = Json.createObjectBuilder()
            .add("id", 1)
            .add("name", "Alice")
            .add("age", 30)
            .add("active", true)
            .add("hobbies", Json.createArrayBuilder()
                .add("reading")
                .add("hiking")
            )
            .build();

        // 转换为字符串
        StringWriter stringWriter = new StringWriter();
        try (JsonWriter writer = Json.createWriter(stringWriter)) {
            writer.writeObject(user);
        }
        String jsonString = stringWriter.toString();
        System.out.println(jsonString);
        // 输出: {"id":1,"name":"Alice","age":30,"active":true,"hobbies":["reading","hiking"]}
    }
}
 

2. 解析 JSON 数据(对象模型)

java
 
运行
 
 
 
 
import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import java.io.StringReader;

public class JsonParsingExample {
    public static void main(String[] args) {
        String jsonString = "{\"id\":1,\"name\":\"Alice\",\"age\":30,\"hobbies\":[\"reading\",\"hiking\"]}";

        // 解析 JSON 字符串
        try (StringReader reader = new StringReader(jsonString)) {
            JsonObject user = Json.createReader(reader).readObject();
            
            // 提取数据
            int id = user.getInt("id");
            String name = user.getString("name");
            JsonArray hobbies = user.getJsonArray("hobbies");
            
            System.out.println("ID: " + id); // 输出: ID: 1
            System.out.println("Name: " + name); // 输出: Name: Alice
            System.out.println("First hobby: " + hobbies.getString(0)); // 输出: First hobby: reading
        }
    }
}
 

3. 流式处理(适合大型 JSON)

java
 
运行
 
 
 
 
import jakarta.json.Json;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParser;
import java.io.StringReader;
import java.io.StringWriter;

public class JsonStreamingExample {
    // 流式生成 JSON
    public static String generateWithStream() {
        StringWriter writer = new StringWriter();
        try (JsonGenerator generator = Json.createGenerator(writer)) {
            generator.writeStartObject()
                .write("name", "Bob")
                .write("age", 25)
                .writeStartArray("skills")
                    .write("Java")
                    .write("JSON")
                .writeEnd()
            .writeEnd();
        }
        return writer.toString();
    }

    // 流式解析 JSON
    public static void parseWithStream(String json) {
        try (JsonParser parser = Json.createParser(new StringReader(json))) {
            while (parser.hasNext()) {
                JsonParser.Event event = parser.next();
                if (event == JsonParser.Event.KEY_NAME && "name".equals(parser.getString())) {
                    parser.next(); // 移动到值
                    System.out.println("Name: " + parser.getString()); // 输出: Name: Bob
                }
            }
        }
    }

    public static void main(String[] args) {
        String json = generateWithStream();
        parseWithStream(json);
    }
}
 

三、特点与适用场景

  1. 标准化:作为 Jakarta EE 规范的一部分,API 稳定且跨实现兼容。
  2. 轻量级:核心 API 简洁,学习成本低。
  3. 灵活性:同时支持对象模型(简单场景)和流式处理(高性能场景)。
  4. 无依赖:仅依赖 Java 标准库,适合嵌入到各种框架中。

适用场景:

  • 需要遵循 Jakarta EE 规范的企业级应用。
  • 对 JSON 处理有标准化需求,避免绑定特定第三方库的场景。
  • 轻量级 JSON 解析 / 生成(如配置文件处理、简单 API 交互)。

四、与其他 JSON 库的对比

特性Jakarta JSON-PJacksonGson
定位 标准规范(多实现) 功能丰富的第三方库 谷歌推出的第三方库
功能完整性 基础功能完善 支持复杂类型、注解 支持泛型、自动转换
性能 中等 高性能 中高性能
学习成本 低(API 简洁) 中(功能多)
适用场景 标准化需求、轻量场景 复杂 JSON 处理 简单对象映射

五、注意事项

  1. 版本迁移:从 javax.json(Java EE)迁移到 jakarta.json(Jakarta EE)时,需替换包名并更新依赖版本。
  2. 实现选择:API 本身不包含具体实现,必须搭配一个实现库才能运行。
  3. 复杂场景:对于复杂对象映射(如嵌套对象、泛型),JSON-P 不如 Jackson 等库便捷,需手动处理。

Jakarta JSON-P 是 Java 生态中处理 JSON 的标准方案之一,尤其适合遵循 Jakarta EE 规范的项目。如果需要更强大的功能(如自动对象映射),可考虑结合 Jackson 等库使用。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
io.netty 是 Netty 框架的 Maven 坐标,Netty 是一个高性能、异步事件驱动的网络应用框架,主要用于开发可扩展的服务器和客户端网络应用程序。它基于 Java NIO(Non-Blocking I/O)构建,解决了原生 NIO 的复杂性和易用性问题,广泛应用于高性能网络通信场景(如分布式系统、游戏服务器、消息中间件等)。

一、Netty 核心价值

  1. 高性能:基于异步非阻塞 I/O 模型,支持高并发连接,单机可轻松处理数万级 TCP 连接。
  2. 易用性:封装了 Java NIO 的复杂 API,提供简洁的编程模型和丰富的组件。
  3. 可靠性:内置断线重连、流量控制、内存管理等机制,保证网络通信的稳定性。
  4. 可扩展性:采用责任链模式(Pipeline)设计,支持自定义协议和业务逻辑的灵活扩展。
  5. 跨协议支持:内置对 HTTP、WebSocket、TCP、UDP 等主流协议的支持,也可自定义私有协议。

二、核心依赖配置

在 Maven 项目中引入 Netty 核心依赖:

xml
 
 
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.94.Final</version> <!-- 最新稳定版,推荐 4.1.x 系列 -->
</dependency>
 

  • netty-all 包含 Netty 的所有模块(如 netty-buffernetty-transport 等),也可根据需求单独引入子模块。

三、核心组件与架构

Netty 的核心架构基于 事件驱动 和 责任链模式,主要组件包括:

组件功能说明
Channel 网络通道,代表一个打开的连接(如 TCP 连接),用于读写数据。
EventLoop 事件循环,处理 Channel 上的 I/O 事件(如连接、读写),绑定一个线程。
ChannelHandler 处理器,定义业务逻辑(如解码、编码、消息处理),通过 ChannelPipeline 组织。
ChannelPipeline 责任链,按顺序执行多个 ChannelHandler,实现数据的链式处理。
ByteBuf 字节缓冲区,Netty 自定义的高效内存缓冲区,替代 Java NIO 的 ByteBuffer
Bootstrap 启动器,用于配置和启动服务器(ServerBootstrap)或客户端(Bootstrap)。

四、快速入门示例

1. TCP 服务器

java
 
运行
 
 
 
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建两个事件循环组:boss 处理连接请求,worker 处理 I/O 读写
        EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 单线程足够
        EventLoopGroup workerGroup = new NioEventLoopGroup(); // 默认 CPU 核心数 * 2 线程

        try {
            // 2. 配置服务器启动器
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // 使用 NIO 通道
                    .option(ChannelOption.SO_BACKLOG, 128) // 连接队列大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 保持连接
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            // 3. 配置处理器链(责任链)
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加字符串编解码器(自动处理字节与字符串的转换)
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            // 添加自定义业务处理器
                            pipeline.addLast(new ServerHandler());
                        }
                    });

            System.out.println("服务器启动中...");
            // 4. 绑定端口并同步等待启动完成
            ChannelFuture future = bootstrap.bind(8080).sync();
            // 5. 等待服务器关闭(阻塞)
            future.channel().closeFuture().sync();
        } finally {
            // 6. 优雅关闭事件循环组
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    // 自定义业务处理器
    static class ServerHandler extends SimpleChannelInboundHandler<String> {
        // 接收客户端消息时触发
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) {
            System.out.println("收到客户端消息:" + msg);
            // 回复客户端
            ctx.writeAndFlush("服务器已收到:" + msg);
        }

        // 客户端连接成功时触发
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            System.out.println("客户端连接成功:" + ctx.channel().remoteAddress());
        }

        // 发生异常时触发
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close(); // 关闭连接
        }
    }
}
 

2. TCP 客户端

java
 
运行
 
 
 
 
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import java.util.Scanner;

public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建事件循环组(客户端只需一个)
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            // 2. 配置客户端启动器
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class) // 使用 NIO 通道
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            // 3. 配置处理器链(与服务器对应)
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new ClientHandler());
                        }
                    });

            System.out.println("客户端启动中...");
            // 4. 连接服务器
            ChannelFuture future = bootstrap.connect("localhost", 8080).sync();
            Channel channel = future.channel();

            // 5. 从控制台输入消息并发送
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()) {
                String msg = scanner.nextLine();
                channel.writeAndFlush(msg);
            }

            // 6. 等待连接关闭
            future.channel().closeFuture().sync();
        } finally {
            // 7. 优雅关闭
            group.shutdownGracefully();
        }
    }

    // 客户端处理器
    static class ClientHandler extends SimpleChannelInboundHandler<String> {
        // 接收服务器消息时触发
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) {
            System.out.println("收到服务器消息:" + msg);
        }
    }
}
 

五、核心特性解析

1. 异步非阻塞 I/O

Netty 基于 Java NIO 的 Selector 实现多路复用,一个线程可管理多个 Channel,避免传统 BIO 中 “一连接一线程” 的资源浪费,支持高并发。

2. 零拷贝机制

  • ByteBuf 设计:支持切片(slice())、复合缓冲区(CompositeByteBuf),避免数据拷贝。
  • 直接内存:可使用堆外内存(DirectByteBuf),减少 JVM 堆内存与操作系统内核之间的拷贝。

3. 编解码器框架

Netty 提供丰富的编解码器(Codec),简化协议解析:

  • 内置支持:StringCodecProtobufCodecHttpCodecWebSocketCodec 等。
  • 自定义协议:通过继承 ByteToMessageDecoder 和 MessageToByteEncoder 实现私有协议解析。

示例:自定义整数解码器

java
 
运行
 
 
 
 
public class IntDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() >= 4) { // 确保有4个字节(int 类型)
            out.add(in.readInt()); // 读取整数并传递给下一个处理器
        }
    }
}
 

4. 事件驱动模型

Netty 通过 ChannelHandler 处理各类事件(如连接、读写、异常),事件按顺序在 ChannelPipeline 中传递,实现业务逻辑与 I/O 操作的解耦。

六、典型应用场景

  1. 分布式系统通信:如 Dubbo、Spring Cloud Alibaba 等 RPC 框架的底层通信依赖 Netty。
  2. 消息中间件:Kafka、RocketMQ 等使用 Netty 处理高并发的生产者 / 消费者连接。
  3. 游戏服务器:支持大量玩家同时在线的实时交互(如战斗、聊天)。
  4. 物联网(IoT):处理海量设备的 MQTT 协议通信。
  5. Web 服务器:内置的 HttpServer 可用于开发高性能 API 服务或网关。

七、注意事项

  1. 内存管理:ByteBuf 需要手动释放(通过 ReferenceCountUtil.release() 或使用 SimpleChannelInboundHandler 自动释放),否则可能导致内存泄漏。
  2. 线程安全:ChannelHandler 实例可能被多个线程共享,需确保线程安全或通过 @Sharable 注解声明可共享。
  3. 性能调优:合理配置 EventLoopGroup 线程数(通常为 CPU 核心数的 2 倍)、ChannelOption(如 SO_RCVBUFSO_SNDBUF)等参数。

总结

io.netty 对应的 Netty 框架是高性能网络编程的事实标准,通过封装 NIO 复杂性、提供事件驱动模型和丰富组件,大幅降低了高并发网络应用的开发难度。其在分布式系统、消息中间件、游戏服务器等场景中不可或缺,是 Java 开发者构建高性能网络应用的首选工具。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
</dependency>
在 Maven 中,<groupId>net.lingala.zip4j</groupId> 对应的是 Zip4j 库,它是一个功能强大的 Java 压缩 / 解压缩工具,支持 ZIP 格式的创建、读取、加密和解密,尤其对各种压缩算法和加密方式有良好的支持。相比 Java 标准库中的 java.util.zip,Zip4j 提供了更丰富的功能,如 AES 加密、分卷压缩、Unicode 文件名支持等。

一、核心依赖配置

在 pom.xml 中引入 Zip4j 依赖的典型配置如下:

xml
 
 
<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>2.11.5</version> <!-- 版本号可根据最新稳定版调整 -->
</dependency>
 

  • 最新版本可在 Maven 中央仓库 查询。
  • 2.x 版本是目前的主流版本,相比 1.x 有更简洁的 API 和更好的性能。

二、核心特性

  1. 全面的 ZIP 格式支持
    支持标准 ZIP 格式、分卷 ZIP(.z01, .z02...)、加密 ZIP(包括传统 ZIP 加密和 AES 加密)。
  2. 强大的加密功能
    • 支持 AES 加密(128/256 位密钥)和传统 ZIP 加密(PKWARE 加密)。
    • 支持对压缩文件设置密码,保护敏感数据。
  3. 丰富的压缩选项
    • 支持不同压缩级别(从 0 级无压缩到 9 级最高压缩)。
    • 支持多种压缩算法(DEFLATE、BZIP2 等)。
  4. 文件操作灵活性
    • 可向现有 ZIP 文件添加 / 删除文件。
    • 支持 Unicode 文件名,解决中文等特殊字符乱码问题。
    • 支持压缩目录、单个文件或内存中的数据。
  5. 分卷压缩与合并
    可将大文件分割为多个分卷(如每个分卷 100MB),便于传输和存储。

三、常用功能示例

1. 创建普通 ZIP 文件

java
 
运行
 
 
 
 
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;

import java.io.File;

public class ZipExample {
    public static void main(String[] args) throws Exception {
        // 创建 ZIP 文件
        try (ZipFile zipFile = new ZipFile("example.zip")) {
            // 配置压缩参数
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionMethod(CompressionMethod.DEFLATE); // 压缩算法
            parameters.setCompressionLevel(CompressionLevel.NORMAL); // 压缩级别(NORMAL 为默认)

            // 添加文件或目录
            File fileToAdd = new File("data.txt");
            zipFile.addFile(fileToAdd, parameters);

            File directoryToAdd = new File("docs");
            zipFile.addFolder(directoryToAdd, parameters);
        }
        System.out.println("ZIP 文件创建成功");
    }
}
 

2. 创建带密码的加密 ZIP 文件

java
 
运行
 
 
 
 
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;

import java.io.File;

public class EncryptedZipExample {
    public static void main(String[] args) throws Exception {
        // 创建加密 ZIP 文件(密码为 "secret123")
        try (ZipFile zipFile = new ZipFile("encrypted.zip", "secret123".toCharArray())) {
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionLevel(CompressionLevel.MAXIMUM);
            
            // 配置加密方式(AES 256 位)
            parameters.setEncryptFiles(true);
            parameters.setEncryptionMethod(EncryptionMethod.AES);
            parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);

            // 添加文件
            zipFile.addFile(new File("sensitive-data.txt"), parameters);
        }
        System.out.println("加密 ZIP 文件创建成功");
    }
}
 

3. 解压缩 ZIP 文件

java
 
运行
 
 
 
 
import net.lingala.zip4j.ZipFile;

public class UnzipExample {
    public static void main(String[] args) throws Exception {
        // 解压缩普通 ZIP
        try (ZipFile zipFile = new ZipFile("example.zip")) {
            zipFile.extractAll("unzipped-files"); // 解压到指定目录
        }

        // 解压缩加密 ZIP(需提供密码)
        try (ZipFile encryptedZip = new ZipFile("encrypted.zip", "secret123".toCharArray())) {
            encryptedZip.extractAll("unzipped-encrypted");
        }
        System.out.println("解压缩完成");
    }
}
 

4. 分卷压缩(大文件分割)

java
 
运行
 
 
 
 
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;

import java.io.File;

public class SplitZipExample {
    public static void main(String[] args) throws Exception {
        // 创建分卷 ZIP(每个分卷 10MB,10*1024*1024 = 10485760 字节)
        try (ZipFile zipFile = new ZipFile("large-file-split.zip")) {
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionLevel(CompressionLevel.HIGHER);

            // 添加大文件并设置分卷大小
            File largeFile = new File("large-video.mp4");
            zipFile.createSplitZipFileFromFolder(largeFile, parameters, true, 10485760);
        }
        System.out.println("分卷 ZIP 创建成功(生成 .zip, .z01, .z02... 文件)");
    }
}
 

四、优势与适用场景

  1. 优势
    • 功能全面,支持多种 ZIP 特性(加密、分卷、Unicode 等)。
    • API 简洁易用,相比 Java 标准库的 java.util.zip 更直观。
    • 解决了标准库的诸多局限(如中文乱码、加密功能弱等)。
    • 活跃维护,版本更新及时,兼容性好。
  2. 适用场景
    • 需要处理加密 ZIP 文件的场景(如安全传输敏感文件)。
    • 涉及大文件分卷压缩 / 合并的需求(如网盘上传、邮件附件)。
    • 需支持 Unicode 文件名(避免中文等字符乱码)。
    • 对压缩级别和算法有精细控制的场景。

五、注意事项

  1. 异常处理:Zip4j 操作可能抛出 ZipException,需妥善处理(如文件不存在、密码错误、格式损坏等)。
  2. 资源释放:使用 try-with-resources 语法确保 ZipFile 正确关闭,避免文件句柄泄露。
  3. 版本兼容性:2.x 版本与 1.x 版本 API 差异较大,迁移时需调整代码。
  4. 性能考量:高压缩级别(如 9 级)会消耗更多 CPU 资源,平衡压缩率和性能需求。

Zip4j 是 Java 生态中处理 ZIP 文件的首选工具之一,尤其适合需要复杂压缩 / 加密功能的场景。其丰富的特性和易用的 API 使其广泛应用于文件管理、数据备份、文件传输等领域。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
</dependency>
org.apache.axis 是 Apache Axis(Apache eXtensible Interaction System)框架的 Maven 坐标,Axis 是一款用于构建和部署 Web Service 的开源框架,主要基于 SOAP(Simple Object Access Protocol)协议和 WSDL(Web Services Description Language)规范,曾是 Java 领域开发 Web Service 的主流工具。

一、Axis 的核心定位与历史

Axis 诞生于 2000 年代初,是 Apache 基金会为解决早期 Web Service 开发复杂性而推出的框架,主要目标是:

  1. 简化基于 SOAP 协议的 Web Service 开发(服务端发布、客户端调用)。
  2. 自动生成 WSDL 文档(服务描述)和客户端调用代码。
  3. 支持多种数据格式(XML、SOAP 信封)和传输协议(HTTP、SMTP 等)。

Axis 经历了两个主要版本:

  • Axis 1.x:基于 Java 实现,兼容早期 SOAP 1.1 和 WSDL 1.1 规范,使用广泛但架构较旧。
  • Axis 2:完全重写的版本,支持 SOAP 1.2、WSDL 2.0,引入模块化设计,但与 1.x 不兼容。

目前,Axis 框架已逐渐被更现代的技术(如 RESTful API、gRPC)替代,维护活跃度较低。

二、核心依赖配置

1. Axis 1.x 依赖

xml
 
 
<dependency>
    <groupId>org.apache.axis</groupId>
    <artifactId>axis</artifactId>
    <version>1.4</version> <!-- 1.x 系列最新稳定版 -->
</dependency>
<dependency>
    <groupId>org.apache.axis</groupId>
    <artifactId>axis-jaxrpc</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>org.apache.axis</groupId>
    <artifactId>axis-saaj</artifactId>
    <version>1.4</version>
</dependency>
 

2. Axis 2 依赖

xml
 
 
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2</artifactId>
    <version>1.8.2</version> <!-- 2.x 系列最新版 -->
</dependency>
<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-transport-http</artifactId>
    <version>1.8.2</version>
</dependency>
 

三、Axis 1.x 基本使用示例

1. 开发 Web Service 服务端

步骤 1:定义服务接口与实现类

java
 
运行
 
 
 
 
// 服务接口
public interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);
}

// 实现类
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }
    @Override
    public int subtract(int a, int b) {
        return a - b;
    }
}
 

步骤 2:通过部署文件 server-config.wsdd 发布服务
在 WEB-INF 目录下创建配置文件,定义服务名称和映射关系:

xml
 
 
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <service name="CalculatorService" provider="java:RPC">
        <parameter name="className" value="com.example.CalculatorImpl"/>
        <parameter name="allowedMethods" value="add subtract"/> <!-- 允许调用的方法 -->
    </service>
</deployment>
 

步骤 3:部署到 Web 容器
将项目打包为 WAR 包部署到 Tomcat 等容器,通过以下地址访问 WSDL 文档:

plaintext
 
 
http://localhost:8080/项目名/services/CalculatorService?wsdl
 

2. 开发客户端调用服务

方式 1:通过 Axis 工具生成客户端代码
使用 Axis 提供的 WSDL2Java 工具根据 WSDL 生成调用代码:

bash
 
 
java org.apache.axis.wsdl.WSDL2Java http://localhost:8080/项目名/services/CalculatorService?wsdl
 

生成的代码包含 CalculatorServiceCalculatorServiceLocator 等类,直接调用即可:

java
 
运行
 
 
 
 
public class Client {
    public static void main(String[] args) throws Exception {
        // 创建服务定位器
        CalculatorServiceLocator locator = new CalculatorServiceLocator();
        // 获取服务接口
        Calculator service = locator.getCalculatorService();
        // 调用服务方法
        int result = service.add(10, 20);
        System.out.println("10 + 20 = " + result); // 输出 30
    }
}
 

方式 2:手动编写客户端(不生成代码)

java
 
运行
 
 
 
 
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;

public class ManualClient {
    public static void main(String[] args) throws Exception {
        // 创建服务和调用对象
        Service service = new Service();
        Call call = (Call) service.createCall();
        
        // 设置服务地址(WSDL 地址)
        call.setTargetEndpointAddress("http://localhost:8080/项目名/services/CalculatorService");
        // 设置调用的方法名
        call.setOperationName(new QName("http://example.com", "add"));
        
        // 调用服务并获取结果
        int result = (Integer) call.invoke(new Object[]{10, 20});
        System.out.println("结果:" + result);
    }
}
 

四、Axis 的局限性与替代方案

尽管 Axis 曾是 Web Service 开发的主流工具,但存在明显局限性:

  1. 架构老旧:Axis 1.x 基于早期 Java 技术,不支持现代开发模式(如注解配置)。
  2. 性能较差:XML 解析和 SOAP 协议本身开销较大,远不及 REST 或 gRPC 高效。
  3. 配置繁琐:依赖大量 XML 配置文件(如 .wsdd),开发效率低。
  4. 安全性弱:原生对现代安全协议(如 OAuth2)支持不足。

现代替代方案

  • RESTful API:基于 HTTP/JSON,简单轻量,替代大部分 SOAP 场景(推荐)。
  • gRPC:基于 HTTP/2 和 Protocol Buffers,高性能二进制协议,适合微服务通信。
  • Spring Web Services:更现代的 SOAP 框架,基于 Spring 生态,支持注解配置。

五、总结

org.apache.axis 对应的 Axis 框架是早期 Web Service 开发的经典工具,通过封装 SOAP 和 WSDL 简化了跨系统通信。但随着 RESTful API、gRPC 等技术的兴起,其复杂的配置和较低的性能使其逐渐被淘汰。目前,仅在维护老旧系统时可能需要接触 Axis,新项目应优先选择更轻量、高效的现代通信方案。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
</dependency>
在 Maven 中,<groupId>commons-discovery</groupId> 对应的是 Apache Commons Discovery 库,它是 Apache 软件基金会旗下的一个工具类库,主要用于帮助开发者自动发现和加载符合特定接口的实现类,主要用于解决 Java 应用中 "接口与实现分离" 场景下的动态绑定问题。

一、核心依赖配置

在 pom.xml 中引入 Commons Discovery 的典型配置如下:

xml
 
 
<dependency>
    <groupId>commons-discovery</groupId>
    <artifactId>commons-discovery</artifactId>
    <version>0.5</version> <!-- 目前最新稳定版,发布于 2007 年 -->
</dependency>
 

  • 注意:该库自 2007 年发布 0.5 版本后长期未更新,属于维护状态,但仍被一些老旧项目依赖。

二、核心功能与设计目标

Commons Discovery 的核心目标是简化 "接口 -> 实现" 的动态查找过程,避免硬编码实现类名,提高代码的灵活性和可扩展性。其主要功能包括:

  1. 服务发现机制
    根据接口类型,自动在类路径(classpath)中查找符合条件的实现类,支持通过配置文件(如 META-INF/services/ 目录下的 SPI 配置)指定实现。
  2. 类型安全的查找
    提供类型化的 API,避免强制类型转换,例如:
    java
     
    运行
     
     
     
     
    // 查找 MyInterface 接口的实现类
    MyInterface impl = Discovery.lookup(MyInterface.class);
    
     
  3. 支持多种查找策略
    • 按类名直接查找
    • 按接口的默认实现类查找
    • 基于 SPI(Service Provider Interface)规范的查找
    • 结合配置文件的自定义查找规则

三、典型使用场景

Commons Discovery 常用于需要动态加载组件实现的框架或库中,例如:

  1. 日志框架适配
    当框架需要兼容多种日志实现(如 Log4j、JUL)时,可通过 Discovery 自动查找当前环境中的日志实现类。
  2. 数据格式解析器
    定义统一的 Parser 接口,通过 Discovery 自动加载 XML、JSON 等具体解析器的实现。
  3. 插件化系统
    允许第三方通过实现特定接口并配置 SPI 文件,使主程序自动发现并加载插件。

四、简单使用示例

假设我们有一个接口 MessageService,需要动态查找其实现类:

1. 定义接口

java
 
运行
 
 
 
 
public interface MessageService {
    String getMessage();
}
 

2. 提供实现类

java
 
运行
 
 
 
 
public class DefaultMessageService implements MessageService {
    @Override
    public String getMessage() {
        return "Default message";
    }
}
 

3. 通过 SPI 配置实现类

在 src/main/resources/META-INF/services/ 目录下创建文件 com.example.MessageService,内容为实现类的全限定名:

plaintext
 
 
com.example.DefaultMessageService
 

4. 使用 Commons Discovery 查找实现

java
 
运行
 
 
 
 
import org.apache.commons.discovery.tools.DiscoverClass;

public class DiscoveryExample {
    public static void main(String[] args) throws Exception {
        // 查找 MessageService 接口的实现类
        DiscoverClass discover = new DiscoverClass();
        MessageService service = (MessageService) discover.newInstance(MessageService.class);
        
        // 调用实现类的方法
        System.out.println(service.getMessage()); // 输出:Default message
    }
}
 

五、特点与局限性

  1. 特点
    • 简化了接口与实现的动态绑定,减少硬编码。
    • 遵循 Java SPI 规范,易于集成第三方实现。
    • 轻量级,依赖少,适合嵌入到其他框架中。
  2. 局限性
    • 长期未更新:最后一个版本发布于 2007 年,可能存在兼容性问题(如对 Java 8+ 的新特性支持不足)。
    • 功能有限:相比现代依赖注入框架(如 Spring)的组件扫描,功能较为基础。
    • 替代方案多:Java 标准库的 ServiceLoader(自 Java 6 引入)可实现类似功能,且更原生。

六、替代方案

由于 Commons Discovery 长期未维护,建议优先选择以下替代方案:

  1. Java 标准库 ServiceLoader
    原生支持 SPI 机制,无需额外依赖,示例:
    java
     
    运行
     
     
     
     
    import java.util.ServiceLoader;
    
    ServiceLoader<MessageService> loader = ServiceLoader.load(MessageService.class);
    MessageService service = loader.iterator().next(); // 获取第一个实现
    
     
  2. 依赖注入框架
    如 Spring 的 @Service + 组件扫描,或 CDI 规范,可更灵活地管理接口与实现的绑定。
  3. Guice 等轻量级注入工具
    通过模块配置实现接口与实现的映射,支持更复杂的依赖管理。

总结

Commons Discovery 是早期 Java 生态中解决 "接口 - 实现" 动态绑定的工具,但其功能已被 Java 标准库和现代框架覆盖。目前主要用于维护老旧项目,新项目建议优先使用 ServiceLoader 或依赖注入框架。如果需要处理历史代码中对该库的依赖,需注意其与高版本 Java 的兼容性问题。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
wsdl4j 是 WSDL4J(Web Services Description Language for Java)库的 Maven 坐标,它是一个用于解析、创建和操作 WSDL(Web Services Description Language) 文档的 Java 工具库。WSDL 是一种 XML 格式的语言,用于描述 Web Service 的功能、参数、返回值和访问方式,而 WSDL4J 则为 Java 开发者提供了操作 WSDL 文档的 API,广泛用于 Web Service 相关框架(如 Apache Axis、CXF 等)的底层实现。

一、WSDL4J 的核心功能

WSDL4J 主要解决 WSDL 文档的处理问题,核心功能包括:

  1. 解析 WSDL 文档:将 XML 格式的 WSDL 文档解析为 Java 对象模型,便于程序读取服务信息(如服务地址、方法、参数类型等)。
  2. 生成 WSDL 文档:通过 Java API 动态构建 WSDL 结构,并导出为 XML 格式文件。
  3. 验证 WSDL 合法性:检查 WSDL 文档是否符合 WSDL 规范(如 WSDL 1.1),确保其可被其他服务或客户端正确解析。
  4. 支持 WSDL 扩展:允许通过自定义扩展元素扩展 WSDL 文档,满足特定业务需求。

二、依赖配置

在 Maven 项目中引入 WSDL4J 依赖:

xml
 
 
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
    <version>1.6.3</version> <!-- 最新稳定版,广泛使用的版本 -->
</dependency>
 

  • 该版本兼容 WSDL 1.1 规范,是大多数 Web Service 框架(如 Axis、CXF)的默认依赖。

三、核心 API 与使用示例

WSDL4J 的核心 API 围绕 WSDL 文档的结构设计,主要类对应 WSDL 的核心元素(如 <definitions><service><port><binding> 等)。

1. 解析 WSDL 文档

示例:读取 WSDL 文档,提取服务地址和方法信息。

java
 
运行
 
 
 
 
import javax.wsdl.*;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import java.util.Iterator;

public class WSDLParser {
    public static void main(String[] args) {
        try {
            // 1. 创建 WSDL 工厂和读取器
            WSDLFactory factory = WSDLFactory.newInstance();
            WSDLReader reader = factory.newWSDLReader();
            reader.setFeature("javax.wsdl.verbose", false); // 关闭详细日志
            reader.setFeature("javax.wsdl.importDocuments", true); // 允许导入其他文档

            // 2. 解析 WSDL 文档(可从文件或 URL 读取)
            Definition definition = reader.readWSDL("http://localhost:8080/CalculatorService?wsdl");

            // 3. 提取服务信息
            System.out.println("WSDL 目标命名空间:" + definition.getTargetNamespace());

            // 4. 遍历所有服务(<service> 元素)
            Service service = (Service) definition.getServices().values().iterator().next();
            System.out.println("服务名称:" + service.getQName().getLocalPart());

            // 5. 提取服务端口(<port> 元素,包含访问地址)
            Iterator<?> ports = service.getPorts().values().iterator();
            while (ports.hasNext()) {
                Port port = (Port) ports.next();
                System.out.println("端口名称:" + port.getName());
                
                // 获取访问地址(SOAP 服务通常在 <address> 元素中)
                Address address = (Address) port.getExtensibilityElements().get(0);
                System.out.println("服务地址:" + address.getLocationURI());
            }

            // 6. 提取绑定信息(<binding> 元素,包含方法和协议)
            Binding binding = (Binding) definition.getBindings().values().iterator().next();
            System.out.println("绑定名称:" + binding.getQName().getLocalPart());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

2. 生成 WSDL 文档

示例:通过 API 动态构建 WSDL 文档并导出为 XML 文件。

java
 
运行
 
 
 
 
import javax.wsdl.*;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLWriter;
import javax.xml.namespace.QName;
import java.io.FileOutputStream;
import java.net.URI;

public class WSDLGenerator {
    public static void main(String[] args) {
        try {
            // 1. 创建 WSDL 工厂和文档定义
            WSDLFactory factory = WSDLFactory.newInstance();
            Definition definition = factory.newDefinition();
            
            // 2. 设置基本信息(目标命名空间、名称)
            String targetNamespace = "http://example.com/calculator";
            definition.setTargetNamespace(targetNamespace);
            definition.setQName(new QName(targetNamespace, "CalculatorService"));

            // 3. 创建类型(<types> 元素,定义数据类型)
            Types types = factory.newTypes();
            definition.setTypes(types);

            // 4. 创建消息(<message> 元素,定义方法参数和返回值)
            Message inputMessage = factory.newMessage();
            inputMessage.setQName(new QName(targetNamespace, "AddInputMessage"));
            // 省略参数定义...(需添加 Part 元素描述参数)
            definition.addMessage(inputMessage);

            // 5. 创建端口类型(<portType> 元素,定义服务接口)
            PortType portType = factory.newPortType();
            portType.setQName(new QName(targetNamespace, "CalculatorPortType"));
            // 省略操作定义...(添加 Operation 元素描述方法)
            definition.addPortType(portType);

            // 6. 创建服务(<service> 元素,定义服务访问地址)
            Service service = factory.newService();
            service.setQName(new QName(targetNamespace, "CalculatorService"));
            Port port = factory.newPort();
            port.setName("CalculatorPort");
            port.setBinding(factory.newBinding()); // 绑定协议信息
            // 设置访问地址
            Address address = factory.newAddress();
            address.setLocationURI("http://localhost:8080/CalculatorService");
            port.addExtensibilityElement(address);
            service.addPort(port);
            definition.addService(service);

            // 7. 导出 WSDL 文档到文件
            WSDLWriter writer = factory.newWSDLWriter();
            try (FileOutputStream fos = new FileOutputStream("calculator.wsdl")) {
                writer.writeWSDL(definition, fos);
            }
            System.out.println("WSDL 文档生成成功!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

四、典型应用场景

  1. Web Service 框架底层:Apache Axis、CXF 等框架使用 WSDL4J 解析 WSDL 文档,生成服务端和客户端代码。
  2. WSDL 文档校验工具:开发工具(如 IDEA、Eclipse)集成 WSDL4J 验证用户编写的 WSDL 是否符合规范。
  3. 动态服务注册:在服务注册中心(如 UDDI)中,使用 WSDL4J 解析服务元数据并存储。
  4. 自定义 WSDL 生成:当默认生成的 WSDL 不符合需求时,通过 WSDL4J 手动调整 WSDL 结构。

五、局限性与替代方案

  1. 局限性:
    • 仅支持 WSDL 1.1 规范,不支持 WSDL 2.0(较新的规范)。
    • API 设计较老旧,使用起来不够直观,需要熟悉 WSDL 的 XML 结构。
    • 随着 RESTful API 的流行,WSDL 的使用场景减少,间接降低了 WSDL4J 的需求。
  2. 替代方案:
    • Apache CXF 的 WSDL 工具:提供更高级的 WSDL 处理 API,兼容 WSDL4J 并支持更多功能。
    • JAX-WS 内置工具:Java EE 中的 wsimport 等工具可自动处理 WSDL,无需直接操作 WSDL4J API。

总结

wsdl4j 对应的 WSDL4J 是 Java 领域处理 WSDL 文档的经典库,为 Web Service 框架提供了底层的 WSDL 解析和生成能力。尽管随着 RESTful API 的兴起,WSDL 的使用场景有所减少,但在维护基于 SOAP 的老旧系统时,WSDL4J 仍是重要的依赖。对于需要直接操作 WSDL 文档的场景(如自定义服务框架),WSDL4J 提供了可靠的 API 支持。

----------------------------------------------------------------------------------------------------------------

 

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-autoconfigure</artifactId>
</dependency>
在 Maven 中,<groupId>org.apache.cxf</groupId> 对应的是 Apache CXF 框架,它是一个开源的 Web 服务开发框架,支持多种 Web 服务标准(如 SOAP、RESTful、XML/HTTP 等),可用于构建和部署高性能、可扩展的服务端和客户端应用。CXF 结合了代码优先(Code-First)和契约优先(Contract-First)两种开发模式,广泛应用于企业级服务集成场景。

一、核心模块与依赖

CXF 包含多个模块,分别对应不同的功能,可根据需求选择性引入:

1. 核心依赖(基础功能)

xml
 
 
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-core</artifactId>
    <version>3.6.2</version> <!-- 版本号可根据最新稳定版调整 -->
</dependency>
 

2. 常用功能模块

  • SOAP 服务支持(传统 WebService):
    xml
     
     
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>3.6.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>3.6.2</version>
    </dependency>
    
     
  • RESTful 服务支持(JAX-RS):
    xml
     
     
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxrs</artifactId>
        <version>3.6.2</version>
    </dependency>
    <!-- JSON 支持(可选,如 Jackson) -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-rs-extension-providers</artifactId>
        <version>3.6.2</version>
    </dependency>
    
     
  • 客户端生成工具(根据 WSDL 生成代码):
    xml
     
     
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-codegen-plugin</artifactId>
        <version>3.6.2</version>
    </dependency>
    
     

二、核心特性

  1. 多协议支持
    • 支持 SOAP 1.1/1.2、RESTful(JAX-RS 2.1)、XML-RPC、JSON-RPC 等。
    • 支持 HTTP、JMS、Servlet、WebSocket 等传输协议。
  2. 开发模式灵活
    • 代码优先:通过 Java 类和注解定义服务接口,自动生成 WSDL 或 REST 契约。
    • 契约优先:基于 WSDL 或 OpenAPI 文档生成 Java 代码,确保接口与契约严格一致。
  3. 企业级特性
    • 支持 WS-* 标准(如安全、事务、可靠消息传递)。
    • 集成 Spring、CDI 等依赖注入框架,便于扩展和配置。
    • 提供监控、日志、拦截器等可扩展机制。
  4. 跨语言互操作性
    生成的服务可被不同语言(如 Java、C#、Python)的客户端调用,遵循标准协议。

三、典型使用示例

1. 创建 RESTful 服务(JAX-RS)

Step 1:定义服务接口

java
 
运行
 
 
 
 
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/users")
public interface UserService {
    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    User getUser(@PathParam("id") String id);
}
 

Step 2:实现服务

java
 
运行
 
 
 
 
public class UserServiceImpl implements UserService {
    @Override
    public User getUser(String id) {
        // 模拟查询用户
        return new User(id, "Alice", "alice@example.com");
    }
}
 

Step 3:发布服务(结合 Spring)

xml
 
 
<!-- spring-cxf.xml 配置 -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:cxf="http://cxf.apache.org/core"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs">
       
    <jaxrs:server id="userService" address="/api">
        <jaxrs:serviceBeans>
            <bean class="com.example.UserServiceImpl"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <!-- 配置 JSON 序列化器 -->
            <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
        </jaxrs:providers>
    </jaxrs:server>
</beans>
 

Step 4:访问服务
通过 http://localhost:8080/api/users/1 即可获取 JSON 格式的用户数据。

2. 创建 SOAP 服务(JAX-WS)

Step 1:定义服务接口(带 JAX-WS 注解)

java
 
运行
 
 
 
 
import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService(targetNamespace = "http://example.com/hello")
public interface HelloService {
    @WebMethod
    String sayHello(String name);
}
 

Step 2:实现服务

java
 
运行
 
 
 
 
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name + "!";
    }
}
 

Step 3:发布服务

java
 
运行
 
 
 
 
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

public class SoapServer {
    public static void main(String[] args) {
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        factory.setServiceClass(HelloServiceImpl.class);
        factory.setAddress("http://localhost:8080/hello");
        factory.create();
        System.out.println("SOAP 服务已发布:http://localhost:8080/hello?wsdl");
    }
}
 

Step 4:生成客户端代码
通过 CXF 工具根据 WSDL 生成客户端:

bash
 
 
wsdl2java -d src/main/java http://localhost:8080/hello?wsdl
 

Step 5:调用服务

java
 
运行
 
 
 
 
public class SoapClient {
    public static void main(String[] args) {
        HelloService service = new HelloServiceImplService().getHelloServiceImplPort();
        String result = service.sayHello("World");
        System.out.println(result); // 输出:Hello, World!
    }
}
 

四、适用场景与优势

  1. 适用场景
    • 企业级服务集成(如 ERP、CRM 系统间的接口对接)。
    • 需要遵循 SOAP 标准的跨组织服务通信。
    • 构建 RESTful API 并需要丰富的扩展功能(如安全、监控)。
    • legacy 系统的 WebService 迁移与维护。
  2. 优势
    • 全面支持 Web 服务标准,兼容性强。
    • 与 Spring 等框架无缝集成,开发效率高。
    • 提供灵活的拦截器机制,便于日志、安全等横切功能实现。
    • 支持代码生成工具,降低客户端开发成本。

五、注意事项

  1. 版本兼容性:CXF 3.x 支持 Java 8+,4.x 需 Java 11+,升级时需注意环境适配。
  2. 性能考量:默认配置可能不适合高并发场景,需优化线程池、缓存等参数。
  3. 安全配置:生产环境需启用 HTTPS、WS-Security 或 OAuth2 等安全机制。
  4. 替代方案:对于纯 RESTful 服务,可考虑更轻量的框架(如 Spring Boot + Spring MVC);对于微服务场景,可结合 gRPC 等现代协议。

Apache CXF 是企业级 Web 服务开发的成熟选择,尤其在需要兼容传统 SOAP 标准或复杂服务治理的场景中表现突出。其丰富的功能和灵活性使其在金融、电商等领域得到广泛应用。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
io.jsonwebtoken 是 JJWT(Java JWT) 库的 Maven 坐标,JJWT 是一个简洁易用的 Java 库,用于创建和验证 JWT(JSON Web Token)。JWT 是一种紧凑的、URL 安全的令牌格式,常用于在网络应用间传递声明信息(如用户身份、权限等),广泛应用于身份认证、信息交换等场景。

一、JJWT 核心价值

  1. 简化 JWT 操作:封装了 JWT 的创建、签名、验证等复杂逻辑,提供直观的 API。
  2. 支持多种算法:内置 HMAC(HS256/HS384/HS512)、RSA(RS256/RS384/RS512)等签名算法。
  3. 丰富的声明支持:支持标准声明(如过期时间 exp、签发时间 iat)和自定义声明。
  4. 类型安全:基于泛型和 builder 模式,避免字符串拼接错误,提升开发效率。

二、依赖配置

在 Maven 项目中引入 JJWT 核心依赖:

xml
 
 
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version> <!-- 最新稳定版,兼容 Java 8+ -->
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId> <!-- 用于 JSON 序列化,可选 -->
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
 

  • jjwt-api:核心 API 接口。
  • jjwt-impl:API 实现,运行时依赖。
  • jjwt-jackson:集成 Jackson 处理 JSON,支持复杂对象的序列化(可选)。

三、核心功能与示例

1. 创建 JWT(生成令牌)

使用 Jwts.builder() 构建 JWT,设置声明和签名算法:

java
 
运行
 
 
 
 
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtCreator {
    // 生成签名密钥(HS256 算法需要 256 位密钥,即 32 字节)
    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    public static String generateToken(Long userId, String username) {
        // 1. 设置过期时间(例如:24小时后过期)
        long expirationTime = System.currentTimeMillis() + 24 * 60 * 60 * 1000;
        Date expirationDate = new Date(expirationTime);

        // 2. 定义自定义声明(可选)
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("role", "USER"); // 用户角色

        // 3. 构建 JWT
        return Jwts.builder()
                // 设置标准声明
                .setSubject(username) // 主题(通常是用户名)
                .setIssuedAt(new Date()) // 签发时间
                .setExpiration(expirationDate) // 过期时间
                // 设置自定义声明
                .addClaims(claims)
                // 签名(使用密钥和算法)
                .signWith(SECRET_KEY, SignatureAlgorithm.HS256)
                // 压缩为字符串
                .compact();
    }

    public static void main(String[] args) {
        String token = generateToken(1L, "zhangsan");
        System.out.println("生成的 JWT:" + token);
    }
}
 

输出示例:

plaintext
 
 
生成的 JWT:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ6aGFuZ3NhbiIsImlhdCI6MTY5NDk...
 

2. 解析与验证 JWT(验证令牌)

使用 Jwts.parserBuilder() 解析 JWT,验证签名和声明:

java
 
运行
 
 
 
 
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.security.Key;

public class JwtValidator {
    // 与生成令牌时使用的密钥必须一致
    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    public static Claims validateToken(String token) {
        try {
            // 1. 构建解析器并设置签名密钥
            Jws<Claims> jws = Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY) // 验证签名的密钥
                    .build()
                    // 2. 解析令牌(自动验证签名和过期时间)
                    .parseClaimsJws(token);

            // 3. 返回解析后的声明
            return jws.getBody();
        } catch (Exception e) {
            // 验证失败(如签名无效、令牌过期等)
            throw new RuntimeException("无效的 JWT 令牌:" + e.getMessage());
        }
    }

    public static void main(String[] args) {
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ6aGFuZ3NhbiIsImlhdCI6MTY5NDk...";
        try {
            Claims claims = validateToken(token);
            System.out.println("用户名:" + claims.getSubject());
            System.out.println("用户ID:" + claims.get("userId", Long.class));
            System.out.println("过期时间:" + claims.getExpiration());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

验证逻辑说明:

  • 自动验证签名是否匹配(防止令牌被篡改)。
  • 自动验证 exp 声明(若令牌已过期,抛出 ExpiredJwtException)。
  • 可通过 setAllowedClockSkewSeconds() 设置时钟偏差容忍(如允许 30 秒误差)。

3. 自定义声明与复杂对象

JJWT 支持自定义复杂对象作为声明(需引入 jjwt-jackson 依赖):

java
 
运行
 
 
 
 
import com.fasterxml.jackson.annotation.JsonProperty;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtCustomObject {
    // 自定义对象
    static class UserInfo {
        @JsonProperty("user_id")
        private Long userId;
        private String username;
        private String role;

        // 构造函数、getter/setter 略
    }

    private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    public static String generateTokenWithObject(UserInfo userInfo) {
        return Jwts.builder()
                .setSubject(userInfo.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 3600_000)) // 1小时过期
                .claim("user_info", userInfo) // 存入自定义对象
                .signWith(SECRET_KEY)
                .compact();
    }

    public static UserInfo parseUserInfo(String token) {
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
        // 解析自定义对象
        return claims.get("user_info", UserInfo.class);
    }
}
 

四、核心类与算法

1. 核心类

  • Jwts:入口类,提供 builder()(创建 JWT)和 parserBuilder()(解析 JWT)方法。
  • Claims:存储 JWT 中的声明信息(标准声明 + 自定义声明)。
  • Key:签名密钥,通过 Keys 工具类生成(如 Keys.secretKeyFor(HS256))。
  • SignatureAlgorithm:签名算法枚举(如 HS256RS256 等)。

2. 常用签名算法

算法类型示例算法特点适用场景
HMAC HS256、HS512 对称加密,密钥需双方共享 内部系统、信任环境
RSA RS256、RS512 非对称加密,使用私钥签名、公钥验证 分布式系统、跨组织通信
ECDSA ES256、ES512 椭圆曲线加密,密钥更短但安全性更高 移动应用、资源受限场景

五、安全最佳实践

  1. 密钥管理:
    • 对称密钥(HMAC)需保密,避免硬编码,建议通过环境变量或密钥管理服务存储。
    • 非对称密钥(RSA)需定期轮换,私钥严格保密,公钥可公开。
  2. 令牌有效期:
    • 设置合理的过期时间(如 15-30 分钟),减少令牌被盗用的风险。
    • 长期登录场景可使用 “刷新令牌” 机制(单独生成长期有效的刷新令牌)。
  3. 避免敏感信息:
    • JWT 内容仅经过 Base64 编码(可解码),不要存储密码等敏感信息。
  4. 签名验证:
    • 生产环境必须验证签名,禁止使用无签名的 JWT(none 算法)。

六、典型应用场景

  1. 身份认证:用户登录后生成 JWT,后续请求携带令牌验证身份(替代 Session)。
  2. 授权控制:在令牌中包含用户权限信息,服务端通过解析令牌判断是否有权限。
  3. 分布式系统通信:跨服务调用时传递身份信息,避免多次认证。
  4. 信息交换:在信任的 parties 之间安全传递声明信息(签名确保信息未被篡改)。

总结

io.jsonwebtoken 对应的 JJWT 库是 Java 开发中处理 JWT 的首选工具,其简洁的 API 大幅降低了 JWT 的使用门槛。通过支持多种签名算法和灵活的声明机制,JJWT 满足了从简单身份认证到复杂分布式系统的需求。使用时需重点关注密钥安全和令牌有效期管理,以确保 JWT 机制的安全性。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
在 Maven 中,<groupId>com.baomidou</groupId> 对应的是国内团队苞米豆(Baomidou)开发的一系列 Java 开发工具库,主要聚焦于简化 Java 企业级开发,尤其在 ORM 框架、权限管理、代码生成等领域有广泛应用。其中最知名的是 MyBatis-Plus,一款增强型 MyBatis 框架。

一、核心项目与依赖

1. MyBatis-Plus(ORM 框架)

MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 基础上只做增强不做改变,简化 CRUD 操作,提供丰富的查询功能和代码生成能力。

Maven 依赖:

xml
 
 
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.5</version> <!-- 最新稳定版,适配 Spring Boot -->
</dependency>
 

核心特性:

  • CRUD 接口:内置 BaseMapper 和 IService,无需编写 SQL 即可实现基本操作。
  • 条件构造器:通过 QueryWrapper 灵活组装查询条件,替代 XML 中的动态 SQL。
  • 代码生成器:自动生成 Entity、Mapper、Service、Controller 等代码,减少重复劳动。
  • 分页插件:一键集成分页功能,支持多种数据库。
  • 逻辑删除:通过注解实现逻辑删除(更新删除标记),无需修改 SQL。

2. Shiro-Plus(权限框架)

基于 Apache Shiro 的增强工具,简化权限配置,提供注解式权限控制、动态权限管理等功能。

Maven 依赖:

xml
 
 
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>shiro-plus-boot-starter</artifactId>
    <version>1.0.2</version>
</dependency>
 

3. Dynamic-Datasource(动态数据源)

用于实现多数据源动态切换,支持主从分离、读写分离,适配 Spring Boot。

Maven 依赖:

xml
 
 
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>
 

二、MyBatis-Plus 核心使用示例

1. 定义实体类

java
 
运行
 
 
 
 
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

@TableName("user") // 映射数据库表名
public class User {
    @TableId(type = IdType.AUTO) // 主键自增
    private Long id;
    private String name;
    private Integer age;
    private String email;
    // getter/setter 省略
}
 

2. 定义 Mapper 接口

java
 
运行
 
 
 
 
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

// 继承 BaseMapper 获得基础 CRUD 方法
public interface UserMapper extends BaseMapper<User> {
    // 无需编写方法,BaseMapper 已包含常用操作
}
 

3. 服务层使用

java
 
运行
 
 
 
 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 继承 ServiceImpl 获得更丰富的 CRUD 方法
    public User getUserByName(String name) {
        // 使用条件构造器查询
        return baseMapper.selectOne(
            new QueryWrapper<User>().eq("name", name)
        );
    }
}
 

4. 分页查询示例

java
 
运行
 
 
 
 
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

public IPage<User> getUsersByPage(int pageNum, int pageSize) {
    Page<User> page = new Page<>(pageNum, pageSize);
    // 分页查询年龄大于 18 的用户
    return baseMapper.selectPage(page, 
        new QueryWrapper<User>().gt("age", 18)
    );
}
 

三、其他实用工具

  1. MyBatis-Plus Generator
    代码生成器,通过配置自动生成全套代码:
    xml
     
     
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.5</version>
    </dependency>
    
     
  2. Lock4j
    分布式锁框架,支持 Redis、Zookeeper 等多种锁实现:
    xml
     
     
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>lock4j-redis-spring-boot-starter</artifactId>
        <version>2.2.4</version>
    </dependency>
    
     

四、优势与适用场景

  1. 优势
    • 本土化支持:由国内团队开发,文档和社区支持完善(中文为主)。
    • 简化开发:大幅减少重复代码,尤其适合 CRUD 密集型业务。
    • 兼容性好:基于 MyBatis、Shiro 等成熟框架,学习成本低。
    • 活跃更新:版本迭代快,持续修复问题并增加新功能。
  2. 适用场景
    • 基于 MyBatis 的 Java Web 项目,需简化数据库操作。
    • 快速开发中小型业务系统,减少样板代码。
    • 需要多数据源、分布式锁等企业级功能的场景。

五、注意事项

  1. 版本适配:MyBatis-Plus 版本需与 MyBatis、Spring Boot 版本兼容(参考官方文档)。
  2. SQL 可控性:过度依赖自动生成的 SQL 可能导致复杂查询难以优化,需灵活结合 XML 编写 SQL。
  3. 学习成本:虽然简化了操作,但建议先掌握 MyBatis 基础,避免 "黑盒" 使用。

----------------------------------------------------------------------------------------------------------------

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
在 Maven 中,<groupId>org.jacoco</groupId> 对应的是 JaCoCo(Java Code Coverage) 工具,它是一个开源的代码覆盖率分析工具,主要用于检测单元测试、集成测试等对代码的覆盖程度,帮助开发者发现未被测试覆盖的代码片段,从而提升测试质量。

一、核心模块与依赖

JaCoCo 主要通过 Maven 插件形式集成到项目中,核心模块包括代码覆盖率检测和报告生成。

1. Maven 插件配置

在 pom.xml 中配置 JaCoCo 插件,用于执行测试时收集覆盖率数据并生成报告:

xml
 
 
<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.10</version> <!-- 最新稳定版 -->
            <executions>
                <!-- 预测试阶段初始化覆盖率收集器 -->
                <execution>
                    <id>prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <!-- 测试后生成覆盖率报告 -->
                <execution>
                    <id>report</id>
                    <phase>test</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
 

二、核心功能与覆盖率指标

JaCoCo 能够检测多种代码覆盖率指标,帮助全面评估测试效果:

  1. 行覆盖率(Line Coverage)
    被测试执行过的代码行数占总代码行数的比例。
  2. 分支覆盖率(Branch Coverage)
    被测试执行过的条件分支(如 ifswitch)占总分支数的比例(例如 if-else 语句中两个分支是否都被执行)。
  3. 方法覆盖率(Method Coverage)
    被测试调用过的方法占总方法数的比例(至少执行一次)。
  4. 类覆盖率(Class Coverage)
    被测试覆盖过的类占总类数的比例(至少有一个方法被执行)。
  5. 指令覆盖率(Instruction Coverage)
    被测试执行过的 Java 字节码指令占总指令数的比例(最基础的覆盖率指标)。

三、使用流程

1. 集成插件

按上述配置在 pom.xml 中添加 JaCoCo 插件。

2. 执行测试并生成报告

通过 Maven 命令执行测试,JaCoCo 会自动收集覆盖率数据并生成报告:

bash
 
 
mvn test
 

3. 查看报告

报告默认生成在 target/site/jacoco/ 目录下,打开 index.html 即可查看可视化结果:

  • 以不同颜色标记代码覆盖情况(绿色:已覆盖,红色:未覆盖,黄色:部分覆盖)。
  • 支持按包、类、方法层级钻取详情,定位未覆盖的代码行。

四、高级配置示例

1. 设置覆盖率门槛(强制检查)

可配置最低覆盖率要求,未达标则构建失败:

xml
 
 
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.10</version>
    <executions>
        <!-- 增加检查阶段 -->
        <execution>
            <id>check</id>
            <phase>test</phase>
            <goals>
                <goal>check</goal>
            </goals>
            <configuration>
                <rules>
                    <rule>
                        <element>PACKAGE</element>
                        <limits>
                            <!-- 行覆盖率最低 80% -->
                            <limit>
                                <counter>LINE</counter>
                                <value>COVEREDRATIO</value>
                                <minimum>0.8</minimum>
                            </limit>
                            <!-- 分支覆盖率最低 70% -->
                            <limit>
                                <counter>BRANCH</counter>
                                <value>COVEREDRATIO</value>
                                <minimum>0.7</minimum>
                            </limit>
                        </limits>
                    </rule>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>
 

2. 排除不需要检测的代码

忽略测试类、生成的代码等:

xml
 
 
<configuration>
    <excludes>
        <exclude>com/example/dto/**/*</exclude> <!-- 排除 DTO 包 -->
        <exclude>**/*Test.class</exclude> <!-- 排除测试类 -->
    </excludes>
</configuration>
 

五、优势与适用场景

  1. 优势
    • 全面的覆盖率指标:支持多种维度的覆盖率分析,满足不同场景需求。
    • 易用性:与 Maven、Gradle 等构建工具无缝集成,配置简单。
    • 可视化报告:HTML 报告直观展示覆盖情况,便于定位未测试代码。
    • 兼容性:支持 Java 5+ 所有版本,适配主流测试框架(JUnit、TestNG 等)。
  2. 适用场景
    • 单元测试质量评估:确保核心业务逻辑被充分测试。
    • 持续集成(CI)流程:作为代码质量门禁,强制达到最低覆盖率。
    • 重构与代码优化:验证重构后测试是否仍能覆盖关键路径。

六、注意事项

  1. 覆盖率并非唯一指标:高覆盖率不代表测试质量高(如仅执行代码但未验证结果),需结合测试用例设计。
  2. 性能影响:收集覆盖率数据会轻微降低测试执行速度,建议仅在开发和 CI 阶段启用。
  3. 合理设置门槛:根据项目类型调整覆盖率要求(如核心库需更高覆盖率,业务代码可适当放宽)。

JaCoCo 是 Java 生态中最常用的代码覆盖率工具之一,广泛应用于各类项目的测试流程中。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
org.freemarker 是 FreeMarker 模板引擎的 Maven 坐标,FreeMarker 是一款基于模板和数据模型生成文本输出(如 HTML、XML、邮件内容、配置文件等)的通用模板引擎。它独立于 Web 容器,可在任意 Java 环境中使用,广泛应用于动态网页生成、代码生成、报表导出等场景。

一、FreeMarker 核心价值

  1. 模板与数据分离:模板专注于输出格式,数据模型专注于业务逻辑,降低耦合度。
  2. 强大的模板语法:支持条件判断、循环、变量引用、宏定义等,满足复杂文本生成需求。
  3. 跨平台与独立性:不依赖特定 Web 框架或容器,可在 Java 应用、命令行工具等多种环境中使用。
  4. 高性能:模板解析后可缓存,重复使用时无需重新解析,提升生成效率。
  5. 丰富的集成能力:与 Spring、Struts 等主流框架无缝集成,也可作为独立工具使用。

二、依赖配置

在 Maven 项目中引入 FreeMarker 依赖:

xml
 
 
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.32</version> <!-- 最新稳定版,兼容 Java 8+ -->
</dependency>
 

三、核心概念与工作流程

1. 核心概念

  • 模板(Template):包含静态文本和动态指令(如 ${variable}#if#list)的文本文件(通常以 .ftl 为后缀)。
  • 数据模型(Data Model):Java 对象的集合(如 Map、POJO),提供模板所需的动态数据。
  • 模板引擎(Template Engine):FreeMarker 核心组件,负责将模板与数据模型结合,生成最终文本。

2. 工作流程

  1. 准备数据模型:将需要动态填充的数据封装到 Java 对象(如 Map)中。
  2. 加载模板:从文件系统、类路径或数据库加载 FreeMarker 模板。
  3. 合并模板与数据:模板引擎解析模板中的指令,用数据模型中的值替换动态部分。
  4. 输出结果:生成最终文本(如写入文件、响应到浏览器)。

四、基本使用示例

1. 生成 HTML 页面

步骤 1:创建模板文件(user.ftl,放在 src/main/resources/templates 目录)

html
 
预览
 
 
 
 
<!DOCTYPE html>
<html>
<head>
    <title>用户信息</title>
</head>
<body>
    <h1>用户列表</h1>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
        <!-- 循环遍历用户列表 -->
        <#list users as user>
        <tr>
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.age}</td>
        </tr>
        </#list>
    </table>
    
    <!-- 条件判断 -->
    <#if users?size == 0>
        <p>暂无用户数据</p>
    </#if>
</body>
</html>
 

步骤 2:编写 Java 代码加载模板并生成 HTML

java
 
运行
 
 
 
 
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FreeMarkerDemo {
    public static void main(String[] args) throws IOException, TemplateException {
        // 1. 配置 FreeMarker
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
        // 设置模板目录(从类路径加载)
        cfg.setClassForTemplateLoading(FreeMarkerDemo.class, "/templates");
        // 设置默认编码
        cfg.setDefaultEncoding("UTF-8");

        // 2. 准备数据模型
        Map<String, Object> dataModel = new HashMap<>();
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "张三", 20));
        users.add(new User(2L, "李四", 25));
        dataModel.put("users", users);

        // 3. 加载模板
        Template template = cfg.getTemplate("user.ftl");

        // 4. 合并模板与数据,生成 HTML 文件
        try (FileWriter writer = new FileWriter(new File("user.html"))) {
            template.process(dataModel, writer);
        }
        System.out.println("HTML 生成成功!");
    }

    // 用户实体类
    static class User {
        private Long id;
        private String name;
        private Integer age;
        // 构造函数、getter/setter 略
    }
}
 

生成的 user.html 部分内容:

html
 
预览
 
 
 
 
<table border="1">
    <tr>
        <th>ID</th>
        <th>姓名</th>
        <th>年龄</th>
    </tr>
    <tr>
        <td>1</td>
        <td>张三</td>
        <td>20</td>
    </tr>
    <tr>
        <td>2</td>
        <td>李四</td>
        <td>25</td>
    </tr>
</table>
 

2. 核心模板语法

FreeMarker 模板语法简洁直观,以下是常用指令:

语法作用说明
${variable} 输出变量值(如 ${user.name} 访问对象属性)。
#if/#elseif/#else 条件判断:
<#if age > 18>成年人<#else>未成年人</#if>
#list 循环遍历集合:
<#list users as user>${user.name}</#list>
#assign 定义变量:
<#assign total = 100> 或 <#assign user = {"name":"张三"}>
#macro 定义宏(可复用的模板片段):
<#macro greet>Hello</#macro><@greet/>
?? 判断变量是否存在:
<#if user??>存在<#else>不存在</#if>
! 设置默认值:
${user.name!"未知"}(若 name 为 null 则显示 “未知”)

五、高级特性

1. 宏与自定义指令

通过 #macro 定义可复用的模板片段,类似函数:

ftl
 
 
<#macro userInfo user>
    <div class="user">
        <p>姓名:${user.name}</p>
        <p>年龄:${user.age}</p>
    </div>
</#macro>

<!-- 调用宏 -->
<@userInfo user=users[0]/>
<@userInfo user=users[1]/>
 

2. 模板继承(#include#import#nested

  • #include:引入其他模板的内容(如公共头部、底部):
    ftl
     
     
    <#include "header.ftl"> <!-- 引入头部模板 -->
    <div>主体内容</div>
    <#include "footer.ftl"> <!-- 引入底部模板 -->
    
     
  • 模板继承(通过 #import 和 #nested 实现):适合构建统一布局的页面。

3. 自定义指令与方法

通过 Java 代码扩展 FreeMarker 功能,例如自定义格式化函数:

java
 
运行
 
 
 
 
// 注册自定义方法
cfg.setSharedVariable("formatDate", new TemplateMethodModelEx() {
    @Override
    public Object exec(List args) {
        Date date = (Date) args.get(0);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }
});
 

在模板中使用:

ftl
 
 
注册时间:${formatDate(user.regTime)}
 

六、典型应用场景

  1. 动态网页生成:与 Spring MVC 集成,作为视图解析器生成 HTML 页面(替代 JSP)。
  2. 代码生成工具:根据模板生成 Java 类、XML 配置文件等(如 MyBatis Generator 底层使用 FreeMarker)。
  3. 邮件模板:生成格式化的邮件内容(如验证码邮件、通知邮件)。
  4. 报表导出:生成 PDF、Word 等格式的报表(结合 POI 等库)。
  5. 配置文件生成:动态生成环境特定的配置文件(如 application-dev.ymlapplication-prod.yml)。

七、与其他模板引擎的对比

模板引擎特点适用场景
FreeMarker 功能全面、独立于 Web 框架、语法灵活 通用场景(网页、代码生成、邮件等)
Thymeleaf 基于 HTML 自然模板、适合前端开发 Spring Boot 网页开发(推荐)
Velocity 语法简单、性能较好但已停止维护 老旧系统维护
JSP 与 Servlet 容器耦合、功能有限 传统 Java Web 项目(逐渐被替代)

总结

org.freemarker 对应的 FreeMarker 是一款功能强大的通用模板引擎,通过模板与数据模型的分离,简化了动态文本生成的开发流程。其丰富的语法和灵活的扩展能力,使其在网页开发、代码生成、报表导出等场景中被广泛应用。尽管在现代 Spring Boot 项目中 Thymeleaf 更受欢迎,但 FreeMarker 在非 Web 场景(如代码生成)和传统项目中仍具有不可替代的地位。

----------------------------------------------------------------------------------------------------------------

<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
</dependency>
在 Maven 中,<groupId>commons-net</groupId> 对应的是 Apache Commons Net 库,它是 Apache 软件基金会旗下的一个开源工具库,提供了一系列用于处理网络协议的 Java 类,简化了常见网络操作的开发。该库支持多种主流网络协议,使开发者无需深入了解协议细节即可实现相关功能。

一、核心依赖配置

在 pom.xml 中引入 Commons Net 的典型配置如下:

xml
 
 
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.10.0</version> <!-- 版本号可根据最新稳定版调整 -->
</dependency>
 

  • 最新版本可在 Maven 中央仓库 查询。
  • 3.x 版本支持 Java 8+,相比旧版本增加了对 TLS 1.2+ 等安全协议的支持。

二、支持的主要协议与功能

Commons Net 涵盖了多种常用网络协议,核心功能如下:

  1. 文件传输协议(FTP/SFTP)
    • FTPClient:实现 FTP 客户端功能,支持文件上传、下载、删除、目录操作等。
    • FTPSClient:支持 FTP over SSL/TLS 加密传输,增强文件传输安全性。
    • SFTPClient(需额外依赖 JSch):通过 SSH 协议实现安全文件传输。
  2. 电子邮件协议(SMTP/POP3/IMAP)
    • SMTPClient:发送电子邮件(支持文本、附件)。
    • POP3Client:从邮件服务器接收邮件。
    • IMAPClient:管理邮件服务器上的邮件(如查看、移动、删除邮件)。
  3. 远程登录协议(Telnet/SSH)
    • TelnetClient:实现 Telnet 客户端,用于远程登录和执行命令。
    • SSHClient(需额外依赖):支持 SSH 协议的远程连接。
  4. 其他协议
    • WhoisClient:查询域名注册信息。
    • TimeClient:获取网络时间服务器的时间。
    • DaytimeClient:获取网络日期时间服务。

三、常用功能示例

1. FTP 文件上传

java
 
运行
 
 
 
 
import org.apache.commons.net.ftp.FTPClient;
import java.io.File;
import java.io.FileInputStream;

public class FtpUploadExample {
    public static void main(String[] args) {
        String server = "ftp.example.com";
        int port = 21;
        String user = "username";
        String pass = "password";
        String localFilePath = "local-file.txt";
        String remoteFilePath = "remote-file.txt";

        FTPClient ftpClient = new FTPClient();
        try {
            // 连接 FTP 服务器
            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            
            // 上传文件
            try (FileInputStream fis = new FileInputStream(new File(localFilePath))) {
                boolean success = ftpClient.storeFile(remoteFilePath, fis);
                if (success) {
                    System.out.println("文件上传成功");
                }
            }
            
            // 退出并断开连接
            ftpClient.logout();
            ftpClient.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

2. FTP 文件下载

java
 
运行
 
 
 
 
import org.apache.commons.net.ftp.FTPClient;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class FtpDownloadExample {
    public static void main(String[] args) {
        String server = "ftp.example.com";
        int port = 21;
        String user = "username";
        String pass = "password";
        String remoteFilePath = "remote-file.txt";
        String localFilePath = "downloaded-file.txt";

        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            
            // 下载文件
            try (OutputStream os = new FileOutputStream(localFilePath)) {
                boolean success = ftpClient.retrieveFile(remoteFilePath, os);
                if (success) {
                    System.out.println("文件下载成功");
                }
            }
            
            ftpClient.logout();
            ftpClient.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

3. 使用 Telnet 远程执行命令

java
 
运行
 
 
 
 
import org.apache.commons.net.telnet.TelnetClient;
import java.io.InputStream;
import java.io.PrintStream;

public class TelnetExample {
    public static void main(String[] args) {
        String server = "telnet.example.com";
        int port = 23;
        String user = "username";
        String pass = "password";

        TelnetClient telnet = new TelnetClient();
        try {
            telnet.connect(server, port);
            
            // 获取输入输出流
            InputStream in = telnet.getInputStream();
            PrintStream out = new PrintStream(telnet.getOutputStream());
            
            // 登录
            readResponse(in); // 读取登录提示
            out.println(user);
            out.flush();
            readResponse(in); // 读取密码提示
            out.println(pass);
            out.flush();
            
            // 执行命令
            out.println("ls -l"); // 示例:列出目录
            out.flush();
            Thread.sleep(1000); // 等待响应
            readResponse(in);
            
            telnet.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 读取服务器响应
    private static void readResponse(InputStream in) throws Exception {
        byte[] buffer = new byte[1024];
        int len;
        while ((len = in.read(buffer)) != -1) {
            System.out.print(new String(buffer, 0, len));
        }
    }
}
 

四、优势与适用场景

  1. 优势
    • 简化开发:封装了底层网络协议细节,提供直观的 API,减少重复编码。
    • 功能全面:支持多种主流网络协议,满足文件传输、远程控制等常见需求。
    • 稳定性高:经过长期迭代和广泛应用,bug 较少,兼容性好。
    • 活跃维护:持续更新以支持新协议特性和安全标准(如 TLS 升级)。
  2. 适用场景
    • 需要实现 FTP/SFTP 文件上传下载的系统(如备份工具、资源管理平台)。
    • 邮件客户端开发(发送 / 接收邮件)。
    • 远程设备管理(通过 Telnet/SSH 控制网络设备)。
    • 网络服务监控(如检查 FTP 服务器状态、获取网络时间)。

五、注意事项

  1. 安全考量:
    • FTP、Telnet 等协议传输数据不加密,敏感场景建议使用 FTPS、SSH 等加密协议。
    • 避免在代码中硬编码用户名和密码,建议通过配置文件或环境变量注入。
  2. 异常处理:网络操作可能出现连接超时、断开等问题,需妥善处理 IOException 等异常。
  3. 资源释放:使用完客户端对象后,需调用 disconnect() 方法释放网络资源。
  4. 替代方案:
    • 纯 FTP/FTPS 场景可考虑更轻量的 ftp4j
    • SSH/SFTP 场景推荐使用 JSch 或 Apache MINA SSHD。
    • 邮件功能可结合 JavaMail API 使用。

Apache Commons Net 是处理传统网络协议的实用工具库,尤其适合需要快速实现多协议支持的项目。其 API 设计简洁,文档丰富,是 Java 开发者处理网络操作的常用选择。

----------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------

 
posted @ 2025-09-19 16:29  hanease  阅读(41)  评论(0)    收藏  举报