All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.core.exceptions.ExceptionUtil Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.core.exceptions;

import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 异常工具类
 *
 * @author Looly
 */
public class ExceptionUtil {

	/**
	 * 获得完整消息,包括异常名,消息格式为:{SimpleClassName}: {ThrowableMessage}
	 *
	 * @param e 异常
	 * @return 完整消息
	 */
	public static String getMessage(Throwable e) {
		if (null == e) {
			return StrUtil.NULL;
		}
		return StrUtil.format("{}: {}", e.getClass().getSimpleName(), e.getMessage());
	}

	/**
	 * 获得消息,调用异常类的getMessage方法
	 *
	 * @param e 异常
	 * @return 消息
	 */
	public static String getSimpleMessage(Throwable e) {
		return (null == e) ? StrUtil.NULL : e.getMessage();
	}

	/**
	 * 使用运行时异常包装编译异常
*

* 如果传入参数已经是运行时异常,则直接返回,不再额外包装 * * @param throwable 异常 * @return 运行时异常 */ public static RuntimeException wrapRuntime(Throwable throwable) { if (throwable instanceof RuntimeException) { return (RuntimeException) throwable; } return new RuntimeException(throwable); } /** * 将指定的消息包装为运行时异常 * * @param message 异常消息 * @return 运行时异常 * @since 5.5.2 */ public static RuntimeException wrapRuntime(String message) { return new RuntimeException(message); } /** * 包装一个异常 * * @param 被包装的异常类型 * @param throwable 异常 * @param wrapThrowable 包装后的异常类 * @return 包装后的异常 * @since 3.3.0 */ @SuppressWarnings("unchecked") public static T wrap(Throwable throwable, Class wrapThrowable) { if (wrapThrowable.isInstance(throwable)) { return (T) throwable; } return ReflectUtil.newInstance(wrapThrowable, throwable); } /** * 包装异常并重新抛出此异常
* {@link RuntimeException} 和{@link Error} 直接抛出,其它检查异常包装为{@link UndeclaredThrowableException} 后抛出 * * @param throwable 异常 */ public static void wrapAndThrow(Throwable throwable) { if (throwable instanceof RuntimeException) { throw (RuntimeException) throwable; } if (throwable instanceof Error) { throw (Error) throwable; } throw new UndeclaredThrowableException(throwable); } /** * 将消息包装为运行时异常并抛出 * * @param message 异常消息 * @since 5.5.2 */ public static void wrapRuntimeAndThrow(String message) { throw new RuntimeException(message); } /** * 剥离反射引发的InvocationTargetException、UndeclaredThrowableException中间异常,返回业务本身的异常 * * @param wrapped 包装的异常 * @return 剥离后的异常 */ public static Throwable unwrap(Throwable wrapped) { Throwable unwrapped = wrapped; while (true) { if (unwrapped instanceof InvocationTargetException) { unwrapped = ((InvocationTargetException) unwrapped).getTargetException(); } else if (unwrapped instanceof UndeclaredThrowableException) { unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable(); } else { return unwrapped; } } } /** * 获取当前栈信息 * * @return 当前栈信息 */ public static StackTraceElement[] getStackElements() { // return (new Throwable()).getStackTrace(); return Thread.currentThread().getStackTrace(); } /** * 获取指定层的堆栈信息 * * @param i 层数 * @return 指定层的堆栈信息 * @since 4.1.4 */ public static StackTraceElement getStackElement(int i) { return Thread.currentThread().getStackTrace()[i]; } /** * 获取指定层的堆栈信息 * * @param fqcn 指定类名为基础 * @param i 指定类名的类堆栈相对层数 * @return 指定层的堆栈信息 * @since 5.6.6 */ public static StackTraceElement getStackElement(String fqcn, int i) { final StackTraceElement[] stackTraceArray = Thread.currentThread().getStackTrace(); final int index = ArrayUtil.matchIndex((ele) -> StrUtil.equals(fqcn, ele.getClassName()), stackTraceArray); if(index > 0){ return stackTraceArray[index + i]; } return null; } /** * 获取入口堆栈信息 * * @return 入口堆栈信息 * @since 4.1.4 */ public static StackTraceElement getRootStackElement() { final StackTraceElement[] stackElements = Thread.currentThread().getStackTrace(); return Thread.currentThread().getStackTrace()[stackElements.length - 1]; } /** * 堆栈转为单行完整字符串 * * @param throwable 异常对象 * @return 堆栈转为的字符串 */ public static String stacktraceToOneLineString(Throwable throwable) { return stacktraceToOneLineString(throwable, 3000); } /** * 堆栈转为单行完整字符串 * * @param throwable 异常对象 * @param limit 限制最大长度 * @return 堆栈转为的字符串 */ public static String stacktraceToOneLineString(Throwable throwable, int limit) { Map replaceCharToStrMap = new HashMap<>(); replaceCharToStrMap.put(StrUtil.C_CR, StrUtil.SPACE); replaceCharToStrMap.put(StrUtil.C_LF, StrUtil.SPACE); replaceCharToStrMap.put(StrUtil.C_TAB, StrUtil.SPACE); return stacktraceToString(throwable, limit, replaceCharToStrMap); } /** * 堆栈转为完整字符串 * * @param throwable 异常对象 * @return 堆栈转为的字符串 */ public static String stacktraceToString(Throwable throwable) { return stacktraceToString(throwable, 3000); } /** * 堆栈转为完整字符串 * * @param throwable 异常对象 * @param limit 限制最大长度 * @return 堆栈转为的字符串 */ public static String stacktraceToString(Throwable throwable, int limit) { return stacktraceToString(throwable, limit, null); } /** * 堆栈转为完整字符串 * * @param throwable 异常对象 * @param limit 限制最大长度,>0表示不限制长度 * @param replaceCharToStrMap 替换字符为指定字符串 * @return 堆栈转为的字符串 */ public static String stacktraceToString(Throwable throwable, int limit, Map replaceCharToStrMap) { final FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); throwable.printStackTrace(new PrintStream(baos)); final String exceptionStr = baos.toString(); final int length = exceptionStr.length(); if (limit < 0 || limit > length) { limit = length; } if (MapUtil.isNotEmpty(replaceCharToStrMap)) { final StringBuilder sb = StrUtil.builder(); char c; String value; for (int i = 0; i < limit; i++) { c = exceptionStr.charAt(i); value = replaceCharToStrMap.get(c); if (null != value) { sb.append(value); } else { sb.append(c); } } return sb.toString(); } else { if(limit == length){ return exceptionStr; } return StrUtil.subPre(exceptionStr, limit); } } /** * 判断是否由指定异常类引起 * * @param throwable 异常 * @param causeClasses 定义的引起异常的类 * @return 是否由指定异常类引起 * @since 4.1.13 */ @SuppressWarnings("unchecked") public static boolean isCausedBy(Throwable throwable, Class... causeClasses) { return null != getCausedBy(throwable, causeClasses); } /** * 获取由指定异常类引起的异常 * * @param throwable 异常 * @param causeClasses 定义的引起异常的类 * @return 是否由指定异常类引起 * @since 4.1.13 */ @SuppressWarnings("unchecked") public static Throwable getCausedBy(Throwable throwable, Class... causeClasses) { Throwable cause = throwable; while (cause != null) { for (Class causeClass : causeClasses) { if (causeClass.isInstance(cause)) { return cause; } } cause = cause.getCause(); } return null; } /** * 判断指定异常是否来自或者包含指定异常 * * @param throwable 异常 * @param exceptionClass 定义的引起异常的类 * @return true 来自或者包含 * @since 4.3.2 */ public static boolean isFromOrSuppressedThrowable(Throwable throwable, Class exceptionClass) { return convertFromOrSuppressedThrowable(throwable, exceptionClass, true) != null; } /** * 判断指定异常是否来自或者包含指定异常 * * @param throwable 异常 * @param exceptionClass 定义的引起异常的类 * @param checkCause 判断cause * @return true 来自或者包含 * @since 4.4.1 */ public static boolean isFromOrSuppressedThrowable(Throwable throwable, Class exceptionClass, boolean checkCause) { return convertFromOrSuppressedThrowable(throwable, exceptionClass, checkCause) != null; } /** * 转化指定异常为来自或者包含指定异常 * * @param 异常类型 * @param throwable 异常 * @param exceptionClass 定义的引起异常的类 * @return 结果为null 不是来自或者包含 * @since 4.3.2 */ public static T convertFromOrSuppressedThrowable(Throwable throwable, Class exceptionClass) { return convertFromOrSuppressedThrowable(throwable, exceptionClass, true); } /** * 转化指定异常为来自或者包含指定异常 * * @param 异常类型 * @param throwable 异常 * @param exceptionClass 定义的引起异常的类 * @param checkCause 判断cause * @return 结果为null 不是来自或者包含 * @since 4.4.1 */ @SuppressWarnings("unchecked") public static T convertFromOrSuppressedThrowable(Throwable throwable, Class exceptionClass, boolean checkCause) { if (throwable == null || exceptionClass == null) { return null; } if (exceptionClass.isAssignableFrom(throwable.getClass())) { return (T) throwable; } if (checkCause) { Throwable cause = throwable.getCause(); if (cause != null && exceptionClass.isAssignableFrom(cause.getClass())) { return (T) cause; } } Throwable[] throwables = throwable.getSuppressed(); if (ArrayUtil.isNotEmpty(throwables)) { for (Throwable throwable1 : throwables) { if (exceptionClass.isAssignableFrom(throwable1.getClass())) { return (T) throwable1; } } } return null; } /** * 获取异常链上所有异常的集合,如果{@link Throwable} 对象没有cause,返回只有一个节点的List
* 如果传入null,返回空集合 * *

* 此方法来自Apache-Commons-Lang3 *

* * @param throwable 异常对象,可以为null * @return 异常链中所有异常集合 * @since 4.6.2 */ public static List getThrowableList(Throwable throwable) { final List list = new ArrayList<>(); while (throwable != null && false == list.contains(throwable)) { list.add(throwable); throwable = throwable.getCause(); } return list; } /** * 获取异常链中最尾端的异常,即异常最早发生的异常对象。
* 此方法通过调用{@link Throwable#getCause()} 直到没有cause为止,如果异常本身没有cause,返回异常本身
* 传入null返回也为null * *

* 此方法来自Apache-Commons-Lang3 *

* * @param throwable 异常对象,可能为null * @return 最尾端异常,传入null参数返回也为null */ public static Throwable getRootCause(final Throwable throwable) { final List list = getThrowableList(throwable); return list.size() < 1 ? null : list.get(list.size() - 1); } /** * 获取异常链中最尾端的异常的消息,消息格式为:{SimpleClassName}: {ThrowableMessage} * * @param th 异常 * @return 消息 * @since 4.6.2 */ public static String getRootCauseMessage(final Throwable th) { return getMessage(getRootCause(th)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy