1、框架简介

      MVC对于我们来说,已经不陌生了,它起源于20世纪80年代针对smalltalk语言的一种软件设计模式。现在已经被广泛应用。近年来,随着java的盛行,MVC的低耦合性、高重用性、可维护性、软件工程的可管理性等诸多优点使其在java平台很受欢迎,期间,也诞生了许多优秀的MVC框架,如专注于控制层的struts、webwork、struts2、JSF等框架;专注于业务逻辑方面的Spring框架;专注于持久层的Hibernate、iBatis、Castor、JORM等框架。

下面对SSI框架:struts2+spring+iBatis的三个开源的MVC框架进行说明

Struts2主要来源于webwork框架,与Struts1相比:

  1. 数据传递方面,Struts2提供了更加强大的OGNL标签功能,使其能够通过action中定义变量来直接与jsp页面中的数据进行相互传值,省去了struts1中的formbean;
  2. 而在跳转控制方面,Struts2简化了配置文件的信息量,使页面和action之间的交换更加的简洁和直观,便于开发人员的管理。

Spring功能非常的强大:

  1. 比如它的控制反转IOC/依赖注入SET GET机制,省去了我们自己书写工厂模式的工作,实现类对我们将要用到的控制类Action业务逻辑类Service数据访问类domain、以及JNDI或者JDBC数据源Dao进行托管;
  2. Spring对AOP支持使我们在用户权限控制、事务处理方面节省了很多工作量;

iBatis则是一种轻量级的OR Mapping框架,与Hibernate相比,iBatis提供了半自动化对象关系映射的实现,开发人员需要编写具体的sql语句,为系统设计提供了更大的自由空间,为sql语句优化提供了便利。

2、框架结构

下面这张图就是我们所用到的这三种框架的结合体,下面对其做以简单的介绍。

SSC架构 ssc架构是什么_struts

(1)控制层

在控制层,利用Strtus2标签功能,在Action中直接与jsp页面上的数据进行交互。在调用业务逻辑层应用时,Struts2提供了对Spring的支持。开发人员需要完成对struts.xml的配置工作和各个Action类的编写。

总的struts.xml配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="struts-init" extends="struts-default">
		<action name="index" class="anonymousAction" method="execute">
			<result name="success">province_level/shanxi/login.jsp</result>
		</action>
		<action name="nologinAct" class="nologinAct">
			<result name="success">/common/nologin.jsp</result>
		</action>

		<!-- 插件下载 -->
		<action name="downLoadFileLogin" class="anonymousAction" method="getDownLoadFile">
			<result name="success" type="stream">
                <!--文件类型,当前是所有的类型 -->
				<param name="contentType">application/octet-stream</param>
                <!--第一个参数是指打开下载框默认是inline浏览器能打开的就不去下载直接打开 -->
				<param name="contentDisposition">attachment;fileName="${fileName}"</param>
				<param name="inputName">inputStream</param> <!--方法名字 -->
				<param name="bufferSize">1024</param>  <!--文件大小 -->
			</result>
		</action>
        <interceptors>
			<!-- 声明拦截器 -->
			<interceptor name="checkPrivilege"
				class="com.highland.criminal.business.sysman.Interceptor.CheckAuthorityInterceptor"></interceptor>
			<interceptor name="json" class="org.apache.struts2.json.JSONInterceptor" />
			<!-- 自定义拦截器 -->
			<interceptor name="exceptionInterceptor" class="com.highland.framework.web.interceptor.ExceptionInterceptor"></interceptor>
			<!-- 声明一个新的拦截器栈(先检查权限) -->
			<interceptor-stack name="myDefaultStack">
				<interceptor-ref name="defaultStack" />
				<interceptor-ref name="checkPrivilege" />
				<interceptor-ref name="exceptionInterceptor" />
				<interceptor-ref name="json" />
			</interceptor-stack>
		</interceptors>

		<!-- 默认使用的拦截器(拦截器栈) -->
		<default-interceptor-ref name="myDefaultStack" />
		<!-- 全局的Result配置 -->
		<global-results>
			<result name="error">/common/error.jsp</result>
			<result name="login" type="redirect">nologinAct.action</result>
			<result name="noPrivilegeError">/xtba/common/noPrivilegeError.jsp</result>
		</global-results>
		<global-exception-mappings>
			<exception-mapping result="error"
				exception="com.highland.framework.exception.BaseException"></exception-mapping>
		</global-exception-mappings>
		<!-- 为兼容ecside增加的错误action -->
		<action name="errorAction"
			class="com.highland.criminal.business.sysman.action.ExceptionAction">
			<result>/common/error.jsp</result>
		</action>
	</package>
    
    <include file="struts/struts-hdzhfx.xml"></include><!-- 综合分析-->

</struts>

