SpringBoot :cannot be cast to org.springframework.web.accept.ContentNegotiationManager

本文解决了在Spring Boot中配置自定义拦截器时出现的类型转换异常问题。通过注释掉application.xml中<mvc:annotation-driven/>配置,成功避免了ContentNegotiationManager类型转换错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot配置拦截器时,始终报错:

cannot be cast to org.springframework.web.accept.ContentNegotiationManager

启动入口:

@EnableAutoConfiguration
@SpringBootApplication
@ImportResource("classpath:application-mvc.xml")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
        ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
        registration.addUrlMappings("*.do", "*.go");
        return registration;
    }
}

Interceptor:

public class CustomSSOSpringInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println();
        return true;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

}

配置拦截器:

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomSSOSpringInterceptor()).addPathPatterns("/**");
    }
}

 

没有问题啊?可是始终报错,网上找了很多资料,都没有一个具体的说法,最后在一个小回复里看到了报错的原因:

http://forum.spring.io/forum/spring-projects/web/124660-spring-3-2-classcastexception-contentnegotiationmanagerfactorybean

I finally found the error, I was including a xml-config with <mvc:annotation-driven/>... I removed this, now it works

原来是我在application.xml文件里面配置了如下东西:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"
       default-autowire="byName">

    <mvc:annotation-driven/>

    <bean class="com.ahoi.demo.common.interceptor.ControllerClassNameHandlerMapping"></bean>

</beans>

注释掉就可以了!

转载于:https://my.oschina.net/u/3047936/blog/1806406

