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%:一行代码完成复杂操作
  • 代码质量提升:减少判空、异常处理等样板代码
  • 可靠性强:经过数千项目验证
  • 无侵入性:无第三方依赖,轻量级
相关推荐
花花鱼2 分钟前
Spring Security 与 Spring MVC
java·spring·mvc
言慢行善1 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
专吃海绵宝宝菠萝屋的派大星1 小时前
使用Dify对接自己开发的mcp
java·服务器·前端
大数据新鸟1 小时前
操作系统之虚拟内存
java·服务器·网络
Tong Z1 小时前
常见的限流算法和实现原理
java·开发语言
凭君语未可1 小时前
Java 中的实现类是什么
java·开发语言
He少年1 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
克里斯蒂亚诺更新2 小时前
myeclipse的pojie
java·ide·myeclipse
迷藏4942 小时前
**eBPF实战进阶:从零构建网络流量监控与过滤系统**在现代云原生架构中,**网络可观测性**和**安全隔离**已成为
java·网络·python·云原生·架构
迷藏4942 小时前
**发散创新:基于Solid协议的Web3.0去中心化身份认证系统实战解析**在Web3.
java·python·web3·去中心化·区块链