@ExceptionHandler捕获异常未返回客户端,Jetty返回500状态码原因及解决
解决方案
可能原因及修复步骤
1. 组件重复扫描导致异常处理器实例化冲突
根配置类RootConfig的@ComponentScan扫描了整个org.example.myapp包,而Servlet配置类ServletConfig也扫描了org.example.myapp.exceptions包,这会导致ExceptionHandlerAdvice在两个Spring上下文中被重复实例化。根上下文的异常处理器无法被DispatcherServlet正确识别,可能干扰响应处理。
修复:
修改RootConfig的组件扫描规则,排除异常处理器所在包:
package org.example.myapp.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @ComponentScan( basePackages = "org.example.myapp", excludeFilters = @ComponentScan.Filter( type = FilterType.REGEX, pattern = "org.example.myapp.exceptions.*" ) ) @EnableJpaRepositories(basePackages = "org.example.myapp.repositories") @EnableTransactionManagement public class RootConfig { // JPA/HIBERNATE相关配置 }
2. Java 8时间类型序列化失败
异常处理方法返回的ErrorContent包含Instant类型字段,如果Spring MVC未配置Jackson支持Java 8时间API,序列化时会抛出隐性异常,导致Jetty最终返回500状态码(尽管异常处理器已执行并打印日志)。
修复:
- 先确保依赖中包含Jackson的Java 8时间模块(Maven示例):
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
- 再在
ServletConfig中配置Jackson消息转换器:
package org.example.myapp.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Configuration; import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration @EnableWebMvc @ComponentScan(basePackages = {"org.example.myapp.controllers", "org.example.myapp.exceptions"}) @EnableSpringDataWebSupport public class ServletConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json() .modules(new JavaTimeModule()) .build(); converters.add(new MappingJackson2HttpMessageConverter(objectMapper)); } }
3. 事务回滚时的异常重抛干扰
如果服务方法标注了@Transactional,当抛出SkillNotFoundException时,事务管理器会回滚并重新抛出异常,可能覆盖异常处理器生成的自定义响应。
修复:
确保SkillNotFoundException继承自RuntimeException(Spring事务默认仅对RuntimeException触发回滚),或者在@Transactional注解中明确指定回滚类型:
@Transactional(rollbackFor = SkillNotFoundException.class) public Skill getSkillById(Long id) { // 业务逻辑,抛出SkillNotFoundException }
内容的提问来源于stack exchange,提问作者starter_dev
相关产品推荐
相关产品推荐

