Java EE向来因为其复杂性而让很多厂商望而却步。本文试图探讨如何简化Java EE 开发中不必要的复杂,并给出的是一个不使用任何框架的架构模型。

Java EE是个适当杂乱的东西,被许多开发者们视为庞然大物。鄙人面的文章中,Javaonejcy讨论了怎么简化Java EE开发中不必要的杂乱,并给出一个不运用任何结构的架构模型。

无结构架构模型讨论:简化的Java EE开发(简述java ee三层架构)  Java EE 无框架 第1张

你能够说心爱的php ,心爱的ror ,心爱的python ,乃至心爱的.net ,可是Java EE ?他太杂乱了。比较其他两种技能,Java EE 的技能体系更全面、更规整也更杂乱,他的杂乱性也让许多厂商望而止步,宁可挑选简略乃至粗陋的php ,这充分说明快速开发是这个年代最火急的需求。

Java EE 的servlet 、javabean 、jdbc 规范给了咱们组件和容器的仅有规范,而更高档的支撑,jsf 、jdo 规范却没能给予咱们仅有的结构级规范,他们被认可的程度远低于相同范畴的开源结构。虽然开源社区给了咱们最丰厚的挑选,可是比较.net 、php 、ror 的全栈式服务,Java EE 开发者有必要DIY 。DIY 不光需求时刻而且需求冒险,这种发烧友做的作业是企业所不愿意做的。一段时刻以来,公司Java EE 方向的招聘简直清一色的要求struts 、spring 、hibernate 这几种干流结构的才干便是一种证明。

Java EE 的开发往往防止不了装备之旅,虽然许多结构都有主动生成东西,可是,面临一个中型项目,依然简略形成紊乱。装备使你不管在开发、测验、集成仍是保护的时都要装备代码两端看。装备给了结构一个注入服务的切入点,可是对人并无高雅可言。ror 给了咱们启示,虽然企业开发是杂乱的,可是大多数的需求都是通用的,事实证明,ror 把这部分通用性用约好的办法笼统得很好。其实Java EE 并不缺少约好,由于他本身便是树立于一系列规范的根底之上,而规范便是约好。所以,Java EE 实践上有时机成为相对简练的开发技能,只不过由于种种原因,这种规范并未呈现。

在许多的Java EE 开发结构中,struts+spring+hibernate 有着黄金组合的美誉,用的人多,会的人多,就算是没出校门的学生,也知道学会ssh 的重要性。可是学会和学懂是两码事,关于一个中型项目,ssh 就成了一柄双刃剑,需求由高水平的规划师引路,才干披荆斩棘。spring+hibernate 给了规划者宽广的空间,而规划需求因项目的行进而演进,假如你的项目进展严重,人手缺少,规划质量就难以保证,给体系带来危险。

“任何优异的言语,都能够协助开发者写出优异的代码,但不能阻挠开发者写出糟糕的代码”。在这一点上,不管是Java EE ,.net ,ror ,php 都不会破例。而开发结构就像是“一间有许多屋梁的房子”,“结构的强壮之处不是他能让你做什么,而是他不能让你做什么”,其实好像言语相同,结构虽然能够给予开发必定程度的规范辅导,可是这种辅导依然是有限的,这真应了那句老话:事在人为。

本文企图讨论怎么简化Java EE 开发中不必要的杂乱,并给出的是一个不运用任何结构的架构模型,让咱们看看仅仅经过用编码约好,结构规划和运用办法的组合能不能满意项目开发的首要需求— 短期培训,下降危险和快速开发。

问题的源头

运用软件开发是杂乱的,但其根本模型至为简略,恳求-处理-呼应。对应于软件的层次结构便是:恳求-Cortrol (C );处理-Model (M );呼应-View (V )。在前期的Java EE 运用中,servlet 担任C ,javabean 和jdbc 在M ,jsp 是V 。这些便是Java EE 的根底设施,他们责任区分的办法被称为JSP Model2 ,现已能够满意web 开发的根本需求,Java EE 的开发一直都围绕着这几项首要技能,结构也不破例。以下的内容,将从这些技能的运用与缺少说起,然后介绍干流结构的处理方案,之后再介绍咱们不必结构的处理办法。

