自己理解的J2EE三层架构(与软件设计模式的联系区别)
如上图
1.J2EE分3层:
服务器端业务逻辑(有业务逻辑层和持久化数据层,BusinnessTier和EISTier)、服务器端表示层(WebTier)及客户端表示层(ClientTier)
可以将J2EE设计模式归纳到6个类别
(1)表示层体系结构模式(服务器端表示层)
a.前端控制器模式
b.MVC模式
c.装饰器模式
(2)表示层高级体系结构模式
a.复合视图模式(在服务器端表示层)
b.视图助手模式
c.服务工作者模式
(3)表示层伸缩性模式(服务器端表示层)
a.异步页面模式
b.缓存过滤器模式
c.资源池模式
(4)业务层模式(服务器端业务逻辑层)
a.复合实体模式
b.域对象模式(业务数据层)
(5)数据传递模式(用于业务逻辑层和表示层之间)
a.DTO模式
b.DTO传递散列模式
c.数据库行集合DTO模式
(6)数据库模式(服务器持久化数据层)
a.DAO模式
b.DAO工厂模式
2.前端控制器模式
常用的应用为,一个servlet作为一个前端控制器,它负责根据页面的请求,然后转发到页面控制器。页面控制器也是一个servlet,这个servlet电泳关于这个请求所应该执行的业务逻辑,并根据业务逻辑的结果返回到具体的现实页面。简化的使用是前端控制器servlet利用“命令模式”将页面控制器转化成一个个更细粒度的类。
AcitonServlet是前端控制器,部分代码
RequestUtils.selecetModule(request,getServletContext());
getRequestProcessor(getModuleConfig(request)).process(request,response);
RequestProcessor的process方法处理公共任务,部分代码
if(!processPreprocess(request,response)){
return;
}
processXXX方法都在处理公共的动作
RequestProcessor的processActionPerform方法实现命令模式,该方式将具体请求的动作分配到Action。
部分代码
return(action.execute(mapping,form,request,response));
前端控制器选择页面控制器解析用户的请求,实现具体业务逻辑,并根据结果转发到页面试图
3.装饰器模式
(1)设计模式的的装饰器模式
装饰器模式为客户端提供一个透明扩充某实例功能的方法,该方法的返回类型就是这个实例,在客户端不断调用这个方法的同时,该实例的内部表象已经随着功能改变完全不同。
(2)J2EE设计模式中的装饰器模式
Servlet支持装饰器模式,装饰一个request请求,利用装饰器类截获所有发送给目标对象的请求,并执行需要的工作,完成之后再把请求转发到下一个装饰器,知道没有了装饰器,最后将请求发送到Servlet
Servlet利过滤器来拦截请求和响应,在请求到达Servlet前,为这个请求做一个些额外处理。处理器可以被看成一个链,每个过滤器之间都能互相传递,以下是过滤器Filter接口的doFilter有三个参数,ServletRRequest,ServletResponse,FilterChain,利用FilterChain的doFilter()激活下一个相关的过滤器
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{
//用secletEncoding方法设置字符编码
if(ingnore||request.getCharacterEncoding()==null){
Stringencoding=selectEncoding(request);
if(encoding!=null)
request.setCharacterEncoding(encoding);
}
chain.doFilter(request,response);
}
4.复合视图模式
设计模式中的“合成模式”
合成模式:提供一个树状的对象结构,树枝类与树叶类都实现同一个接口,以便客户端在调用任何对象时都只要需要调用该树状结构的根接口就可以了。
J2EE设计模式中的“复合视图模式”
将视图的布局从中抽离出来,形成由一系列通用组件的模板。可以利用XML来描述视图的组成
5.视图助手模式
jsp页面的标签库和struts的标签库,一个标签应该继承javax.servlet.jsp.tagext.TagSupport,并给出doStarTag和doEndTag两个方法的实现。
doStarTag实现业务逻辑
doEndTag控制输出
6.服务工作者模式
将页面流转、前端控制器模式,视图助手模式合在一起使用,表示“请求-转发-视图”的一整套流程。该模式也是MVC模式的实现标准,struts也基于这个模式实现
7.异步页面模式
当远程数据发生变化时,将其缓存下来,称为“发布者-订阅者-模型”。在J2EE的功能是,利用一个订阅者角色,在一个的时间间隔或数据发生变化时,接受来自发布者角色的数据,订阅者角色同时会利用模式曾来更新数据库。这样的工作累世于软件设计模式中的“观察者模式”。常见的应用为,当发布服务器需要显示最新信息的HTML页面时,会利用一个订阅者角色来负责。例如ActionServlet
8.缓存过滤器模式
这个模式用来椽村动态产生的页面,尽可能减少重复生成的页面。在J2EE的功能是,利用一个缓存过滤器截获请求,判断该请求所返回的页面是否有缓存。缓存过滤器应该放在“装饰过滤器”和工作Servlet之前。缓存过滤器是装饰过滤器的一个变体。对HTTPServletResponse对象进行装饰来保存请求处理的结果。
9.资源池模式
客户端在需要JDBC连接时,应该从一个池中去取得。如果池中有可用的JDBC连接,则返回这一对象资源。如果没有任何可用资源,但池中还有容量,就使用工厂生成一个新的实例。如果池中没有任何可用资源且池的容量已经沾满,那就必须等待,知道其他客户端还回至少一个对象。
10.复合实体模式
该模式可以降低工作环境中的复杂性和通信开销。一个复合实体将来自各种不同来源的数据集中到一个单独的对象中。应用为EJB环境的集中对象。
11.域对象模式
将一张数据库中的表结构对象化,例如hibernate中的表转化成对象,使用在持久层框架理论中
12.DTO模式
struts的ActionForm就是一个DTO模式的实现,从页面视图得到数据传递给模型层,模型层通过业务逻辑的调用后将返还数据给ActionForm用作视图层的数据显示
ActionForm仅仅被用在从视图层传递到模型层。
13.DTO散列模式
struts的DynaActionForm就是一个DTO散列模式,让程序员设置某个数据的主键,而后在Acton中可以通过该主键得到页面数据
14.数据库行集合DTO模式
将JDBC的ResultSet发送到客户端显示,使用ResultSet接口的一个独立类作为DTO发送到客户端显示。
15.DAO模式
数据访问对象模式被认为是持久层的一种基本模式
DAO模式有反问数据和处理业务逻辑的功能,现在不再流行
16.DAO工厂模式
用户只对被创建的产品感兴趣,而这些被创建的产品在创建之前所做的许多额外的工作被封装到工厂接口的子类中,而不适用具体产品类的构造函数,达到隐式的使用
改模式只有和数据库连接的功能,没有实现访问数据的功能
17.J2EE设计模式与设计模式的区别
(1)软件设计模式是设计,J2EE设计模式关注的就是构架
(2)软件设计模式为了解决各种软件世界中常见问题提炼的一种最佳时间,是许多经验丰富的软件设计者不断成功和失败的总结。
J2EE模式为了解决企业级应用的构架问题。
(3)软件设计模式的主要目的是解耦,可以在J2EE模型的任何层中出现软件设计模式。
J2EE设计模式对于J2EE模型中的分层进行解耦。软件设计模式关注的是微观的方法学,J2EE设计模式则是宏观的方法学。
18.
(1)前端控制器模式、MVC模式、服务工作者模式被整合成了表示层框架,如struts框架,webwork框架
(2)复合视图模式有Tiles框架实现
(3)视图助手模式的主要实现是标签库,JSTL标签库
(4)DAO工厂模式随着中间层框架Spring的依赖注入,已经不一定需要实现。
下面摘自网友的文章:
一、MVC架构
Struts是一个不错的MVC架构,我一直以来都用它,通过简单的配置即可将view,controler,和Model结合起来。View主要以JSP来实现,因为它是面向标签的,所以对于网页设计人员提供了很好的接口。FormBean是介于JSP和Action之间的中间数据载体,它肩负着数据从JSP到ACTION的传递过程。Action是流程的中转站,不同的业务在不同的Action中以不同的Model调用来实现。Model就是实现具体业务的操作过程,不过这种过程是一种在较高水平上的实现。
总之,MVC架构实现了三层结构中的两层,即表现层和业务层,另外还有一层被称之为持久化层。
二、三层架构
正如以上所说的,三层架构即“表现层”,“业务层”,“持久化层”。表现层实现的代表作品是Struts框架,业务层实现的代表作品是Spring,持久层实现的代表作品是Hibernate。不过在我的开发中Spring被省掉了,因为我认为业务过于简单,还不至于用Spring来实现。下面我将具体的来说说我的三层实现。
1、三种Bean
在我的实现中,总共有三种Bean,它们都是为保存对象状态而存在的。持久层中,这种Bean就是POJO对象。它是面向数据库的,或者说多少得照顾到数据库的实现,因为我习惯于用PowerDesigner来设计数据库,做出来的结构也是比较中规中矩的,而如果直接用Hibernate来实数据库的话,就不那么干净了。所以POJO对象的设计就不能完全面向对象。业务层中的Bean我把它称之为Entity,这是一个完全面向程序逻辑的Bean。它可能是好几个POJO的集合。对于业务逻辑来,这种被称之为Entity的Bean做到了“拿来就用”,很便于业务的进行。在显示层中的Bean就是FormBean了,主要用于传入数据所用。
POJO仅生存于持久化层,到了业务层就将数据交给Entity了。而Entity不仅生存于业务层,它还被传到了JSP中,用于显示。
2、Pojo与Dao
我认为这是数据与操作的关系,Dao只在呼操作,而Pojo仅用于保存数据。下面是我Dao接口的实个现。
publicinterfaceDao{
/
publicvoidresetPO(Pojopojo){
this.userPo=(UserPo)pojo;
}
publicStringsave(){
Stringoid=null;
try{
//Sessionsession=HibernateUtil.currentSession()已经被提至构造函数中初始化了
Transactiontx=session.beginTransaction();
if(userPo.getId()==null){
oid=(String)session.save(userPo);//如果这是一个新的pojo则进行insert操作。
session.flush();
tx.commit();
}else{
session.update(userPo,userPo.getId());//如果该pojo已被初始化过则进行update操作
session.flush();
tx.commit();
}
}catch(HibernateExceptionex){
System.out.println("//\nUserDao.save()出现异常!");
log.error("UserDao.save()出现异常!",ex);
}
returnoid;
}
publicPojoload(){
UserPotmp=newUserPo();
try{
//Sessionsession=HibernateUtil.currentSession()已经被提至构造函数中初始化了
tmp=(UserPo)session.get(UserPo.class,userPo.getId());//用确切存在的ID值获得对象
}catch(HibernateExceptionhbe){
hbe.printStackTrace();
}
if(tmp!=null){
userPo=tmp;
returnuserPo;
}
else
returnnull;
}
publicListfind(shortby){
//Sessionsession=HibernateUtil.currentSession()已经被提至构造函数中初始化了
Queryquery=null;
Stringwhere=null;
switch(by){
case0:
where="";
break;
case1:
where="whereus.name='"+userPo.getName()+"'";
break;
case2:
where="whereus.account='"+userPo.getAccount()+"'";
break;
case3:
where="whereus.password='"+userPo.getPassword()+"'";
break;
case4:
where="whereus.account='"+userPo.getAccount()+"'andus.password='"+userPo.getPassword()+"'";
}
query=session.createQuery("fromUserPous"+where);
returnquery.list();
}
publicvoidclose(){
HibernateUtil.closeSession();
}
}
其中HibernateUtil是一个Hibernate方法类,它提供线程安全的Session。和关闭这个Session的方法(虽然关闭Session过于简单)。每个Dao是由DaoFactory来产生的。DaoFactory也有一个公共的接口。如下:
publicinterfaceDaoFactory{
DaogetDocumentDAO();
DaogetDocHeadDAO();
DaogetDocAccessoryDAO();
DaogetUserDao(Useru);
}
下面是一个基于Hibernate的Dao的实现。
publicclassHbDaoFactoryimplementsDaoFactory{
publicHbDaoFactory(){
}
publicDaogetDocumentDAO(){
returnnewcom.cecs.dao.DocumentDAO();
}
publicDaogetDocHeadDAO(){
thrownewjava.lang.UnsupportedOperationException("MethodgetDocHeadDAO()notyetimplemented.");
}
publicDaogetDocAccessoryDAO(){
thrownewjava.lang.UnsupportedOperationException("MethodgetDocAccessoryDAO()notyetimplemented.");
}
publicDaogetUserDao(Useru){
returnnewUserDao(u);
}
}
这样一但不用Hibernate来实现持久层,也可以很方便改为其它的Dao而不用修改业务层。