Hutool工具库实战

Hutool工具库实战

一、引言:为什么选择Hutool?

在Java开发中,我们经常需要处理各种繁琐的操作:

  • 日期格式化:SimpleDateFormat线程不安全,代码冗长
  • 字符串处理:判空、分割、格式化需要大量判断
  • 类型转换:各种类型间转换缺少统一API
  • 文件操作:原生API复杂,异常处理麻烦

Hutool是一个Java工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以"甜甜的"。Hutool中的工具方法来自每个用户的精雕细琢,经过上千项目的实际验证。

Hutool的核心优势:

全面 :涵盖日期、字符串、IO、加密、线程等全方位工具 ✅ 简洁 :一行代码完成复杂操作 ✅ 可靠 :经过数千项目验证,稳定可靠 ✅ 无侵入:无任何第三方依赖,轻量级

本文将深入介绍Hutool中最常用的8大核心工具类,通过真实案例展示它们在生产环境中的应用。

二、DateUtil:日期时间处理利器

2.1 日期解析与格式化

基础用法:

java 复制代码
import cn.hutool.core.date.DateUtil;
import java.util.Date;

// 字符串转Date - 自动识别常见格式
Date date1 = DateUtil.parse("2024-01-15");
Date date2 = DateUtil.parse("2024-01-15 10:30:45");
Date date3 = DateUtil.parse("2024/01/15");  // 自动识别

// 格式化Date为字符串
String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
// "2024-01-15 10:30:45"

// 格式化为常用格式
String today = DateUtil.today();              // 2024-01-15
String now = DateUtil.now();                  // 2024-01-15 10:30:45

生产案例:订单时间处理

java 复制代码
public class OrderService {

    // 创建订单时记录时间
    public Order createOrder(OrderDTO dto) {
        Order order = new Order();
        order.setOrderNo(generateOrderNo());
        order.setCreateTime(DateUtil.now());  // 当前时间字符串
        order.setPayDeadline(DateUtil.offsetHour(new Date(), 2));  // 2小时后
        return orderRepository.save(order);
    }

    // 查询指定日期的订单
    public List<Order> findOrdersByDate(String dateStr) {
        Date date = DateUtil.parseDate(dateStr);  // 解析日期
        Date beginOfDay = DateUtil.beginOfDay(date);  // 当天开始时间
        Date endOfDay = DateUtil.endOfDay(date);      // 当天结束时间

        return orderRepository.findByCreateTimeBetween(beginOfDay, endOfDay);
    }
}

2.2 日期计算与偏移

java 复制代码
// 日期偏移
Date now = new Date();
Date tomorrow = DateUtil.tomorrow();                  // 明天
Date yesterday = DateUtil.yesterday();                // 昨天
Date nextWeek = DateUtil.offsetWeek(now, 1);         // 下周
Date nextMonth = DateUtil.offsetMonth(now, 1);       // 下个月
Date oneHourLater = DateUtil.offsetHour(now, 1);     // 1小时后

// 计算时间差
long betweenDay = DateUtil.between(start, end, DateUnit.DAY);       // 相差天数
long betweenHour = DateUtil.between(start, end, DateUnit.HOUR);     // 相差小时
long betweenMinute = DateUtil.between(start, end, DateUnit.MINUTE); // 相差分钟

生产案例:会员到期提醒

java 复制代码
public class MembershipService {

    // 检查会员是否即将过期(7天内)
    public boolean isExpiringSoon(Member member) {
        Date expireDate = member.getExpireDate();
        Date now = new Date();

        // 计算剩余天数
        long remainDays = DateUtil.between(now, expireDate, DateUnit.DAY);

        return remainDays > 0 && remainDays <= 7;
    }

    // 续费会员
    public void renewMembership(Long memberId, int months) {
        Member member = memberRepository.findById(memberId);
        Date currentExpire = member.getExpireDate();

        // 如果已过期,从今天开始计算
        Date baseDate = DateUtil.compare(currentExpire, new Date()) > 0
            ? currentExpire
            : new Date();

        // 延长指定月份
        Date newExpireDate = DateUtil.offsetMonth(baseDate, months);
        member.setExpireDate(newExpireDate);

        memberRepository.save(member);
    }
}