(C) 挑选操控器

根底规范的缺少

任何web 运用,处理恳求之后回来呼应是有必要的环节,假如编码规范,传统的呼应便是转向到某个页面,servlet 处理转向有两种办法,其间request 转向隐藏着重复提交的问题,response 重定向带来参数传递的编码解码的问题,一起许多的转向地址直接写在servlet 中也十分不雅观,别的,jsp 和javabean 有一种超卓的相关技能,便是在jsp 里能够把来自恳求表单的数据主动组装到javabean 中。糟糕的是,这么有用的技能却无法在servlet 中运用,所以Model2 缺少对表单数据的主动转化处理。servlet 有这些缺少很好了解,由于servlet 毕竟是较早呈现的技能,他的责任仅仅将(http )恳求转化为面向目标的视图和输出呼应罢了,由于他是低阶组件,所以部分功用的缺失是正常的。不过这就让servlet 成为了Model2 最单薄的一环。

开发结构的处理方案

由于以上需求是共性的,所以编写一个通用结构就成为了许多人尽力的作业,struts 很快推出而且很快盛行。咱们先来看一看struts 的特性:

前端操控器: struts 运用一个servlet 作为前端操控器,一切恳求先经过这儿,再分派给装备指定的action (这儿是指行为,而不是详细的Action ),目的是以一个中间层将视图层和操控层解耦,这种思路带来了三种或许的长处:1 视图和操控别离,所以能够挑选不同的视图技能,比方视图模板既能够用jsp ,也能够用Volecity 、FrEEMarker ;2 能够对一切恳求预处理,和后处理(webwork );3 能够将呼应的转向地址办理起来。前端操控器也存在一种直接的缺少:装备繁琐。

ActionForm : struts 首要是一个操控层结构,所以他并不目的深化到模型层,ActionForm 是一种无法的挑选,虽然供给了表单数据到javabean 的转化,可是惋惜的是这个javabean 并不能直接运用,还要手艺的转化为模型javabean ,使得ActionForm 的方位有些为难。

国际化支撑、标签库和大局反常: 国际化和标签库都是struts 的亮点,不过大局反常效果有限。

咱们的挑选

Java EE 的操控器必定是一个servlet ,咱们也不能破例,由于咱们有必要要运行在servlet 容器之中。不过,咱们挑选的是servlet 的演进版别-jsp 。别误会,咱们并不是要退回到JSP Model1 。一个典型的示例是,假如我有一个职工信息录入的功用点,那么为了完成这个功用,我能够树立下面两个文件:

worker_input.jsp

worker_inputOper.jsp

worker_input.jsp 里不写操控代码,worker_inuptOper.jsp 里也不写视图代码,这种用法实践是JSP Model1 和JSP Model2 的综合体。这样做最大的长处便是,免除装备的烦恼,可是等等.. 前端操控器呢?咱们的中间层呢?

考虑一下,你有一个企业信息的表单,表单中有一个企业名称域,对这个域的要求是不能在已有企业中重名,域周围有一个按钮,业务员能够经过点击这个按钮取得录入企业名称是否重复的提示。假如是传统办法,点击按钮将导致一个页面提交,假如用struts ,即将装备这个action 处理之后转向的URL 地址,这便是传统web 运用的呼应办法- 根据URL 地址的页面导航。

web2.0 来了,ajax 来了,异步恳求的呈现完全推翻了传统的web 交互模型。关于ajax 运用而言,服务器端回来呼应只需求out.print ,恳求从哪来,回哪去,转向(假如需求)和更新视图的使命都交给了客户端脚本,也便是说,根据异步交互方式的web 运用,根本就没有需求装备的result URL 途径。这样,页面导航的问题就主动处理了。而关于预处理,咱们能够用filter 替代。所以,咱们完全能够和前端操控器说:再会。

由于客户端技能的趋势,在webappdemo 中咱们将全面运用ajax 。或许你会说,假如客户端浏览器禁用脚本呢?这个忧虑在现在现已没有必要,你能够拜访高兴或许当当,看看禁用脚本他们能不能作业。年代在前进,富客户RIA 是必定的挑选。

