Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
模块 介绍
hutool-aop JDK动态代理封装,提供非IOC下的切面支持
hutool-bloomFilter 布隆过滤,提供一些Hash算法的布隆过滤
hutool-cache 简单缓存实现
hutool-core 核心,包括Bean操作、日期、各种Util等
hutool-cron 定时任务模块,提供类Crontab表达式的定时任务
hutool-crypto 加密解密模块,提供对称、非对称和摘要算法封装
hutool-db JDBC封装后的数据操作,基于ActiveRecord思想
hutool-dfa 基于DFA模型的多关键字查找
hutool-extra 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等)
hutool-http 基于HttpUrlConnection的Http客户端封装
hutool-log 自动识别日志实现的日志门面
hutool-script 脚本执行封装,例如Javascript
hutool-setting 功能更强大的Setting配置文件和Properties封装
hutool-system 系统参数调用封装(JVM信息等)
hutool-json JSON实现
hutool-captcha 图片验证码实现
hutool-poi 针对POI中Excel和Word的封装
hutool-socket 基于Java的NIO和AIO的Socket封装
Convert类
可以说是一个工具方法类,里面封装了针对Java常见类型的转换,用于简化类型转换。Convert类中大部分方法为toXXX,参数为Object,可以实现将任意可能的类型转换为指定类型。同时支持第二个参数defaultValue用于在转换失败时返回一个默认值。
int a = 1;
//aStr为"1"
String aStr = Convert.toStr(a);long[] b = {1,2,3,4,5};
//bStr为:"[1, 2, 3, 4, 5]"
String bStr = Convert.toStr(b);
String[] b = { "1", "2", "3", "4" };
//结果为Integer数组
Integer[] intArray = Convert.toIntArray(b);long[] c = {1,2,3,4,5};
//结果为Integer数组
Integer[] intArray2 = Convert.toIntArray(c);
日期转换
String str = "2012-12-12";
// 以前这样将字符串转为日期
Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(str);// 现在这样将字符串转为日期
Date date = Convert.toDate(str);
System.out.println(date);
String str1 = "2012/12/12";
Date date1 = Convert.toDate(str1);
System.out.println(date1);
集合转换
Object[] a = {"a", "你", "好", "", 1};
List<?> list = Convert.convert(List.class, a);
//从4.1.11开始可以这么用
List<?> lists = Convert.toList(a);
编码转换
String a = "我不是乱码";
//转换后result为乱码
// 将utf-8编码转为ISO_8859_1编码
String result = Convert.convertCharset(a, CharsetUtil.UTF_8, CharsetUtil.ISO_8859_1);
// 将ISO_8859_1编码转为utf-8编码
String raw = Convert.convertCharset(result, CharsetUtil.ISO_8859_1, "UTF-8");
Assert.assertEquals(raw, a);
时间转换
long a = 4535345;//结果为:75
// 将毫秒转为秒
long minutes = Convert.convertTime(a, TimeUnit.MILLISECONDS, TimeUnit.MINUTES);
SpringUtil
在SpringBoot上加注解
@EnableSpringUtil
1、模拟HTTP请求
hutool提供了「HttpUtil」 和 「HttpRequest」 两个工具类都可用来模拟发送http请求,这两个用法大同小异这里只拿「HttpRequest」举例 「示例场景:」 在项目开发中Swagger可作为后端接口测试的良方,但在和别人对接,或使用别人提供的接口时常常需要后端自己去模拟请求发送,去校验接口
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;/*** @author 遇见0和1* @company lingStudy* @create 2021-06-03 17:04*/
@Slf4j
public class HttpTest {/*** putOnce:一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略* putOpt:在键和值都为非空的情况下put到JSONObject中*/@Testvoid postTest(){JSONObject jsonObject = JSONUtil.createObj();// 或 JSONObject jsonObject = new JSONObject();jsonObject.putOnce("customerTel","17563964456");jsonObject.putOnce("remarks","备注1:我是HttpRequest测试请求!");HttpResponse response = HttpRequest.post("http://127.0.0.1:9001/caiyun-record/saveRecord")//设置请求头(可任意加).header("Content-Type", "application/json")// 添加token.header("Authorization","eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJ7E3NjJ9.9vgMKLpftjcXxmvViSyJDnBcXrO6c3bLlatwD83frAs")//请求参数.body(jsonObject.toString()).execute();log.info("请求响应结果:{}",response);log.info("响应数据:{}",response.body());}@Testvoid getTest(){HttpResponse response = HttpRequest.get("http://127.0.0.1:9001/caiyun-record/login?paramData=I0CZZJYUBP9JixsyeDkhRnIfFgyXP-NaP1DiJ8_AWoY1eEeZN5BwF_HMSfb4wl6oE").execute();log.info("get请求返回:{}",response.body());}}
2、JSONUtil 序列化
将一个对象序列化,也是后端开发中常遇到的,阿里以前挺火的 「fastjson」 「示例场景:」 返回给前端的token中要存对象时可将对象转为字符串,在拦截器中再将该字符串重新转为对象,若在登录后存的是该对象到session中,还可以在拦截器中通过判断session中的值是否为空,来解决「后端重启后session丢失」的问题。
//对象转字符串
String userInfoStr = JSONUtil.toJsonStr(userInfoDTO);
log.info("对象转字符串userInfoStr:{}", userInfoStr);//生成token
String jwtToken = TokenUtil.createJwtToken(userInfoStr);//字符串转对象
UserInfoDTO userInfo = JSONUtil.toBean(jti, UserInfoDTO.class);
request.getSession().setAttribute("userInfo",userInfo);
log.info("重设session后:{}",request.getSession().getAttribute("userInfo"));
List< Map >转List< Entity >
// HuTool
List<User> userList = JSONUtil.toList(new JSONArray(userMapList),User.class);
// 同fastjson
List<User> userList = JSON.parseObject(JSON.toJSONString(userMapList),new TypeReference<>() {});
3、BeanUtil:Map与javaBean的转换
「示例场景:」 面对POST或者一些参数较多的GET请求等,懒得新建参数对象,可用Map来接收前端传递的参数
@ApiOperation(value = "新增记录")
@ApiImplicitParams({@ApiImplicitParam(paramType = "query", dataType = "String", name = "customerTel", value = "客户号码",required = true),@ApiImplicitParam(paramType = "query", dataType = "String", name = "remarks", value = "备注")})@PostMapping("/saveRecord")public ResultVo<Object> saveRecord(@ApiIgnore @RequestBody Map<String, Object> param){log.info("新增登记记录 param:{}",param);try {HecaiyunRecord hecaiyunRecord = new HecaiyunRecord();//将map赋值给HecaiyunRecord中与map的key对应的字段BeanUtil.fillBeanWithMap(param,hecaiyunRecord,false);UserInfoDTO userInfo = (UserInfoDTO) request.getSession().getAttribute("userInfo");//用userInfo填充与hecaiyunRecord相同的字段BeanUtils.copyProperties(userInfo,hecaiyunRecord);//添加系统日志sysLogService.saveSysLog(userInfo,request,"add","新增登记");return recordService.saveRecord(hecaiyunRecord);} catch (Exception e) {log.error("新增登记记录失败");e.printStackTrace();throw new MyException(StatusEnum.ERROR);}}
「反过来:将 JavaBean 转为 Map」
User user = new User();
user.setAge(3);
user.setName("遇见0和1");//将 user 转成map
Map<String, Object> map = BeanUtil.beanToMap(user);//将userInfo对象复制给map,key保留userInfo中属性的驼峰形式不做下划线处理,不忽略userInfo中值为null的属性
BeanUtil.beanToMap(userInfo,map,false,false); //不会清空map (个人常用)
4、CaptchaUtil 生成图形验证码
「示例场景:」 图形验证码在登录时非常常见,Hutool也用几种类型的验证码,这里只举例个人常用的一种。
@ApiOperation(value = "获得图形验证码")
@GetMapping("/getCaptcha")
public void getCaptcha(HttpServletResponse response){//生成验证码图片(定义图形的宽和高,验证码的位数,干扰线的条数)//CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 25);CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(100, 50, 4, 25);//告诉浏览器输出内容为jpeg类型的图片response.setContentType("image/jpeg");//禁止浏览器缓存response.setHeader("Pragma","No-cache");try {ServletOutputStream outputStream = response.getOutputStream();//图形验证码写出到流,也可以写出到文件如:circleCaptcha.write(“d:/circle25.jpeg”);circleCaptcha.write(outputStream);//从图形验证码图片中获取它的字符串验证码(获取字符串验证码要在图形验证码wirte写出后面才行,不然得到的值为null)String captcha = circleCaptcha.getCode();request.getSession().setAttribute("captcha",captcha);log.info("生成的验证码:{}",captcha);log.info("session id:{}",request.getSession().getId());//关闭流outputStream.close();} catch (IOException e) {e.printStackTrace();throw new MyException(StatusEnum.ERROR);}
}
5、UserAgentUtil
「示例场景:」 系统操作日志里常常需要判断访问的是什么设备 「UserAgentUtil」 可以获取到服务的浏览器详细信息,也可以判断访问是不是移动设备。
//自己实现
public String isDevice(HttpServletRequest request){String requestHeader = request.getHeader("user-agent");//定义移动端请求的所有可能类型String[] deviceArray = {"android", "iphone","ipod","ipad", "windows phone","mqqbrowser"};//将字符串转换为小写requestHeader = requestHeader.toLowerCase();for (String device : deviceArray) {if (requestHeader.contains(device)){return "移动端";}}return "PC端";
}//使用UserAgentUtil
public String isDeviceHuTool(HttpServletRequest request){String requestHeader = request.getHeader("user-agent");UserAgent userAgent = UserAgentUtil.parse(requestHeader);if (userAgent.isMobile()){return "移动端";}return "PC端";
}
访问者的ip地址常常也是需要保存的一个数据,个人暂时没找到hutool对这个的支持,方便后面来抄作业,下面放一个搬来的获取ip的方法
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;import javax.servlet.http.HttpServletRequest;/*** @author 遇见0和1* @company lingStudy* @create 2021-03-30 9:31*/
@Slf4j
public class IPUtils {/*** 获取IP地址** 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址*/public static String getIpAddr(HttpServletRequest request) {String ip = null;try {ip = request.getHeader("x-forwarded-for");if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (StrUtil.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");}if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");}if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}} catch (Exception e) {log.error("IPUtils ERROR:",e);}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if(!StrUtil.isEmpty(ip) && ip.length() > 15) {if(ip.indexOf(",") > 0) {ip = ip.substring(0, ip.indexOf(","));}}return ip;}}
6、FileUtil
「示例场景:」 文件上传下载在项目中也是一个常见并且重要的业务点,Hutool的「FileUtil」类对着方面也做了很好的支持。
@Value("${upload-file.img-path}")
private String imgPath;@ApiOperation(value = "上传图片")
@PostMapping(value = "/uploadImg",headers = "content-type=multipart/form-data")
public ResultVo<Object> uploadFile(@ApiParam(value = "file") @RequestParam(value = "file" ,required = false) MultipartFile file){if (file == null){throw new MyException(StatusEnum.BUSINID);}if (!FileUtil.exist(imgPath)){FileUtil.mkdir(imgPath);}//String fileName = UUID.randomUUID().toString() + "@" + multipartFile.getOriginalFilename();log.info("原文件名:{}",file.getOriginalFilename());//包括扩展名//文件扩展名String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1);String fileName = System.currentTimeMillis() + RandomUtil.randomNumbers(4) + "." +suffix;try {File file1 = FileUtil.writeBytes(file.getBytes(), imgPath + fileName);log.info("file1:{}",file1);return ResultVo.success();} catch (IOException e) {e.printStackTrace();throw new MyException(StatusEnum.ERROR);}}
加密解密
加密分为三种:
- 「对称加密(symmetric)」:例如:AES、DES等
- 「非对称加密(asymmetric)」:例如:RSA、DSA等
- 「摘要加密(digest)」:例如:MD5、SHA-1、SHA-256、HMAC等
对常用到的算法,HuTool提供「SecureUtil」工具类用于快速实现加解密
// 对称加密
SecureUtil.aes
SecureUtil.des
// 摘要算法
SecureUtil.md5
SecureUtil.sha1
SecureUtil.hmac
SecureUtil.hmacMd5
SecureUtil.hmacSha1
// 非对称加密
SecureUtil.rsa
SecureUtil.dsa
// UUID
SecureUtil.simpleUUID 方法提供无“-”的UUID
// 密钥生成
SecureUtil.generateKey 针对对称加密生成密钥
SecureUtil.generateKeyPair 生成密钥对(用于非对称加密)
SecureUtil.generateSignature 生成签名(用于非对称加密)