前言
Java本身自带了许多非常好用的工具类,但有时我们的业务千奇百怪,自带的工具类又无法满足业务需求,需要在这些工具类的基础上进行二次封装改造。以下就是作者在实际工作中,积累总结的一些Util。
一、时间相关
package com.test.java.util;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 时间工具类
*/
@Slf4j
public class DateUtil {
/*** 常用的时间模型常量*/
public static final String PATTERN_DATE_TIME_MONTH = "yyyy-MM-dd";
private static final String PATTERN_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
public static final String PATTERN_DATE_TIME_MILLISECOND = "yyyy-MM-dd HH:mm:ss.SSS";
private static final String EXPORT_FORMAT_DATE_TIME = "yyyyMMdd-hhmmss";
/*** 周末*/
public static List<Integer> holidays = Lists.newArrayList(6, 7);
/*** 工作日*/
public static List<Integer> workdays = Lists.newArrayList(1, 2, 3, 4, 5);
/**
* 获取指定的format,每次重建避免线程安全问题 yyyy-MM-dd HH:mm:ss
*/
public static SimpleDateFormat getYyyyMmDdHhMmSs() {
return new SimpleDateFormat(PATTERN_DATE_TIME);
}
/**
* LocalDateTime转为String,格式为:"2023-10-13 15:40:23"
*/
public static String formatDateTime(LocalDateTime dateTime) {
if (Objects.isNull(dateTime)) {
return "";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_DATE_TIME);
return dateTime.format(formatter);
}
/**
* LocalDateTime转为String,格式为:"2023-10-13"
*/
public static String formatDateTimeOfMonth(LocalDateTime dateTime) {
if (Objects.isNull(dateTime)) {
return "";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_DATE_TIME_MONTH);
return dateTime.format(formatter);
}
/**
* LocalDateTime转为Date
*/
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* LocalDateTime转为时间戳
*/
public static String dateTimestamp(LocalDateTime date) {
return DateTimeFormatter.ofPattern("yyMMddHHmmssSSS").format(date);
}
/**
* LocalDateTime转为String,自定义时间格式
*
* @param dateTime LocalDateTime类型的时间
* @param pattern 自定义的时间格式
*/
public static String formatDateTime(LocalDateTime dateTime, String pattern) {
if (Objects.isNull(dateTime)) {
return "";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return dateTime.format(formatter);
}
/**
* Date转为String,格式为:“2023-01-01”
*/
public static String formatDateTime(Date dateTime) {
if (Objects.nonNull(dateTime)) {
return DateFormatUtils.format(dateTime, PATTERN_DATE_TIME_MONTH);
}
return "";
}
/**
* Date转为String,格式为:“2023-01-01 12:10:50”
*/
public static String formatDateOfDate(Date dateTime) {
if (Objects.nonNull(dateTime)) {
return DateFormatUtils.format(dateTime, PATTERN_DATE_TIME);
}
return "";
}
/**
* Date转为String,格式为:“20230101-121050”
*/
public static String exportFormatDateTime(Date dateTime) {
if (Objects.nonNull(dateTime)) {
return DateFormatUtils.format(dateTime, EXPORT_FORMAT_DATE_TIME);
}
return "";
}
/**
* Date转为String,格式为:“2023.01.01”
*/
public static String formatDate(Date dateTime) {
if (Objects.nonNull(dateTime)) {
return DateFormatUtils.format(dateTime, "yyyy.MM.dd");
}
return "";
}
/**
* Date转为String时间,自定义时间格式
*
* @param dateTime Date时间
* @param pattern 自定义的时间格式
*/
public static String formatDateTime(Date dateTime, String pattern) {
if (Objects.nonNull(dateTime)) {
return DateFormatUtils.format(dateTime, pattern);
}
return "";
}
/**
* 字符串时间转为Date,格式为:"Sun Oct 01 00:00:00 CST 2023"
*/
public static Date strToDateTimeOfMonth(String strDate) {
try {
strDate = strDate.substring(0, 10);
return DateUtils.parseDate(strDate, PATTERN_DATE_TIME_MONTH);
} catch (ParseException e) {
log.error("时间转换异常:{}", e.getMessage());
throw new RuntimeException(e);
}
}
/**
* 字符串时间转为Date,格式为:"Sun Oct 01 02:56:20 CST 2023"
*/
public static Date strToDateTime(String strDate) {
if (strDate.length() != 19) {
throw new RuntimeException("入参时间格式不正确");
}
try {
return DateUtils.parseDate(strDate, PATTERN_DATE_TIME);
} catch (ParseException e) {
log.error("时间转换异常:{}", e.getMessage());
throw new RuntimeException(e);
}
}
/**
* 将Date对象转化为指定格式dateFormat的字符串
*
* @return String
*/
public static String getDate(Date date, String dateFormat) {
SimpleDateFormat format = new SimpleDateFormat(dateFormat);
return format.format(date);
}
/**
* 将指定格式fromFormat的Date字符串转化为Date对象
*/
public static Date getDate(String date) {
SimpleDateFormat sdf = getYyyyMmDdHhMmSs();
try {
return sdf.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将指定格式fromFormat的Date字符串转化为Date对象
*
* @return Date
*/
public static Date getDate(String date, String fromFormat) {
try {
SimpleDateFormat fromSimpleDateFormat = new SimpleDateFormat(fromFormat);
return fromSimpleDateFormat.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 字符串时间转为LocalDateTime,格式为:"2023-10-01T02:56:20"
*/
public static LocalDateTime strToLocalDateTime(String strDate) {
if (strDate.length() != 19) {
throw new RuntimeException("入参时间格式不正确");
}
try {
Date date = DateUtils.parseDate(strDate, "yyyy-MM-dd HH:mm:ss");
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
} catch (ParseException e) {
log.error("时间转换异常:{}", e.getMessage());
throw new RuntimeException(e);
}
}
/**
* 字符串时间转为LocalDateTime,格式为:"2023-10-01T02:56:20.001"
*/
public static LocalDateTime strToLocalDateTimeMillisecond(String strDate) {
try {
if (strDate.length() != 23) {
throw new RuntimeException("入参时间格式不正确");
}
Date date = DateUtils.parseDate(strDate, PATTERN_DATE_TIME_MILLISECOND);
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
} catch (ParseException e) {
log.error("时间转换异常:{}", e.getMessage());
throw new RuntimeException(e);
}
}
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate) {
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = Math.abs(endDate.getTime() - nowDate.getTime());
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day + "天" + hour + "小时" + min + "分钟";
}
/**
* 计算两个时间相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2) {
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/**
* 计算两个时间相差小时
*/
public static int differentHourByMillisecond(Date date1, Date date2) {
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600)));
}
/**
* 计算两个时间相差分钟
*/
public static int differentMinByMillisecond(Date date1, Date date2) {
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 60)));
}
/**
* 获得某天最大时间,例如:Wed Nov 29 23:59:59 CST 2023
*/
public static Date getEndOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 获得某天最小时间,例如:Wed Nov 29 00:00:00 CST 2023
*/
public static Date getStartOfDay(Date date) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 获取相对于date前后的某一天
*/
public static Date anotherDay(Date date, int i) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, i);
return cal.getTime();
}
/**
* 给定值向后加月份
*/
public static Date stepMonth(Date sourceDate, int month) {
Calendar c = Calendar.getInstance();
c.setTime(sourceDate);
c.add(Calendar.MONTH, month);
return c.getTime();
}
/**
* 给定值向后加年份
*/
public static Date stepYear(Date sourceDate, int year) {
Calendar c = Calendar.getInstance();
c.setTime(sourceDate);
c.add(Calendar.YEAR, year);
return c.getTime();
}
/**
* 该年最后一天的 时、分、秒以23:59:59结尾
*/
public static Date dateTimeYearEndWidth(Date dateTime) {
String dateTimeString = getDate(dateTime, PATTERN_DATE_TIME);
return getDate(dateTimeString.substring(0, 4) + "-12-31 23:59:59");
}
/**
* 获取过去N天内的日期数组(不包含今天)返回的时间类型为:yyyy-MM-dd
*/
public static ArrayList<String> getLastDays(int intervals) {
ArrayList<String> pastDaysList = new ArrayList<>();
for (int i = intervals; i > 0; i--) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - i);
Date today = calendar.getTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
pastDaysList.add(format.format(today));
}
return pastDaysList;
}
}
附上测试demo:
public static void main(String[] args) {
LocalDateTime nowDate = LocalDateTime.now();
Date date = new Date();
String a = DateUtil.formatDateTime(nowDate);
System.out.println("LocalDateTime转为String时间(带时分秒):" + a);
String b = DateUtil.formatDateTimeOfMonth(nowDate);
System.out.println("LocalDateTime转为String时间(不带时分秒):" + b);
String c = DateUtil.dateTimestamp(nowDate);
System.out.println("LocalDateTime转为时间戳:" + c);
String d = DateUtil.formatDateTime(nowDate, "yyyy-MM-dd ");
System.out.println("LocalDateTime转为String时间(自定义格式):" + d);
Date dt = DateUtil.localDateTimeToDate(nowDate);
System.out.println("LocalDateTime转为Date:" + dt);
String s = DateUtil.formatDateTime(date);
System.out.println("Date转为String时间(不带时分秒):" + s);
String s1 = DateUtil.formatDateOfDate(date);
System.out.println("Date转为String时间(带时分秒):" + s1);
String s2 = DateUtil.exportFormatDateTime(date);
System.out.println("Date转为String时间(导出模式):" + s2);
String s3 = DateUtil.formatDate(date);
System.out.println("Date转为String时间(特殊模式):" + s3);
String s4 = DateUtil.formatDateTime(date, "yyyy-MM-dd");
System.out.println("Date转为String时间(自定义格式):" + s4);
Date date1 = DateUtil.strToDateTimeOfMonth("2023-10-01 02:56:20");
System.out.println("字符串时间转为Date(不带时分秒)" + date1);
Date date2 = DateUtil.strToDateTime("2023-10-01 02:56:20");
System.out.println("字符串时间转为Date(带时分秒)" + date2);
LocalDateTime ld = DateUtil.strToLocalDateTime("2023-10-01 02:56:20");
System.out.println("字符串时间转为LocalDateTime(带时分秒):" + ld);
LocalDateTime ld2 = DateUtil.strToLocalDateTimeMillisecond("2023-10-01 02:56:20.001");
System.out.println("字符串时间转为LocalDateTime(带毫秒)" + ld2);
String str1 = "2023-11-25 08:00:00";
String str2 = "2023-11-29 00:00:00";
Date date3 = DateUtil.strToDateTime(str1);
Date date4 = DateUtil.strToDateTime(str2);
String datePoor = DateUtil.getDatePoor(date3, date4);
System.out.println("两时间相差:" + datePoor);
int i = DateUtil.differentDaysByMillisecond(date3, date4);
System.out.println("两时间相差:" + i + "天");
int i2 = DateUtil.differentHourByMillisecond(date3, date4);
System.out.println("两时间相差:" + i2 + "小时");
int i3 = DateUtil.differentMinByMillisecond(date3, date4);
System.out.println("两时间相差:" + i3 + "分钟");
Date endOfDay = DateUtil.getEndOfDay(date);
System.out.println("某天最大时间:" + endOfDay);
Date startOfDay = DateUtil.getStartOfDay(date);
System.out.println("某天最小时间:" + startOfDay);
Date date5 = DateUtil.anotherDay(date, 1);
System.out.println("昨天的时间:" + date5);
Date date6 = DateUtil.stepMonth(date, 1);
System.out.println("下个月的时间:" + date6);
Date date7 = DateUtil.stepYear(date, 1);
System.out.println("明年的时间:" + date7);
Date date8 = DateUtil.dateTimeYearEndWidth(date);
System.out.println("本年最后一天的时间:" + date8);
ArrayList<String> lastDays = DateUtil.getLastDays(7);
System.out.println("过去7天内的日期:" + lastDays);
}
结果:
二、正则校验
package com.test.java.util;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正则相关工具类
*/
public class ValidateUtil {
/*** 手机号(简单),以1开头的11位纯数字*/
public static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$";
/**
* 手机号(精确)
* <p>移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188</p>
* <p>联通:130、131、132、145、155、156、175、176、185、186</p>
* <p>电信:133、153、173、177、180、181、189</p>
* <p>全球星:1349</p>
* <p>虚拟运营商:170</p>
*/
public static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$";
/*** 固定电话号码*/
public static final String REGEX_TEL = "^0\\d{2,3}[- ]?\\d{7,8}";
/*** 身份证号(15位身份证号)*/
public static final String REGEX_ID_CARD15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
/*** 身份证号(18位身份证号)*/
public static final String REGEX_ID_CARD18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9Xx])$";
/*** 身份证号(15和18位)*/
public static final String REGEX_ID_CARD15AND18 = "(^\\d{8}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}$)|(^\\d{6}(18|19|20)\\d{2}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}(\\d|X|x)$)";
/*** 邮箱*/
public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
/*** 网址URL*/
public static final String REGEX_URL = "[a-zA-z]+://[^\\s]*";
/*** 汉字*/
public static final String REGEX_ZH = "^[\\u4e00-\\u9fa5]+$";
/*** 用户名(取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位)*/
public static final String REGEX_USERNAME = "^[\\w\\u4e00-\\u9fa5]{6,20}(?<!_)$";
/*** yyyy-MM-dd格式的日期校验,已考虑平闰年*/
public static final String REGEX_DATE = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
/*** IP地址*/
public static final String REGEX_IP = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
/*** 双字节字符(包括汉字在内)*/
public static final String REGEX_DOUBLE_BYTE_CHAR = "[^\\x00-\\xff]";
/*** 空白行*/
public static final String REGEX_BLANK_LINE = "\\n\\s*\\r";
/*** QQ号*/
public static final String REGEX_TENCENT_NUM = "[1-9][0-9]{4,}";
/*** 中国邮政编码*/
public static final String REGEX_ZIP_CODE = "[1-9]\\d{5}(?!\\d)";
/*** 正整数*/
public static final String REGEX_POSITIVE_INTEGER = "^[1-9]\\d*$";
/*** 负整数*/
public static final String REGEX_NEGATIVE_INTEGER = "^-[1-9]\\d*$";
/*** 整数*/
public static final String REGEX_INTEGER = "^-?[1-9]\\d*$";
/*** 非负整数(正整数 + 0)*/
public static final String REGEX_NOT_NEGATIVE_INTEGER = "^[1-9]\\d*|0$";
/*** 非正整数(负整数 + 0)*/
public static final String REGEX_NOT_POSITIVE_INTEGER = "^-[1-9]\\d*|0$";
/*** 正浮点数*/
public static final String REGEX_POSITIVE_FLOAT = "^[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$";
/*** 负浮点数*/
public static final String REGEX_NEGATIVE_FLOAT = "^-[1-9]\\d*\\.\\d*|-0\\.\\d*[1-9]\\d*$";
/**
* 验证手机号(简单)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isMobileSimple(CharSequence input) {
return isMatch(REGEX_MOBILE_SIMPLE, input);
}
/**
* 验证手机号(精确)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isMobileExact(CharSequence input) {
return isMatch(REGEX_MOBILE_EXACT, input);
}
/**
* 验证固定电话号码
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isTel(CharSequence input) {
return isMatch(REGEX_TEL, input);
}
/**
* 验证身份证号码(15位)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isIdCard15(CharSequence input) {
return isMatch(REGEX_ID_CARD15, input);
}
/**
* 验证身份证号码(18位)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isIdCard18(CharSequence input) {
return isMatch(REGEX_ID_CARD18, input);
}
/**
* 验证身份证号码(15/18位)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isIdCard15and18(CharSequence input) {
return isMatch(REGEX_ID_CARD15AND18, input);
}
/**
* 验证邮箱
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isEmail(CharSequence input) {
return isMatch(REGEX_EMAIL, input);
}
/**
* 验证网址URL
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isUrl(CharSequence input) {
return isMatch(REGEX_URL, input);
}
/**
* 验证汉字
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isZh(CharSequence input) {
return isMatch(REGEX_ZH, input);
}
/**
* 验证用户名(取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位)
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isUsername(CharSequence input) {
return isMatch(REGEX_USERNAME, input);
}
/**
* 验证yyyy-MM-dd格式的日期校验,已考虑平闰年
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isDate(CharSequence input) {
return isMatch(REGEX_DATE, input);
}
/**
* 验证IP地址
*
* @param input 待验证文本
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isIp(CharSequence input) {
return isMatch(REGEX_IP, input);
}
/**
* 判断是否匹配正则
*
* @param regex 正则表达式
* @param input 要匹配的字符串
* @return true: 匹配 <br> false: 不匹配
*/
public static boolean isMatch(String regex, CharSequence input) {
return input != null && input.length() > 0 && Pattern.matches(regex, input);
}
/**
* 获取正则匹配的部分
*
* @param regex 正则表达式
* @param input 要匹配的字符串
* @return 正则匹配的部分
*/
public static List<String> getMatches(String regex, CharSequence input) {
if (input == null) {
return null;
}
List<String> matches = new ArrayList<>();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
matches.add(matcher.group());
}
return matches;
}
/**
* 获取正则匹配分组
*
* @param input 要分组的字符串
* @param regex 正则表达式
* @return 正则匹配分组
*/
public static String[] getSplits(String input, String regex) {
if (input == null) {
return null;
}
return input.split(regex);
}
/**
* 替换正则匹配的第一部分
*
* @param input 要替换的字符串
* @param regex 正则表达式
* @param replacement 代替者
* @return 替换正则匹配的第一部分
*/
public static String getReplaceFirst(String input, String regex, String replacement) {
if (input == null) {
return null;
}
return Pattern.compile(regex).matcher(input).replaceFirst(replacement);
}
/**
* 替换所有正则匹配的部分
*
* @param input 要替换的字符串
* @param regex 正则表达式
* @param replacement 代替者
* @return 替换所有正则匹配的部分
*/
public static String getReplaceAll(String input, String regex, String replacement) {
if (input == null) {
return null;
}
return Pattern.compile(regex).matcher(input).replaceAll(replacement);
}
}
三、水印相关
相关的添加水印的代码,在我之前写过的文章里有详细的介绍,感兴趣的同学可以去看看。附上链接:Java实现添加文字水印、图片水印
package com.test.java.util;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
/**
* 水印相关util
*/
public class WatermarkUtil {
/**
* 读取本地图片
*
* @param path 本地图片存放路径
*/
public static Image readLocalPicture(String path) {
if (null == path) {
throw new RuntimeException("本地图片路径不能为空");
}
// 读取原图片信息 得到文件
File srcImgFile = new File(path);
try {
// 将文件对象转化为图片对象
return ImageIO.read(srcImgFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 读取网络图片
*
* @param path 网络图片地址
*/
public static Image readNetworkPicture(String path) {
if (null == path) {
throw new RuntimeException("网络图片路径不能为空");
}
try {
// 创建一个URL对象,获取网络图片的地址信息
URL url = new URL(path);
// 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
BufferedImage bugImg = ImageIO.read(url.openStream());
if (null == bugImg) {
throw new RuntimeException("网络图片地址不正确");
}
return bugImg;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 水印处理
*
* @param image 图片对象
* @param type 水印类型(1-文字水印 2-图片水印)
* @param watermark 水印内容(文字水印内容/图片水印的存放路径)
*/
public static String manageWatermark(Image image, Integer type, String watermark) {
int imgWidth = image.getWidth(null);
int imgHeight = image.getHeight(null);
BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 加水印:
// 创建画笔
Graphics2D graphics = bufImg.createGraphics();
// 绘制原始图片
graphics.drawImage(image, 0, 0, imgWidth, imgHeight, null);
// 校验水印的类型
if (type == 1) {
if (StringUtils.isEmpty(watermark)) {
throw new RuntimeException("文字水印内容不能为空");
}
// 添加文字水印:
// 根据图片的背景设置水印颜色
graphics.setColor(new Color(255, 255, 255, 128));
// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小为45pt
graphics.setFont(new Font("微软雅黑", Font.BOLD, 45));
// 设置水印的坐标(为原图片中间位置)
int x = (imgWidth - getWatermarkLength(watermark, graphics)) / 2;
int y = imgHeight / 2;
// 画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
graphics.drawString(watermark, x, y);
graphics.dispose();
} else {
// 添加图片水印:
if (StringUtils.isEmpty(watermark)) {
throw new RuntimeException("图片水印存放路径不能为空");
}
Image srcWatermark = readLocalPicture(watermark);
int watermarkWidth = srcWatermark.getWidth(null);
int watermarkHeight = srcWatermark.getHeight(null);
// 设置 alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));
// 绘制水印图片 坐标为中间位置
graphics.drawImage(srcWatermark, (imgWidth - watermarkWidth) / 2,
(imgHeight - watermarkHeight) / 2, watermarkWidth, watermarkHeight, null);
graphics.dispose();
}
// 定义存储的地址
String tarImgPath = "C:/Users/admin/Desktop/watermark.jpg";
// 输出图片
try {
FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
ImageIO.write(bufImg, "png", outImgStream);
outImgStream.flush();
outImgStream.close();
return "水印添加成功";
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 添加水印
*
* @param pictureType 图片来源类型(1-本地图片 2-网络图片)
* @param watermarkType 水印类型(1-文字水印 2-图片水印)
* @param path 图片路径
* @param watermark 水印内容(文字水印内容/图片水印的存放路径)
*/
public static String addWatermark(Integer pictureType, Integer watermarkType, String path, String watermark) {
if (null == pictureType) {
throw new RuntimeException("图片来源类型不能为空");
}
if (null == watermarkType) {
throw new RuntimeException("水印类型不能为空");
}
Image image;
if (pictureType == 1) {
// 读取本地图片
image = readLocalPicture(path);
} else {
// 读取网络图片
image = readNetworkPicture(path);
}
if (watermarkType == 1) {
// 添加文字水印
return manageWatermark(image, 1, watermark);
} else {
// 添加图片水印
return manageWatermark(image, 2, watermark);
}
}
/**
* 获取水印文字的长度
*
* @param watermarkContent 文字水印内容
* @param graphics 图像类
*/
private static int getWatermarkLength(String watermarkContent, Graphics2D graphics) {
return graphics.getFontMetrics(graphics.getFont()).charsWidth(watermarkContent.toCharArray(), 0, watermarkContent.length());
}
public static void main(String[] args) {
// 本地图片路径:
String localPath = "C:/Users/admin/Desktop/bg.jpg";
// 网络图片地址:
String networkPath = "https://img0.baidu.com/it/u=3708545959,316194769&fm=253&fmt=auto&app=138&f=PNG?w=1000&h=1000";
// 文字水印内容
String textWatermark = "Hello World!";
// 图片水印路径
String pictureWatermark = "C:\\Users\\admin\\Desktop\\wm.jpg";
// 本地图片 添加文字水印
//addWatermark(1, 1, localPath, textWatermark);
// 网络图片 添加文字水印
//addWatermark(2, 1, networkPath, textWatermark);
// 本地图片 添加图片水印
//addWatermark(1, 2, localPath, pictureWatermark);
// 网络图片 添加图片水印
addWatermark(2, 2, networkPath, pictureWatermark);
}
}
如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。