如何让Spring Converter抛出自定义异常并在服务层直接捕获?
我之前刚好碰到过这个问题!核心原因是Spring的ConversionUtils在处理转换器抛出的异常时,会把所有不属于ConversionException子类的RuntimeException都包装成ConversionFailedException。下面给你两种简单的解决办法:
方案一:让自定义异常继承Spring的ConversionException(推荐)
这是最省心的方案,直接利用Spring的内置逻辑:Spring会直接抛出ConversionException的子类,不会进行包装。
只需要修改你的ElasticSearchException,让它继承自org.springframework.core.convert.ConversionException:
import org.springframework.core.convert.ConversionException; public class ElasticSearchException extends ConversionException { public ElasticSearchException(String message) { super(message); } }
修改完成后,当你在ElasticSearchConverter中抛出ElasticSearchException时,Spring会直接把这个异常抛给服务层,不会再包装成ConversionFailedException。你在ElasticService里就能直接捕获到它了。
方案二:自定义ConversionService包装类(适用于无法修改异常继承结构的场景)
如果因为某些限制不能修改异常的继承关系,可以实现一个代理类包装Spring默认的ConversionService,在调用时还原自定义异常:
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.stereotype.Component; @Component public class CustomConversionService implements ConversionService { private final ConversionService delegate; // 构造注入Spring默认的ConversionService public CustomConversionService(ConversionService delegate) { this.delegate = delegate; } @Override public boolean canConvert(Class<?> sourceType, Class<?> targetType) { return delegate.canConvert(sourceType, targetType); } @Override public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { return delegate.canConvert(sourceType, targetType); } @Override public <T> T convert(Object source, Class<T> targetType) { try { return delegate.convert(source, targetType); } catch (ConversionFailedException e) { // 检查异常根源是否为自定义的ElasticSearchException,是则重新抛出 if (e.getCause() instanceof ElasticSearchException) { throw (ElasticSearchException) e.getCause(); } // 其他异常保持原样抛出 throw e; } } @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { try { return delegate.convert(source, sourceType, targetType); } catch (ConversionFailedException e) { if (e.getCause() instanceof ElasticSearchException) { throw (ElasticSearchException) e.getCause(); } throw e; } } }
然后在你的服务类中注入这个自定义的CustomConversionService:
@Service public class ElasticService { @Autowired private CustomConversionService conversionService; public ResponseModel getResponse(RequestModel requestModel) { try { return conversionService.convert(requestModel, ResponseModel.class); } catch (ElasticSearchException e) { // 这里就能直接捕获到自定义异常了 // 编写你的异常处理逻辑 throw e; } } }
这样就能在服务层成功捕获到你自定义的ElasticSearchException了。
内容的提问来源于stack exchange,提问作者Grammin
相关产品推荐
相关产品推荐

