SSH 与 SSM

SSM 指:SpringMVC、Spring 和 MyBatis

SSH 指:Struts、Spring 和 Hibernate

两种框架的对比和对照为:

控制器事务层持久层
SSHStrutsSpringHibernate
SSMSpringMVCSpringMyBatis

SSH 框架采用 Struts 作为控制器,即 Controller,Spring 作为事务层,即 Service,Hibernate 作为持久层,即 Dao 层。

SSM 框架采用 SpringMVC 作为控制层,即 Controller,Spring 作为事务层,即 Service,MyBatis 作为持久层,即 Dao 层。

Struts 之于 SpringMVC

相同点:它们都是表现层框架,都是基于 MVC 模型编写的。它们的底层都离不开原始的 servletAPI。同时它们处理请求的机制都是一个核心控制器。

区别:Spring MVC 的入口是 Servlet,而 Struts 的入口是 Filter;Spring MVC 是基于方法设计的,而 Struts 是基于类,因此 Struts 每次执行都会创建一个 Action 动作类,所以 Spring MVC会稍微比 Struts 快些;Spring MVC 框架采用松耦合可插拔的组件结构,具有高度可配置性,比其他 MVC 框架更具有扩展性和灵活性;Spring MVC 本身就是 Spring 框架的一部分,与 Spring 框架的整合可以说是无缝集成,如果使用 Struts2 还需要自己配置内容;Struts 和 SpringMVC 控制视图和模型的交互机制不同;Strtus 是 Action 类级别,SpringMVC 是方法级别,更容易实现 RESTful 风格。

Struts 是一个优秀、开源、免费的 MVC 的框架。

其优点有:

  • 实现了 MVC 模式,层次结构清晰,使程序员只需关注业务逻辑的实现。
  • 丰富的标签库,大大提高了开发的效率。
  • Struts 提供丰富的拦截器实现。
  • 通过配置文件,就可以掌握整个系统各个部分之间的关系。
  • 异常处理机制,只需在配置文件中配置异常的映射,即可对异常做相应的处理。
  • Struts 的可扩展性高。
  • 面向切面编程的思想在 Struts 中也有了很好的体现。

其缺点有:

  • Struts 中 Action 中取得从 jsp 中传过来的参数时还是有点麻烦。
  • 校验还是感觉比较繁琐,感觉太烦乱,也太细化了,如果校验出错的只能给用户提示一些信息。
  • 安全性有待提高。

Struts 执行步骤(Struts 使用 Filter 嵌入):

  1. 客户端初始化指向 Service 容器(Tomcat)的请求;
  2. 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做 ActionContextCleanUp 的可选过滤器,这个过滤器对于 Struts 和其他框架的集成很有帮助);
  3. 接着 FilterDispatcher 被调用,FilterDispatcher 询问 ActionMapper 来决定这个请求是否需要调用某个 Action;
  4. 如果 ActionMapper 决定需要调用某个 Action,FilterDispatcher 把请求的处理交给 ActionProxy;
  5. ActionProxy 通过 ConfigurationManger 询问框架的配置文件,找到需要调用的 Action 类;
  6. ActionProxy 创建一个 ActionInvocation 的实例;
  7. ActionInvocation 实例使用命名模式来调用,在调用 Action 的过程前后,涉及到相关拦截器(Intercepter)的调用;
  8. 一旦 Action 执行完毕,ActionInvocation 负责根据 struts.xml 中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外一个Action链)一个需要被表示的 jsp 或者 FreeMarker 的模板;
  9. 将处理结果返回

Spring

Spring 是一个分层的 full-stack(一站式)轻量级框架,以 Ioc(Inversion of Control,控制反转)和  AOP(Aspect Oriented Programming,面向切片编程)为内核,使用简单的 JavaBean 来完成以前只能由 EJB(Enterprise Java Beans)完成的工作,取代了臃肿、低效的 EJB。

