Springboot中常用工具类

1)对象属性拷贝:

前提条件是两个类中的属性名称要相同,属性个数可以不同,使用org.Springframework.beans中的BeanUtils工具类,调用内部的copyProgects方法,次方法第一个参数表示要拷贝的类,第一个参数表示要拷贝到的类

ag: 将addEmployeeDTO类中的属性拷贝到employee类中

java 复制代码
// 对象属性拷贝
BeanUtils.copyProperties(addEmployeeDTO,employee);

2)MD5加密:

将密码存入数据库时一般进行加密,这里使用org.Springframework.util中的md5DigestAsHex方法,参数为字节数组

ag:将字符串密码1234进行加密

java 复制代码
// 设置密码(默认密码)
employee.setPassword(DigestUtils.md5DigestAsHex("1234".getBytes(StandardCharsets.UTF_8)));

3)ThreadLocal:

threadLocal并不是一个线程,二是thread的局部变量,ThreadLocal为每一个线程单独提供一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外择不能访问(每一次请求就是一个单独的线程)

ThreadLocal常用方法:

  • public void set(T value):设置当前线程的线程局部变量的值

  • Public T get():返回当前线程对应的线程局部变量的值

  • public void remove():移除当前线程的线程局部变量

java 复制代码
/**
 * ThreadLocal工具类
 */
public class BaseContext {
    // 创建一个ThreadLocal的对象
    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    // 定义一个方法调用ThreadLocal内部的set方法
    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }
    // 定义一个方法调用ThreadLocal内部的get方法
    public static Long getCurrentId() {
        return threadLocal.get();
    }
    //  定义一个方法调用ThreadLocal内部的remove方法
    public static void removeCurrentId() {
        threadLocal.remove();
    }
}

4)使用pageHelper简化分页查询:

引入依赖:

java 复制代码
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>版本号</version>
</dependency>

调用PageHelper中的startPage方法进行分页:

java 复制代码
// 参数1:表示页数
// 参数2:表示每页的记录数
PageHelper.startPage(参数1,参数2);

如果分页查询还有其它选项,就可以单独编写sql语句,但返回的结果必须为PageHelper包下的Page类型,范型为对应的实体:

eg:

java 复制代码
 public PageResult selectEmployeePageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        // 开始分页查询
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        // 分页查询的基础上添加姓名的模糊查询
        Page<Employee> page = employeeMapper.selectPage(employeePageQueryDTO);
        // 获取page中的数据转换为PageResult结果
        long total = page.getTotal();       // 获取中的记录数
        List<Employee> result = page.getResult();   // 获取查询到的结果
        return new PageResult(total,result);
    }

对应的映射文件中就可以直接编写拼接的sql:

java 复制代码
<select id="selectPage" resultType="com.sky.entity.Employee">
      select * from employee
      <where>
          <if test="name != null and name != ''">
              and name like concat('%',#{name},'%')
          </if>
      </where>
</select>

5)处理后端响应前端时的LocalDateTime时间格式问题:

**方法一:**在对应的实体类中的LocalDateTime类型的数据上添加@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解

java 复制代码
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

方法二: 扩展springMVC的消息转换器,创建类继承WebMvcConfigurationSupport类重写内部的extendMessageConverters方法

java 复制代码
/**
     * 扩展spring MVC的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 创建一个消息转换器对象
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        // 设置对象转换器,可以将Java对象转换为json字符串
        mappingJackson2HttpMessageConverter.setObjectMapper(new 消息转换器类对象);
        // 将自己的转换器对象放入spring MVC框架中
        converters.add(0,mappingJackson2HttpMessageConverter);
    }

对象转换器类:

java 复制代码
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]
 */
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)));
​
        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

**注意:**方法二继承的类与Swagger继承的类相同

6)公共字段自动填充

数据库中多张表中都有重复字段时,可以使用公共字段填充,减少开发中代码的冗余

实现思路:

  • 自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法

  • 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值

  • 在Mapper的方法上加入AutoFill的注解

eg:

自定义注解:

java 复制代码
/**
 * 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
 */
@Target(ElementType.METHOD)         // target标识该注解加入的位置,这里设置只能添加到方法上
@Retention(RetentionPolicy.RUNTIME) // 用于指定注解的保留策略。RetentionPolicy.RUNTIME 表示该注解在运行时仍然可用。
public @interface AutoFill {
    // 使用枚举标,识数据库操作类型
    OperationType value();
}

枚举类实现:

java 复制代码
/**
 * 数据库操作类型
 */
public enum OperationType {
    // 更新操作
    UPDATE,
  
    // 插入操作
    INSERT
}

自定义切面类:

java 复制代码
/**
 *  自定义切面类,实现公共字段自动填充的处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 定义切入点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}
​
    /**
     * 前置通知,在通知中进行公共字段的赋值
     */
    @Before("autoFillPointCut()")
    public void autofill(JoinPoint joinPoint){
        log.info("开始公共字段自动填充···");
        // 获取当前被拦截的方法上的数据库的操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();     // 获取被拦截方法的签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);    // 获取方法上的注解对象
        OperationType operationType = autoFill.value();                             // 获取数据库操作类型
        // 获取当前被拦截的方法的参数--实体对象
        Object[] args = joinPoint.getArgs();                                        // 获取所有的参数
        // 判断获取的参数是否为空
        if (args == null || args.length == 0){
            return;
        }
        // 获取实体类对象
        Object entity = args[0];
        // 准备赋值的数据
        LocalDateTime nowTime = LocalDateTime.now();                                // 当前时间
        Long currentId = BaseContext.getCurrentId();                                // 获取当前用户ID
        // 根据当前不同的操作类型,为对应的属性通过反射进行赋值
        if(operationType == OperationType.INSERT){
            // 获取对应实体类中的set方法进行赋值
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 通过反射进行赋值
                setCreateTime.invoke(entity,nowTime);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,nowTime);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else if (operationType == OperationType.UPDATE) {
            // 获取对应实体类中的set方法进行赋值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 通过反射进行赋值
                setUpdateTime.invoke(entity,nowTime);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
相关推荐
先睡3 小时前
Redis的缓存击穿和缓存雪崩
redis·spring·缓存
Albert Edison5 小时前
【最新版】IntelliJ IDEA 2025 创建 SpringBoot 项目
java·spring boot·intellij-idea
Piper蛋窝6 小时前
深入 Go 语言垃圾回收:从原理到内建类型 Slice、Map 的陷阱以及为何需要 strings.Builder
后端·go
Bug退退退1237 小时前
RabbitMQ 高级特性之死信队列
java·分布式·spring·rabbitmq
六毛的毛9 小时前
Springboot开发常见注解一览
java·spring boot·后端
AntBlack9 小时前
拖了五个月 ,不当韭菜体验版算是正式发布了
前端·后端·python
31535669139 小时前
一个简单的脚本,让pdf开启夜间模式
前端·后端
uzong9 小时前
curl案例讲解
后端
开开心心就好10 小时前
免费PDF处理软件,支持多种操作
运维·服务器·前端·spring boot·智能手机·pdf·电脑
一只叫煤球的猫10 小时前
真实事故复盘:Redis分布式锁居然失效了?公司十年老程序员踩的坑
java·redis·后端