# sshTest **Repository Path**: hzaccp/sshTest ## Basic Information - **Project Name**: sshTest - **Description**: 一个ssh例子,描述:http://blog.csdn.net/hzaccp3/article/details/11949781。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2013-09-23 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 最近找了份去年的SSH例子,做个简单的配置分析,记录些技术点方便以后使用。
CSDN:http://blog.csdn.net/hzaccp3/article/details/11949781

技术点:
        SSH整合、AOPLog及Log4j使用、声明式事务使用
版本:
        Struts2:2.3.15.1
        Spring:2.0
        Hibernate:3.2.0.cr4
jar包:

其中:
        hzaccp.jar 为工具包,包含部分基类、时间处理及字符串处理等,源码也一起打包。
目录结构:

1:左边是src,使用三层结构,由于用的是struts2,所以注入都在applicationContext.xml中完成。biz中注入ICompanyDao,action中注入ICompanyService。
2:右图是web目录,将所有jsp都放在WEB-INF目录下,不能直接访问到,只能通过struts2引用过来。
配置:
web.xml
<!-- 检索Spring的配置,可以定义多个配置文件。这里有两个适配器,第一个指WEB-IN下的xml, 第二个检索classpath(一般在WEB-INF\classes),第一个*为项目,第二个*为模块, 如例子,在myproject项目中,permission模块下就有一个。 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/applicationContext.xml,classpath:com/hzaccp/*/*/applicationContext.xml</param-value>
</context-param>

<!-- 用于初始化Spring容器的Listener -->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Spring提供的字符过滤器 -->
<filter>
	<filter-name>encodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>utf-8</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>encodingFilter</filter-name>
	<url-pattern>*.jsp</url-pattern>
</filter-mapping>

<!-- Hibernate懒加载处理,很少用到这个 -->
<filter>
	<filter-name>lazyLoadingFilter</filter-name>
	<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

<!-- Struts的入口,定义Struts2的FilterDispathcer的Filter。 -->
<filter>
	<filter-name>struts2</filter-name>
	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- 欢迎页 -->
<welcome-file-list>
	<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

src\struts.xml
<!-- struts的扩展名,以jhtml结尾。以前用.do、.action -->
<constant name="struts.action.extension" value="jhtml" />

<!-- 是否使用spring注入 -->
<constant name="struts.objectFactory" value="spring" />

<!-- 设置编码 -->
<constant name="struts.i18n.encoding" value="utf-8" />

<!-- 是否使用动态方法拦截器 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />

<!-- 是否每次请求都去重新加载资源 -->
<constant name="struts.i18n.reload" value="true" />

<!-- 开发模式,开启后,action会慢一个级别 -->
<constant name="struts.devMode" value="true" />

<!-- 文件上传的临时目录。这个目录不一定会存在,上传完成后,文件也会自动删除 -->
<constant name="struts.multipart.saveDir" value="c:/hzaccp/temp/" />

<!-- 文件上传大小,配置为10M,超过这个大小则报错 -->
<constant name="struts.multipart.maxSize" value="10485760" />

<!-- 默认包 -->
<package name="default" extends="struts-default">
	<action name="*" class="com.hzaccp.comm.BaseAction">
		<result>/{1}.jsp</result>
	</action>
</package>

<!-- 导入模块 -->
<include file="com/hzaccp/myporject/permission/action/Company-struts.xml" />

src\struts.xml
<!-- 数据库账号和密码 -->
<property name="connection.username">sa</property>
<property name="connection.password">123456789</property>

<!-- 数据库连接信息,为本地的test数据库 -->
<property name="connection.url">jdbc:sqlserver://127.0.0.1;databaseName=test</property>

<!-- 数据库方言,我用的是sqlServer,所以选用这个,也可以选用org.hibernate.dialect.MySQL5Dialect等。如果需要自定义hibernate函数,可以继承这个类,并指向自定义的类。 -->
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>

<!-- sql驱动类 -->
<property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>

<!-- 输出sql -->
<property name="show_sql">true</property>

<!-- 添加hibernate映射 -->
<mapping resource="com/hzaccp/myporject/permission/entity/CompanyInfo.hbm.xml" />

WEB-INF\applicationContext.xml
<!-- 声明一个hibernate session工厂,并注入配置文件,也就是上面所说的hibernate.cfg.xml -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
	<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>

<!-- 声明hibernate事务管理器,并注入hibernate session工厂 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory">
		<ref bean="sessionFactory"></ref>
	</property>
</bean>

<!-- 使用声明式事务,对add、update、delete开头的方法使用事务,其他使用SUPPORTS事务。这里只是声明,并没有使用 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="add*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="delete*" propagation="REQUIRED" />
		<tx:method name="*" propagation="SUPPORTS" read-only="true" />
	</tx:attributes>
</tx:advice>

<!-- 定义了一个AOP切入点,只对Biz层添加事务支持。使用前面配置的transactionManager是专对Hibernate的事务管理器 -->
<aop:config>
	<aop:pointcut id="allServiceMethods" expression="execution(* com.hzaccp.*.*.biz.impl.*.*(..))" />
	<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods" />