2.3 时间判断

java 复制代码
// 判断是否为今天
boolean isToday = DateUtil.isToday(date);

// 判断是否为周末
boolean isWeekend = DateUtil.isWeekend(new Date());

// 判断是否在指定范围内
boolean isIn = DateUtil.isIn(checkDate, startDate, endDate);

// 获取星期几
String week = DateUtil.dayOfWeekEnum(new Date()).toChinese();  // "星期一"

// 获取月份天数
int days = DateUtil.lengthOfMonth(1, 2024);  // 29天(2024年是闰年)

生产案例:定时任务调度

java 复制代码
@Component
public class ScheduledTasks {

    // 工作日提醒
    @Scheduled(cron = "0 9 0 * * ?")
    public void workdayReminder() {
        if (!DateUtil.isWeekend(new Date())) {
            // 发送工作日提醒
            notificationService.sendWorkdayReminder();
        }
    }

    // 月末统计
    @Scheduled(cron = "0 0 23 * * ?")
    public void monthEndStatistics() {
        Date today = new Date();
        Date tomorrow = DateUtil.tomorrow();

        // 判断明天是否为下个月
        if (DateUtil.month(today) != DateUtil.month(tomorrow)) {
            // 执行月末统计
            statisticsService.monthEndReport();
        }
    }
}

三、StrUtil:字符串操作神器

3.1 字符串判空与处理

java 复制代码
import cn.hutool.core.util.StrUtil;

// 判空(比StringUtils更强大)
boolean isEmpty = StrUtil.isEmpty(str);           // null或空串
boolean isBlank = StrUtil.isBlank(str);          // null、空串或空白
boolean isNotEmpty = StrUtil.isNotEmpty(str);
boolean isNotBlank = StrUtil.isNotBlank(str);

// 去除空白
String trimmed = StrUtil.trim(str);               // 去除首尾空白
String trimStart = StrUtil.trimStart(str);        // 去除开头空白
String trimEnd = StrUtil.trimEnd(str);            // 去除结尾空白

// 字符串为空时返回默认值
String result = StrUtil.emptyToDefault(str, "默认值");
String result2 = StrUtil.blankToDefault(str, "默认值");

生产案例:用户输入校验

java 复制代码
public class UserValidator {

    public void validateUser(UserDTO dto) {
        // 校验用户名
        if (StrUtil.isBlank(dto.getUsername())) {
            throw new ValidationException("用户名不能为空");
        }

        // 校验并清理输入
        String username = StrUtil.trim(dto.getUsername());
        String email = StrUtil.trimToEmpty(dto.getEmail());

        // 设置默认昵称
        String nickname = StrUtil.blankToDefault(dto.getNickname(), username);

        dto.setUsername(username);
        dto.setEmail(email);
        dto.setNickname(nickname);
    }
}

3.2 字符串分割与拼接

java 复制代码
// 分割字符串
List<String> list = StrUtil.split("a,b,c", ',');          // [a, b, c]
String[] array = StrUtil.splitToArray("a-b-c", '-');      // [a, b, c]

// 分割并去除空白
List<String> cleaned = StrUtil.splitTrim("a, b , c", ','); // [a, b, c]

// 拼接字符串
String joined = StrUtil.join(",", "a", "b", "c");         // "a,b,c"
String joined2 = StrUtil.join(",", list);                 // "a,b,c"

生产案例:SQL条件拼接

java 复制代码
public class QueryBuilder {

    public String buildWhereClause(QueryDTO query) {
        List<String> conditions = new ArrayList<>();

        if (StrUtil.isNotBlank(query.getName())) {
            conditions.add("name LIKE '%" + query.getName() + "%'");
        }

        if (query.getMinAge() != null) {
            conditions.add("age >= " + query.getMinAge());
        }

        if (query.getMaxAge() != null) {
            conditions.add("age <= " + query.getMaxAge());
        }

        if (conditions.isEmpty()) {
            return "";
        }

        return " WHERE " + StrUtil.join(" AND ", conditions);
    }
}

3.3 字符串格式化

