From 2235c45510ac7f70b05b9a4fc1e94b15edbe04d6 Mon Sep 17 00:00:00 2001 From: ehlxr Date: Sat, 15 Jul 2023 20:29:51 +0800 Subject: [PATCH] budd-utils module --- budd-common/pom.xml | 12 + budd-utils/pom.xml | 38 ++ .../main/java/io/github/ehlxr/utils/Try.java | 424 ++++++++++++++++++ pom.xml | 1 + 4 files changed, 475 insertions(+) create mode 100644 budd-utils/pom.xml create mode 100644 budd-utils/src/main/java/io/github/ehlxr/utils/Try.java diff --git a/budd-common/pom.xml b/budd-common/pom.xml index b77f81b..fa27c35 100644 --- a/budd-common/pom.xml +++ b/budd-common/pom.xml @@ -40,4 +40,16 @@ guava + + + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + + diff --git a/budd-utils/pom.xml b/budd-utils/pom.xml new file mode 100644 index 0000000..0fc2a3a --- /dev/null +++ b/budd-utils/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + io.github.ehlxr + budd + 0.0.1-SNAPSHOT + + + budd-utils + + + 8 + 8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + \ No newline at end of file diff --git a/budd-utils/src/main/java/io/github/ehlxr/utils/Try.java b/budd-utils/src/main/java/io/github/ehlxr/utils/Try.java new file mode 100644 index 0000000..fc5073f --- /dev/null +++ b/budd-utils/src/main/java/io/github/ehlxr/utils/Try.java @@ -0,0 +1,424 @@ +/* + * The MIT License (MIT) + * + * Copyright © 2020 xrv + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package io.github.ehlxr.utils; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; + +/** + * 异常处理,简化 try catch + * + * @author ehlxr + * @since 2020-12-03 10:37. + */ +public interface Try { + /** + * 构建消费型(有入参,无返回)Tryable 对象 + * + * @param consumer {@link ThrowableConsumer} 类型函数式接口 + * @param

入参类型 + * @return {@link TryConsumer} + */ + static

TryConsumer

of(ThrowableConsumer consumer) { + return new TryConsumer<>(consumer); + } + + /** + * 构建供给型(无入参,有返回)Tryable 对象 + * + * @param supplier {@link ThrowableSupplier} 类型函数式接口 + * @param 返回值类型 + * @return {@link TrySupplier} + */ + static TrySupplier of(ThrowableSupplier supplier) { + return new TrySupplier<>(supplier); + } + + /** + * 构建功能型(有入参,有返回)Tryable 对象 + * + * @param function {@link ThrowableFunction} 类型函数式接口 + * @param

入参类型 + * @param 返回值类型 + * @return {@link TryFunction} + */ + static TryFunction of(ThrowableFunction function) { + return new TryFunction<>(function); + } + + /** + * 构建运行型(无入参,无返回)Tryable 对象 + * + * @param runnable {@link ThrowableRunnable} 类型函数式接口 + * @return {@link TryRunnable} + */ + static TryRunnable of(ThrowableRunnable runnable) { + return new TryRunnable(runnable); + } + + @SuppressWarnings({"ConstantConditions", "Convert2MethodRef"}) + static void main(String[] args) { + System.out.println("------------有返回值,无入参----------------"); + // 有返回值,无入参 + String param = "hello"; + Long result = Try.of(() -> Long.valueOf(param)).get(0L); + System.out.println("Long.valueOf 1: " + result); + + result = Try.of(() -> Long.valueOf(param)).get(); + System.out.println("Long.valueOf 2: " + result); + + System.out.println("------------有返回值,有入参----------------"); + // 有返回值,有入参 + result = Try., Long>of(s -> Long.valueOf(s.get("k1"))) + // .apply(ImmutableMap.of("k1", param)) + .trap(e -> System.out.println("Long.valueOf exception: " + e.getMessage())) + .andFinally(() -> System.out.println("This message will ignore.")) + .andFinally(s -> { + // Map returnMap = JsonUtils.string2Obj(JsonUtils.obj2String(s), new TypeReference>() { + // }); + // System.out.println("Long.valueOf finally run code." + s); + // // 演示抛异常 + // String k2 = returnMap.get("k2").toString(); + // System.out.println(k2); + }) + .finallyTrap(e -> System.out.println("Long.valueOf finally exception: " + e.getMessage())) + .get(); + System.out.println("Long.valueOf 3: " + result); + + ArrayList list = null; + + System.out.println("-----------无返回值,无入参-----------------"); + // 无返回值,无入参 + Try.of(() -> Thread.sleep(-1L)) + .andFinally(() -> list.clear()) + // .andFinally(list::clear) //https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb + .run(); + + System.out.println("--------------无返回值,有入参--------------"); + // 无返回值,有入参 + Try.of(v -> list.add(0, v)) + .andFinally(s -> System.out.println(s)) + .accept("hello"); + } + + class TryRunnable extends Tryable { + private final ThrowableRunnable runnable; + + protected TryRunnable(ThrowableRunnable runnable) { + Objects.requireNonNull(runnable, "No runnable present"); + this.runnable = runnable; + + super.c = this; + } + + /** + * 计算结果 + */ + public void run() { + try { + runnable.run(); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + } finally { + doFinally(); + } + } + } + + class TrySupplier extends Tryable> { + private final ThrowableSupplier supplier; + + protected TrySupplier(ThrowableSupplier supplier) { + Objects.requireNonNull(supplier, "No supplier present"); + this.supplier = supplier; + + super.c = this; + } + + /** + * 如果有异常返回默认值,否则返回计算结果 + * + * @param r 指定默认值 + * @return 实际值或默认值 + */ + public R get(R r) { + try { + return supplier.get(); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + return r; + } finally { + doFinally(); + } + } + + /** + * 如果有异常返回 null,否则返回计算结果 + * + * @return 实际值或 null + */ + public R get() { + try { + return supplier.get(); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + return null; + } finally { + doFinally(); + } + } + } + + @FunctionalInterface + interface ThrowableConsumer

{ + /** + * Performs this operation on the given argument. + * + * @param p the input argument + * @throws Throwable throwable + */ + void accept(P p) throws Throwable; + } + + @FunctionalInterface + interface ThrowableSupplier { + /** + * Gets a result. + * + * @return a result + * @throws Throwable throwable + */ + R get() throws Throwable; + } + + @FunctionalInterface + interface ThrowableRunnable { + /** + * Performs this operation + * + * @throws Throwable throwable + */ + void run() throws Throwable; + } + + @FunctionalInterface + interface ThrowableFunction { + /** + * Applies this function to the given argument. + * + * @param p the function argument + * @return the function result + * @throws Throwable throwable + */ + R apply(P p) throws Throwable; + } + + abstract class Tryable { + Consumer throwConsumer; + ThrowableRunnable finallyRunnable; + ThrowableConsumer finallyConsumer; + Consumer finallyThrowConsumer; + C c; + + /** + * 处理 finally + */ + protected void doFinally() { + Optional.ofNullable(finallyRunnable).ifPresent(r -> { + try { + r.run(); + } catch (final Throwable e) { + Optional.ofNullable(finallyThrowConsumer).ifPresent(tc -> tc.accept(e)); + } + }); + } + + /** + * 处理带参数类型 finally + * + * @param p 入参 + * @param

入参类型 + */ + protected

void doFinally(P p) { + if (Objects.nonNull(finallyConsumer)) { + try { + finallyConsumer.accept(p); + } catch (final Throwable e) { + Optional.ofNullable(finallyThrowConsumer).ifPresent(tc -> tc.accept(e)); + } + } else { + doFinally(); + } + } + + /** + * 如果有异常,调用自定义异常处理表达式 + * + * @param throwableConsumer 自定义异常处理 lambda 表达式 + * @return {@link C} + */ + public C trap(Consumer throwableConsumer) { + Objects.requireNonNull(throwableConsumer, "No throwableConsumer present"); + this.throwConsumer = throwableConsumer; + return c; + } + + /** + * 自定义 finally 处理表达式 + *

+ * 注意:如果类型为 {@link TryConsumer}、{@link TryFunction} 并且已经调用 {@link #andFinally(ThrowableConsumer)} 则忽略 + * + * @param finallyRunnable finally 处理 lambda 表达式 + * @return {@link C} + */ + public C andFinally(ThrowableRunnable finallyRunnable) { + Objects.requireNonNull(finallyRunnable, "No finallyRunnable present"); + this.finallyRunnable = finallyRunnable; + return c; + } + + /** + * 自定义 finally 处理表达式 + *

+ * 注意:只会对 {@link TryConsumer}、{@link TryFunction} 类型对象起作用 + * + * @param finallyConsumer finally 处理 lambda 表达式 + * @return {@link C} + */ + public C andFinally(ThrowableConsumer finallyConsumer) { + Objects.requireNonNull(finallyConsumer, "No finallyConsumer present"); + this.finallyConsumer = finallyConsumer; + return c; + } + + /** + * 如果 finally 有异常,调用自定义异常处理表达式 + * + * @param finallyThrowableConsumer 自定义异常处理 lambda 表达式 + * @return {@link C} + */ + public C finallyTrap(Consumer finallyThrowableConsumer) { + Objects.requireNonNull(finallyThrowableConsumer, "No finallyThrowableConsumer present"); + this.finallyThrowConsumer = finallyThrowableConsumer; + return c; + } + } + + class TryConsumer

extends Tryable> { + private final ThrowableConsumer consumer; + + protected TryConsumer(ThrowableConsumer consumer) { + Objects.requireNonNull(consumer, "No consumer present"); + this.consumer = consumer; + + super.c = this; + } + + /** + * 计算结果 + * + * @param p 要计算的入参 + */ + public void accept(P p) { + try { + Objects.requireNonNull(p, "No accept param present"); + + consumer.accept(p); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + } finally { + // doFinally(); + doFinally(p); + } + } + } + + class TryFunction extends Tryable> { + private final ThrowableFunction function; + private P p; + + protected TryFunction(ThrowableFunction function) { + Objects.requireNonNull(function, "No function present"); + this.function = function; + + super.c = this; + } + + /** + * 传入要计算的入参 + * + * @param p 要计算的入参 + * @return {@link TryFunction} + */ + public TryFunction apply(P p) { + Objects.requireNonNull(p, "Apply param should not null"); + + this.p = p; + return this; + } + + /** + * 如果有异常返回默认值,否则返回计算结果 + * + * @param r 指定默认值 + * @return 实际值或默认值 + */ + public R get(R r) { + try { + Objects.requireNonNull(function, "No apply param present"); + + return function.apply(p); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + return r; + } finally { + // doFinally(); + doFinally(p); + } + } + + /** + * 如果有异常返回 null,否则返回计算结果 + * + * @return 实际值或 null + */ + public R get() { + try { + Objects.requireNonNull(p, "No apply param present"); + + return function.apply(p); + } catch (final Throwable e) { + Optional.ofNullable(throwConsumer).ifPresent(tc -> tc.accept(e)); + return null; + } finally { + // doFinally(); + doFinally(p); + } + } + } +} diff --git a/pom.xml b/pom.xml index 041b1c2..a90ff7b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,6 +6,7 @@ budd-common budd-demo budd-server + budd-utils io.github.ehlxr