SpringBoot--手写常用工具类

原文网址:SpringBoot--手写常用工具类_IT利刃出鞘的博客-CSDN博客

简介

        本文介绍我自己手写的一些SpringBoot的工具类,很好用。

获得SpringContext

说明

        可以通过本工具类静态获取ApplicationContext,从而进一步使用ApplicationContext进行处理,比如:从容器中获取bean。

优点

        方便快捷,调用者直接使用静态方法即可,调用者无需自己再去实现ApplicationContextAware接口。

相关网址

Spring(SpringBoot)--ApplicationContext--使用/教程/原理_IT利刃出鞘的博客-CSDN博客

代码

package com.knife.common.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        ApplicationContextHolder.context = context;
    }

    public static ApplicationContext getContext() {
        return context;
    }
}  

用法

  • 根据class获得bean
    • Xxx xxx = ApplicationContextHolder.getContext().getBean(Xxx.class);
  • 根据名字获得代理后的bean(常用)
    • Xxx xxx = ApplicationContextHolder.getContext().getBean("userService");
  • 根据名字获得未代理的bean(即FactoryBean)(不常用)
    • Xxx xxx = ApplicationContextHolder.getContext().getBean("&userService");

Json转换

说明

        本工具是对Jackson(也就是ObjectMapper)的封装。

优点

  1. 调用者无需捕获异常
    1. 本工具捕获了checked 异常,然后抛出RuntimeException,所以无需外部捕获
  2. 缺陷少
    1. 本文基于Jackson,没有FastJson那么多bug

相关网址

Jackson--使用/教程/示例_IT利刃出鞘的博客-CSDN博客_jackson教程

代码

package com.knife.common.util;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;
import java.util.Map;

/**
 * Json工具
 */
public class JsonUtil {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        // 反序列化:JSON字段中有Java对象中没有的字段时不报错
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 反序列化:不允许基本类型为null
        //objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);

