自行封装 [散装 常用工具类]

import javax.annotation.Nonnull;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


/**
 * @author fengbinbin
 * @version 1.0
 * @since 2021/1/7 14:28
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(@Nonnull ApplicationContext ctx) {
        applicationContext = ctx;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

/**
 * 机构的数据源支持, 通过实例化jdbcTemplate来进行实现
 *
 * 在上传机构配置的时候, 会根据对应的数据源配置创建jdbcTemplate对象
 * 之后所有的数据库操作, 都是通过 路由键 来 获取指定的jdbcTemplate来实现的
 *
 * @author fengbinbin
 * @since 2020-05-20 20:17
 **/
@Slf4j
@Component
@Validated
public class JdbcTemplateHolder {

    /**
     * 缓存 jdbcTemplate
     */
    private static final Map<String, NamedParameterJdbcOperations> HOLDER = new ConcurrentHashMap<>(20);
    /**
     * 路由键 作为线程变量
     */
    private static final ThreadLocal<String> LOCAL_ROUTE_KEY = ThreadLocal.withInitial(String::new);

    /**
     * 注册数据源
     *
     * @param key key
     * @param dataSource 数据源
     */
    public void register(
        @NotBlank(message = "illegal key") String key,
        @NotNull(message = "illegal dataSource") DataSource dataSource) {
        HOLDER.put(key, new NamedParameterJdbcTemplate(dataSource));
    }

    /**
     * 获取jdbcTemplate
     */
    public NamedParameterJdbcOperations get() {
        String routeKey = Variables.requireNotBlank(LOCAL_ROUTE_KEY.get(), " can not find local jdbcTemplate key");

        return Objects.requireNonNull(HOLDER.get(routeKey), " jdbcTemplate is null, please check ");
    }

    /**
     * 指定 key
     * @param key jdbcTemplate key
     */
    public static void assign(@NotBlank(message = "illegal jdbcTemplate key") String key) { LOCAL_ROUTE_KEY.set(key); }

    /**
     * 移除key
     */
    public static void removeKey() { LOCAL_ROUTE_KEY.remove();}

    /**
     * 获取所有数据源
     * @return 所有数据源
     */
    public Map<String, NamedParameterJdbcOperations> getHolder() {
        return HOLDER;
    }

    /**
     * jdbcTemplate 路由器, 使用ThreadLocal 来从{@link JdbcTemplateHolder}中获取对应key来实现路由
     */
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    public static class JdbcRouters {

        /**
         * 使用方法和PageHelper类似, 但是 {@link RouteJdbcTemplate}中的方法, 会自动释放掉ThreadLocal变量
         *
         * 指定 jdbcTemplate, 必须在和数据库交互之前调用!!!!! 否则无效
         * 且只能生效一次! 当用完之后, 需要再次设置路由, 路由才能生效
         * @param jdbcTemplateKey key
         */
        public static void doRoute(String jdbcTemplateKey) {
            JdbcTemplateHolder.assign(jdbcTemplateKey);
        }
    }
}

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Spliterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 用来对同一个流执行多种操作
 * 流拷贝
 *
 * @author fengbinbin
 * @version 1.0
 * @since 2020/7/20 15:31
 */
public class StreamForks<T> {

    private final Stream<T> stream;
    private final Map<Object, Function<Stream<T>, ?>> forks = new HashMap<>(16);

    public StreamForks(Stream<T> stream) {
        this.stream = stream;
    }

    public static <T> StreamForks<T> of(Collection<T> collection) {
        return new StreamForks<>(collection.stream());
    }

    public static <T> StreamForks<T> of(T[] array) {
        return new StreamForks<>(Stream.of(array));
    }

    public StreamForks<T> fork(Object key, Function<Stream<T>, ?> fn) {
        forks.put(key, fn);
        return this;
    }

    public ForkResult done() {
        ForkingStreamConsumer<T> consumer = build();

        try {
            stream.sequential().forEach(consumer);
        } finally {
            consumer.finish();
        }
        return consumer;
    }

    private ForkingStreamConsumer<T> build() {
        List<BlockingQueue<T>> queues = new ArrayList<>(10);

        Map<Object, Future<?>> actions = forks.entrySet().stream().reduce(new HashMap<>(16), (map, e) -> {
            map.put(e.getKey(), getForkResult(queues, e.getValue()));
            return map;
        }, (m1, m2) -> {
            m1.putAll(m2);
            return m1;
        });

        return new ForkingStreamConsumer<>(queues, actions);
    }

    private Future<?> getForkResult(List<BlockingQueue<T>> queues, Function<Stream<T>, ?> fn) {
        BlockingQueue<T> queue = new LinkedBlockingQueue<>();
        queues.add(queue);
        Spliterator<T> spliterator = new BlockingQueueSpliterator<>(queue);
        Stream<T> source = StreamSupport.stream(spliterator, false);

        return CompletableFuture.supplyAsync(() -> fn.apply(source));
    }

