Java Spring MVC@Controller:由于“组件扫描”标记的“使用默认过滤器”而导致事务性问题
我对SpringMVC有点陌生,所以我正在创建一个小的web应用程序来尝试它 我正在使用Spring4.2和Hibernate5 该web应用程序有一个springservlet-context.xml和一个springapplication-context.xml 我有一个@Controller,它有一个使用@Service的方法。此服务有一个标记为@Transactional的findAll方法 web.xml如下所示:Java Spring MVC@Controller:由于“组件扫描”标记的“使用默认过滤器”而导致事务性问题,java,spring,spring-mvc,spring-transactions,Java,Spring,Spring Mvc,Spring Transactions,我对SpringMVC有点陌生,所以我正在创建一个小的web应用程序来尝试它 我正在使用Spring4.2和Hibernate5 该web应用程序有一个springservlet-context.xml和一个springapplication-context.xml 我有一个@Controller,它有一个使用@Service的方法。此服务有一个标记为@Transactional的findAll方法 web.xml如下所示: ... <listener> <listen
...
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:*-context.xml
</param-value>
</context-param>
<servlet>
<servlet-name>myDispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
...
servlet-context.xml
请注意,这与application-context.xml中的组件扫描的基本包相同
配置3工作模式
与2相同,因此servlet-context.xml中的base package=my.package,不同之处在于,我没有用@Service注释我的服务,而是在application-context.xml中将其显式声明为bean:
TL;博士
有人能解释一下为什么我得到org.hibernate.hibernate异常:当我使用配置2而不是配置1和3点击控制器映射方法时,无法获得当前线程的事务同步会话吗?
我相信这三种配置都是等效的
谢谢。经过几个小时的反复试验,我发现了这个问题 在所有3种配置中,servlet-context.xml的组件扫描标记需要另一个属性:use default filters必须设置为false
<context:component-scan base-package="my.package" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
如果根据默认值将其设置为true,则本质上类似于有一个默认的include过滤器,如下所示:
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component"/>
这意味着在包扫描期间,它还加载了定义的@Service和@Repository等。。
由于服务是由Servlet上下文加载的,该上下文没有标记,因此没有为服务启用事务上下文,并且引发了异常
在配置1中,由于用于扫描的基本包仅限于控制器包,因此绕过了该问题。Servlet上下文仅加载控制器,因此使用的服务是由启用了事务上下文的应用程序上下文加载的服务
在配置3中,因为我在正确的事务上下文application-context.xml中使用了服务bean的手动定义,所以也忽略了这个问题。classpath:-context.xml应该是application-context.xml,否则两个上下文文件都会加载,这可能是问题的原因。感谢您的评论,@zeroplagl。不幸的是,这似乎不是问题所在。我使用配置2将类路径:*-context.xml更改为application-context.xml,但仍然引发了相同的异常。我怀疑在配置加载中也可能存在重复,这就是为什么我在配置1中限制了组件扫描的基本包,但我无法理解为什么:排除/包括筛选器应该保证每个组件加载一次。@zeroflagL:似乎我发现了问题。这确实是一个重复加载问题,但不是您指出的问题。不过,谢谢你的评论,这让我走上了正轨;
@Repository("userDao")
public class UserDaoImpl implements UserDao
{
@Autowired
private SessionFactory sessionFactory;
@Override
@SuppressWarnings("unchecked")
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public List<User> findAll()
{
Query query = sessionFactory.getCurrentSession().createQuery("from User ");
return query.list();
}
}
...
<tx:annotation-driven />
<context:component-scan base-package="my.package">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="packagesToScan">
<list>
<value>my.package.entities</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDb" />
</bean>
...
...
<context:component-scan base-package="my.package.inner.package">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
...
<context:component-scan base-package="my.package">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
...
<bean id="userManager" class="my.package.services.impl.UserManagerImpl">
</bean>
...
<context:component-scan base-package="my.package" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Component"/>