由于项目中可能涉及多个功能模块,所以在总的struts.xml中通过<include>标签引入各个功能模块的xml配置。这里以综合分析模块为例,对struts-hdzhfx.xml配置文件进行分析

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>	
    <!-- 综合分析报告-->
    <package name="hdzhfx" namespace="/" extends="struts-init">
        <!-- 这种方式配置返回值链接:返回简单json字符串参数total和rows -->
        <action name="glhdfx_new" class="hdzhfxAction" method="glhdfx_new">
		  <result name="success" type="json">
		  <param name="includeProperties">
				  total,rows
				</param>
		  </result>
		 </action>

        <!-- 这种方式配置简单的查询方法链接 -->
		 <action name="zhfx_thqfx" class="hdzhfxAction" method="thqfx_Query"></action>
        <!--  这种方式配置返回值链接:返回list数据 -->
        <action name="listhdkxx" class="hdzhfxAction" method="listhdxx" >
			<result name="success">/xzzxyw/hdfx/queryHdxxList.jsp</result>
			<result name = "success_hdxx" type = "json">
				<param name = "root">
					bkxxs
				</param>
			</result>
		</action>
    </package>
</struts>

(2)业务逻辑层

业务逻辑层,利用Spring框架的依赖注入实现对业务逻辑类和Dao类的实例进行托管;

事务处理方面,利用Spring提供的面向切面的事务处理功能,使对数据的事务控制脱离于数据访问接口实现;

对象关系映射方面,利用Spring数据库连接池托管和对iBatis框架的支持。

开发人员需要完成对数据源的配置、对不同模块所对应的application*.xml文件的配置,以及对业务逻辑接口的定义和业务逻辑实现的编写。

SSC架构 ssc架构是什么_spring_02

① spring-->ibatis-->applicationContext-ibatis.xml:这里加载数据源配置及事务机制

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <!-- 引入项目的jdbc配置文件 -->
    <bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:/jdbc.properties</value>
			</list>
		</property>
	</bean>

    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
		<property name="driverClass"><value>${jdbc.driverClassName}</value></property>
		<property name="jdbcUrl"><value>${jdbc.url}</value></property>
		<property name="user"><value>${jdbc.username}</value></property>
		<property name="password"><value>${jdbc.password}</value></property>
		<property name="initialPoolSize"><value>50</value></property>
		<property name="minPoolSize"><value>50</value></property>
		<property name="maxPoolSize"><value>300</value></property>
		<property name="checkoutTimeout"><value>5000</value></property>
		<property name="maxIdleTime"><value>1800</value></property>
		<property name="idleConnectionTestPeriod"><value>3000</value></property>
		<property name="acquireIncrement"><value>5</value></property>
		<property name="maxStatements" value="0"/>
		<property name="testConnectionOnCheckout" value="false"/> 
	</bean>

    <!-- 定义事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"><ref bean="dataSource"/></property>
    </bean>

    
    <!-- Spring的IBatis模板 -->
    <!-- 加入对大数据类型操作的支持 -->
	<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>
    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
		<property name="configLocations">
            <!-- 重点:这里将spring中的ibatis层与ibatis连接起来了 -->
			<value>classpath*:/ibatis/app-sqlmap-config.xml</value>
		</property>
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="lobHandler" ref="lobHandler"/> <!-- 加入对大数据类型操作的支持 -->  
	</bean>
    
    <bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
        <property name="sqlMapClient" ref="sqlMapClient"></property>  
    </bean>


    <!--开启事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

spring-->ibatis-->app-ibatis-hdzhfx.xml (这个文件与applicationContext-ibatis.xml是通过<ref bean="sqlMapClient">关联到一起的)

这里配置Dao的bean值,是为下一层spring-->service-->app-service-hdzhfx.xml中的bean的返回值<ref bean="tbryhdDao" />做的配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="tbryhdDao" class="com.highland.criminal.business.dao.stdao.TbRyHdDao">
		<property name="sqlMapClient">
			<ref bean="sqlMapClient" />
		</property>
	</bean>
	<bean id="tbryhdtxlbdDao" class="com.highland.criminal.business.dao.stdao.TbRyHdTxlBdDao">
		<property name="sqlMapClient">
			<ref bean="sqlMapClient" />
		</property>
	</bean>
</beans>

② spring-->service-->app-service-hdzhfx.xml承上启下的作用。

承上:<ref bean="tbryhdDao" />这里的ref中bean的值对应的是spring-->ibatis-->app-ibatis-hdzhfx.xml中配置的bean的id    

启下:这里的bean 的id值zhHdfxService对应的是spring-->struts-->app-struts-hdzhfx.xml中需要的service的名字 <ref bean="zhHdfxService" />。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	
    <!-- 配置bean:注意这里的bean的id对应的是spring中app-struts-hdzhfx.xml中的ref对应的bean值-->
    <bean id="zhHdfxService" parent="baseTransactionProxy">
		<property name="target">
			<bean class="com.highland.criminal.business.xzqbyp.hdfx.service.imp.HdZhfxServiceImpl">
                <!-- 这里的ref中bean的值对应的是spring中的ibatis下app-ibatis-hdzhfx.xml中配置的bean的id -->	
				<property name="tbryhdDao"><ref bean="tbryhdDao" /></property>
				<property name="tbRyhdtxlDao"><ref bean="tbryhdtxlbdDao" /></property>
			</bean>
		</property>
	</bean>