java 复制代码
// 格式化字符串(占位符{})
String formatted = StrUtil.format("Hello {}, you are {} years old", "Alice", 25);
// "Hello Alice, you are 25 years old"

// 带序号的占位符
String formatted2 = StrUtil.format("Hello {1}, your ID is {0}", 1001, "Bob");
// "Hello Bob, your ID is 1001"

// 截取字符串
String sub = StrUtil.sub("Hello World", 0, 5);    // "Hello"
String sub2 = StrUtil.subPre("Hello World", 5);   // "Hello"
String sub3 = StrUtil.subSuf("Hello World", 5);   // " World"

生产案例:日志记录

java 复制代码
@Aspect
@Component
public class LoggingAspect {

    @Around("@annotation(log)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint, Log log) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 格式化日志
        String logMsg = StrUtil.format("Method [{}] started with args: {}",
            methodName, JSONUtil.toJsonStr(args));
        logger.info(logMsg);

        Object result = joinPoint.proceed();

        long endTime = System.currentTimeMillis();
        String completeMsg = StrUtil.format("Method [{}] completed in {}ms",
            methodName, endTime - startTime);
        logger.info(completeMsg);

        return result;
    }
}

3.4 其他实用方法

java 复制代码
// 重复字符串
String repeated = StrUtil.repeat("*", 10);        // "**********"

// 填充字符串
String padded = StrUtil.padPre("123", 6, '0');    // "000123"
String padded2 = StrUtil.padAfter("123", 6, '0'); // "123000"

// 首字母大写/小写
String capitalized = StrUtil.upperFirst("hello"); // "Hello"
String lowered = StrUtil.lowerFirst("Hello");     // "hello"

// 下划线转驼峰
String camelCase = StrUtil.toCamelCase("user_name"); // "userName"

// 驼峰转下划线
String underline = StrUtil.toUnderlineCase("userName"); // "user_name"

四、Convert:万能类型转换器

4.1 基础类型转换

java 复制代码
import cn.hutool.core.convert.Convert;

// 转换为字符串
String str = Convert.toStr(123);                    // "123"
String str2 = Convert.toStr(true);                  // "true"

// 转换为数字
Integer num = Convert.toInt("123");                 // 123
Long longNum = Convert.toLong("1000");              // 1000L
Double doubleNum = Convert.toDouble("3.14");        // 3.14

// 转换失败时返回默认值
Integer num2 = Convert.toInt("abc", 0);             // 0

生产案例:配置参数读取

java 复制代码
@Component
public class ConfigService {

    @Value("${app.page.size:20}")
    private String pageSize;

    @Value("${app.cache.enabled:true}")
    private String cacheEnabled;

    @Value("${app.timeout:30000}")
    private String timeout;

    public int getPageSize() {
        return Convert.toInt(pageSize, 20);
    }

    public boolean isCacheEnabled() {
        return Convert.toBool(cacheEnabled, true);
    }

    public long getTimeout() {
        return Convert.toLong(timeout, 30000L);
    }
}

4.2 集合类型转换

java 复制代码
// 数组转List
Integer[] array = {1, 2, 3, 4, 5};
List<Integer> list = Convert.toList(Integer.class, array);

// List转数组
List<String> strList = Arrays.asList("a", "b", "c");
String[] strArray = Convert.toStrArray(strList);

// 字符串转List
List<Integer> numList = Convert.toList(Integer.class, "1,2,3,4,5");

// 转换集合元素类型
List<String> stringList = Arrays.asList("1", "2", "3");
List<Integer> intList = Convert.toList(Integer.class, stringList);

生产案例:批量数据处理

java 复制代码
public class DataImportService {

    public void importUsers(String csvData) {
        List<String> lines = StrUtil.split(csvData, '\n');

        for (String line : lines) {
            List<String> fields = StrUtil.split(line, ',');

            if (fields.size() >= 3) {
                User user = new User();
                user.setName(fields.get(0));
                user.setAge(Convert.toInt(fields.get(1), 0));
                user.setEmail(fields.get(2));

                userRepository.save(user);
            }
        }
    }

    public List<Long> parseUserIds(String idsStr) {
        // "1,2,3,4,5" -> [1L, 2L, 3L, 4L, 5L]
        return Convert.toList(Long.class, idsStr);
    }
}