</aop:config>

<!-- 日志AOP,与事务类似 -->
<bean id="methodAdive" class="com.hzaccp.comm.AOPLogBean"></bean>
<aop:config>
	<aop:pointcut id="allMethod" expression="execution(* com.hzaccp.*.*.biz.impl.*.*(..))" />
	<aop:aspect id="logAspect" ref="methodAdive">
		<aop:around method="intercept" pointcut-ref="allMethod" />
	</aop:aspect>
</aop:config>

<!-- 声明DAO父类,并注入Hibernate的session工厂 -->
<bean id="baseDAO" class="com.hzaccp.comm.dao.HibernateBaseDAO">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

src\log4j.properties
#DEBUG级别,并声明两个记录器
log4j.rootLogger=DEBUG,stdout,hzaccp

#stdout记录器输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n

#hzaccp记录器输出到文件
log4j.appender.hzaccp=org.apache.log4j.RollingFileAppender
log4j.appender.hzaccp.File=hzaccp.log  
log4j.appender.hzaccp.MaxFileSize=100KB
log4j.appender.hzaccp.MaxBackupIndex=1
log4j.appender.hzaccp.layout=org.apache.log4j.PatternLayout
log4j.appender.hzaccp.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m -(:%L)%n

#以下添加各个模块的输出过滤
# Print only messages of level FATAL or above in the package noModule.
log4j.logger.noModule=FATAL

# Freemarker模块
# struts2升级到2.3.15.1后,jsp界面用到struts标签后,输出的log
log4j.logger.freemarker=ERROR
log4j.logger.freemarker.cache=INFO

# OpenSymphony模块
log4j.logger.com.opensymphony=INFO
log4j.logger.org.apache.struts2=INFO

# Hibernate模块
log4j.logger.org.hibernate=INFO

# Spring模块
log4j.logger.org.springframework=INFO

# hzaccp模块
log4j.logger.com.hzaccp=DEBUG


模块内部醒置:每个模块都会包含action、biz、dao及entity包。在action中,包含各个组件的action文件及对应struts.xml文件。entity包中包含组件的Info及对应的hbm.xml文件。
具体配置:
com.hzaccp.myporject.permission.applicationContext.xml
<!-- dao -->
<bean id="companyDAO" class="com.hzaccp.myporject.permission.dao.impl.CompanyDAOImpl" parent="baseDAO" />

<!-- biz -->
<bean id="companyService" class="com.hzaccp.myporject.permission.biz.impl.CompanyServiceImpl">
	<property name="companyDAO" ref="companyDAO" />
</bean>

<!-- action -->
<bean id="companyAction" class="com.hzaccp.myporject.permission.action.CompanyAction" scope="prototype">
	<property name="companyService" ref="companyService" />
</bean>

com.hzaccp.myporject.permission.action.Company-struts.xml
<!-- add -->
<action name="toAddCompany" class="companyAction" method="toAddCompany">
	<result name="success">/WEB-INF/permission/addCompany.jsp</result>
</action>
<action name="addCompany" class="companyAction" method="addCompany">
	<result name="success" type="chain"><!-- 跳转至list -->
		<param name="actionName">companyList</param>
		<param name="namespace">/permission</param>
	</result>
</action>

<!-- update -->
<action name="toUpdateCompany" class="companyAction" method="toUpdateCompany">
	<result name="success">/WEB-INF/permission/updateCompany.jsp</result>
</action>
<action name="updateCompany" class="companyAction" method="updateCompany">
	<result name="success" type="chain"><!-- 跳转至list -->
		<param name="actionName">companyList</param>
		<param name="namespace">/permission</param>
	</result>
</action>

<!-- list -->
<action name="companyList" class="companyAction" method="companyList">
	<result name="success">/WEB-INF/permission/companyList.jsp</result>
</action>

<!-- detail -->
<action name="companyDetail" class="companyAction" method="companyDetail">
	<result name="success">/WEB-INF/permission/companyDetail.jsp</result>
</action>

<!-- delete -->
<action name="deleteCompany" class="companyAction" method="deleteCompany">
	<result name="success" type="chain"><!-- 跳转至list -->
		<param name="actionName">companyList</param>
		<param name="namespace">/permission</param>
	</result>
</action>
各个action之间的跳转如图:


总结:
1: web.xml中的contextConfigLocation,如果配置不正确,则无法检索到spring配置.
2:WEB-INF\applicationContext.xml中的allServiceMethods及txAdvice,配置不正确会导致数据库死锁。如:在biz中其中一个方法执行了更新数据库,但该方法没在txAdvice配置,则事务就无法提交。
3: struts.xml中的struts.devMode,该值为true时,Requests per second=573。为false时, Requests per second=1893。struts本来就慢,在部署后,必须关闭开发模式,有必要是,把AOP日志之类的也可以关闭。