</beans>

③ spring -->struts-->app-struts-hdzhfx.xml:

<ref bean="zhHdfxService" />这里的bean的值对应的是spring-->service-->app-service-hdzhfx.xml中配置的bean的id

这里bean的id值hdzhfxAction对应的是配置struts-hdzhfx.xml中需要的action的class类值

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<!-- 配置bean:注意这里的bean的id对应的是spring中struts-hdzhfx.xml中的action的class -->
	<bean id="hdzhfxAction" class="com.highland.criminal.business.xzqbyp.hdfx.action.HdZhfxAction"  scope="prototype">
		<property name="zhHdfxService">
            <ref bean="zhHdfxService" /><!-- 注意:这里的bean的值对应的是spring中service中的app-service-hdzhfx.xml中配置的bean的id -->
        </property>
	</bean>

</beans>

(3) 持久层

在持久层,利用iBatis提供的半自动化对象关系映射实现。开发人员需要编写具体的sql语句,为系统设计提供了更大的自由空间。另外,开发人员需要完成对ibatis的配置文件app-sqlmap-config.xml和*-sqlmap.xml的配置,以及对DAO接口的定义和DAO接口的实现。

app-sqlmap-config.xml:这里配置了多个sql文件的引用

与spring层之间的关联:在spring-->ibatis-->applicationContext-ibatis.xml中配置了这:

<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
         <property name="sqlMapClient" ref="sqlMapClient"></property>  
     </bean>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "sql-map-config-2.dtd">
<sqlMapConfig>
	<settings cacheModelsEnabled="false" enhancementEnabled="false"
    lazyLoadingEnabled="false" maxRequests="3000" maxSessions="3000"
    maxTransactions="3000" useStatementNamespaces="true" />
	<sqlMap resource="/ibatis/app/hdzhfx-sqlmap.xml" />
</sqlMapConfig>

hdzhfx-sqlmap.xml:这个文件里写sql语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "sql-map-2.dtd">
<sqlMap namespace="hdfxnew">
    <!-- 映射实体 -->
    <typeAlias alias="hdfxxx" type = "com.highland.framework.hdanalysis.domain.hdfxdomain" />
	
	<!-- 根据id查询信息 -->
	<select id="queryHdInfo" parameterClass="hdfxxx" resultClass="hdfxxx">
		
	select BJGSD,CTLX,MYZT,THDD,THJZ,JZDQ,JZXQ,IMEI,IMSI,JD,WD,
		DFTHDD,DFTHJZ,DFJZDM,DFIMSI,DFGSD,DFIMEI,DFHMJZXM,DFCH,
		DFJZQW,DFJD,DFWD,HOLDING_TIME,BJHM,DFHM,CALL_TYPE,
		START_TIME,END_TIME from HD_CALL_INFO where 1=1 and scbz=0
		<isNotEmpty property="BJHM"> and BJHM= #BJHM#</isNotEmpty>
		<isNotEmpty property="DFHM"> and DFHM= #DFHM#</isNotEmpty>
		<isNotEmpty property="CALL_TYPE"> and CALL_TYPE= #CALL_TYPE#</isNotEmpty>
		<isNotEmpty property="START_TIME"> and to_date(START_TIME,'yyyy-MM-dd hh24miss') >= to_date(#START_TIME#,'yyyy-MM-dd')</isNotEmpty>
		<isNotEmpty property="END_TIME"> and to_date(END_TIME,'yyyy-MM-dd hh24miss') <![CDATA[<=]]> to_date(#END_TIME#,'yyyy-MM-dd')</isNotEmpty>
		<isNotEmpty property="THDD"> and THDD= #THDD#</isNotEmpty>
	</select>
	<!-- 新增记录 -->
	<insert id="savedrrzdata" parameterClass="hdfxxx">
		insert into HD_CALL_LOG (xxzjbh,jzhm,ckrxm,asjbh,ckrsfzh,drzs,drms,drsj)
        values (#xxzjbh#,#jzhm#,#ckrxm#,#asjbh#,#ckrsfzh#,#drzs#,#drms#,#drsj#)
        <selectKey resultClass="java.lang.String" keyProperty="xxzjbh">
           select #xxzjbh# as xxzjbh from dual
        </selectKey>
	</insert>
	<!-- 查询所有的信息 -->
	<select id="queryHdlogInfo" parameterClass="hdfxxx" resultClass="hdfxxx">
		select xxzjbh,ckrsfzh,jzhm,ckrxm,asjbh,drzs,drms,drsj from HD_CALL_LOG where 1=1 and scbz=0
	</select>
</sqlMap>

(4)小结

        在各层之间进行交换的过程中,利用数据传输类进行数据的传递和交互。其中数据传输类与数据库表一一对应。

SSI框架能够降低代码的耦合度,增强了代码的健壮性和可重用性,加快了开发速度,但是也有一些不足之处,比如由于三种框架的配置文件较多,也会带来一些不便,特别是对于较小的应用来说更是如此。