4.3 日期与时间转换

java 复制代码
// 各种类型转Date
Date date1 = Convert.toDate("2024-01-15");
Date date2 = Convert.toDate(System.currentTimeMillis());
Date date3 = Convert.toDate(LocalDateTime.now());

// Date转其他类型
LocalDateTime localDateTime = Convert.toLocalDateTime(new Date());
long timestamp = Convert.toLong(new Date());

4.4 进制转换

java 复制代码
// 十进制转其他进制
String hex = Convert.toHex(255);           // "FF"
String binary = Convert.toBinaryStr(10);   // "1010"

// 其他进制转十进制
int decimal = Convert.hexToInt("FF");      // 255
int decimal2 = Convert.binaryToInt("1010"); // 10

五、JSONUtil / BeanUtil / IdUtil:数据处理三剑客

5.1 JSONUtil:JSON处理

java 复制代码
import cn.hutool.json.JSONUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;

// 对象转JSON字符串
User user = new User("Alice", 25);
String jsonStr = JSONUtil.toJsonStr(user);
// {"name":"Alice","age":25}

// JSON字符串转对象
String json = "{\"name\":\"Bob\",\"age\":30}";
User user2 = JSONUtil.toBean(json, User.class);

// JSON字符串转JSONObject
JSONObject jsonObj = JSONUtil.parseObj(json);
String name = jsonObj.getStr("name");
Integer age = jsonObj.getInt("age");

// 数组转JSON
List<User> users = Arrays.asList(user, user2);
String arrayJson = JSONUtil.toJsonStr(users);

// JSON字符串转List
String jsonArray = "[{\"name\":\"Alice\",\"age\":25}]";
List<User> userList = JSONUtil.toList(jsonArray, User.class);

生产案例:API响应封装

java 复制代码
public class ApiResponse<T> {

    private int code;
    private String message;
    private T data;

    public static <T> String success(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("success");
        response.setData(data);
        return JSONUtil.toJsonStr(response);
    }

    public static String error(String message) {
        ApiResponse<Void> response = new ApiResponse<>();
        response.setCode(500);
        response.setMessage(message);
        return JSONUtil.toJsonStr(response);
    }
}

@RestController
public class UserController {

    @GetMapping("/api/users/{id}")
    public String getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ApiResponse.success(user);
    }
}

5.2 BeanUtil:Bean操作

java 复制代码
import cn.hutool.core.bean.BeanUtil;

// Bean属性拷贝
User source = new User("Alice", 25);
User target = new User();
BeanUtil.copyProperties(source, target);

// 忽略空值拷贝
BeanUtil.copyProperties(source, target, CopyOptions.create().ignoreNullValue());

// Bean转Map
Map<String, Object> map = BeanUtil.beanToMap(user);

// Map转Bean
Map<String, Object> userMap = new HashMap<>();
userMap.put("name", "Bob");
userMap.put("age", 30);
User user = BeanUtil.mapToBean(userMap, User.class, false);

// 填充Bean属性
User user = new User();
BeanUtil.fillBeanWithMap(userMap, user, false);

生产案例:DTO转换

java 复制代码
public class UserService {

    public UserVO convertToVO(User user) {
        UserVO vo = new UserVO();

        // 拷贝同名属性
        BeanUtil.copyProperties(user, vo);

        // 额外设置
        vo.setRegisteredDays(calculateDays(user.getCreateTime()));

        return vo;
    }

    public User convertToEntity(UserDTO dto) {
        User user = BeanUtil.toBean(dto, User.class);

        // 设置默认值
        if (user.getStatus() == null) {
            user.setStatus(UserStatus.ACTIVE);
        }

        return user;
    }

    // 批量转换
    public List<UserVO> convertToVOList(List<User> users) {
        return users.stream()
            .map(this::convertToVO)
            .collect(Collectors.toList());
    }
}

5.3 IdUtil:ID生成

java 复制代码
import cn.hutool.core.util.IdUtil;

// UUID
String uuid = IdUtil.randomUUID();           // 带-的UUID
String simpleUUID = IdUtil.simpleUUID();     // 不带-的UUID
String fastUUID = IdUtil.fastUUID();         // 性能更好的UUID

