CompositeExceptionResolverFactoryBean.java
package cn.home1.oss.lib.errorhandle.starter;
import com.google.common.collect.ImmutableMap;
import cn.home1.oss.lib.errorhandle.api.ApplicationException;
import cn.home1.oss.lib.errorhandle.api.ConcreteExceptionResolver;
import cn.home1.oss.lib.errorhandle.api.ExceptionResolver;
import cn.home1.oss.lib.errorhandle.api.ExceptionTranslator;
import cn.home1.oss.lib.errorhandle.api.StackTraceIndicator;
import cn.home1.oss.lib.errorhandle.internal.CompositeExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.ApplicationErrorExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.ConstraintViolationExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.DefaultExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.HttpMediaTypeNotSupportedExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.HttpRequestMethodNotSupportedExceptionResolver;
import cn.home1.oss.lib.errorhandle.internal.resolver.MethodArgumentNotValidExceptionResolver;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.util.ClassUtils;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import java.util.Map;
@Setter
@Slf4j
public class CompositeExceptionResolverFactoryBean implements FactoryBean<ExceptionResolver<Throwable>> {
  public static final String CONSTRAINT_VIOLATION_EXCEPTION = "javax.validation.ConstraintViolationException";
  @Autowired
  private ExceptionTranslator exceptionTranslator;
  @Autowired
  private StackTraceIndicator stackTraceIndicator;
  @SuppressWarnings({"rawtypes", "unchecked"})
  static Map<Class<? extends Throwable>, ConcreteExceptionResolver> buildInResolvers( //
    final ConversionService conversionService, //
    final ExceptionTranslator exceptionTranslator, //
    final StackTraceIndicator stackTraceIndicator //
  ) {
    final ImmutableMap.Builder<Class<? extends Throwable>, ConcreteExceptionResolver> builder = ImmutableMap.builder();
    if (ClassUtils.isPresent( //
      CONSTRAINT_VIOLATION_EXCEPTION, //
      Thread.currentThread().getContextClassLoader() //
    )) {
      try {
        final Class clazz = Class.forName(CONSTRAINT_VIOLATION_EXCEPTION);
        builder.put(clazz, new ConstraintViolationExceptionResolver());
      } catch (final ClassNotFoundException ex) {
        // ignore
        if (log.isDebugEnabled()) {
          log.debug("class {} not found", CONSTRAINT_VIOLATION_EXCEPTION, ex);
        }
      }
    }
    builder.put(HttpMediaTypeNotSupportedException.class, new HttpMediaTypeNotSupportedExceptionResolver());
    builder.put(HttpRequestMethodNotSupportedException.class, new HttpRequestMethodNotSupportedExceptionResolver());
    builder.put(MethodArgumentNotValidException.class, new MethodArgumentNotValidExceptionResolver());
    builder.put(ApplicationException.class, new ApplicationErrorExceptionResolver());
    final Map<Class<? extends Throwable>, ConcreteExceptionResolver> map = builder.build();
    map.values().forEach(exceptionResolver -> {
      exceptionResolver.setConversionService(conversionService);
      exceptionResolver.setExceptionTranslator(exceptionTranslator);
      exceptionResolver.setStackTraceIndicator(stackTraceIndicator);
    });
    return map;
  }
  @Override
  public ExceptionResolver<Throwable> getObject() {
    final ConversionService conversionService = new DefaultConversionService(); // TODO conversionService
    @SuppressWarnings("rawtypes")
    final Map<Class<? extends Throwable>, ConcreteExceptionResolver> buildInResolvers = buildInResolvers( //
      conversionService, //
      this.exceptionTranslator, //
      this.stackTraceIndicator //
    );
    final DefaultExceptionResolver defaultResolver = new DefaultExceptionResolver();
    defaultResolver.setConversionService(conversionService);
    defaultResolver.setExceptionTranslator(this.exceptionTranslator);
    defaultResolver.setStackTraceIndicator(this.stackTraceIndicator);
    final CompositeExceptionResolver compositeExceptionResolver = new CompositeExceptionResolver();
    compositeExceptionResolver.setDefaultResolver(defaultResolver);
    compositeExceptionResolver.setResolverMap(buildInResolvers);
    return compositeExceptionResolver;
  }
  @Override
  public Class<?> getObjectType() {
    return ExceptionResolver.class;
  }
  @Override
  public boolean isSingleton() {
    return false;
  }
}