JAVA网页编程之了解jsp形式2架构:MVC计划形式探险
再说第三点:我并没有提到服务器也要整合,然后是IDE,一个好的IDE能够200%提高开发的速度,就说图形方面:你是经过简单托拽和点击就能实现功能好那。js|架构|计划 择要:经由过程开辟一个熟习的基于web的购物店,你将学到怎样工具化mvc计划形式而且真正地在利用jsp的时分分别内容和体现。GovindSeshadri会向你展现这是何等的简单(2000字(原笔墨数))。只管绝对抛开比来的相干先容而言,jsp手艺正在很好地以本人的体例成为出色的创立供应静态web内容的使用程序的java手艺。java开辟者由于很多分歧的来由喜好jsp。一些人喜好它给交互式web页面带来了“一次编写,各处运转”的变更这个现实;另外一些人浏览它易学易用而且匡助人们把java作为服务器端剧本利用。可是都公认一件事――利用jsp最年夜的优点是可以无效地分别内容与体现。在这篇文章里,我来供应一个深切的意见,关于怎样利用jsp形式2架构取得最好的内容与体现的分别。这个形式也能够被看做盛行的mvc计划形式在服务真个完成。请注重在入手下手之前你应当熟习jsp和servlet编程,由于我不会在这篇文章中会商语法成绩。
那末,servlet有甚么成绩?
既然jsp用来供应静态web内容而且关于从体现层平分离内容很不错,一些人大概想晓得为何servlet要从jsp中离开出来与它并列。servlet的服从没有成绩。它关于服务端处置干得很好,并且,因为它主要的已安装基本,就合适这个。实践上,从布局上说,你能够把jsp看做完成为servlet2.1api的扩大的servlet初级笼统。仍旧不该该不加区分地利用servlet;它大概不会合用于每个人。举个例子来讲,只管页面计划者可以很简单地利用惯例html大概xml工具编写jsp页面,而servlet一般更合适背景开辟者,他们一般利用某种IDE――一个一般必要高条理的编程专门常识的历程。当公布servlet时,即便开辟者也必需寄望和确认在内容和体现之间没有紧耦合。一般,你能够经由过程到场第三方的html封装包好比htmlkona来做这个。即便如许做了,只管带来了一些复杂的关于屏幕变更的伸缩性,仍旧不克不及为你避免免受体现格局本身的变更的影响。比方,假如你的体现情势从html变化到dhtml,你将仍旧必要确认你的封装包是不是兼容这类新格局。在最坏的情形下,假如封装包不克不及用了,你大概终极会在静态内容外部硬编码体现情势。那末,办理举措是甚么?就像你你将要看到的,一个举措将会同时利用jsp和servlet来创立使用体系。
差别哲学
初期的jsp标准主意两种利用jsp手艺创立使用的哲学思绪。这两种思绪,用术语来讲就是jsp形式1和形式2,实质上的区分在于年夜部分哀求的处置产生的地位。在形式1架构中,如所示,jsp页面自力地卖力处置哀求和发送反应给客户端。这里仍旧有内容和体现的分别,由于一切的数据会见是利用bean完成的。只管形式1架构应当很合适复杂使用,可是关于庞大的完成是不成取的。这类布局的恣意利用一般会招致大批的剧本和java代码嵌进到jsp页面中,出格是在有大批的哀求必要处置的情形下。只管这大概对java开辟者来讲不是一个年夜成绩,可是却无疑是一个成绩,假如你的jsp页面是由计划师创立和保护的话――在年夜项目中一般云云。终极,这个成绩乃至会招致脚色界说和义务分派的凌乱,引发本能够轻松制止的项目办理的贫苦。
:jsp形式1布局
形式2架构如所示,是一个为静态内容服务的夹杂计划,由于它同时利用了servlet和jsp。它使用了两种手艺的上风,利用jsp发生体现层而servlet卖力实行敏感义务。在这里,servlet饰演把持器的脚色,卖力哀求处置和发生jsp要利用的bean和对象,和依据客户的举措决意下一步转发到哪个jsp页面。出格要注重的是jsp页面外部并没有处置逻辑;它只是复杂地卖力获得多是servelet事前创立的对象和bean,并为在了静态模版中拔出从servlet开释出静态内容。我的概念是,这个举措一样平常会构成最洁净完全的体现与内容的分别,使得你的开辟团队里的开辟者和页面计划师的脚色与义务可以明晰。实践上,你的使用越庞大,利用形式2带来的优点就越多。
:jsp形式2布局
为了弄清形式2面前的观点,我们来观光一个细化的详细完成:一个叫做音乐无界的在线音乐商铺样品。
懂得音乐无界
主视图,大概说体现层,关于我们的音乐无界由jsp页面EShop.jsp发生(见清单1)。你会注重到这个页面几近仅仅处置这个使用的次要用户界面,并且没有做任那边理事情――一个最好的jsp剧本。也注重一下另外一个jsp页面,cart.jsp(见清单2),经由过程指令<jsp:includepage="Cart.jsp"flush="true"/>包括在EShop.jsp以内。
清单1
EShop.jsp
<%@pagesession="true"%>
<html>
<head>
<title>MusicWithoutBorders</title>
</head>
<bodybgcolor="#33CCFF">
<fontface="TimesNewRoman,Times"size="+3">
MusicWithoutBorders
</font>
<hr><p>
<center>
<formname="shoppingForm"
action="/examples/servlet/ShoppingServlet"
method="POST">
<b>CD:</b>
<selectname=CD>
<option>Yuan|TheGuoBrothers|China|$14.95</option>
<option>DrumsofPassion|BabatundeOlatunji|Nigeria|$16.95</option>
<option>Kaira|TounamiDiabate|Mali|$16.95</option>
<option>TheLionisLoose|EliadesOchoa|Cuba|$13.95</option>
<option>DancetheDevilAway|Outback|Australia|$14.95</option>
<option>RecordofChanges|Samulnori|Korea|$12.95</option>
<option>Djelika|TounamiDiabate|Mali|$14.95</option>
<option>Rapture|NusratFatehAliKhan|Pakistan|$12.95</option>
<option>CesariaEvora|CesariaEvora|CapeVerde|$16.95</option>
<option>Ibuki|Kodo|Japan|$13.95</option>
</select>
<b>Quantity:</b><inputtype="text"name="qty"SIZE="3"value=1>
<inputtype="hidden"name="action"value="ADD">
<inputtype="submit"name="Submit"value="AddtoCart">
</form>
</center>
<p>
<jsp:includepage="Cart.jsp"flush="true"/>
</body>
</html>清单2
Cart.jsp
<%@pagesession="true"import="java.util.*,shopping.CD"%>
<%
Vectorbuylist=(Vector)session.getValue("shopping.shoppingcart");
if(buylist!=null&&(buylist.size()>0)){
%>
<center>
<tableborder="0"cellpadding="0"width="100%"bgcolor="#FFFFFF">
<tr>
<td><b>ALBUM</b></td>
<td><b>ARTIST</b></td>
<td><b>COUNTRY</b></td>
<td><b>PRICE</b></td>
<td><b>QUANTITY</b></td>
<td></td>
</tr>
<%
for(intindex=0;index<buylist.size();index++){
CDanOrder=(CD)buylist.elementAt(index);
%>
<tr>
<td><b><%=anOrder.getAlbum()%></b></td>
<td><b><%=anOrder.getArtist()%></b></td>
<td><b><%=anOrder.getCountry()%></b></td>
<td><b><%=anOrder.getPrice()%></b></td>
<td><b><%=anOrder.getQuantity()%></b></td>
<td>
<formname="deleteForm"
action="/examples/servlet/ShoppingServlet"
method="POST">
<inputtype="submit"value="Delete">
<inputtype="hidden"name="delindex"value=<%=index%>>
<inputtype="hidden"name="action"value="DELETE">
</form>
</td>
</tr>
<%}%>
</table>
<p>
<formname="checkoutForm"
action="/examples/servlet/ShoppingServlet"
method="POST">
<inputtype="hidden"name="action"value="CHECKOUT">
<inputtype="submit"name="Checkout"value="Checkout">
</form>
</center>
<%}%> 这里,Cart.jsp处置基于session的购物车的体现情势,它指定了我们的MVC布局中的模子。察看Cart.jsp开首这一段剧本:
<%
Vectorbuylist=(Vector)session.getValue("shopping.shoppingcart");
if(buylist!=null&&(buylist.size()>0)){
%>
基础上,这段剧本从session中提出了购物车。假如购物车为空大概还未创立,它不会显现任何工具;因而,当用户第一次会见的时分,他见到的页面如。
:音乐无界,主视图
假如购物车不是空的,那末已选中的物品会一次一个地从购物车中被提出,像上面的剧本树模的那样:
<%
for(intindex=0;index<buylist.size();index++){
CDanOrder=(CD)buylist.elementAt(index);
%>
一旦形貌物品的变量已创立,它们就复杂地被JSP表达式拔出到静态HTML模版中往。显现了用户已放了一些工具到购物车里往是的情形。
:音乐无界,购物车视图
这里要注重的主要的一件事是对一切举措的处置既不产生在EShop.jsp也不在Cart.jsp里,而是由把持器servlet,ShoppingServlet.java处置,见清单3:
清单3
ShoppingServlet.java
importjava.util.*;
importjava.io.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
importshopping.CD;
publicclassShoppingServletextendsHttpServlet{
publicvoidinit(ServletConfigconf)throwsServletException{
super.init(conf);
}
publicvoiddoPost(HttpServletRequestreq,HttpServletResponseres)
throwsServletException,IOException{
HttpSessionsession=req.getSession(false);
if(session==null){
res.sendRedirect("http://localhost:8080/error.html");
}
Vectorbuylist=
(Vector)session.getValue("shopping.shoppingcart");
Stringaction=req.getParameter("action");
if(!action.equals("CHECKOUT")){
if(action.equals("DELETE")){
Stringdel=req.getParameter("delindex");
intd=(newInteger(del)).intValue();
buylist.removeElementAt(d);
}elseif(action.equals("ADD")){
//anypreviousbuysofsamecd?
booleanmatch=false;
CDaCD=getCD(req);
if(buylist==null){
//addfirstcdtothecart
buylist=newVector();//firstorder
buylist.addElement(aCD);
}else{//notfirstbuy
for(inti=0;i<buylist.size();i++){
CDcd=(CD)buylist.elementAt(i);
if(cd.getAlbum().equals(aCD.getAlbum())){
cd.setQuantity(cd.getQuantity()+aCD.getQuantity());
buylist.setElementAt(cd,i);
match=true;
}//endofifnamematches
}//endoffor
if(!match)
buylist.addElement(aCD);
}
}
session.putValue("shopping.shoppingcart",buylist);
Stringurl="/jsp/shopping/EShop.jsp";
ServletContextsc=getServletContext();
RequestDispatcherrd=sc.getRequestDispatcher(url);
rd.forward(req,res);
}elseif(action.equals("CHECKOUT")){
floattotal=0;
for(inti=0;i<buylist.size();i++){
CDanOrder=(CD)buylist.elementAt(i);
floatprice=anOrder.getPrice();
intqty=anOrder.getQuantity();
total+=(price*qty);
}
total+=0.005;
Stringamount=newFloat(total).toString();
intn=amount.indexOf(.);
amount=amount.substring(0,n+3);
req.setAttribute("amount",amount);
Stringurl="/jsp/shopping/Checkout.jsp";
ServletContextsc=getServletContext();
RequestDispatcherrd=sc.getRequestDispatcher(url);
rd.forward(req,res);
}
}
privateCDgetCD(HttpServletRequestreq){
//imagineifallthiswasinascriptlet...ugly,eh?
StringmyCd=req.getParameter("CD");
Stringqty=req.getParameter("qty");
StringTokenizert=newStringTokenizer(myCd,"|");
Stringalbum=t.nextToken();
Stringartist=t.nextToken();
Stringcountry=t.nextToken();
Stringprice=t.nextToken();
price=price.replace($,).trim();
CDcd=newCD();
cd.setAlbum(album);
cd.setArtist(artist);
cd.setCountry(country);
cd.setPrice((newFloat(price)).floatValue());
cd.setQuantity((newInteger(qty)).intValue());
returncd;
}
} 每次用户在EShop.jsp中增加一件物品,哀求都被发送到这个把持器servlet。它顺次决意符合的举措,然后处置响应要增加的物品的哀求参数。它就实例化一个新的CDbean(见清单4)代表这个选择的物品,接着在把这个bean放进session之前处置购物车的更新。
清单4
CD.java
packageshopping;
publicclassCD{
Stringalbum;
Stringartist;
Stringcountry;
floatprice;
intquantity;
publicCD(){
album="";
artist="";
country="";
price=0;
quantity=0;
}
publicvoidsetAlbum(Stringtitle){
album=title;
}
publicStringgetAlbum(){
returnalbum;
}
publicvoidsetArtist(Stringgroup){
artist=group;
}
publicStringgetArtist(){
returnartist;
}
publicvoidsetCountry(Stringcty){
country=cty;
}
publicStringgetCountry(){
returncountry;
}
publicvoidsetPrice(floatp){
price=p;
}
publicfloatgetPrice(){
returnprice;
}
publicvoidsetQuantity(intq){
quantity=q;
}
publicintgetQuantity(){
returnquantity;
}
} 注重我们在这个servlet中还包含了分外的智能,因而它可以晓得假如选择了一张已在购物车中的CD,那末应当复杂地增添session中CDbean的计数。它也处置从Cart.jsp中触发的举措,好比用户从购物车中删除物品,或是持续往收银台结帐。注重把持器老是对哪一个资本应当被挪用来对特定的举措发生回馈有完整的把持权。比方,对购物车形态的改动,像增添和删除,会引发把持器将哀求处置后转发给EShop.jsp页面。如许引发该页面按照已更新的购物车顺次从头显现主视图。假如用户决意结帐,则哀求被处置后转发给Checkout.jsp(见清单5),经由过程前面的哀求分派器,象上面显现的如许:
Stringurl="/jsp/shopping/Checkout.jsp";
ServletContextsc=getServletContext();
RequestDispatcherrd=sc.getRequestDispatcher(url);
rd.forward(req,res);
清单5
Checkout.jsp
<%@pagesession="true"import="java.util.*,shopping.CD"%>
<html>
<head>
<title>MusicWithoutBordersCheckout</title>
</head>
<bodybgcolor="#33CCFF">
<fontface="TimesNewRoman,Times"size=+3>
MusicWithoutBordersCheckout
</font>
<hr><p>
<center>
<tableborder="0"cellpadding="0"width="100%"bgcolor="#FFFFFF">
<tr>
<td><b>ALBUM</b></td>
<td><b>ARTIST</b></td>
<td><b>COUNTRY</b></td>
<td><b>PRICE</b></td>
<td><b>QUANTITY</b></td>
<td></td>
</tr>
<%
Vectorbuylist=(Vector)session.getValue("shopping.shoppingcart");
Stringamount=(String)request.getAttribute("amount");
for(inti=0;i<buylist.size();i++){
CDanOrder=(CD)buylist.elementAt(i);
%>
<tr>
<td><b><%=anOrder.getAlbum()%></b></td>
<td><b><%=anOrder.getArtist()%></b></td>
<td><b><%=anOrder.getCountry()%></b></td>
<td><b><%=anOrder.getPrice()%></b></td>
<td><b><%=anOrder.getQuantity()%></b></td>
</tr>
<%
}
session.invalidate();
%>
<tr>
<td></td>
<td></td>
<td><b>TOTAL</b></td>
<td><b>$<%=amount%></b></td>
<td></td>
</tr>
</table>
<p>
<ahref="/examples/jsp/shopping/EShop.jsp">Shopsomemore!</a>
</center>
</body>
</html> Checkout.jsp仅仅从session中提出购物车并为此哀求提掏出总金额,然后显现选中的物品和他们的总代价。显现了却算时的用户视图。一旦用户往结帐,删除session对象是一样主要的。这个由页面末了的session.invalidate()挪用来完成。有两个来由必需如许做。第一,假如没有使session有效,用户的购物车不会从头初始化;假如用户结帐后试图入手下手新一轮的推销,她的购物车会持续保留着已付过钱的物品。第二,假如用户结帐后仅仅是分开了网站,这个session对象不会被渣滓搜集机制接纳而是持续占用可贵的体系资本直到租约到期。由于缺省的session租约工夫是约莫三非常钟,在一个年夜容量体系上这将会很快招致体系内存耗尽。固然,我们都晓得对一个耗尽了体系内存的使用程序会产生甚么。
:结账视图
注重这个使用一切的资本都是session相干的,由于这里的形式存储在session里。因而,你必需确保用户不会由于某些缘故原由乃至因为毛病间接会见把持器。你能够在把持器检测到短少无效session的时分让客户端主动转向到一个毛病页面(见列表6),来制止这类情形的产生。
列表6
error.html
<html>
<body>
<h1>
Sorry,therewasanunrecoverableerror!<br>
Pleasetry<ahref="/examples/jsp/shopping/EShop.jsp">again</a>.
</h1>
</body>
</html>
部署音乐无界
我假定你正在利用来自sun的最新版本的JavaServerWebDevelopmentKit(JSWDK)来运转这个例子。假如不是,参看资本大节往看看到那里获得它。假定服务器安装在jswdk-1.0.1,这是MicrosoftWindows体系下的缺省路径,能够象上面如许部署音乐无界使用:
Createshoppingdirectoryunderjswdk-1.0.1examplesjsp
CopyEShop.jsptojswdk-1.0.1examplesjspshopping
CopyCart.jsptojswdk-1.0.1examplesjspshopping
CopyCheckout.jsptojswdk-1.0.1examplesjspshopping
Compilethe.javafilesbytypingjavac*.java
CopyShoppingServlet.classtojswdk-1.0.1webpagesWeb-Infservlets
Createshoppingdirectoryunderjswdk-1.0.1examplesWeb-Infjspeans
CopyCD.classtojswdk-1.0.1examplesWeb-Infjspeansshopping
Copyerror.htmltojswdk-1.0.1webpages
Onceyourserverhasbeenstarted,youshouldbeabletoaccesstheapplicationusinghttp://localhost:8080/examples/jsp/shopping/EShop.jspastheURL
只需你的服务器启动,你应当可使用URLhttp://localhost:8080/examples/jsp/shopping/EShop.jsp来会见这个使用程序。
使用jsp和servlet
着这个例子里,我们从细节上反省了把持的条理和形式2架构供应的天真性。实践上,我们已看到了servlet和jsp页面最好的特征是怎样开辟出最年夜化的内容与体现的剥离。只需准确地使用,形式2架构会将一切的处置逻辑会合到把持器servlet手里,而jsp页面只卖力视图大概说体现层的事情。但是,利用形式2布局的阻力在于它的庞大性。因而,关于复杂使用利用形式1也是能够承受的。
那这个对象有什么意义?现在很多用javabean的人就不能保证对象有完整的意义,不成熟的使用模式等导致代码疯狂增长,调试维护的时间要得多得多。在说性能之前,先说说你这个比较的来历。据说微软为了证明。net比java好。 是一种为 Internet发展的计算机语言 让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。 应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展 Java语言支持Internet应用的开发,在基本的Java应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。 Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站 Java是一种计算机编程语言,拥有跨平台、面向对java Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。 有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想) 是一种突破用户端机器环境和CPU 科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。 如果要向java web方向发展也要吧看看《Java web从入门到精通》学完再到《Struts2.0入门到精通》这样你差不多就把代码给学完了。有兴趣可以看一些设计模块和框架的包等等。
页:
[1]