// ObjectId(MongoDB风格)
String objectId = IdUtil.objectId();

// Snowflake算法(分布式ID)
long workerId = 1;
long datacenterId = 1;
Snowflake snowflake = IdUtil.getSnowflake(workerId, datacenterId);
long id = snowflake.nextId();                // 生成ID
String idStr = snowflake.nextIdStr();        // 生成字符串ID

生产案例:订单号生成

java 复制代码
@Component
public class OrderNoGenerator {

    private final Snowflake snowflake;

    public OrderNoGenerator() {
        // 从配置中获取机器ID
        long workerId = getWorkerId();
        long datacenterId = getDatacenterId();
        this.snowflake = IdUtil.getSnowflake(workerId, datacenterId);
    }

    // 生成订单号
    public String generateOrderNo() {
        // 订单前缀 + 雪花ID
        return "ORD" + snowflake.nextIdStr();
    }

    // 生成支付流水号
    public String generatePaymentNo() {
        return "PAY" + DateUtil.format(new Date(), "yyyyMMdd") + snowflake.nextIdStr();
    }

    // 生成退款单号
    public String generateRefundNo() {
        return "REF" + snowflake.nextIdStr();
    }

    private long getWorkerId() {
        // 从配置或环境变量获取
        return 1L;
    }

    private long getDatacenterId() {
        return 1L;
    }
}

六、FileUtil / HttpUtil:IO与网络操作

6.1 FileUtil:文件操作

java 复制代码
import cn.hutool.core.io.FileUtil;

// 读取文件
String content = FileUtil.readUtf8String("data.txt");
List<String> lines = FileUtil.readUtf8Lines("data.txt");
byte[] bytes = FileUtil.readBytes("image.png");

// 写入文件
FileUtil.writeUtf8String("Hello Hutool", "output.txt");
FileUtil.appendUtf8String("\nNew Line", "output.txt");
FileUtil.writeBytes(bytes, "copy.png");

// 复制文件
FileUtil.copy("source.txt", "target.txt", true);

// 删除文件
FileUtil.del("temp.txt");

// 创建文件(自动创建父目录)
File file = FileUtil.touch("dir/subdir/file.txt");

// 判断文件
boolean exists = FileUtil.exist("data.txt");
boolean isDirectory = FileUtil.isDirectory("dir");

生产案例:文件上传下载

java 复制代码
@RestController
@RequestMapping("/api/file")
public class FileController {

    @Value("${upload.path}")
    private String uploadPath;

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) {
        try {
            // 生成文件名
            String originalName = file.getOriginalFilename();
            String extension = FileUtil.extName(originalName);
            String fileName = IdUtil.simpleUUID() + "." + extension;

            // 保存文件
            String filePath = uploadPath + File.separator + fileName;
            FileUtil.writeBytes(file.getBytes(), filePath);

            return ApiResponse.success(fileName);
        } catch (IOException e) {
            return ApiResponse.error("上传失败");
        }
    }

    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName, HttpServletResponse response) {
        String filePath = uploadPath + File.separator + fileName;

        if (!FileUtil.exist(filePath)) {
            response.setStatus(404);
            return;
        }

        // 读取文件
        byte[] bytes = FileUtil.readBytes(filePath);

        // 设置响应头
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        try {
            response.getOutputStream().write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6.2 HttpUtil:HTTP请求

java 复制代码
import cn.hutool.http.HttpUtil;
import cn.hutool.http.HttpRequest;

// GET请求
String result = HttpUtil.get("https://api.example.com/users");

// 带参数的GET请求
Map<String, Object> params = new HashMap<>();
params.put("page", 1);
params.put("size", 20);
String result2 = HttpUtil.get("https://api.example.com/users", params);

// POST请求
String postResult = HttpUtil.post("https://api.example.com/users", "{\"name\":\"Alice\"}");

// 下载文件
long size = HttpUtil.downloadFile("https://example.com/file.pdf", "output.pdf");

// 更复杂的请求
String result3 = HttpRequest.post("https://api.example.com/login")
    .header("Content-Type", "application/json")
    .header("Authorization", "Bearer token")
    .body("{\"username\":\"admin\",\"password\":\"123456\"}")
    .timeout(20000)
    .execute()
    .body();

生产案例:第三方API调用

java 复制代码
@Service
public class WechatApiService {

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.secret}")
    private String secret;

    // 获取AccessToken
    public String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token";

        Map<String, Object> params = new HashMap<>();
        params.put("grant_type", "client_credential");
        params.put("appid", appid);
        params.put("secret", secret);

        String result = HttpUtil.get(url, params);
        JSONObject json = JSONUtil.parseObj(result);

        return json.getStr("access_token");
    }

    // 发送模板消息
    public boolean sendTemplateMessage(String openid, String templateId, Map<String, Object> data) {
        String accessToken = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;

        Map<String, Object> body = new HashMap<>();
        body.put("touser", openid);
        body.put("template_id", templateId);
        body.put("data", data);

        String result = HttpRequest.post(url)
            .header("Content-Type", "application/json")
            .body(JSONUtil.toJsonStr(body))
            .execute()
            .body();

        JSONObject json = JSONUtil.parseObj(result);
        return json.getInt("errcode") == 0;
    }
}