Spring 致力于 JavaEE 应用各层的解决方案,是企业应用一站式开发很好的选择,在表现层它提供了 SpringMVC 以及整合 Struts 的功能,在业务逻辑层可以管理事务、记录日志等,在持久层可以整合 Hibernate、Mybatis 等框架。虽然 Spring 贯穿表现层、业务逻辑层、持久层,但 Spring 并不是要取代那些已有的优秀框架,而是可以高度开放的与其它优秀框架无缝整合。

Spring 的优势:

1、非侵入式设计。Spring 是一种非侵入式(no-invasive)框架,它可以使应用程序代码对框架的依赖最小化。

2、方便解耦、简化开发。Spring 是一个大工厂,可以将所有对象的创建、依赖关系的维护交给Spring 容器管理,大大降低了组件之间的耦合。

3、支持AOP。允许将一些通用任务,比如安全、事务、日志等,进行集中式管理,从而提高程序的复用性。

4、支持声明式事务处理。通过配置就可以完成对事务的管理,无需手动编程。

5、方便整合其它优秀框架。Spring 可以与大多数框架无缝整合。

6、测试方便。Spring 支持 Junit4,可通过注解测试程序,很方便。

7、降低了使用 JavaEE API 的难度。Spring对JavaEE开发中难用的一些API进行了封装,降低了这些API的使用难度。

Hibernate 之于 MyBatis

Hibernate 是 Java 领域的一款开源的 ORM 框架技术,对 JDBC 进行了非常轻量级的对象封装。

Hibernate 是全自动,而 MyBatis 是半自动。

Hibernate 完全可以通过对象关系模型实现对数据库的操作,拥有完整的 JavaBean 对象与数据库的映射结构来自动生成 sql。而 MyBatis 仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写 sql 来实现和管理。

Hibernate 数据库移植性远大于 MyBatis。

Hibernate 通过它强大的映射结构和 hql 语言,大大降低了对象与数据库(oracle、mysql等)的耦合性,而 MyBatis 由于需要手写 sql,因此与数据库的耦合性直接取决于程序员写 sql 的方法,如果 sql 不具通用性而用了很多某数据库特性的 sql 语句的话,移植性也会随之降低很多,成本很高。

Hibernate 拥有完整的日志系统,MyBatis 则欠缺一些。

Hibernate 日志系统非常健全,涉及广泛,包括:sql 记录、关系异常、优化警告、缓存提示、脏数据警告等;而 MyBatis 除了基本记录功能外,功能薄弱很多。

MyBatis 相比 Hibernate 需要关心很多细节。

Hibernate 配置要比 MyBatis 复杂的多,学习成本也比 MyBatis 高。但也正因为 MyBatis 使用简单,才导致它要比 Hibernate 关心很多技术细节。MyBatis 由于不用考虑很多细节,开发模式上与传统 jdbc 区别很小,因此很容易上手并开发项目,但忽略细节会导致项目前期 bug 较多,因而开发出相对稳定的软件很慢,而开发出软件却很快。Hibernate则正好与之相反。但是如果使用 Hibernate 很熟练的话,实际上开发效率丝毫不差于甚至超越 MyBatis。

sql 直接优化上,MyBatis 要比 Hibernate 方便很多。

由于 MyBatis 的 sql 都是写在 xml 里,因此优化 sql 比 Hibernate 方便很多。而 Hibernate 的 sql 很多都是自动生成的,无法直接维护 sql;虽有 hql,但功能还是不及 sql 强大,Hibernate 虽然也支持原生 sql,但开发模式上却与 ORM 不同,需要转换思维,因此使用上不是非常方便。总之写 sql 的灵活度上 Hibernate 不及 MyBatis。

总结来说就是:

MyBatis:小巧、方便、高效、简单、直接、半自动

Hibernate:强大、方便、高效、复杂、绕弯子、全自动

MyBatis:入门简单,即学即用,提供了数据库查询的自动对象绑定功能,而且延续了很好的 sql 使用经验,对于没有那么高的对象模型要求的项目来说,相当完美;可以进行更为细致的 sql 优化,可以减少查询字段。缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改;二级缓存机制不佳。