        // 序列化:序列化BigDecimal时不使用科学计数法输出
        objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);

        // 序列化:Java对象为空的字段不拼接JSON
        //objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    public static <T> T getObjectFromString(String string, Class<T> cls) {
        try {
            return objectMapper.readValue(string, cls);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("rawtypes")
    public static Map getMapFromString(String str) {
        try {
            return objectMapper.readValue(str, Map.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T getMapFromString(String str, TypeReference<T> valueTypeRef) {
        try {
            return objectMapper.readValue(str, valueTypeRef);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getStringFromObject(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> List<T> getObjectListFromString(String string, TypeReference<List<T>> typeReference) {
        try {
            return objectMapper.readValue(string, typeReference);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static JsonNode getTreeFromString(String string) {
        try {
            return objectMapper.readTree(string);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}

用法

跟ObjectMapper一样。例如:User user = JsonUtil.getObjectFromString(str, User.class);

获得空值属性名

说明

        可以获得某个对象中值为空(为null或者空字符串等)的属性名,然后可以用于作为BeanUtils.copyProperties的最后一个参数,不拷贝这些空的属性。

优点

        方便快捷。

相关网址

Spring--BeanUtils忽略空值拷贝--方法/实例_IT利刃出鞘的博客-CSDN博客_bean拷贝忽略空值

代码

package com.example.util;
 
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
 
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
 
public class PropertyUtil {
    public static String[] getNullPropertyNames(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();
 
        Set<String> emptyNames = new HashSet<>();
 
        for (PropertyDescriptor pd : pds) {
            //check if value of this property is null then add it to the collection
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null){
                emptyNames.add(pd.getName());
            }
        }
 
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
}

用法

package com.example.controller;
 
import com.example.entity.Blog;
import com.example.entity.User;
import com.example.util.PropertyUtil;
import com.example.vo.BlogRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.time.LocalDateTime;
import java.util.Arrays;
 
@RestController
public class HelloController {
    @Autowired
    private ObjectMapper objectMapper;
 
    @GetMapping("/test")
    public String test() {
        BlogRequest blogRequest = new BlogRequest();
        blogRequest.setId(10L);
        blogRequest.setTitle("Java实战");
        // blogRequest.setContent("本文介绍获取null的字段名的方法");
        blogRequest.setUser(new User());
        blogRequest.setCreateTime(LocalDateTime.now());
        // blogRequest.setCreateTime(LocalDateTime.now());
        blogRequest.setDeletedFlag(0L);
 
        User user = new User();
        user.setId(15L);
        user.setUserName("Tony");
        // user.setNickName("Iron Man");
        // user.setStatus(1);
 
        String[] nullPropertyNames = PropertyUtil.getNullPropertyNames(blogRequest);
        System.out.println(Arrays.toString(nullPropertyNames));
 
        System.out.println("------------------------------");
        Blog blog = new Blog();
        BeanUtils.copyProperties(blogRequest, blog, nullPropertyNames);
 
        try {
            System.out.println(objectMapper.writeValueAsString(blog));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
 
        return "test success";
    }
}

获取异常的堆栈信息

说明

        本工具类可以打印详细的异常堆栈的信息。

        比如:在抛出NullPointException时,message是这样的:java.lang.NullPointException。用本工具可以获得方法的调用流程,方便排查问题。

优点

异常信息很详细

代码

package com.knife.common.util;

/**
 * 异常工具类
 */
public class ThrowableUtil {
    /**
     * 获取以指定包名为前缀的堆栈信息
     *
     * @param e             异常
     * @return 堆栈信息
     */
    public static String getStackTrace(Throwable e) {
        StringBuilder s = new StringBuilder().append(e);
        for (StackTraceElement traceElement : e.getStackTrace()) {
            s.append("    at ").append(traceElement);
        }
        return s.toString();
    }

    /**
     * 获取以指定包名为前缀的堆栈信息
     *
     * @param e             异常
     * @param packagePrefix 包前缀
     * @return 堆栈信息
     */
    public static String getStackTraceByPackage(Throwable e, String packagePrefix) {
        StringBuilder s = new StringBuilder().append(e);
        for (StackTraceElement traceElement : e.getStackTrace()) {
            if (!traceElement.getClassName().startsWith(packagePrefix)) {
                break;
            }
            s.append("    at ").append(traceElement);
        }
        return s.toString();
    }

    /**
     * 获取最后n条堆栈信息
     * @param e 异常对象
     * @param n 最后n条
     * @return 错误信息
     */
    public static String getLastStackTrace(Throwable e, Integer n) {
        Integer lineNumber = n;
        if (lineNumber == null) {
            lineNumber = 10;
        }

        StringBuilder s = new StringBuilder().append(e);
        int i = 0;
        for (StackTraceElement traceElement : e.getStackTrace()) {
            s.append("    at ").append(traceElement);
            if (i >= lineNumber) {
                break;
            }
            i++;
        }
        return s.toString();
    }
}

用法

try{
    ...
} catch(Exception e) {
    log.error(ThrowableUtil.getLastStackTrace(e, 10));
}

字段校验

说明

        本工具可以手动对@NotBlank、@NotNull等字段进行校验。

        使用场景:controller接口的入参很多,需要他人提供,但他人提供的类的字段很多,字段都没有加@NotNull等注解;而且这个类以后很可能再变动。

        解决方案:写一个中间类,将入参转换为中间类,在中间类的字段上加@NotBlank等注解,然后用本工具手动校验它。

优点

利用@NotBlank等校验,方便快捷

相关网址

SpringBoot--用hibernate validator手动校验--方法/实例_IT利刃出鞘的博客-CSDN博客_springboot 手动校验

代码

package com.knife.common.util;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.util.Set;

/**
 * hibernate validator的校验工具
 */
public class ValidateUtil {
    private static final Validator validator =
            Validation.buildDefaultValidatorFactory().getValidator();

    /**
     * 校验实体类
     */
    public static <T> void validate(T t) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
        if (constraintViolations.size() > 0) {
            StringBuilder validateError = new StringBuilder();
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                validateError.append(constraintViolation.getMessage()).append(";");
            }

            throw new ValidationException(validateError.toString());
        }
    }

    /**
     * 通过组来校验实体类
     */
    public static <T> void validate(T t, Class<?>... groups) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t, groups);
        if (constraintViolations.size() > 0) {
            StringBuilder validateError = new StringBuilder();
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                validateError.append(constraintViolation.getMessage()).append(";");
            }

            throw new ValidationException(validateError.toString());
        }
    }
}

用法

User user = new User();
//对user字段赋值
ValidateUtil.validate(user);

猜你喜欢

转载自blog.csdn.net/feiying0canglang/article/details/125235541