七、生产实战综合案例

案例1:用户注册登录系统

java 复制代码
@Service
public class AuthService {

    @Autowired
    private UserRepository userRepository;

    // 用户注册
    public User register(RegisterDTO dto) {
        // 1. 参数校验(StrUtil)
        if (StrUtil.hasBlank(dto.getUsername(), dto.getPassword(), dto.getEmail())) {
            throw new ValidationException("参数不能为空");
        }

        // 2. 创建用户对象(BeanUtil)
        User user = BeanUtil.toBean(dto, User.class);

        // 3. 生成用户ID(IdUtil)
        user.setId(IdUtil.getSnowflake(1, 1).nextId());

        // 4. 设置注册时间(DateUtil)
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());

        // 5. 密码加密(SecureUtil)
        String encryptedPassword = SecureUtil.md5(dto.getPassword());
        user.setPassword(encryptedPassword);

        return userRepository.save(user);
    }

    // 用户登录
    public String login(LoginDTO dto) {
        // 查询用户
        User user = userRepository.findByUsername(dto.getUsername());

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 验证密码
        String encryptedPassword = SecureUtil.md5(dto.getPassword());
        if (!StrUtil.equals(user.getPassword(), encryptedPassword)) {
            throw new BusinessException("密码错误");
        }

        // 生成Token(JWT)
        Map<String, Object> payload = new HashMap<>();
        payload.put("userId", user.getId());
        payload.put("username", user.getUsername());
        payload.put("exp", DateUtil.offsetHour(new Date(), 24).getTime());

        return JWTUtil.createToken(payload, "secret".getBytes());
    }
}

案例2:数据导入导出

java 复制代码
@Service
public class DataExportService {

    // 导出用户数据为CSV
    public void exportUsers(List<User> users, String filePath) {
        List<String> lines = new ArrayList<>();

        // 添加标题行
        lines.add("ID,姓名,年龄,邮箱,注册时间");

        // 添加数据行
        for (User user : users) {
            String line = StrUtil.format("{},{},{},{},{}",
                user.getId(),
                user.getName(),
                user.getAge(),
                user.getEmail(),
                DateUtil.format(user.getCreateTime(), "yyyy-MM-dd HH:mm:ss")
            );
            lines.add(line);
        }

        // 写入文件
        FileUtil.writeUtf8Lines(lines, filePath);
    }

    // 从CSV导入用户数据
    public List<User> importUsers(String filePath) {
        List<User> users = new ArrayList<>();

        // 读取文件
        List<String> lines = FileUtil.readUtf8Lines(filePath);

        // 跳过标题行
        for (int i = 1; i < lines.size(); i++) {
            List<String> fields = StrUtil.split(lines.get(i), ',');

            if (fields.size() >= 5) {
                User user = new User();
                user.setId(Convert.toLong(fields.get(0)));
                user.setName(fields.get(1));
                user.setAge(Convert.toInt(fields.get(2)));
                user.setEmail(fields.get(3));
                user.setCreateTime(DateUtil.parse(fields.get(4)));

                users.add(user);
            }
        }

        return users;
    }
}