<think>我们正在处理一个关于Spring Boot应用中的ClassCastException异常的问题。具体错误是:`EntityManagerHolder`无法转换为`SessionHolder`。根据提供的引用信息,我们可以分析可能的原因。 首先,理解异常信息: - `EntityManagerHolder`:是Spring ORM中用于JPA(Java Persistence API)的类,它持有JPA的EntityManager。 - `SessionHolder`:是Spring ORM中用于Hibernate的类,它持有Hibernate的Session。 这个异常表明,在某个地方,我们期望得到一个Hibernate的`SessionHolder`,但实际上得到了一个JPA的`EntityManagerHolder`。这通常发生在混合使用JPA和Hibernate原生API的情况下,或者配置不正确。 可能的原因分析: 1. **配置混合使用JPA和Hibernate**: - 如果项目同时配置了JPA(通过`@EnableJpaRepositories`)和Hibernate原生API(例如,直接使用Hibernate的`SessionFactory`),则可能会导致类型不匹配。 - Spring Boot默认使用JPA作为抽象层,底层使用Hibernate实现。但如果你直接使用Hibernate的API(如`Session`)而没有正确配置,可能会出现问题。 2. **事务管理器的配置问题**: - JPA使用`JpaTransactionManager`,而Hibernate原生使用`HibernateTransactionManager`。如果配置不当,可能导致在事务上下文中期望的是Hibernate的Session,但实际是JPA的EntityManager。 3. **ErrorPageFilter的问题**: - `ErrorPageFilter`是Spring Boot用于处理错误页面的过滤器。在出现异常时,它会尝试转发到错误页面。在这个过程中,它可能会访问当前的事务资源(如数据库连接)。 - 如果此时事务资源是JPA的`EntityManagerHolder`,但代码中试图将其当作Hibernate的`SessionHolder`来使用,就会抛出`ClassCastException`。 4. **热部署(DevTools)干扰**: - 根据引用[5]的信息,热部署有时会引起类加载器问题,导致类型转换异常。尽管这个异常看起来与热部署没有直接关系,但也不能完全排除。 5. **依赖冲突或不兼容**: - 可能存在多个版本的Hibernate或Spring相关库,导致类型不匹配。 解决方案建议: 1. **统一使用JPA或Hibernate**: - 推荐使用JPA(即使用`EntityManager`)作为标准,避免混合使用Hibernate原生API。如果必须使用Hibernate原生API,请确保配置正确。 2. **检查事务管理器配置**: - 确保只配置了一种事务管理器。在Spring Boot中,如果你使用JPA,会自动配置`JpaTransactionManager`。如果你需要直接使用Hibernate的`SessionFactory`,那么应该配置`HibernateTransactionManager`,并且避免使用JPA的注解(如`@Entity`)和JPA的仓库接口。 3. **检查ErrorPageFilter**: - 考虑是否可以在错误处理时避免访问数据库资源?或者检查在错误页面处理过程中是否有代码试图获取Hibernate Session。 - 可以尝试排除`ErrorPageFilter`,看是否解决问题(但这样会失去错误页面处理功能): ```java @SpringBootApplication(exclude = ErrorPageFilter.class) ``` 4. **排除热部署干扰**: - 尝试暂时移除`spring-boot-devtools`依赖,看问题是否消失(引用[5]提到热部署可能引起类似问题)。 5. **检查依赖版本**: - 确保所有Spring Boot和Hibernate相关依赖的版本兼容。 6. **检查代码中是否混用API**: - 例如,在同一个事务中,是否有一部分代码使用`EntityManager`,而另一部分代码使用Hibernate的`Session`?如果是,应该统一使用一种API。 由于具体代码和配置未知,以上建议需要根据实际情况调整。 相关问题: 1. 如何配置Spring Boot使用纯Hibernate而不是JPA? 2. 在Spring Boot中如何正确排除ErrorPageFilter? 3. 如何解决热部署引起的类加载器问题? 4. 如何检查Spring Boot应用中的依赖冲突?</think>### Spring Boot ErrorPageFilter ClassCastException 分析 该异常`org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder`的根本原因是**类加载器冲突导致的类型转换错误**,常见于混合使用JPA和Hibernate原生API的环境中。以下是具体原因和解决方案: #### 核心原因分析 1. **JPA与Hibernate API混用冲突** - `EntityManagerHolder`是JPA规范的标准实现类,而`SessionHolder`是Hibernate原生API的专用类 - 当代码中同时使用`@PersistenceContext`(JPA)和`SessionFactory`(Hibernate)时,Spring无法统一管理两种资源类型[^1] 2. **热部署类加载器隔离问题** 使用`spring-boot-devtools`热部署时,会创建独立的`RestartClassLoader`,导致: ```mermaid graph LR A[系统类加载器] --> B[应用类] A --> C[EntityManagerHolder] D[RestartClassLoader] --> E[热部署加载的类] D --> F[SessionHolder] ``` 同一类被不同加载器加载,JVM视为不同类,触发类型转换异常[^3][^5] 3. **事务管理器配置冲突** 未明确指定事务管理器时,Spring可能同时激活: - `JpaTransactionManager`(生成EntityManagerHolder) - `HibernateTransactionManager`(期待SessionHolder) 两者在事务资源绑定时发生冲突 #### 解决方案 1. **统一持久化技术栈** ```java // 移除Hibernate原生API依赖 @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // 仅使用JPA配置 } ``` 2. **禁用热部署(临时验证)** 在`application.properties`中添加: ```properties spring.devtools.restart.enabled=false ``` 确认是否由热部署引起[^5] 3. **显式配置事务管理器** ```java @Configuration @EnableTransactionManagement public class PersistenceConfig { @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { return new JpaTransactionManager(emf); // 强制使用JPA事务管理器 } } ``` 4. **检查依赖冲突** 使用Maven检查依赖树: ```bash mvn dependency:tree -Dincludes=org.hibernate ``` 确保Hibernate版本统一(推荐与Spring Boot版本匹配) 5. **ErrorPageFilter特殊处理** 在`@SpringBootApplication`中排除问题组件: ```java @SpringBootApplication(exclude = { ErrorPageFilter.class, HibernateJpaAutoConfiguration.class }) ``` #### 预防措施 - 避免在同一事务中混用`EntityManager`和`Session` API - 使用`@Transactional`注解时明确事务管理器: ```java @Transactional(value = "jpaTransactionManager") public void serviceMethod() { ... } ``` - 升级Spring Boot至2.3+版本(优化了类加载隔离机制) > **关键提示**:当看到`A cannot be cast to A`这类"反直觉"报错时,90%是类加载器隔离导致的内存多版本冲突[^5],需优先排查热部署和依赖树问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值