CompositeExceptionResolver.java
package cn.home1.oss.lib.errorhandle.internal;
import cn.home1.oss.lib.errorhandle.api.ConcreteExceptionResolver;
import cn.home1.oss.lib.errorhandle.api.ExceptionResolver;
import cn.home1.oss.lib.errorhandle.api.ResolvedError;
import cn.home1.oss.lib.errorhandle.internal.resolver.DefaultExceptionResolver;
import cn.home1.oss.lib.errorhandle.starter.CompositeExceptionResolverFactoryBean;
import org.springframework.web.context.request.RequestAttributes;
import java.util.Map;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
/**
 * A {@link ExceptionResolver ExceptionResolver} that resolves exceptions through the provided
 * {@link ExceptionResolver ExceptionResolvers}.
 *
 * @see CompositeExceptionResolverFactoryBean
 */
public class CompositeExceptionResolver implements ExceptionResolver<Throwable> {
  private DefaultExceptionResolver defaultResolver;
  @SuppressWarnings("rawtypes")
  private Map<Class<? extends Throwable>, ConcreteExceptionResolver> resolverMap;
  @Override
  public ResolvedError resolve(final HttpServletRequest request, final Throwable throwable) {
    final ResolvedError resolvedError;
    final Optional<ExceptionResolver<Throwable>> resolverOptional = resolver(throwable);
    if (resolverOptional.isPresent()) {
      final ExceptionResolver<Throwable> resolver = resolverOptional.get();
      final ResolvedError resolved = resolver.resolve(request, throwable);
      if (resolved != null) {
        resolvedError = resolved;
      } else {
        resolvedError = this.defaultResolver.resolve(request, throwable);
      }
    } else {
      resolvedError = this.defaultResolver.resolve(request, throwable);
    }
    return resolvedError;
  }
  @Override
  public ResolvedError resolve(final RequestAttributes requestAttributes, final Throwable throwable) {
    final ResolvedError resolvedError;
    final Optional<ExceptionResolver<Throwable>> resolverOptional = resolver(throwable);
    if (resolverOptional.isPresent()) {
      final ExceptionResolver<Throwable> resolver = resolverOptional.get();
      final ResolvedError resolved = resolver.resolve(requestAttributes, throwable);
      if (resolved != null) {
        resolvedError = resolved;
      } else {
        resolvedError = this.defaultResolver.resolve(requestAttributes, throwable);
      }
    } else {
      resolvedError = this.defaultResolver.resolve(requestAttributes, throwable);
    }
    return resolvedError;
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  Optional<ExceptionResolver<Throwable>> resolver(final Throwable throwable) {
    ExceptionResolver<Throwable> result = null;
    if (throwable != null) {
      for (Class type = throwable.getClass(); type != Throwable.class; type = type.getSuperclass()) {
        if (this.resolverMap.containsKey(type)) {
          result = this.resolverMap.get(type);
          break;
        }
      }
    }
    return Optional.ofNullable(result);
  }
  public void setDefaultResolver(final DefaultExceptionResolver defaultResolver) {
    this.defaultResolver = defaultResolver;
  }
  @SuppressWarnings("rawtypes")
  public void setResolverMap(final Map<Class<? extends Throwable>, ConcreteExceptionResolver> resolverMap) {
    this.resolverMap = resolverMap;
  }
}