Hibernate:功能强大,数据库无关性好,O/R 映射能力强,如果对 Hibernate 相当精通,而且对 Hibernate 进行了适当的封装,那么项目整个持久层代码会相当简单,需要写的代码很少,开发速度很快,非常爽;有更好的二级缓存机制,可以使用第三方缓存;缺点就是学习门槛高,要精通门槛更高,而且考虑怎么设计 O/R 映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好 Hibernate 方面需要你的经验和能力都很强才行。

举个形象的比喻:

MyBatis:机械工具,使用方便,拿来就用,但工作还是要自己来作,不过工具是活的,怎么使由我决定。

Hibernate:智能机器人,但研发它(学习、熟练度)的成本很高,工作都可以摆脱他了,但仅限于它能做的事。

SSM 框架的相关配置文件:

hibernate-conf 文件夹下完成相关 Hibernate 的配置:xxxDO.hbm.xml 记录表与表的对应关系,即完成一对多、多对一的表关系。通过 one-to-many 或 many-to-one  来实现。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="xxx.user.model.UserDO" table="T_USER">
        <id name="id" type="java.lang.Long">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="loginName" type="java.lang.String">
            <column name="LOGIN_NAME" not-null="true" />
        </property>
        <property name="userName" type="java.lang.String">
            <column name="USER_NAME" not-null="true" />
        </property>
        <property name="phone" type="java.lang.String">
            <column name="PHONE" length="50" />
        </property>
        <property name="mail" type="java.lang.String">
            <column name="MAIL" />
        </property>
        <property name="credentialSet" type="java.lang.Long">
            <column name="CREDENTIAL_SET" not-null="true">
                
            </column>
        </property>
        <property name="showNum" type="java.lang.Integer">
            <column name="SHOW_NUM" not-null="true">
                
            </column>
        </property>
        <property name="accountStatus" type="java.lang.Short">
            <column name="ACCOUNT_STATUS" not-null="true">
                
            </column>
        </property>
        <property name="lockStatus" type="java.lang.Short">
            <column name="LOCK_STATUS" not-null="true">
                
            </column>
        </property>
        <property name="isDeleted" type="java.lang.Short">
            <column name="IS_DELETED" not-null="true">
                
            </column>
        </property>
        <property name="lastUpdate" type="java.lang.Long">
            <column name="LAST_UPDATE" not-null="true" />
        </property>
        <property name="createTime" type="java.util.Date">
            <column name="CREATE_TIME" length="19" not-null="true" />
        </property>
        <property name="lockTime" type="java.util.Date">
            <column name="LOCK_TIME" length="19" />
        </property>
        <property name="failedTimes" type="java.lang.Integer">
            <column name="FAILED_TIMES" not-null="true" />
        </property>
        <property name="lastLoginSuccessTime" type="java.util.Date">
            <column name="LAST_LOGIN_SUCCESS_TIME" length="19" />
        </property>
        <property name="lastLoginFailedTime" type="java.util.Date">
            <column name="LAST_LOGIN_FAILED_TIME" length="19" />
        </property>
        <set name="userTempPassDOs" inverse="true">
            <key>
                <column name="USER_ID" not-null="true">
                    
                </column>
            </key>
            <one-to-many class="xxx.credential.model.UserTempPassDO" />
        </set>
        <set name="userCertDOs" inverse="true">
            <key>
                <column name="USER_ID" not-null="true">
                    
                </column>
            </key>
            <one-to-many class="xxx.credential.model.UserCertDO" />
        </set>
        <set name="authLockAidDOs" inverse="true">
            <key>
                <column name="USER_ID" not-null="true">
                    
                </column>
            </key>
            <one-to-many class="xxx.authentication.model.AuthLockAidDO" />
        </set>
        <set name="deptUserRelDOs" inverse="true">
            <key>
                <column name="USER_ID" not-null="true">
                    
                </column>
            </key>
            <one-to-many class="xxx.user.model.DeptUserRelDO" />
        </set>
        <set name="userAssistantAccountDOs" inverse="true">
            <key>
                <column name="USER_ID" not-null="true">
                    
                </column>
            </key>
            <one-to-many class="xxx.user.model.UserAssistantAccountDO" />
        </set>
    </class>