运用jsp 作为操控器,还使咱们得到了另一个要害的特性,那便是从form 表单数据到javabean 的主动创立和输入,使javabean 本身既是模型也是DTO ,再也不必象ActionForm 那样还要手艺转化。这儿还有一个隐含的长处,便是强制一致了表单域名和模型特色名,不然,有或许呈现这样的状况:表单域:child_center ;模型特色:branch 。以下是worker_inputOper.jsp 的写法:

Jsp代码

  1. <jsp:useBeanid="worker"class="webappdemo.worker.entity.Worker"scope="page"/>
  2. <jsp:setPropertyname="worker"property="*"/>
  3. <%
  4. response.setContentType("text/x-json;charset=UTF-8");
  5. response.setHeader("Cache-Control","no-cache");
  6. Stringmethod=request.getParameter("method");
  7. if("save".equals(method)){
  8. EntityServicees=newEntityService();
  9. Messagem=es.add(worker);
  10. out.print(newJSONObject().put(m.isSucceed()?"succeed":"error",m.getMessage()));
  11. return;
  12. }
  13. %>

能够看出,只需将实体类名引进标签,咱们就能够取得主动组装的Worker 目标。关于杂乱目标或复合目标,由于request 里相同有咱们需求的一切恳求参数,所以你能够在主动创立的javabean 根底上修正部分特色,以契合业务需求。

代码还展现了根据“method ”的用法,这仅仅一个字符串,用来告知oper jsp 要用哪个办法来处理恳求,这类似于ror 操控器内部界说的办法以及struts 的DispatchAction 但比他更灵敏,变通的处理了jsp 的恳求不能直接面向办法的缺少。

在调用服务处理恳求之后,worker_inputOper.jsp 将处理成果out.print 回客户端,这句代码的意思是新建一个JSON 目标,将处理成果添加进去,然后输出这个目标,便利客户端js 脚本解析。JSON 目标能够添加多个处理成果,只需他们的key 不同就能够。在实践运用中,往往回来处理音讯,或许html 视图的字符串。最终别忘了return; 不然程序依然会向下进行。

假如你的项目需求国际化,咱们能够运用fmt 标签,而关于反应音讯的国际化,咱们或许就需求树立一个大局MessageSource 目标了,这个问题在webappdemo 中没有触及,由于笔者以为这不是遍及需求。

关于反常处理,其实jsp 现已供给了简略的机制,咱们能够在web.xml 中装备:

Xml代码

  1. <error-page>
  2. <error-code>404</error-code>
  3. <location>/404.jsp</location>
  4. </error-page>
  5. <error-page>
  6. <error-code>500</error-code>
  7. <location>/500.jsp</location>
  8. </error-page>

这种简略的处理其实正是咱们需求的悉数,由于笔者以为,web 运用的体系过错和java 的反常没有差异,即检测过错和运行时过错。在web2.0 年代,一切的过错都应该被捕获,而且把内容经处理后在用户输入方位反应给用户,而不应该从头定向。运行时过错归于体系bug ,是需求修正的代码级过错,这种过错是真实的“意外”,所以咱们用定制的过错页面反应给用户就能够了。

综上所述,咱们用ajax+jsp+ 操控jsp 的办法替代了servlet 或许action ,摆脱了前端操控器,用模型javabean 替代了进程javabean ActionForm ,这些运用办法使咱们不需求装备即能够开发运用程序,除了ajax 是相对新概念外不需求额定学习结构技能也是他的长处。

(M)ORM 能够做什么

根底规范的缺少

jdbc 是java 运用程序数据耐久化的根底,也是许多数据库厂商与java 的接口。直接运用jdbc 编写代码十分繁琐,比方数据库资源的取得和开释,反常捕获和业务处理等等,重复代码多是他的一个特色。别的,不同的数据库,在数据类型,主键类型仍是sql 句子都和SQL 规范小有收支,所以怎么使运用程序能够在不同数据库渠道便利的搬迁,也是个问题。

