解决Day02中存在的问题
- 1. BeanUtils类
- 2. DigestUtils类
- 3. LocalDateTime类
- 4. ThreadLocal类
- 5.扩展Spring MVC框架的消息转化器
1. BeanUtils类
项目应用:属性拷贝
目的:在新增分类中为了减少类category中的setXXX()次数,使用了BeanUtils类中的属性拷贝方法。这里要求categoryDTO中属性的名称必须要和category中的属性名称一致。
BeanUtils是一个Java类库,用于简化Java Bean对象之间的属性拷贝和赋值操作,可以减少Java开发人员在属性复制和赋值时的工作量和代码量,提高开发效率。BeanUtils提供了一组静态方法,可以快速地实现Bean对象之间的属性复制、属性转换、属性赋值等操作。最常用的方法是copyProperties()方法,该方法可以将一个Bean对象(Java类)的属性值复制到另一个Bean对象中。下面是copyProperties()方法的使用方式:
public static void copyProperties(Object source, Object target)
在使用BeanUtils进行属性复制时,会自动匹配两个Bean对象中相同名称的属性,并将源Bean对象中对应属性的值复制到目标Bean对象中。需要注意的是,两个Bean对象中的属性名称和类型必须要匹配,否则会抛出异常。BeanUtils还提供了一些其他的方法,例如getProperty()、setProperty()、populate()等等,可以用于获取属性值、设置属性值、批量设置属性值等操作。下面是一个使用getProperty()和setProperty()方法的示例代码:
String value = BeanUtils.getProperty(bean, "propertyName"); // 获取bean中属性的值
BeanUtils.setProperty(bean, "propertyName", "value"); // 为bean中属性赋值
// populate(Object obj, Map map):将map集合的键值对信息封装到对应的JavaBean对象当中去
BeanUtils.populate(loginUser, map);
2. DigestUtils类
项目应用: 对用户密码进行MD5加密之后再插入到数据库中,防止数据泄露
在新增用户的时候为了保护用户的隐私信息需要对用户的password进行加密,然后存入到数据库中,如下所示:
在用户登录的时候向后端传入用户名和密码,通过对该密码进行MD5加密和数据库中该用户对应密文密码进行对比判断该用户是否能正常登录。
DigestUtils源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.apache.commons.codec.digest;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.binary.StringUtils;
public class DigestUtils {
private static final int STREAM_BUFFER_LENGTH = 1024;
private final MessageDigest messageDigest;
public static byte[] digest(MessageDigest messageDigest, byte[] data) {
return messageDigest.digest(data);
}
public static byte[] digest(MessageDigest messageDigest, ByteBuffer data) {
messageDigest.update(data);
return messageDigest.digest();
}
public static byte[] digest(MessageDigest messageDigest, File data) throws IOException {
return updateDigest(messageDigest, data).digest();
}
public static byte[] digest(MessageDigest messageDigest, InputStream data) throws IOException {
return updateDigest(messageDigest, data).digest();
}
public static MessageDigest getDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException var2) {
throw new IllegalArgumentException(var2);
}
}
public static MessageDigest getDigest(String algorithm, MessageDigest defaultMessageDigest) {
try {
return MessageDigest.getInstance(algorithm);
} catch (Exception var3) {
return defaultMessageDigest;
}
}
public static MessageDigest getMd2Digest() {
return getDigest("MD2");
}
public static MessageDigest getMd5Digest() {
return getDigest("MD5");
}
public static MessageDigest getSha1Digest() {
return getDigest("SHA-1");
}
public static MessageDigest getSha256Digest() {
return getDigest("SHA-256");
}
public static MessageDigest getSha384Digest() {
return getDigest("SHA-384");
}
public static MessageDigest getSha512Digest() {
return getDigest("SHA-512");
}
/** @deprecated */
@Deprecated
public static MessageDigest getShaDigest() {
return getSha1Digest();
}
public static byte[] md2(byte[] data) {
return getMd2Digest().digest(data);
}
public static byte[] md2(InputStream data) throws IOException {
return digest(getMd2Digest(), data);
}
public static byte[] md2(String data) {
return md2(StringUtils.getBytesUtf8(data));
}
public static String md2Hex(byte[] data) {
return Hex.encodeHexString(md2(data));
}
public static String md2Hex(InputStream data) throws IOException {
return Hex.encodeHexString(md2(data));
}
public static String md2Hex(String data) {
return Hex.encodeHexString(md2(data));
}
public static byte[] md5(byte[] data) {
return getMd5Digest().digest(data);
}
public static byte[] md5(InputStream data) throws IOException {
return digest(getMd5Digest(), data);
}
public static byte[] md5(String data) {
return md5(StringUtils.getBytesUtf8(data));
}
public static String md5Hex(byte[] data) {
return Hex.encodeHexString(md5(data));
}
public static String md5Hex(InputStream data) throws IOException {
return Hex.encodeHexString(md5(data));
}
public static String md5Hex(String data) {
return Hex.encodeHexString(md5(data));
}
/** @deprecated */
@Deprecated
public static byte[] sha(byte[] data) {
return sha1(data);
}
/** @deprecated */
@Deprecated
public static byte[] sha(InputStream data) throws IOException {
return sha1(data);
}
/** @deprecated */
@Deprecated
public static byte[] sha(String data) {
return sha1(data);
}
public static byte[] sha1(byte[] data) {
return getSha1Digest().digest(data);
}
public static byte[] sha1(InputStream data) throws IOException {
return digest(getSha1Digest(), data);
}
public static byte[] sha1(String data) {
return sha1(StringUtils.getBytesUtf8(data));
}
public static String sha1Hex(byte[] data) {
return Hex.encodeHexString(sha1(data));
}
public static String sha1Hex(InputStream data) throws IOException {
return Hex.encodeHexString(sha1(data));
}
public static String sha1Hex(String data) {
return Hex.encodeHexString(sha1(data));
}
public static byte[] sha256(byte[] data) {
return getSha256Digest().digest(data);
}
public static byte[] sha256(InputStream data) throws IOException {
return digest(getSha256Digest(), data);
}
public static byte[] sha256(String data) {
return sha256(StringUtils.getBytesUtf8(data));
}
public static String sha256Hex(byte[] data) {
return Hex.encodeHexString(sha256(data));
}
public static String sha256Hex(InputStream data) throws IOException {
return Hex.encodeHexString(sha256(data));
}
public static String sha256Hex(String data) {
return Hex.encodeHexString(sha256(data));
}
public static byte[] sha384(byte[] data) {
return getSha384Digest().digest(data);
}
public static byte[] sha384(InputStream data) throws IOException {
return digest(getSha384Digest(), data);
}
public static byte[] sha384(String data) {
return sha384(StringUtils.getBytesUtf8(data));
}
public static String sha384Hex(byte[] data) {
return Hex.encodeHexString(sha384(data));
}
public static String sha384Hex(InputStream data) throws IOException {
return Hex.encodeHexString(sha384(data));
}
public static String sha384Hex(String data) {
return Hex.encodeHexString(sha384(data));
}
public static byte[] sha512(byte[] data) {
return getSha512Digest().digest(data);
}
public static byte[] sha512(InputStream data) throws IOException {
return digest(getSha512Digest(), data);
}
public static byte[] sha512(String data) {
return sha512(StringUtils.getBytesUtf8(data));
}
public static String sha512Hex(byte[] data) {
return Hex.encodeHexString(sha512(data));
}
public static String sha512Hex(InputStream data) throws IOException {
return Hex.encodeHexString(sha512(data));
}
public static String sha512Hex(String data) {
return Hex.encodeHexString(sha512(data));
}
/** @deprecated */
@Deprecated
public static String shaHex(byte[] data) {
return sha1Hex(data);
}
/** @deprecated */
@Deprecated
public static String shaHex(InputStream data) throws IOException {
return sha1Hex(data);
}
/** @deprecated */
@Deprecated
public static String shaHex(String data) {
return sha1Hex(data);
}
public static MessageDigest updateDigest(MessageDigest messageDigest, byte[] valueToDigest) {
messageDigest.update(valueToDigest);
return messageDigest;
}
public static MessageDigest updateDigest(MessageDigest messageDigest, ByteBuffer valueToDigest) {
messageDigest.update(valueToDigest);
return messageDigest;
}
public static MessageDigest updateDigest(MessageDigest digest, File data) throws IOException {
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(data));
MessageDigest var3;
try {
var3 = updateDigest(digest, (InputStream)stream);
} finally {
stream.close();
}
return var3;
}
public static MessageDigest updateDigest(MessageDigest digest, InputStream data) throws IOException {
byte[] buffer = new byte[1024];
for(int read = data.read(buffer, 0, 1024); read > -1; read = data.read(buffer, 0, 1024)) {
digest.update(buffer, 0, read);
}
return digest;
}
public static MessageDigest updateDigest(MessageDigest messageDigest, String valueToDigest) {
messageDigest.update(StringUtils.getBytesUtf8(valueToDigest));
return messageDigest;
}
public static boolean isAvailable(String messageDigestAlgorithm) {
return getDigest(messageDigestAlgorithm, (MessageDigest)null) != null;
}
/** @deprecated */
@Deprecated
public DigestUtils() {
this.messageDigest = null;
}
public DigestUtils(MessageDigest digest) {
this.messageDigest = digest;
}
public DigestUtils(String name) {
this(getDigest(name));
}
public MessageDigest getMessageDigest() {
return this.messageDigest;
}
public byte[] digest(byte[] data) {
return updateDigest(this.messageDigest, data).digest();
}
public byte[] digest(String data) {
return updateDigest(this.messageDigest, data).digest();
}
public byte[] digest(ByteBuffer data) {
return updateDigest(this.messageDigest, data).digest();
}
public byte[] digest(File data) throws IOException {
return updateDigest(this.messageDigest, data).digest();
}
public byte[] digest(InputStream data) throws IOException {
return updateDigest(this.messageDigest, data).digest();
}
public String digestAsHex(byte[] data) {
return Hex.encodeHexString(this.digest(data));
}
public String digestAsHex(String data) {
return Hex.encodeHexString(this.digest(data));
}
public String digestAsHex(ByteBuffer data) {
return Hex.encodeHexString(this.digest(data));
}
public String digestAsHex(File data) throws IOException {
return Hex.encodeHexString(this.digest(data));
}
public String digestAsHex(InputStream data) throws IOException {
return Hex.encodeHexString(this.digest(data));
}
}
3. LocalDateTime类
项目应用:设置新增的时间日期
获取当前时间:
LocalDateTime now = LocalDateTime.now(); // 获取当前时间
System.out.println(now); // 2024-02-27T17:09:54.940
System.out.println(LocalDate.now()); // 2024-02-27 获取: 年,月,日
System.out.println(LocalTime.now()); // 17:10:32.190 获取: 时,分,秒,毫秒
获取当前时间的年月日时分秒:
LocalDateTime now = LocalDateTime.now(); // 获取当前时间
int year = now.getYear(); // 获取年份
int month = now.getMonthValue(); // 获取月份
int day = now.getDayOfMonth(); // 获取月中的天数
int hour = now.getHour(); // 获取当前的小时
int minute = now.getMinute(); // 获取当前分钟
int second = now.getSecond(); // 获取当前秒数
在当前时间基础上加上或者减去对应时间:
// 在当前时间基础上加上对应时间
LocalDateTime now = LocalDateTime.now(); // 当前时间
LocalDateTime now1 = now.plusYears(5); // 在当前时间加上5年
LocalDateTime now2 = now.plusMonths(5);// 在当前时间商加上5月
LocalDateTime now3 = now.plusDays(7); // 在当前时间加上7天
LocalDateTime now4 = now.plusHours(2); // 在当前时间加上2个小时
LocalDateTime now5 = now.plusMinutes(30); // 在当前时间加上30分钟
LocalDateTime now6 = now.plusSeconds(30); // 在当前时间加上30秒
// 在当前时间基础上减去对应时间
LocalDateTime now = LocalDateTime.now(); // 当前时间
LocalDateTime now1 = now.minusYears(5); // 在当前时间减上5年
LocalDateTime now2 = now.minusMonths(5);// 在当前时间商减上5月
LocalDateTime now3 = now.minusDays(7); // 在当前时间减上7天
LocalDateTime now4 = now.minusHours(2); // 在当前时间减上2个小时
LocalDateTime now5 = now.minusMinutes(30); // 在当前时间减上30分钟
LocalDateTime now6 = now.minusSeconds(30); // 在当前时间减上30秒
改变当前时间:
LocalDateTime now = LocalDateTime.now(); // 当前时间
LocalDateTime now1 = now.withYear(2060); // 改变当前年份(变成2060年)
LocalDateTime now2 = now.withMonth(12); // 改变当前月份(变成12月份)
LocalDateTime now3 = now.withDayOfMonth(29); //改变当前天数(变成29日)
LocalDateTime now4 = now.withHour(23); // 改变当前小时数(变成23时)
LocalDateTime now5 = now.withMinute(30); // 改变当前分钟(变成30分钟)
LocalDateTime now6 = now.withSecond(23); // 改变当前小时数(变成23时)
LocalDateTime now7 = now.withDayOfYear(60); // 从一月一号开始加上60天
比较两个时间:
LocalDateTime now = LocalDateTime.now(); // 当前时间
LocalDateTime now1 = now.plusYears(5); // 在当前时间加上5年
// 给LocalDateTime 赋值
LocalDateTime of = LocalDateTime.of(2022,2,5,1,1,1);
LocalDateTime of1 = LocalDateTime.of(2022,8,5,1,1,1);
//两个时间作比较,第一个时间减去第二个时间(如果年份相同,比较月份,月份相同比较天数,以此类推)
int compareTo = now1.compareTo(now);
int compareTo1 = now.compareTo(now1);
int compareTo2 = now.compareTo(of);
int compareTo3 = now.compareTo(of1);
System.out.println(now); // 输出 2022-08-13 14:35:52
System.out.println(now1); // 输出 2027-08-13 14:35:52
System.out.println(of); // 输出 2022-02-05T01:01:01
System.out.println(of1); // 输出 2022-08-05T01:01:01
System.out.println(compareTo); // 输出 5年
System.out.println(compareTo1); // 输出 -5年
System.out.println(compareTo2); // 输出 6月
System.out.println(compareTo3); // 输出 8天
给LocalDateTime赋值:
// 给LocalDateTime 赋值
LocalDateTime of = LocalDateTime.of(2022,2,5,1,1,1);
System.out.println(of); // 输出 2022-02-05T01:01:01
// 给LocalDateTime 赋值 注意(text文本格式要于yyyy-MM-dd HH:mm:ss一致,不然会报错)
LocalDateTime parse = LocalDateTime.parse("2022-02-05 01:01:01", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(parse); // 输出 2022-02-05 1:1:1
时间转换:
计算时间差:
LocalDateTime now = LocalDateTime.now(); // 当前时间
// 给LocalDateTime 赋值
LocalDateTime of = LocalDateTime.of(2022,7,13,1,1,1);
Duration duration = Duration.between(of, now); // now - of 时间
long days = duration.toDays(); //相差的天数
long hours = duration.toHours(); //相差的小时数
long minutes = duration.toMinutes(); //相差的分钟数
long millis = duration.toMillis(); //相差毫秒数
参考文章:https://blog.csdn.net/ITKidKid/article/details/126314871
4. ThreadLocal类
项目应用:在添加人员信息时需要获取创建人id,使用ThreadLocal类可以访问登录人员的id信息;
ThreadLocal是JDK提供的线程局部变量工具类,ThreadLocal中填充的变量属于当前线程,对于其他线程隔离。ThreadLocal本身不存储值而是作为一个Key来让线程获取线程的局部变量。
ThreadLocal 概述
- ThreadLocal类用来提供线程内部的局部变量,不同的线程之间不会相互干扰;
- 这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量;
- 在线程的生命周期内起作用,可以减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度.
5.扩展Spring MVC框架的消息转化器
项目需求:在前后端数据交互的时候,后端返回前端数据日期数据不是 yyyy-MM-dd HH:mm:ss 格式,这里就需要用到对象转换器JacksonObjectMapper。(总结:请求和响应的数据格式不匹配)
扩展Spring MVC框架的消息转化器:
- Spring MVC框架的消息转换器是用来处理请求和响应的数据格式转换的组件.
- 在SpringMVC中,java对象转JSON对象是通Jackson实现的,涉及到SpringMVC中的消息转换器MappingJackson2HttpMessageConverter.
- 当请求和响应的数据格式不匹配时,就需要对消息转换器功能进行拓展.
涉及工具——对象转换器JacksonObjectMapper
在自定义的对象转换器中,主要指定了进行JSON数据序列化及反序列化时,LocalDateTime、LocalDate、LocalTime的格式处理方式;以及BigInteger及Long类型数据,直接转换为字符。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
* 该自定义的对象转换器, 主要指定在进行json数据序列化及反序列化时, LocalDateTime、LocalDate、LocalTime的处理方式,
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
// .addSerializer(BigInteger.class, ToStringSerializer.instance)
// .addSerializer(Long.class, ToStringSerializer.instance) // 将long转化为string,可以解决前端页面不能正确显示超过固定尾位数的数字
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
在WebMvcConfig中重写方法:
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 扩展mvc框架的消息转换器,项目启动时即调用,
log.info("扩展消息转换器...");
// 创建消息转换器
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器,底层使用将jackson将java对象转化为json
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 将上面的消息转化器对象追加到mvc的转化器集合中
converters.add(0,messageConverter); // 将我们的转化器放在最前面,实现优先使用
}