</hibernate-mapping>

spring-conf 文件夹下完成 Dao 与 Service 的配置:daoContext.xml 来完成 Dao 层实现类的配置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-autowire="byName">
<!-- dao实现类的配置 -->
	<bean id="userDAO" class="xxx.user.dao.impl.UserDAOImpl" />
	<bean id="deptDAO" class="xxx.user.dao.impl.DeptDAOImpl" />
	<bean id="deptUserRelDAO" class="xxx.user.dao.impl.DeptUserRelDAOImpl" />
</beans>

serviceContext.xml 来完成 Service 层实现类的配置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-autowire="byName">
	<!-- service实现类的配置 -->
	<bean id="userService" class="xxx.user.service.impl.UserServiceImpl" />
	<bean id="deptService" class="xxx.user.service.impl.DeptServiceImpl" />
	<bean id="deptUserRelService" class="xxx.user.service.impl.DeptUserRelServiceImpl" />
</beans>

在 struts-conf 文件夹下完成 struts 相关的配置:struts-config.xml。可通俗理解为建立页面与 Action 方法返回值的对应关系。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
	<form-beans>
		<form-bean name="deptVO" type="xxx.user.vo.DeptVO" />
		<form-bean name="userVO" type="xxx.user.vo.UserVO" />
	</form-beans>

	<action-mappings>
		<action attribute="userVO"
				path="/xxx/user/userManage" 
				input=""
				name="userVO" 
				parameter="method" 
				type="xxx.user.action.UserManageAction"
				scope="request">
			<forward name="xxxshowUserList" path="/xxx/xxx/user/user/xxxuserListDetail.jsp"></forward>
			<forward name="xxxxuserList" path="/xxx/xxx/user/user/xxxuserList.jsp"></forward>
			<forward name="xxxtoUserDetail" path="/xxx/xxx/user/user/toUserDetail.jsp"></forward>
		</action>
		
		<action attribute="deptVO"
				path="/xxx/user/deptManage" 
				input=""
				name="deptVO" 
				parameter="method" 
				type="xxx.user.action.DeptManageAction"
				scope="request">
				
			<forward name="xxxshowDeptTree" path="/xxx/xxx/user/dept/xxxdeptListDetail.jsp"></forward>
			<forward name="xxxtoAddDept" path="/xxx/xxx/user/dept/xxxtoAddDept.jsp"></forward>
		</action>
		
	</action-mappings>
</struts-config>

在 struts-spring-conf 文件夹下完成 Struts 与 Spring 的相关配置,可通俗理解为配置 Struts 接入 Spring:spring-action.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-autowire="byName">
	<bean name="/xxx/user/xxxManage"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target">
			<bean class="xxxx.user.action.UserManageAction"/>
		</property>
	</bean>
	
	<bean name="/xxx/user/xxxManage"
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target">
			<bean class="xxx.user.action.DeptManageAction"/>
		</property>
	</bean>
</beans>

配置 Service 实现类就相当于 SSM 框架中使用 @Service 注解去将 Service 交由 Spring 容器管理,在 SSM 框架中,使用 Service 时是通过 @Autowired 注解去实现的,使用 Dao 层的 Mapper 时也可以通过 @Autowired 注解实现,在 SSH 框架中,通过如下方式完成对 Service 或 Dao 层 Mapper 的使用:


private IUserService userService;
	
private IDeptService deptService;

public void setUserService(IUserService userService) {
	this.userService = userService;
}

public void setDeptService(IDeptService deptService) {
	this.deptService = deptService;
}


private IUserDAO userDAO;

public void setUserDAO(IUserDAO userDAO) {
	this.userDAO = userDAO;
}

本文参考自:SSH和SSM的区别_一只菜鸡小猴ou的博客-CSDN博客_ssh和ssm

hibernate 与mybatis 的区别 和特点_ww !的博客-CSDN博客_hibernate和mybatis

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值