案例3:定时报表生成

java 复制代码
@Component
public class ReportScheduler {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private EmailService emailService;

    // 每天凌晨1点生成昨日报表
    @Scheduled(cron = "0 0 1 * * ?")
    public void generateDailyReport() {
        // 获取昨天的日期范围
        Date yesterday = DateUtil.yesterday();
        Date startTime = DateUtil.beginOfDay(yesterday);
        Date endTime = DateUtil.endOfDay(yesterday);

        // 查询订单数据
        List<Order> orders = orderRepository.findByCreateTimeBetween(startTime, endTime);

        // 统计数据
        int totalCount = orders.size();
        BigDecimal totalAmount = orders.stream()
            .map(Order::getAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 生成报表内容
        StringBuilder report = new StringBuilder();
        report.append("日期: ").append(DateUtil.format(yesterday, "yyyy-MM-dd")).append("\n");
        report.append("订单总数: ").append(totalCount).append("\n");
        report.append("交易总额: ").append(totalAmount).append("\n");

        // 保存报表文件
        String fileName = StrUtil.format("report_{}.txt",
            DateUtil.format(yesterday, "yyyyMMdd"));
        FileUtil.writeUtf8String(report.toString(), "reports/" + fileName);

        // 发送邮件通知
        emailService.send("admin@example.com", "日报", report.toString());
    }
}

八、最佳实践与注意事项

8.1 性能优化建议

复用Snowflake实例:

java 复制代码
// 推荐:单例模式
@Component
public class IdGenerator {
    private final Snowflake snowflake = IdUtil.getSnowflake(1, 1);

    public long nextId() {
        return snowflake.nextId();
    }
}

// 不推荐:每次创建新实例
public long generateId() {
    return IdUtil.getSnowflake(1, 1).nextId();  // 每次都创建
}

合理使用缓存:

java 复制代码
// 缓存常用的DateFormat
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";

public String formatDate(Date date) {
    return DateUtil.format(date, DATE_PATTERN);
}

8.2 异常处理

java 复制代码
// Convert转换时指定默认值
Integer age = Convert.toInt(ageStr, 0);

// 文件操作捕获异常
try {
    String content = FileUtil.readUtf8String("config.txt");
} catch (IORuntimeException e) {
    logger.error("读取文件失败", e);
    // 使用默认配置
}

// HTTP请求超时设置
HttpRequest.post(url)
    .timeout(5000)  // 5秒超时
    .execute();

8.3 线程安全

Hutool的大部分工具类都是线程安全的,但注意:

  • DateUtil:线程安全
  • StrUtil:线程安全
  • FileUtil:文件操作本身需要注意并发
  • Snowflake:线程安全,建议单例使用

九、总结

Hutool工具库为Java开发提供了全方位的工具支持:

核心优势:

  • 开发效率提升60%:一行代码完成复杂操作
  • 代码质量提升:减少判空、异常处理等样板代码
  • 可靠性强:经过数千项目验证
  • 无侵入性:无第三方依赖,轻量级
相关推荐
镜花水月linyi2 小时前
Java 线程创建的完整链路:从 Java 层 → JVM 层 → 操作系统层
java·后端·面试
zfj3212 小时前
排查java应用内存溢出的工具和方法
java·开发语言·jvm·内存溢出
历程里程碑3 小时前
C++ 7vector:动态数组的终极指南
java·c语言·开发语言·数据结构·c++·算法
ss2733 小时前
高并发读场景:写时复制容器(Copy-On-Write)
java·开发语言·rpc
一人の梅雨3 小时前
淘宝商品视频接口深度解析:从视频加密解密到多端视频流重构
java·开发语言·python
是喵斯特ya3 小时前
java反序列化漏洞解析+URLDNS利用链分析
java·安全
她说..3 小时前
MySQL数据处理(增删改)
java·开发语言·数据库·mysql·java-ee
BD_Marathon3 小时前
【JavaWeb】ServletContext_域对象相关API
java·开发语言
重生之后端学习3 小时前
238. 除自身以外数组的乘积
java·数据结构·算法·leetcode·职场和发展·哈希算法