相信SSH没人不知道了吧,struts2+spring+hibernate,企业开发的“基础”架构,为什么基础标上引号,因为这个基础只是很多人自以为的而已,最基础的是servlet,很多培训机构很多基础都不教,直接上来就三大框架了,SSH不然就SSI,搞得很多人以为JAVAWEB开发就一定要框架,没框架就跟没了手一个样。三大框架没有什么坏处,实用,很多公司都在用,直接上手开发。但毕业以为真的好久没用三大框架了,spring倒是有用,特别是springMVC,感觉用起来比struts2爽多了。其实想想也知道,spring是吸收了struts的一些优点的,另外加上一些RESTFUL的东西,感觉爽多了。但今天我们不看springMVC,以后我们再抽时间来一起看看springMVC的优雅的地方。
进入正题啦。SSH一直在更新版本,这里我还是要说一下版本,不然一堆朋友会骂我一顿的,struts2我用的是2.3.4,spring是最新的3.2.2,hibernate是4.1.9,还是蛮新的啊。
在进入代码前,我们先来了解下三大框架各自扮演的角色。
1)struts:为什么我们用struts,跟servlet比起来什么区别?实际上不用struts我们还是可以做到MVC的,只是在配置文件上面可能就比较郁闷点了。struts主要帮我们实现分发的一个功能,将我们的具体的请求分到某一个具体的类中,并帮我们进行属性的设置(struts1.X中通过ActionForm来进行)。struts2相比struts1是进步很多了,自动设值,没有强制要求实现或继承类,并且有了一系列的请求链之类的概念。由于这些用得不多,免得误导各位兄弟,就不多说了。
2)spring:相信spring的大名没有搞JAVA的不知道了吧。很多人接触spring最开始应该也是通过它的IOC了解的吧,或者直接啥都不知道,就三大框架SSH来了。没关系,反正当我们用三大框架时,spring很大程度上是作为一个纽带类的工具,结合另外两大框架,SSI,SSH都一样,spring只是提供了工具让我们更方便地使用三大框架。当然,框架结合中很大程序也依赖了spring的IOC,另外,事务我们也当然会用到。AOP这些比较高级的东西,就要看需要了,如有什么日志要求,拦截要求,用AOP就可以实现地比较好了。
3)Hibernate:Hibernate在JAVA界也是大名鼎鼎的了,基本上是ORM的标准了。它提供了缓存,一级和二级,并且还有HQL,三大框架结合的时候,我们用它的什么呢?当然就是ORM这个映射的主要功能了,缓存的我们暂时不考虑了。很多人没考虑过为什么需要ORM吧。其实主要还是因为数据的字段和类之间的冲突,如果用JDBC来操作,一个个字段去set,估计做久了,人都会疯掉,所以这时ORM就出现了。
三大框架各自负责的东西如下:struts2——负责请求转发及表单的相应处理,spring——类的组织(即IOC),把本来由struts2管理的Action作为bean来管理,hibernate——ORM映射,把类映射到表中。
了解了大概分工,当然就开始我们的编码了。三大框架比较麻烦的就是包了,很多人喜欢用myeclipse主要还是因为它可以帮我们导入三大框架的包。但建议新手还是不要用那个,一是myeclipse有自己的项目结构,拿到eclipse一导还要设置一些project facet之类的,给别人带来不便;二是公司里面很少用myeclipse,还是熟悉eclipse好点。或者喜欢idea的也不错。
struts2的必须的包如下:antlr,asm,xwork,struts2-core,ognl,common-logging,common-fileupload,struts-spring-plugin,大概就这几个,可能没写全,大家可以在启动时报错的情况再加上,不建议一上来就丢所有包,三大框架有一些包是冲突的。
spring3需要的包如下:spring-beans,spring-core,spring-context,spring-context-support,spring-expression,spring-orm(我们用到三大框架,需要ORM支持),spring-web,spring-tx(我们用到事务,但例子中不涉及)。
hibernate4需要的包如下:hibernate下载包内的required文件夹的所有JAR包。
就大概这些包就OK了,还是那句话,不建议一上来就放所有包,因为三大框架有些包是有冲突的,在需要的时候酌情加上就好,出现ClassNotFound的时候就把到相应的JAR包,放到lib目录下。
准备工作就到此结束了,我们正式开始了。
1)首先,我们需要使用struts2,肯定要让他拦截请求
1
2
3
4
5
6
7
8
|
< 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 >
|
这段代码就让struts拦截所有请求,当然,并不是说就这样所有请求就被spring拦截了,我们还可以配置struts.xml,让struts拦截特定的后缀名,一般情况下都是action。如下:
1
2
|
< constant name = "struts.objectFactory" value = "spring" />
< constant name = "struts.action.extension" value = "action" />
|
struts.action.extension就配置了拦截的默认后缀名,这样在拦截的时候就会检查后缀名,符合的就会被struts进行转发了。而struts.objectFactory而是表示把struts的转发处理类交由spring来进行管理,也即是作为bean进行管理。
2)平常我们直接使用spring的时候,会调用*ApplicationContext,但我们现在是在WEB情况下,总不能手动调用吧。实际上,spring提供了一个供WEB情况下调用的方法,有一个servlet(这个我没用过,不大清楚怎么用),一个listener,servlet是供不支持filter的应用服务器调用的,但现在我们基本上都使用listener了。
1
2
3
|
< listener >
< listener-class >org.springframework.web.context.ContextLoaderListener</ listener-class >
</ listener >
|
这种情况下是spring需要和其他框架结合的情况下使用的大部分情况,当我们只是使用springMVC时,就可以直接配置DispatcherServlet进行替换上面的struts的servlet,具体我们之后用springMVC的时候再看。
这种情况下,一般会去加载WEB-INF目录下的applicationContext.xml文件,当你文件名不是这个,或者路径不在这里时,就可以配置configContextPath属性
1
2
3
4
|
< context-param >
< param-name >configContextPath</ param-name >
< param-value >WEB-INF/applicationContext.xml</ param-value >
</ context-param >
|
它支持使用classpath:前缀等,这里不多说了,可以详细看spring的配置文件。这样实际上我们就已经把struts和spring结合起来了,只是没有进行一些bean的配置和struts的转发罢了。
3)而作为ORM的hibernate,此时也由spring来一起管理。spring提供了一个LocalSessionFactory,注意,这个类,hibernate3和4是不同的,spring提供了两个。下面这段配置在applicationContext.xml中
1
2
3
4
5
6
7
8
9
10
11
|
< bean id = "sessionFactory" class = "org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
< property name = "dataSource" ref = "dataSource" />
< property name = "mappingResources" >
< list >
</ list >
</ property >
< property name = "hibernateProperties" >
< props >
</ props >
</ property >
</ bean >
|
其实的配置就跟hibernate中的类似了,这里不多说具体的代码了。
4)在以前spring2.5.x的时候,我们用的最多的是HibernateDaoSupport,但spring3.X开始就不提供这个支持了,我们需要用原生的session进行操作(只需要注入SessionFactory即可),但这里实际上就涉及到一个问题,如果我们每个请求都去打开关闭连接,会比较消耗资源,但如果不关闭连接,又会不大好。所以就需要有一个折衷的方案,有一个管理器来管理连接。这里spring提供了一个OpenSessionInView,在每打开一个view(基本上是每一个请求时),会打开Session,这里它内部怎么管理我们就暂时先不管了。
1
2
3
4
5
6
7
8
|
< filter >
< filter-name >openSessionInViewFilter</ filter-name >
< filter-class >org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</ filter-class >
</ filter >
< filter-mapping >
< filter-name >openSessionInViewFilter</ filter-name >
< url-pattern >/*</ url-pattern >
</ filter-mapping >
|
这里还是让他拦截所有的请求,当然可以配置成只拦截action后缀的,就没有必要浪费资源了。
5)基本上,我们的SSH框架就搭好了,接下来只是代码的问题了。只需要在spring配置文件中配置bean,或者喜欢Annotation的话可以直接@Component(value='bean名称')就可以了,但要记得在配置文件中开启Component-scan。
代码就不写详细的了,大致如下的:
1
2
3
4
5
6
7
8
|
@Component(value="userAction")
public class UserAction{}
< package name = "user" extends = "struts-default" namespace = "/user" >
<!-- 用户登录 -->
< action name = "login" class = "userAction" method = "login" >
< result name = "ERROR" >/pages/login.jsp</ result >
</ action >
</ package >
|
实际上也就是把class中的指向修改为指向bean即可。
代码详细的就不贴了,毕竟是总结贴。总得来说,SSH对于一个团队内规范代码是比较有好处的,因为在框架的规范下写出的代码基本上有一个特定的形式在,对以后的维护也好点。但对于初学的朋友来说,建议不要太多的依赖框架,真非要用,至少需要在总体上了解一下这个框架做了什么,什么情况下需要用它,什么情况下绝不要用。