    /**
     * fork操作后返回的结果
     */
    public interface ForkResult {

        /**
         * 获取fork操作后的结果
         *
         * @param key fork key
         * @param <R> 结果
         * @return 返回fork处理后的结果
         */
        <R> R get(Object key);
    }

    @SuppressWarnings("unchecked")
    public static class ForkingStreamConsumer<T> implements Consumer<T>, ForkResult {

        static final Object END_OF_STREAM = new Object();

        private final List<BlockingQueue<T>> queues;
        private final Map<Object, Future<?>> actions;

        public ForkingStreamConsumer(List<BlockingQueue<T>> queues, Map<Object, Future<?>> actions) {
            this.queues = queues;
            this.actions = actions;
        }

        void finish() {
            accept((T) END_OF_STREAM);
        }

        @Override
        public <R> R get(Object key) {
            try {
                return ((Future<R>) actions.get(key)).get();
            } catch (Exception exception) {
                throw new RuntimeException(exception);
            }
        }

        @Override
        public void accept(T t) {
            queues.forEach(q -> q.add(t));
        }
    }

    public static class BlockingQueueSpliterator<T> implements Spliterator<T> {

        private final BlockingQueue<T> queue;

        public BlockingQueueSpliterator(BlockingQueue<T> queue) {
            this.queue = queue;
        }

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            T t;

            while (true) {
                try {
                    t = queue.take();
                    break;
                } catch (InterruptedException exception) {
                    throw new RuntimeException(exception);
                }
            }

            if (t != ForkingStreamConsumer.END_OF_STREAM) {
                action.accept(t);
                return true;
            }

            return false;
        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }

        @Override
        public long estimateSize() {
            return 0;
        }

        @Override
        public int characteristics() {
            return 0;
        }
    }
}

import static org.apache.commons.lang3.reflect.MethodUtils.invokeMethod;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.util.regex.Pattern;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.reflect.FieldUtils;

/**
 * Attribute tool class, get attribute name according to lambda Borrow mybatis plus!!!!!!!
 *
 * @author fengbinbin
 * @version 1.0
 * @since 2020/5/25 10:33
 */
@UtilityClass
@SuppressWarnings("unchecked")
public class Fields {

    private final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*");
    private final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*");

    public <T> String fieldName(Fn<T> fn) {
        try {
            SerializedLambda serializedLambda = (SerializedLambda) invokeMethod(fn, true, "writeReplace");
            String getter = serializedLambda.getImplMethodName();

            if (GET_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(3);
            } else if (IS_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(2);
            }

            return Introspector.decapitalize(getter);
        }
        catch (ReflectiveOperationException exception) { throw new UnsupportedOperationException("get field name error", exception); }
    }

    public void write(Object object, Field field, Object value) { write(object, field.getName(), value); }

    public void write(Object object, String fieldName, Object value) {
        try {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fieldName, object.getClass());
            propertyDescriptor.getWriteMethod().invoke(object, value);
        }
        catch (Exception exception) {
            throw new UnsupportedOperationException(
                "write field fail, Class is: [" + object.getClass() + "], field named: [" + fieldName + "]", exception);
        }
    }

    public <T> T read(Object object, Field field) {
        return read(object, field.getName());
    }

    public <T> T read(Object object, String fieldName) {
        try {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(fieldName, object.getClass());
            return (T) propertyDescriptor.getReadMethod().invoke(object);
        }
        catch (Exception exception) {
            throw new UnsupportedOperationException(
                "read field fail, Class is: [" + object.getClass() + "], field named: [" + fieldName + "]", exception);
        }
    }

    public <T> T readStatic(Class<?> clazz, String staticFieldName) {
        try { return (T)FieldUtils.readStaticField(clazz, staticFieldName, true); }
        catch (IllegalAccessException exception) {
            throw new UnsupportedOperationException( "read static field fail, Class is: [" + clazz+ "], static field named: [" + staticFieldName + "]", exception);
        }
    }

    public <T extends Number> Class<T> readPrimitiveClass(Class<T> numberClass) { return readStatic(numberClass, "TYPE"); }

    @FunctionalInterface
    public interface Fn<T> extends Serializable {

        /**
         * declare field
         * @param object object
         * @return attribute
         */
        Object apply(T object);
    }
}

 

