Spring MVC + Hibernate 4 + Spring Security
Posted
技术标签:
【中文标题】Spring MVC + Hibernate 4 + Spring Security【英文标题】: 【发布时间】:2012-12-05 04:06:23 【问题描述】:从现在开始,我一直在努力完成所有这些工作,不知道该怎么办。我相信我在 SO 上浏览了关于该主题的每一篇文章,并浏览了数十个教程......
这是我此时收到的信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fruitController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.controller.FruitController.setFruitManager(com.service.FruitManager); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.service.FruitManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations:
我过去已经能够解决这个错误,但只是有一个新的“没有为当前线程找到会话”。当没有这个时,我的 Assembler 和 UserDetailsServiceImpl bean 无法在我的 spring-security.xml 文件中被识别出一些问题......
我认为问题不是来自我的代码,我只是无法正确设置我的配置文件,我可能在这里遗漏了一些东西。
这里是配置文件:
web.xml:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<!-- Spring MVC -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config/>
<!-- Load everything except @Controllers -->
<context:component-scan base-package="com">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="save*" />
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.dao.HibernateFruitDAO</value>
</list>
</property>
<property name="packagesToScan">
<list>
<value>com.service</value>
<value>com.controller</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.mysql5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/basename" />
<property name="username" value="xxx" />
<property name="password" value="yyy" />
</bean>
</beans>
mvc-dispatcher-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:annotation-config />
<context:property-placeholder location="classpath:hibernate.properties" />
<!-- Load @Controllers only -->
<context:component-scan base-package="com.controller"
use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mymessages</value>
</list>
</property>
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
</beans>
spring-security.xml http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.1.xsd">
<beans:bean id="userDetailsService" class="com.service.UserDetailsServiceImpl">
</beans:bean>
<beans:bean id="assembler" class="com.service.Assembler">
</beans:bean>
<http auto-config='true' use-expressions='true'>
<intercept-url pattern="/login*" access="isAnonymous()" />
<intercept-url pattern="/secure/**" access="hasRole('ROLE_Admin')" />
<logout logout-success-url="/listing.htm" />
<form-login login-page="/login.htm" login-processing-url="/j_spring_security_check"
authentication-failure-url="/login_error.htm" default-target-url="/listing.htm"
always-use-default-target="true" />
</http>
<beans:bean id="com.daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService" />
</beans:bean>
<beans:bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="com.daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder hash="plaintext" />
</authentication-provider>
</authentication-manager>
</beans:beans>
水果控制器:
package com.controller;
@Controller
public class FruitController
protected final Log logger = LogFactory.getLog(getClass());
private FruitManager fruitManager;
@Autowired
public void setFruitManager(FruitManager FruitManager)
this.fruitManager = fruitManager;
@RequestMapping(value = "/listing", method = RequestMethod.GET)
public String getFruits(ModelMap model)
model.addAttribute("fruits", this.fruitManager.getFruits());
return "listing";
水果道: 公共接口 FruitDAO
public List<Fruit> getFruitList();
public List<Fruit> getFruitListByUserId(String userId);
public void saveFruit(Fruitprod);
public void updateFruit(Fruitprod);
public void deleteFruit(int id);
public Fruit getFruitById(int id);
HibernateFruitDAO
package com.dao;
@Repository("fruitDao")
public class HibernateFruitDAO implements FruitDAO
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory)
this.sessionFactory = sessionFactory;
public List<Fruit> getList()
return (List<Fruit>) getSession().createCriteria ( Fruit.class ).list();
public List<Fruit> getFruitListByUserId(String userId)
return (List<Fruit>)sessionFactory.getCurrentSession().createCriteria("from Fruit where userId =?", userId).list();
public void saveFruit(Fruit fruit)
sessionFactory.getCurrentSession().save(fruit);
public void updateFruit(Fruit fruit)
sessionFactory.getCurrentSession().update(fruit);
public void deleteFruit(int id)
Fruit fruit = (Fruit) sessionFactory.getCurrentSession().load(Fruit.class, id);
if (null != fruit)
sessionFactory.getCurrentSession().delete(fruit);
public Fruit getFruitById(int id)
return (Fruit)sessionFactory.getCurrentSession().load(Fruit.class, id);
private Session getSession()
return sessionFactory.getCurrentSession();
界面水果管理器:
package com.service;
import java.io.Serializable;
import java.util.List;
import com.domain.Fruit;
public interface FruitManager extends Serializable
public List<Fruit> getFruits();
public List<Fruit> getFruitsByUserId(String userId);
public void addFruit(Fruit fruit);
public void removeFruit(int id);
public Fruit getFruitById(int id);
public void updateFruit(Fruit fruit);
FruitManager 的实现:
package com.service;
@Repository("fruitManager")
@Transactional
public class SimpleFruitManager implements FruitManager
/**
*
*/
private static final long serialVersionUID = ...;
@Autowired
private FruitDAO fruitDao;
public List<Fruit> getFruits()
return fruitDao.getFruitList();
public List<Fruit> getFruitsByUserId(String userId)
return fruitDao.getFruitListByUserId(userId);
public void setFruitDao(FruitDAO fruitDao)
this.fruitDao = fruitDao;
public void addFruit(Fruit fruit)
fruitDao.saveFruit(fruit);
public void removeFruit(int id)
fruitDao.deleteFruit(id);
public getFruitById(int id)
return fruitDao.getFruitById(id);
public void updateFruit(Fruit fruit)
fruitDao.updateFruit(fruit);
【问题讨论】:
【参考方案1】:我认为你必须在 DaoImpl 中使用它来获取会话:
@Autowired
private SessionFactory sessionFactory;
【讨论】:
【参考方案2】:乍一看,您似乎遇到了一个常见问题,即不了解 Spring ApplicationContexts 如何组合在一起来构建 Web 应用程序。请参阅我对完全相同问题的其他答案,看看它是否可以解决问题:
Declaring Spring Bean in Parent Context vs Child Context
您也可能对类似主题的这个答案有所启发,该答案链接到我之前提到的答案以及另一个答案:
Spring XML file configuration hierarchy help/explanation
几个简短的提示可以让你朝着正确的方向前进......
按照惯例,Spring 的 ContextLoaderListener 从 WEB-INF/applicationContext.xml
加载 bean 以创建根应用程序上下文。当您覆盖默认值时,将不再加载该文件。
提示 #1:坚持常规行为。它会让你的生活更简单。
同样按照惯例,启动 Spring DispatcherServlet 从 WEB-INF/<servlet name>-context.xml
加载 bean 以创建用于配置调度程序 servlet 的上下文。此上下文成为根上下文的子上下文。
提示 #2:参见提示 #1
所以你看,你现在过度配置了东西。阅读链接的答案和其中链接的参考资料。学习使用 Spring 而不是反对它。
【讨论】:
感谢您的启发性回答,这对我帮助很大。我想我已经清理了大部分配置文件并理解了它是如何工作的。这次我对 spring-security.xml 有一个遗留问题:“没有定义名为 'userDetailsService' 的 bean”。未找到 userDetailsService bean。我确实在我的 spring-security.xml(Assembler 和 UserDetailsServiceImpl)中注释了两个 bean 声明。我删除它们的原因是它们应该已经被根上下文扫描了。 这个答案和提供的链接帮助我获得了有意义的干净配置文件。我也更好地理解它应该工作的方式以及应该使用 Spring 的方式。非常有用的答案。【参考方案3】:在您的 web.xml 文件中,applicationContext.xml
永远不会被加载。你应该把它放在context-param
。将mvc-dispatcher-servlet.xml
的位置(包含与控制器相关的 bean)作为 DispatcherServlet 的 init-param 代替:
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</init-param>
【讨论】:
以上是关于Spring MVC + Hibernate 4 + Spring Security的主要内容,如果未能解决你的问题,请参考以下文章
从 Migrate 迁移到 Spring MVC 4 + Hibernate5
通用后台管理系统(ExtJS 4.2 + Spring MVC 3.2 + Hibernate)
Spring+Spring MVC+Hibernate框架搭建实例
杰克逊 JSON、Spring MVC 4.2 和 Hibernate JPA 问题的无限递归