1. Spring和Hibernate整合:hibernate委托给spring托管。需要改动的地方:
(1)需要导入的包:spring.jar + hibernate最小导入包 + commons-dbcp.jar/commons-collections.jar/commons-pool.jar(数据库缓冲池);
(2)applicationContext.xml中增加两个bean:dataSource和sessionFactory。这两个bean取代了hibernate.cfg.xml文件,即对hibernate进行托管;
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <property name="url" value="jdbc:mysql://localhost:3306/testcasetrack" />
- <property name="username" value="root" />
- <property name="password" value="" />
- </bean>
- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="dataSource">
- <ref bean="dataSource" />
- </property>
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- </props>
- </property>
- <property name="mappingResources">
- <list>
- <value>edu/hust/vo/User.hbm.xml</value>
- </list>
- </property>
- </bean>
(3)使DAO接口实现类继承自org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- public class UserDAOImpl extends HibernateDaoSupport implements UserDAO {
- private Query query;
- private User user;
- private List<User> uList;
- public boolean isLogin(User user) {
- query = this.getHibernateTemplate().getSessionFactory().openSession().createQuery("FROM User AS u WHERE u.uid=? AND u.password=?");
- query.setString(0, user.getUid());
- query.setString(1, user.getPassword());
- if (!query.list().isEmpty()) {
- user = (User) query.list().get(0);
- return true;
- }
- return false;
- }
- public void delete(int id) {
- query = this.getHibernateTemplate().getSessionFactory().openSession().createQuery("DELETE FROM User WHERE id=?");
- query.setInteger(0, id);
- query.executeUpdate();
- }
- public void insert(User user) {
- try {
- this.getHibernateTemplate().getSessionFactory().openSession().save(user);
- // this.getSession().save(user);
- } catch (ConstraintViolationException cve) {
- System.err.println("不能插入重复数据!!!.....");
- }
- }
- ......
- }
- /*
- * 可以使用spring中的HibernateDAOSupport与HibernateTemplate类来进行数据持久化操作:
- * A、HibernateDAOSupport类中定义了对session、sessionFactory的操作方法,getHibernateTemplate()方法可以获得一个HibernateTemplate实例;
- * B、HibernateTemplate类中定义了对数据持久化的各种封装的方法,我们可以用它来对数据进行操作。
- * 因此在使用时,我们可以继承HibernateDAOSupport类,然后实例化HibernateTemplate类来进行数据持久化。
- *
- * */
(4)applicationContext.xml中增加对DAO接口实现类的配置;
- <bean id="userDAO" class="edu.hust.dao.impl.UserDAOImpl">
- <property name="sessionFactory">
- <ref bean="sessionFactory"/>
- </property>
- </bean>
2. struts2与spring整合:struts的action委托给spring管理。
(1)需要导入的包:spring.jar + freemaker.jar/ognl.jar/struts2-core.jar/xwork.jar/commons-collections.jar + struts2-spring-plugin.jar(除了spring.jar,其余6个jar均来自struts2);
补充:<constent name="struts.objectFactory" value="spring" />:指定struts的工厂类, value="spring":使用spring的IoC来管理struts的Action。具体机理:这个consten将框架常量struts.objectFactory覆盖了,覆盖为"spring"(org.apache.struts2.spring.StrutsSpringObjectFactory的缩写);默认情况下Struts框架中的对象都是由ObjectFactory实例化的,同时ObjectFactory提供了与其它IoC容器如Spring等集成的方法。所以覆盖ObjectFactory的类必须继承ObjectFactory类或者它的任何子类(这里org.apache.struts2.spring.StrutsSpringObjectFactory继承自objectFactory,即我们用org.apache.struts2.spring.StrutsSpringObjectFactory代替了默认的ObjectFactory)。
配置当创建一个对象的时候,值为"spring"的objectFactory(覆盖后的ObjectFactory)会用Struts2配置文件中action tag中的class属性去和Spring配置文件中bean tag中的id属性进行关联。
在struts2-spring-plugin-2.1.2.jar中的struts-plugin.xml中已经对其进行了配置。不需要我们在struts.xml中配置了。
(2)web.xml中增加配置:利用Spring配置文件(applicationContext.xml)来注册对象、Spring监听器;
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
这里有一点要注意的是,我们还要指定Spring配置文件的地点,默认情况下,容器会到WEB-INF目录下面去寻找applicationContext.xml文件。如果我们想指定别的地方的配置文件或者指定多个配置文件,可以通过在web.xml文件中定义context-param元素来指定,如下所示:
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/classes/applicationContext.xml, classpath:applicationContext-*.xml</param-value>
- </context-param>
上面一段话表示WEB-INF下面的applicationContext.xml文件以及classpath下面的所有匹配applicationContext-*.xml模式的文件都会作为Spring配置文件被装载。
(3)applicationContext.xml中增加对action的配置;
- <bean id="userAction" class="edu.hust.action.UserAction" scope="prototype">
- <property name="userDAO">
- <ref bean="userDAO"/>
- </property>
- </bean>
scope="prototype"不能少。scope="prototype"会在该类型的对象被请求时创建一个新的action对象。
<1>singleton作用域(默认作用域):当一个bean的作用域设置为singleton,那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean。
<2>prototype作用域:prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当于一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。
<3>二者选择的原则:有状态的bean都使用Prototype作用域,而对无状态的bean则应该使用singleton作用域。action是一个请求就是一个action对象,而在spring中则不是的,它是自动分配类的实例的,是使用的单态模式来生产类的实例的,不符合action,因此在applicationContext.xml文件中定义每个action时,都要在类后加上: scope="prototype"。
(4)配置struts.xml文件;
- <package name="struts2" extends="struts-default">
- <action name="UserAction_login" class="userAction" method="login">
- <result type="redirect-action">UserAction_queryAll</result>
- </action>
- <action name="UserAction_queryAll" class="userAction" method="queryAll">
- <result>/user/user_list.jsp</result>
- </action>
- <action name="UserAction_insert" class="userAction" method="insert">
- <result type="redirect-action">UserAction_queryAll</result>
- </action>
- <action name="UserAction_update" class="userAction" method="update">
- <result type="redirect-action">UserAction_queryAll</result>
- </action>
- </package>
class="userAction"。struts.xml文件中配置一个action时,它的class就不是一个类了,而是在applicationContext.xml文件中定义过的类的id,在struts.xml文件中就只需要引用这个id就可以了。
(5)在Action中利用IoC获得userDAO,而不是利用getBean()的方式获得userDAO
这种方式是正确的:
- public class UserAction extends ActionSupport implements ServletRequestAware {
- //其他代码片段
- private UserDAO userDAO;
- public UserDAO getUserDAO() {
- return userDAO;
- }
- public void setUserDAO(UserDAO userDAO) {
- this.userDAO = userDAO;
- }
- public String insert() {
- user = new User();
- user.setUid(this.getUid());
- user.setName(this.getName());
- user.setPassword(this.getPassword());
- user.setEmail(this.getEmail());
- user.setDepartment(this.getDepartment());
- user.setActor(this.getActor());
- userDAO.insert(user);
- return SUCCESS;
- }
- public String queryAll() {
- uList = userDAO.queryAll();
- req.getSession().setAttribute("uList", uList);
- return SUCCESS;
- }
- //其他代码片段
- }
这种方式是错误的:
- public class UserAction extends ActionSupport implements ServletRequestAware {
- //其他代码片段
- private UserDAO userDAO;
- public UserAction() {
- ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- userDAO = (UserDAO) ctx.getBean("userDAO");
- }
- public String insert() {
- user = new User();
- user.setUid(this.getUid());
- user.setName(this.getName());
- user.setPassword(this.getPassword());
- user.setEmail(this.getEmail());
- user.setDepartment(this.getDepartment());
- user.setActor(this.getActor());
- userDAO.insert(user);
- return SUCCESS;
- }
- public String queryAll() {
- uList = userDAO.queryAll();
- req.getSession().setAttribute("uList", uList);
- return SUCCESS;
- }
- //其他代码片段
- }