一、[Web.xml]
1、配置Spring的ContextLoaderListener监听器。
(1)用来初始化Spring的ApplicationContext。
(2)配置contextConfigLocation上下文参数,即用逗号分割的applicationXXXX context.xml文件。
2、配置Spring的OpenSessionInViewFilter过滤器。
(1)建立一个用来管理Hibernate Session的Servlet过滤器。
(2)为发送Request的的当前客户端请求线程提供一个(创建或连接)Hibernate Session。
(3)默认的时候使用Spring提供的HibernateTemplate的类将会使用同一个Hibernate Session。
(4)HibernateTemplate使用的是Spring提供出来的 SessionFactoryUtils.getSession方法。
(5)SessionFactoryUtils.getSession方法将会使用已经存在的Hibernate Session。
3、配置MyFaces的StartupServletContextListener。
(1)初始化MyFaces。
(2)配置javax.faces.CONFIG_FILES参数,即用逗号分割的faces-context.xml文件。
(3)这个我觉得应该是分领域的莱分割faces-context.xml文件,比如faces-context-navigation.xml、faces-context-managed-beans.xml等。
4、配置JSF FacesServlet
(1)用来处理请求。
5、我自己写了一些Filter,所以配置了FilterToBeanProxy,让Spring来统一管理我的Filters。
下面是我的配置文件(因项目关系,做了大量删减,只有参考意义)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/ConfigFiles/WebFramework/JavaServerFaces/faces-config.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ConfigFiles/spring/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<listener>
<listener-class>org.vsoft.framework.core.view.web.listeners.InitFrameworkContextListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Restrict access to JSP pages</display-name>
<web-resource-collection>
<web-resource-name>Restrict access to JSP pages</web-resource-name>
<url-pattern>/process/*jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>With no roles defined, no access granted</description>
</auth-constraint>
</security-constraint>
</web-app>
(1)初始化MyFaces。
(2)配置javax.faces.CONFIG_FILES参数,即用逗号分割的faces-context.xml文件。
(3)这个我觉得应该是分领域的莱分割faces-context.xml文件,比如faces-context-navigation.xml、faces-context-managed-beans.xml等。
4、配置JSF FacesServlet
(1)用来处理请求。
5、我自己写了一些Filter,所以配置了FilterToBeanProxy,让Spring来统一管理我的Filters。
下面是我的配置文件(因项目关系,做了大量删减,只有参考意义)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/ConfigFiles/WebFramework/JavaServerFaces/faces-config.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ConfigFiles/spring/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>net.sf.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<listener>
<listener-class>org.vsoft.framework.core.view.web.listeners.InitFrameworkContextListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Restrict access to JSP pages</display-name>
<web-resource-collection>
<web-resource-name>Restrict access to JSP pages</web-resource-name>
<url-pattern>/process/*jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>With no roles defined, no access granted</description>
</auth-constraint>
</security-constraint>
</web-app>
下面说说OpenInSessionViewFilter,如果谁感兴趣,可以仔细研读一下Karl Baum的《Lazy Initialization and the DAO pattern with Hibernate and Spring Hibernate and Lazy Initialization》这篇文章,文章的地址在[http://www.jroller.com/comments/kbaum/Weblog/orm_lazy_initialization_with_dao]。
这里需要有一点要注意,OpenInSessionViewFilter能够让使用Hibenrate的程序员避免出现lazy initialization的错误。Lazy Initialization的意思是自读那些取一对多和多对多关系属性的时候,只有真正读取的时候,才向数据库发出查询请求。但是这种OpenInSessionViewFilter只不过是一种权宜之计,Hibernate的HQL查询在某些时候需要特别的使用方法。比如,如果查询语句返回大量Object,这将让Web应用的性能急剧下降。如果HQL查询不直接返回大量数据的话,又极有可能会导致可怕的N+1问题(关于N+1问题可以在Java Eyes找到描述)。综上所述,使用OpenInSessionViewFilter方法来管理Session,并得不到多少好处,这一点Spring的OpenInSessionViewFilter API参考手册上也说明了。举例来说,在用户事务(请求)为其他DAOs读取到的对象肯定不是从数据库中重新得到的。
这里需要有一点要注意,OpenInSessionViewFilter能够让使用Hibenrate的程序员避免出现lazy initialization的错误。Lazy Initialization的意思是自读那些取一对多和多对多关系属性的时候,只有真正读取的时候,才向数据库发出查询请求。但是这种OpenInSessionViewFilter只不过是一种权宜之计,Hibernate的HQL查询在某些时候需要特别的使用方法。比如,如果查询语句返回大量Object,这将让Web应用的性能急剧下降。如果HQL查询不直接返回大量数据的话,又极有可能会导致可怕的N+1问题(关于N+1问题可以在Java Eyes找到描述)。综上所述,使用OpenInSessionViewFilter方法来管理Session,并得不到多少好处,这一点Spring的OpenInSessionViewFilter API参考手册上也说明了。举例来说,在用户事务(请求)为其他DAOs读取到的对象肯定不是从数据库中重新得到的。
下面好戏出台,配置JSF+Spring+Hibernate:
1、配置一个非Web相关的applicationContext.xml。
这样测试就非常方便了。俺的K-7牌老牛车可经不住一次一次的重新启动Tomcat、JBoss。
2、配置一个Web相关的applicationContext。
(1)分层编写applicationContext配置文件。
(2)每层根据不同的业务逻辑在编写多个applicationContext配置文件,这样,单个配置文件就比较容易管理了,查看起来N方便,但是配置文件的数量就比较多了。
包含非Web相关的配置文件我是这么写的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="classes/org/vsoft/framework/view/web/jsf/bom/hibernate/context/resources/applicationContext.xml" />
<import resource="webContext.xml" />
</beans>
注意:web.xml中配置的applicationContext.xml包含了class path中的applicationContext.xml。这样就比较容易使用ClassPathXMLApplicationContext编写JUnit测试了。
webContext.xml仅仅配置在服务器端,它仅仅包括那些服务器端必须在服务器端运行的bean,比如Filter什么的。
ClassPath下的配置文件是这么写的:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="applicationContextProperties.xml" />
<import resource="daoContext.xml" />
<import resource="managerContext.xml" />
<import resource="serviceContext.xml" />
…
…
</beans>
差点忘了,还有一个applicationContextProperties.xml,这个配置文件里面主要是描述那些平台相关的配置信息的,随着不同的项目或者在开发与部署环境不同的时候,又或者在做测试的时候,它是会经常被改变的。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:org/vsoft/product/vsofterp/resources/applicationContext.properties</value>
<value>classpath:org/vsoft/product/vsofterp/resources/db.properties</value>
</list>
</property>
<!– Override properties in file with system properties –>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
</bean>
</beans>
大概就是这样了,呵呵。
1、配置一个非Web相关的applicationContext.xml。
这样测试就非常方便了。俺的K-7牌老牛车可经不住一次一次的重新启动Tomcat、JBoss。
2、配置一个Web相关的applicationContext。
(1)分层编写applicationContext配置文件。
(2)每层根据不同的业务逻辑在编写多个applicationContext配置文件,这样,单个配置文件就比较容易管理了,查看起来N方便,但是配置文件的数量就比较多了。
包含非Web相关的配置文件我是这么写的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="classes/org/vsoft/framework/view/web/jsf/bom/hibernate/context/resources/applicationContext.xml" />
<import resource="webContext.xml" />
</beans>
注意:web.xml中配置的applicationContext.xml包含了class path中的applicationContext.xml。这样就比较容易使用ClassPathXMLApplicationContext编写JUnit测试了。
webContext.xml仅仅配置在服务器端,它仅仅包括那些服务器端必须在服务器端运行的bean,比如Filter什么的。
ClassPath下的配置文件是这么写的:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="applicationContextProperties.xml" />
<import resource="daoContext.xml" />
<import resource="managerContext.xml" />
<import resource="serviceContext.xml" />
…
…
</beans>
差点忘了,还有一个applicationContextProperties.xml,这个配置文件里面主要是描述那些平台相关的配置信息的,随着不同的项目或者在开发与部署环境不同的时候,又或者在做测试的时候,它是会经常被改变的。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:org/vsoft/product/vsofterp/resources/applicationContext.properties</value>
<value>classpath:org/vsoft/product/vsofterp/resources/db.properties</value>
</list>
</property>
<!– Override properties in file with system properties –>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
</bean>
</beans>
大概就是这样了,呵呵。
对于DAO,我没有简单的从Spring提供的HibernateTemplate继承,而是继承自HibernateDaoSupport
代码示例如下:
public class HiberanteBOMDAO extends HibernateDaoSupport implements IHiberanteBOMDAO
{
public void saveBOM(IBOM bom) {
this.getHibernateTemplate().save(bom);
}
…
…
}
这个DAO配置部分如下:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!– You can setup a HibernateTemplate that configures Hiberante sessions in special ways.
For example, you could set a different FlushMode than the default.
NOTE THIS COMMENTED OUT AS THE DEFAULTS ARE ACCEPTABLE.
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="cacheQueries">
<value>true</value>
</property>
</bean>
–>
<bean id="hibernateDaoSupport"
class="org.springframework.orm.hibernate3.support.HibernateDaoSupport"
abstract="true">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<!– You could use the configured Hibernate template or create
a new mapping that uses a configured hibernate template.
HibernateDaoSupport creates a HibernateTempalte with the default settings.
NOTE THIS IS COMMENTED OUT.
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
–>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
<bean id="rssDAO"
class="com.example.jsf.hibernate.example.dao.HibernateRssFeedDAO"
parent="hibernateDaoSupport"/>
</bean>
代码示例如下:
public class HiberanteBOMDAO extends HibernateDaoSupport implements IHiberanteBOMDAO
{
public void saveBOM(IBOM bom) {
this.getHibernateTemplate().save(bom);
}
…
…
}
这个DAO配置部分如下:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!– You can setup a HibernateTemplate that configures Hiberante sessions in special ways.
For example, you could set a different FlushMode than the default.
NOTE THIS COMMENTED OUT AS THE DEFAULTS ARE ACCEPTABLE.
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="cacheQueries">
<value>true</value>
</property>
</bean>
–>
<bean id="hibernateDaoSupport"
class="org.springframework.orm.hibernate3.support.HibernateDaoSupport"
abstract="true">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<!– You could use the configured Hibernate template or create
a new mapping that uses a configured hibernate template.
HibernateDaoSupport creates a HibernateTempalte with the default settings.
NOTE THIS IS COMMENTED OUT.
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
–>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
<bean id="rssDAO"
class="com.example.jsf.hibernate.example.dao.HibernateRssFeedDAO"
parent="hibernateDaoSupport"/>
</bean>