import static java.util.stream.Collectors.joining;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 应用异常处理器
 *
 * @author fengbinbin
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 业务异常
     * @param exception 异常对象
     * @return 异常对应的响应
     */
    @ExceptionHandler(BusinessException.class)
    public Response handleBusinessException(BusinessException exception) {
        log.error("OFF PAY BusinessException: {}", exception.getRtnMsg());

        return Response.fail(exception.getRtnCode(), exception.getRtnMsg());
    }

    /**
     * 参数绑定异常
     *
     * @param exception 异常对象
     * @return 异常响应对象
     */
    @ExceptionHandler(value = BindException.class)
    public Response handleBindException(BindException exception) {
        String exceptionMessage = exception.getBindingResult().getAllErrors().stream()
            .map(ObjectError::getDefaultMessage).collect(joining(";"));

        log.error("OFF PAY BindException: {}", exceptionMessage);

        return Response.fail(exceptionMessage);
    }

    /**
     * 应用异常, 包含异常code
     *
     * @param exception 异常对象
     * @return 异常响应对象
     */
    @ExceptionHandler(ApplicationException.class)
    public Response handleApplicationException(ApplicationException exception) {
        log.error("OFF PAY BusinessException: {}", exception.getMessage());

        return Response.fail(exception.getCode(), exception.getMessage());
    }

    /**
     * {@link RequestParam } 参数校验 异常
     * @param exception 异常对象
     * @return 异常对应的响应对象
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Response handleMissingServletRequestParameterException(MissingServletRequestParameterException exception) {
        log.error("OFF PAY BusinessException: {}", exception.getMessage());

        return Response.fail(exception.getMessage());
    }

    /**
     * 方法级别参数校验异常
     * @param exception 异常对象
     * @return 异常对应的响应对象
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Response handleConstraintViolationException(ConstraintViolationException exception) {
        String exceptionMessage = exception.getConstraintViolations().stream().map(ConstraintViolation::getMessage)
            .collect(joining(";"));

        log.error("OFF PAY ConstraintViolationException: {}", exceptionMessage);

        return Response.fail(exceptionMessage);
    }
    /**
     * 处理 jsr303 异常
     *
     * @param exception 异常对象
     * @return 校验异常统一响应对象
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        log.error("OFF PAY MethodArgumentNotValidException: {}", exception.getMessage());

        return Response.fail(exception.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * 请求方式异常
     *
     * @param exception 异常对象
     * @return 请求方式异常对象
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Response handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
        log.error("OFF PAY HttpRequestMethodNotSupportedException: {}", exception.getMessage());

        return Response.fail("unSupport http method");
    }

    /**
     * 拦截未知的运行时异常
     *
     * @param exception 异常对象
     * @return 异常响应
     */
    @ExceptionHandler(RuntimeException.class)
    public Response handleRuntimeException(RuntimeException exception) {
        log.error("OFF PAY RuntimeException: {}", exception.getMessage());

        return Response.fail(exception.getMessage());
    }
}

import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * completable future tool
 * use {@link ThreadPoolTaskExecutor} to deal task
 *
 * @author fengbinbin
 * @version 1.0
 * @since 2020/10/13 11:15
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class Futures implements InitializingBean {

    private static Futures self;
    private final ThreadPoolTaskExecutor executor;

    public static <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {
        return CompletableFuture.supplyAsync(supplier, self.executor);
    }

    public static CompletableFuture<Void> runAsync(Runnable runnable) {
        return CompletableFuture.runAsync(runnable, self.executor);
    }

    @Override
    public void afterPropertiesSet() { self = this; }
}

import java.util.function.Supplier;
import lombok.experimental.UtilityClass;

/**
 * 本类所有方法都会>>>抑制空指针异常<<<, 从而进行进一步的操作
 * 本类不能完全替代 Optional {@link java.util.Optional}
 * 但是某些场景能获得比Optional更好的 代码可读性 和 简洁性
 *
 * 使用示例: NullSafe.nullDefault(() -> user.getName().getLength(), "xx")
 *  此例中 user对象为null, 整个方法将返回指定的默认值 "xx"
 *
 * @apiNote 本类中的所有Lambda禁止使用方法引用来替代!!!
 * @author fengbinbin
 */
@UtilityClass
public class NullSafe {

    /**
     * 示例: String nameLength = NullSafe.nullable(() -> user.getName().length());
     * 如果user为空,不会抛出空指针异常,返回null
     *   # 不能使用方法引用来代替!!!!!! #
     * @param supplier supplier
     * @param <T> 返回值类型
     * @return 抑制空指针异常, 返回null
     */
    public static <T> T nullable(Supplier<T> supplier) {
        try { return supplier.get(); }
        catch (NullPointerException e) { return null; }
    }

    /**
     * 为空则使用默认值
     *
     * @param supplier supplier
     * @param defaultValue 默认值
     * @param <T> 返回值类型
     * @return 抑制空指针异常, 返回默认值
     */
    public static <T> T nullDefault(Supplier<T> supplier, T defaultValue) {
        try { return supplier.get(); }
        catch (NullPointerException e) { return defaultValue; }
    }

    /**
     * 为空则抛出 指定异常
     *
     * @param supplier supplier
     * @param exception 异常对象
     * @param <T> 返回值类型
     * @return 抑制空指针异常, 返回自定义异常对象
     */
    public static <T> T nullThrow(Supplier<T> supplier, RuntimeException exception) {
        try { return supplier.get(); }
        catch (NullPointerException e) { throw exception; }
    }

    public void nullThrow(Runnable runnable, RuntimeException exception) {
        try { runnable.run(); }
        catch (NullPointerException e) { throw exception; }
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值