<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:Calibri; mso-font-alt:"Century Gothic"; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:Calibri; mso-fareast-font-family:宋体; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} h1 {mso-style-link:" Char Char2"; mso-style-next:正文; margin-top:17.0pt; margin-right:0cm; margin-bottom:16.5pt; margin-left:0cm; text-align:justify; text-justify:inter-ideograph; line-height:240%; mso-pagination:lines-together; page-break-after:avoid; mso-outline-level:1; font-size:22.0pt; font-family:Calibri; mso-font-kerning:22.0pt;} p.a, li.a, div.a {mso-style-name:列出段落; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; text-indent:21.0pt; mso-char-indent-count:2.0; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:Calibri; mso-fareast-font-family:宋体; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} span.CharChar2 {mso-style-name:" Char Char2"; mso-style-locked:yes; mso-style-link:"标题 1"; mso-ansi-font-size:22.0pt; mso-bidi-font-size:22.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-fareast-font-family:宋体; mso-hansi-font-family:Calibri; mso-font-kerning:22.0pt; mso-ansi-language:EN-US; mso-fareast-language:ZH-CN; mso-bidi-language:AR-SA; font-weight:bold;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1147864669; mso-list-type:hybrid; mso-list-template-ids:1609476242 1141398998 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} @list l0:level1 {mso-level-number-format:japanese-counting; mso-level-text:%1,; mso-level-tab-stop:none; mso-level-number-position:left; margin-left:21.0pt; text-indent:-21.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->
公司使用的是 ssh 框架,用代码生成工具生成从 dao 到 service 的所有代码和配置文件,使用 spring 框架对 hibernate 进行事务管理, struts 自己管理自己的组件, spring 管理从 service 到 vo 对象的组件,在 struts 的 action 通过 webapplicationcontext 来获取 spring 管理的 bean 对象,事务管理在 service 层进行,通过定义一个抽象的事务模板让 service 对象继承来实现,同时,将 hibernate 的 session 绑定到 web 的每个 request 线程中,整个 request 的生命周期中都可见,需要注意的是此处 hibernate 的 session 默认使用的是 flushnever 模式,即该 session 永远不会执行 flush ,具体的事务控制都在 service 层进行,在 service 层调用的时候该 session 会被临时设置成自动 flush 模式,调用完后又会被设置成 neverflush 模式。
具体内容如下:
一, struts 配置
struts 配置和一般的配置没有多少区别,不同的是为了实现按模块配置 struts 将配置文件拆分成几个配置文件,因此,在配置 actionservlet 时为他配置了一个初始化参数 configlocation ,如下
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>com.thunisoft.dataapplatform.servlet.ThunisoftActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/config/struts/struts-config.xml
</param-value>
</init-param>
<init-param>
<param-name>configLocation</param-name>
<param-value>
/WEB-INF/config/struts
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
/WEB-INF/config/struts 目录下面放置的是被按模块拆分后的多个 struts 配置文件,为了能保证这些配置文件能被 struts 的 actionservlet 读到,需要将他们追加到 actionservlet 的 config ,代码如下
protected void initOther() throws ServletException {
super .initOther();
String value = getServletConfig().getInitParameter( "configLocation" );
if (value != null ) {
configPath = value;
if ( this . config == null ) this . config = findFileNames( configPath );
else if ( "" .equals( this . config )) this . config = findFileNames( configPath );
else this . config = this . config + "," + findFileNames( configPath );
}
}
上面这段代码的作用就是将在 configlocation 项中配置的目录下的 struts 配置文件的路径追加到 config ,让 actionservlet 能够根据这些配置文件进行初始化。
spring 配置
由于该框架并没有将 struts 的 action 对象纳入到 spring 的管理中,因此需要在 web 。 Xml 中配置 spring 的 webcontextlisteners 上下文监听器,并且需要在 webcontext 中配置 spring 配置文件路径。具体配置如下:
配置上下文监听器
<listener>
<listener-class>com.thunisoft.dataapplatform.listener.WebContextListener</listener-class>
</listener>
在 struts 的 action 中取得 spring 的 context 对象的代码
import org.springframework.web.context.support.WebApplicationContextUtils;
WebApplicationContextUtils.getRequiredWebApplicationContext(servlet.getServletContext());
配置 spring 配置文件路径
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring/applicationContext-*.xml</param-value>
</context-param>
具体可参考 spring 手册集成其他框架 - 通用配置 15.2
Spring 中 hibernate 的配置
此处都是通用配置,看 spring 文档即可
Spring 中抽象事务模板的配置
< bean id = "txProxyTemplate" abstract = "true"
class = "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
< property name = "transactionManager" ref = "transactionManager" />
< property name = "transactionAttributes" >
< props >
<!-- ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
PROPAGATION_REQUIRES_NEW
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
PROPAGATION_NESTED
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop-->
< prop key = "query*" > PROPAGATION_SUPPORTS,readOnly </ prop >
< prop key = "*" > PROPAGATION_REQUIRED </ prop >
</ props >
</ property >
</ bean >
使用模板
< bean id = "sysLogLoginInfoService" parent = "txProxyTemplate" >
< property name = "target" >
< bean class = "com.thunisoft.core.service.log.impl.SysLogLoginInfoServiceImpl" autowire = "byName" />
</ property >
</ bean >
用 spring 的 OpenSessionInViewFilter 将 hibernate 的 session 生命周期绑定到 request 中
< filter >
< filter-name > hibernateFilter </ filter-name >
< filter-class > org .springframework .orm .hibernate3.support.OpenSessionInViewFilter </ filter-class >
</ filter >
用 spring 的 IntrospectorCleanupListener 保证内存整理的有效进行
这里需要补充一下, jdk 本身有自己的内存整理机制,使得一些不再被使用的内存对象整理能自动有效的进行,但是在 web 环境下,有些对象会被注册为上下文中的对象,这就导致即使这些对象不被使用了也不能被有效的清理,使用 IntrospectorCleanupListener 的话能有效保证这样对象也能被清理掉,从而提高能存的使用效率,具体配置如下:
< listener >
< listener-class > org .springframework .web.util .IntrospectorCleanupListener </ listener-class >
</ listener >