开发结构的处理方案

spring 和hibernate 的呈现使状况大为好转,spring 面向切面办理业务, hibernate 主动ORM 能够大大简化开发,spring 和hibernate 都有.net 的版别,这证明了他们的成功。可是“用好hibernate ,需求厚实的把握联系模型和SQL ”,一起对面向目标规划和hibernate 本身的运行机制也要有十分明晰的知道,只要这种水平才干发挥hibernate 的威力,下降hibernate 带来的危险。所以,在适宜的层面上装备好spring 的业务办理,规划好目标模型,把对hibernate 的直接运用操控在必定范围内是规划者要处理的根本问题。假如规划欠安,或许直接交给初出校门的开发者去用,那这种组合就会变成祸不单行,一起也不利于团队成员的生长。

咱们的挑选

假如只要jdbc ,咱们的体系也能够作业,只不过要写许多重复和机械的代码,经过结构的ORM 的映射,能够将数据库表的数据主动填入javabean ,这节省了劳动力,也使体系结构天然明晰。假如不必ORM 东西,咱们能不能经过某种方式来模仿他的行为呢?咱们能够创立这样一个接口:

Java代码

  1. publicinterfaceIOper{
  2. booleanload(Connectionconnect)throwsSQLException;
  3. booleanadd(Connectionconnect)throwsSQLException;
  4. booleanupdate(Connectionconnect)throwsSQLException;
  5. booleandelete(Connectionconnect)throwsSQLException;
  6. }

在接口中界说 CRUD 办法。回来类型为 boolean 而非影响的行数,目的是目标内部的操作或许是杂乱的多过程的,所以对他的上层运用来说,知道成果成功与否就能够了。接下来在他的完成类里能够这么写:

Java代码

  1. publicclassWorkerimplementsIOper{
  2. //Fields
  3. privateIntegerworkerId;
  4. privateStringworkerName;
  5. privateStringlogonName;
  6. privateStringlogonPwd;
  7. /*
  8. *关于答应为空的字段赋予初始值,防止页面显现null
  9. */
  10. privateStringmobile="";
  11. privateStringemail="";
  12. privateStringremark="";
  13. privateStringisFreeze="0";
  14. //Constructors
  15. /**defaultconstructor*/
  16. //Propertyaccessors
  17. publicbooleanadd(Connectionconnect)throwsSQLException{
  18. SQLBuffersql=newSQLBuffer();
  19. sql.segment("insertintoworker(worker_name,logon_name,logon_pwd,");
  20. sql.segment("mobile,email,remark,is_freeze)values(");
  21. sql.value(this.workerName);
  22. sql.comma();
  23. sql.value(this.logonName);
  24. sql.comma();
  25. sql.value(this.logonPwd);
  26. sql.comma();
  27. sql.value(this.mobile);
  28. sql.comma();
  29. sql.value(this.email);
  30. sql.comma();
  31. sql.value(this.remark);
  32. sql.comma();
  33. sql.value(this.isFreeze);
  34. sql.segment(")");
  35. returnProxy.update(connect,sql)==1;
  36. }
  37. publicbooleandelete(Connectionconnect)throwsSQLException{
  38. //冻住用户
  39. SQLBuffersql=newSQLBuffer();
  40. sql.segment("updateworkersetis_isfreeze=");
  41. this.isFreeze="1";
  42. sql.value(this.isFreeze);
  43. sql.segment("whereworker_id=");
  44. sql.value(this.workerId);
  45. returnProxy.update(connect,sql)==1;
  46. }
  47. publicbooleanload(Connectionconnect)throwsSQLException{
  48. SQLBuffersql=newSQLBuffer(
  49. "selectworker_name,logon_name,logon_pwd,mobile,email,remark,is_freezefromworker");
  50. sql.segment("whereworker_id=");
  51. sql.value(this.workerId);
  52. MapRowmr=Proxy.getMapRow(connect,sql);
  53. if(mr==null){
  54. returnfalse;
转载请说明出处
知优网 » 无结构架构模型讨论:简化的Java EE开发(简述java ee三层架构)

发表评论

您需要后才能发表评论