JSP构架
--2种Model I方式:和Model II Lance Lavandowska
作者: blueski
编译:
Servlet
如果你经常去或JSP的Model I 新闻组或者邮件列表,那么一定会看到不少关于和Model II 方OOP法的讨论。究竟采用哪一种,这取决于你的个人喜好、团队工作策略以及是否采用正统的。 Model I
简单地说,将business logic事务逻辑()presentation code和表示代码()HTML融合在一起(如在中Model II);则 提倡最大限度地将所有的代码放到内容表示之外。 Model I
: 简 单的单层次应用 Java
如果是在一个人人都精通和HTML的HTML环境中,或者你独自做着所有的工作,假如每个人都有清晰的编程结构和思路,那么这种方法会很有效,不过这样的假设不在本文讨论范围之内。这种方法的第一个优点是如果你的应用改变了,你只需维护一个文件。而最大的缺陷是可读性!除非十分小心,否则你的和Java代 码会相互混杂,从而难以维护。 TimeZone
在下面这个例子中,我们将增加一个元JSP素,从而使它变成文TimeZone件,它会返回基于时间的所期待的。 TimeZone如果没有提交, 那么缺省的是服务器的缺省时间。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} since we
//re basing our time from GMT, well set our Locale to Brittania, and get a Calendar. Calendar myCalendar
= Calendar.getInstance(timeZone, Locale.UK) ; jsp
</:scriptlet> myCalendar.get
<%=(Calendar.HOUR_OF_DAY) % >: myCalendar.get
<%=(Calendar.MINUTE) % >: myCalendar.get
<%=(Calendar.SECOND) % >
====================================================================== JavaBean
相应地,数据也可以从取 得并加以显示。在下一个例子中我们就可以看到。 Model II
: 重Redirecting Requests定向请求() HTML
在一个团队开发环境中,有些是设Java计者,另一些则是程Java序员,这时这一方法显得非常重要。程HTML序员可以集中精力创建可重用代码,而设 计师可以集中精力于内容表示,彼此相对对立,可以分别动态地修改自己的内容,只要总体的输入输出不变。 Model II
现在我们可以使用来Model I表示的Model-View-Controller 那个例子。这一方法遵循了(MVC) 范 例(cite Design Patterns book) 。在servlet这个例子中,我们只有一个类(页或者) 处Controller理请求()TimeZone,取得,View设置所有用于表示的变量,并将控制传递到表示页() 。作为如此简单的应用,可以没有"Model" 。 Controller
: timeByZone.jsp controller
可servlet以是一个或JSP一个页JSP。我推荐使用,granularity因为这样我不必担心每当我做修改时要对类重新编译,但是,你将因此失去( 颗粒性),以后要扩展该类也比较困难。
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; HttpSession mySession
= request.getSession( ); mySession.putValue
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet> jsp
<:forward page=displayTime.jsp"" / >
====================================================================== View
: displayTime.jsp view
同样地,这个既servlet可以是一个也jsp可以是一个文Session件。这里我们从中Bean取得并显示它的值。实际上我们会将这做两次,来示范是 如何被使用的。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=session"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone.jsp --> jsp
<:scriptlet> HttpSession mySession
= request.getSession( ); TimeBean timeBean
= mySession.getValue(tempTimeBean"" ); if
(timeBean ! null=)
{/ check to make sure its not null/, to avoid NullPointerExceptions out.print
(timeBean.getHours( )); out.print
( ":"); out.print
(timeBean.getMinutes( )); out.print
( ":"); out.print
(timeBean.getSeconds( ));
} else
{ out.println
(Press your Back button and select a TimeZone"" );
} jsp
</:scriptlet>
====================================================================== null
第二种方法(在内部使用了代码)可能有些笨重,但允许开发者确保输出不至于很糟糕(例如":null:null null"Session bean),假定还 没有被实例化以及没有进行值的设置。这View种情况发生在客户端直接调用了页scriptlets。问题是使用脚本可url以允许更强的控制。如果你确信你可以控制存bean取,那么方 View法当然更适合于开发,并使页HTML更方便于设 计者的协同工作。 Model II
上面的是"传统的"设Session计。所有的变量都包装了并放在对2象中。这有个 不足: 1
) 如Session果客户端拒绝参与的话,是 不可得到的。 2
) 除Session非变Session量被显式地移走,否则它回一直存在,直到被 破坏或过期。 cookies
第一种案例很可能发生在这样的场合,即使用了作mechanism为声明的结构()form而开发者没有能够提供声明的结构的替代表单()URL,即改 写。 Sessions
第二个案例甚至更为严重,因为它可能引起很大的内存消耗,如果被30定义为保存比标准存留时间更长的话((标准存留时间是分30钟)。即使是分Session钟的,Model这种也Session可能在大的应用中引起灾难性的内存泄露。为什么呢?在对Session象内部设置的对象被实例化了,并且在终references止以前一直没有被移去。因为它们仍然有关联(Session对 象)指garbage-collected向它们,所以无法被垃圾收集()Model II 。在模Session型中,很多对象被放到中JavaBean(要么直接地,要么通过)Session。随着的Session进行,更多的页被存取,内存使用会增加并持续下去直到客户端终止了或Session者过Session期。要一直等到变. 得非法,放在那的对象才能被垃圾收集,而那些损失的内存本可以用于任何其它的用途。 Beans
改进的方法之一是将或Request者其它变量放到对RequestDispatcher.include象中去,并使用(RequestDispatcher.forward)而不是(View )。这样做以后,页Controller具有和一Model II样的存取请求的对象。传统的设 计的不足可以被排除。 Model II
一个最后的评注:尽管有如上所述,我个人仍有些不喜欢的 范例,如果它用通常方法开发的话。客 户端被引送到某一个地址,然后又被转向到另一个不同的类,我不喜欢创建这样的系统。基于这样的原因,我修改了设计,使它变成了以下的样子: Controller
: timeByZone2.jsp controller
和前面一样,使Request用值View来取得必要的数据,并且将数据放到请求的对象中去。这回的区别是页RequestDispatcher.include将使用(Controller)来调用。chained在这种方法中,客户端再也不做重定向,请求不是"链接class的。相当于/jsp请 求了另一方来为它做一些工作,然后继续。
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; request.setAttribute
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet>
====================================================================== View
: displayTime2.jsp displayTime.jsp
和非timeByZone2.jsp常相似,但在 也的顶部被调用。请注意<jsp:useBean / >中scope的""request已经被换成了"" 。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:include page=timeByZone2.jsp"" / > jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=request"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone2.jsp -->
====================================================================== View
在一个在建系统中,我们已经使用这种方法来创建类的链,每一个都只对它所处理的工作负责。通过辨别公用的表示格式,我们创建了一个对JSP象,即使在很高层次的中 它也可以重复使用。我们的目标就是建立一些可重用的页,同时减少用于表示的类的数量。 Servlet Model
单个的(A Model II Design)
什么时候我有足够时间来研究这个课题,我会在这里发表更多的东西。
附原文: JSP Architectures
An explanation and comparison of the methodologies
commonly known as
"Model I" and "Model II". Lance Lavandowska To Outline
If you spend any time reading through Servlet or JSP related newsgroups or mailing lists
, youre likely to encounter a discussion of Model I versus Model II methodologies . Which one you use depends on personal taste, team work strategies and OOP orthodoxy. Loosely described
, Model I is an approach where business logic and presentation code can be intermixed with the presentation itself (HTML in our arena). Model II proscribes that all code, to the extent this is possible, be excluded from the presentation. Model I
: Simple 2 1/2 Tier Application In a team environment where everyone knows Java and HTML
, or if youre doing it all yourself, this approach can work well, provided everyone maintains a clear coding structure (that discussion is outside the bounds of this article). The primary advantage of this approach is that there is only one file to maintain for changes to your application. The major disadvantage is readability! Unless great care is taken, your HTML and Java code can become so intermingled that it becomes difficult to debug and maintain your application. For this example
, we are going to revisit the "Sample Page" from the JSP Quick Start chapter. Im going to add a TimeZone element, so well have a JSP that returns the time based on the desired timezone. If no TimeZone is submitted, well default to that of the server.
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} since we
//re basing our time from GMT, well set our Locale to Brittania, and get a Calendar. Calendar myCalendar
= Calendar.getInstance(timeZone, Locale.UK) ; jsp
</:scriptlet> myCalendar.get
<%=(Calendar.HOUR_OF_DAY) % >: myCalendar.get
<%=(Calendar.MINUTE) % >: myCalendar.get
<%=(Calendar.SECOND) % >
====================================================================== Similarly
, the data to be displayed could have been gotten from a JavaBean. Well see a little of that in the next example. Model II
: Redirecting Requests In a team environment where some members are HTML designers and others are Java programmers
, this approach can be particularly strong. The Java programmers can focus on creating (re)usable code, while the HTML designers can focus on presentation. While the two remain dependant on each other, one or the other can change dramatically so long as the principle inputs and outputs (respectively) remain the same. Now we
ll take the same desired behaviour from the Model I example, and present it using the Model II methodology. This methodology follows the Model-View-Controller (MVC) paradigm (cite Design Patterns book). For this example, well have one class (or page or servlet) process the request (Controller) get the TimeZone,, set all the required variables for presentation, and pass control off to a presentation page (View). For simple apps like this, there is no "Model". Controller
: timeByZone.jsp The controller can be a servlet or a jsp file. I prefer to use JSP
, as I dont have to worry about compiling the class each time I make changes. However, you lose granularity this way, and make it more difficult to extend this class later (well review this in Advanced JSP Programming).
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; HttpSession mySession
= request.getSession( ); mySession.putValue
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet> jsp
<:forward page=displayTime.jsp"" / >
====================================================================== View
: displayTime.jsp Again
, the view can be either a servlet or a jsp file. Here well get the Bean from the Session, and display its values. Well actually do this twice, to illustrate again how Beans are used.
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=session"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone.jsp --> jsp
<:scriptlet> HttpSession mySession
= request.getSession( ); TimeBean timeBean
= mySession.getValue(tempTimeBean"" ); if
(timeBean ! null=)
{/ check to make sure its not null/, to avoid NullPointerExceptions out.print
(timeBean.getHours( )); out.print
( ":"); out.print
(timeBean.getMinutes( )); out.print
( ":"); out.print
(timeBean.getSeconds( ));
} else
{ out.println
(Press your Back button and select a TimeZone"" );
} jsp
</:scriptlet>
====================================================================== The second method
(using code inside) may be more cumbersome, but allows the developer to ensure against ugly output (such as "null:null:null null" if the Session bean has not been instantiated )& had its values set. This would likely only happen if the client somehow called the View page directly. The point is that using scriptlets allows for greater control. If you are certain you can control url access, the bean approach certainly eases development, and makes the View page easier for HTML designers to work with. The above is the
"traditional" Model II design. Youll note that all the variables are wrapped up and placed into the Session object. This has two weaknesses: 1) no Session is availabe because the client has refused to participate, 2) unless the Session variable is explicitly removed it will continue to exist until the Session is destroyed or expires. The first case is most likely to happen when cookies are used as the State mechanism and the developers have failed to provide for the alternative form of State maintenance
, URL rewriting. The second case is even more serious
, as it can lead to great memory use if Sessions are defined to exist for more than the standard amount of time (30 minutes appears to be the standard). Even in the case of 30 minute Sessions, this Model can lead to disastrous memory leaks in systems under great use. Why? Objects get instantiated, set inside the Session object, and are not removed until the Session ends. Because they still have references (the Session object) pointing to them, they are not garbage-collected. In the Model II pattern, many objects are placed into the Session (either directly or via a JavaBean). As the Session progresses (more pages are accessed) memory-use increases and persists until the client ends the Session or the Session times out. Until the Session is invalidated, the objects placed there cannot be garbage-collected, and thus consume memory that could be of use elsewhere. One means of addressing this issue is to place the Beans or other variables into the Request object
, and use RequestDispatcher.include( rather than RequestDispatcher.forward)(. By doing so), the View page has access to the same Request object as the Controller, and the weaknesses of the traditional Model II design are obviated. One final comment
: despite all the above, I have a personal distaste for the Model II paradigm as it is commonly implemented. The creation of a system where the client is sent to an address, but is redirected to a different class, is for some reason abhorrent to me. For this reason, Ive modified the design in the following manner: Controller
: timeByZone2.jsp As before
, the controller uses the Request values to obtain the necessary data and put that data into the Request object. The difference this time is that the View page will call the Controller using RequestDispatcher.include(. In this way), the client is never redirected, and Requests are not "chained". Rather, the class/jsp called asks someone else to do some work for it, then continues.
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; request.setAttribute
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet>
====================================================================== View
: displayTime2.jsp Much like displayTime.jsp
, however youll see that timeByZone2.jsp is called at the top of the page. Notice that the scope of <jsp:useBean / has changed to >"request".
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:include page=timeByZone2.jsp"" / > jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=request"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone2.jsp -->
====================================================================== In a system currently under construction
, weve made use of this method to create chains of classes, each responsible for its own processing. By identifying common presentation formats, weve created View objects that can be reused in yet higher level JavaServer Pages. Our goal is to create pages that are designed for reuse, and to reduce the number of presentation classes. Single Servlet Model
(A Model II Design) When I
ve had time to adequately research and implement this idea, Ill post something here.
--2种Model I方式:和Model II Lance Lavandowska
作者: blueski
编译:
Servlet
如果你经常去或JSP的Model I 新闻组或者邮件列表,那么一定会看到不少关于和Model II 方OOP法的讨论。究竟采用哪一种,这取决于你的个人喜好、团队工作策略以及是否采用正统的。 Model I
简单地说,将business logic事务逻辑()presentation code和表示代码()HTML融合在一起(如在中Model II);则 提倡最大限度地将所有的代码放到内容表示之外。 Model I
: 简 单的单层次应用 Java
如果是在一个人人都精通和HTML的HTML环境中,或者你独自做着所有的工作,假如每个人都有清晰的编程结构和思路,那么这种方法会很有效,不过这样的假设不在本文讨论范围之内。这种方法的第一个优点是如果你的应用改变了,你只需维护一个文件。而最大的缺陷是可读性!除非十分小心,否则你的和Java代 码会相互混杂,从而难以维护。 TimeZone
在下面这个例子中,我们将增加一个元JSP素,从而使它变成文TimeZone件,它会返回基于时间的所期待的。 TimeZone如果没有提交, 那么缺省的是服务器的缺省时间。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} since we
//re basing our time from GMT, well set our Locale to Brittania, and get a Calendar. Calendar myCalendar
= Calendar.getInstance(timeZone, Locale.UK) ; jsp
</:scriptlet> myCalendar.get
<%=(Calendar.HOUR_OF_DAY) % >: myCalendar.get
<%=(Calendar.MINUTE) % >: myCalendar.get
<%=(Calendar.SECOND) % >
====================================================================== JavaBean
相应地,数据也可以从取 得并加以显示。在下一个例子中我们就可以看到。 Model II
: 重Redirecting Requests定向请求() HTML
在一个团队开发环境中,有些是设Java计者,另一些则是程Java序员,这时这一方法显得非常重要。程HTML序员可以集中精力创建可重用代码,而设 计师可以集中精力于内容表示,彼此相对对立,可以分别动态地修改自己的内容,只要总体的输入输出不变。 Model II
现在我们可以使用来Model I表示的Model-View-Controller 那个例子。这一方法遵循了(MVC) 范 例(cite Design Patterns book) 。在servlet这个例子中,我们只有一个类(页或者) 处Controller理请求()TimeZone,取得,View设置所有用于表示的变量,并将控制传递到表示页() 。作为如此简单的应用,可以没有"Model" 。 Controller
: timeByZone.jsp controller
可servlet以是一个或JSP一个页JSP。我推荐使用,granularity因为这样我不必担心每当我做修改时要对类重新编译,但是,你将因此失去( 颗粒性),以后要扩展该类也比较困难。
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; HttpSession mySession
= request.getSession( ); mySession.putValue
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet> jsp
<:forward page=displayTime.jsp"" / >
====================================================================== View
: displayTime.jsp view
同样地,这个既servlet可以是一个也jsp可以是一个文Session件。这里我们从中Bean取得并显示它的值。实际上我们会将这做两次,来示范是 如何被使用的。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=session"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone.jsp --> jsp
<:scriptlet> HttpSession mySession
= request.getSession( ); TimeBean timeBean
= mySession.getValue(tempTimeBean"" ); if
(timeBean ! null=)
{/ check to make sure its not null/, to avoid NullPointerExceptions out.print
(timeBean.getHours( )); out.print
( ":"); out.print
(timeBean.getMinutes( )); out.print
( ":"); out.print
(timeBean.getSeconds( ));
} else
{ out.println
(Press your Back button and select a TimeZone"" );
} jsp
</:scriptlet>
====================================================================== null
第二种方法(在内部使用了代码)可能有些笨重,但允许开发者确保输出不至于很糟糕(例如":null:null null"Session bean),假定还 没有被实例化以及没有进行值的设置。这View种情况发生在客户端直接调用了页scriptlets。问题是使用脚本可url以允许更强的控制。如果你确信你可以控制存bean取,那么方 View法当然更适合于开发,并使页HTML更方便于设 计者的协同工作。 Model II
上面的是"传统的"设Session计。所有的变量都包装了并放在对2象中。这有个 不足: 1
) 如Session果客户端拒绝参与的话,是 不可得到的。 2
) 除Session非变Session量被显式地移走,否则它回一直存在,直到被 破坏或过期。 cookies
第一种案例很可能发生在这样的场合,即使用了作mechanism为声明的结构()form而开发者没有能够提供声明的结构的替代表单()URL,即改 写。 Sessions
第二个案例甚至更为严重,因为它可能引起很大的内存消耗,如果被30定义为保存比标准存留时间更长的话((标准存留时间是分30钟)。即使是分Session钟的,Model这种也Session可能在大的应用中引起灾难性的内存泄露。为什么呢?在对Session象内部设置的对象被实例化了,并且在终references止以前一直没有被移去。因为它们仍然有关联(Session对 象)指garbage-collected向它们,所以无法被垃圾收集()Model II 。在模Session型中,很多对象被放到中JavaBean(要么直接地,要么通过)Session。随着的Session进行,更多的页被存取,内存使用会增加并持续下去直到客户端终止了或Session者过Session期。要一直等到变. 得非法,放在那的对象才能被垃圾收集,而那些损失的内存本可以用于任何其它的用途。 Beans
改进的方法之一是将或Request者其它变量放到对RequestDispatcher.include象中去,并使用(RequestDispatcher.forward)而不是(View )。这样做以后,页Controller具有和一Model II样的存取请求的对象。传统的设 计的不足可以被排除。 Model II
一个最后的评注:尽管有如上所述,我个人仍有些不喜欢的 范例,如果它用通常方法开发的话。客 户端被引送到某一个地址,然后又被转向到另一个不同的类,我不喜欢创建这样的系统。基于这样的原因,我修改了设计,使它变成了以下的样子: Controller
: timeByZone2.jsp controller
和前面一样,使Request用值View来取得必要的数据,并且将数据放到请求的对象中去。这回的区别是页RequestDispatcher.include将使用(Controller)来调用。chained在这种方法中,客户端再也不做重定向,请求不是"链接class的。相当于/jsp请 求了另一方来为它做一些工作,然后继续。
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; request.setAttribute
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet>
====================================================================== View
: displayTime2.jsp displayTime.jsp
和非timeByZone2.jsp常相似,但在 也的顶部被调用。请注意<jsp:useBean / >中scope的""request已经被换成了"" 。
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:include page=timeByZone2.jsp"" / > jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=request"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone2.jsp -->
====================================================================== View
在一个在建系统中,我们已经使用这种方法来创建类的链,每一个都只对它所处理的工作负责。通过辨别公用的表示格式,我们创建了一个对JSP象,即使在很高层次的中 它也可以重复使用。我们的目标就是建立一些可重用的页,同时减少用于表示的类的数量。 Servlet Model
单个的(A Model II Design)
什么时候我有足够时间来研究这个课题,我会在这里发表更多的东西。
附原文: JSP Architectures
An explanation and comparison of the methodologies
commonly known as
"Model I" and "Model II". Lance Lavandowska To Outline
If you spend any time reading through Servlet or JSP related newsgroups or mailing lists
, youre likely to encounter a discussion of Model I versus Model II methodologies . Which one you use depends on personal taste, team work strategies and OOP orthodoxy. Loosely described
, Model I is an approach where business logic and presentation code can be intermixed with the presentation itself (HTML in our arena). Model II proscribes that all code, to the extent this is possible, be excluded from the presentation. Model I
: Simple 2 1/2 Tier Application In a team environment where everyone knows Java and HTML
, or if youre doing it all yourself, this approach can work well, provided everyone maintains a clear coding structure (that discussion is outside the bounds of this article). The primary advantage of this approach is that there is only one file to maintain for changes to your application. The major disadvantage is readability! Unless great care is taken, your HTML and Java code can become so intermingled that it becomes difficult to debug and maintain your application. For this example
, we are going to revisit the "Sample Page" from the JSP Quick Start chapter. Im going to add a TimeZone element, so well have a JSP that returns the time based on the desired timezone. If no TimeZone is submitted, well default to that of the server.
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} since we
//re basing our time from GMT, well set our Locale to Brittania, and get a Calendar. Calendar myCalendar
= Calendar.getInstance(timeZone, Locale.UK) ; jsp
</:scriptlet> myCalendar.get
<%=(Calendar.HOUR_OF_DAY) % >: myCalendar.get
<%=(Calendar.MINUTE) % >: myCalendar.get
<%=(Calendar.SECOND) % >
====================================================================== Similarly
, the data to be displayed could have been gotten from a JavaBean. Well see a little of that in the next example. Model II
: Redirecting Requests In a team environment where some members are HTML designers and others are Java programmers
, this approach can be particularly strong. The Java programmers can focus on creating (re)usable code, while the HTML designers can focus on presentation. While the two remain dependant on each other, one or the other can change dramatically so long as the principle inputs and outputs (respectively) remain the same. Now we
ll take the same desired behaviour from the Model I example, and present it using the Model II methodology. This methodology follows the Model-View-Controller (MVC) paradigm (cite Design Patterns book). For this example, well have one class (or page or servlet) process the request (Controller) get the TimeZone,, set all the required variables for presentation, and pass control off to a presentation page (View). For simple apps like this, there is no "Model". Controller
: timeByZone.jsp The controller can be a servlet or a jsp file. I prefer to use JSP
, as I dont have to worry about compiling the class each time I make changes. However, you lose granularity this way, and make it more difficult to extend this class later (well review this in Advanced JSP Programming).
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; HttpSession mySession
= request.getSession( ); mySession.putValue
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet> jsp
<:forward page=displayTime.jsp"" / >
====================================================================== View
: displayTime.jsp Again
, the view can be either a servlet or a jsp file. Here well get the Bean from the Session, and display its values. Well actually do this twice, to illustrate again how Beans are used.
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=session"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone.jsp --> jsp
<:scriptlet> HttpSession mySession
= request.getSession( ); TimeBean timeBean
= mySession.getValue(tempTimeBean"" ); if
(timeBean ! null=)
{/ check to make sure its not null/, to avoid NullPointerExceptions out.print
(timeBean.getHours( )); out.print
( ":"); out.print
(timeBean.getMinutes( )); out.print
( ":"); out.print
(timeBean.getSeconds( ));
} else
{ out.println
(Press your Back button and select a TimeZone"" );
} jsp
</:scriptlet>
====================================================================== The second method
(using code inside) may be more cumbersome, but allows the developer to ensure against ugly output (such as "null:null:null null" if the Session bean has not been instantiated )& had its values set. This would likely only happen if the client somehow called the View page directly. The point is that using scriptlets allows for greater control. If you are certain you can control url access, the bean approach certainly eases development, and makes the View page easier for HTML designers to work with. The above is the
"traditional" Model II design. Youll note that all the variables are wrapped up and placed into the Session object. This has two weaknesses: 1) no Session is availabe because the client has refused to participate, 2) unless the Session variable is explicitly removed it will continue to exist until the Session is destroyed or expires. The first case is most likely to happen when cookies are used as the State mechanism and the developers have failed to provide for the alternative form of State maintenance
, URL rewriting. The second case is even more serious
, as it can lead to great memory use if Sessions are defined to exist for more than the standard amount of time (30 minutes appears to be the standard). Even in the case of 30 minute Sessions, this Model can lead to disastrous memory leaks in systems under great use. Why? Objects get instantiated, set inside the Session object, and are not removed until the Session ends. Because they still have references (the Session object) pointing to them, they are not garbage-collected. In the Model II pattern, many objects are placed into the Session (either directly or via a JavaBean). As the Session progresses (more pages are accessed) memory-use increases and persists until the client ends the Session or the Session times out. Until the Session is invalidated, the objects placed there cannot be garbage-collected, and thus consume memory that could be of use elsewhere. One means of addressing this issue is to place the Beans or other variables into the Request object
, and use RequestDispatcher.include( rather than RequestDispatcher.forward)(. By doing so), the View page has access to the same Request object as the Controller, and the weaknesses of the traditional Model II design are obviated. One final comment
: despite all the above, I have a personal distaste for the Model II paradigm as it is commonly implemented. The creation of a system where the client is sent to an address, but is redirected to a different class, is for some reason abhorrent to me. For this reason, Ive modified the design in the following manner: Controller
: timeByZone2.jsp As before
, the controller uses the Request values to obtain the necessary data and put that data into the Request object. The difference this time is that the View page will call the Controller using RequestDispatcher.include(. In this way), the client is never redirected, and Requests are not "chained". Rather, the class/jsp called asks someone else to do some work for it, then continues.
====================================================================== xml version
<=1.0"" ? > --Worker Class
<!, nobody should see me--> jsp
<:scriptlet> the parameter
//"zone" shall be equal to a number between 0 and 24 (inclusive) TimeZone timeZone
= TimeZone.getDefault( );/returns the default TimeZone for the server / if
(request.getParameterValues(zone"" )! null=)
{ String timeZoneArg
= request.getParameterValues(zone""0)[] ; timeZone
= TimeZone.getTimeZone(GMT"+ "+ timeZoneArg + "00:" ); gets a TimeZone. For this example we
//re just going to assume its a positive argument
//, not a negative one.
} TimeBean timeBean
= new TimeBean( ); timeBean.setHours
= myCalendar.get(Calendar.HOUR_OF_DAY) ; timeBean.setMinutes
= myCalendar.get(Calendar.MINUTE) ; timeBean.setSeconds
= myCalendar.get(Calendar.SECOND) ; request.setAttribute
(tempTimeBean"" timeBean,) ; jsp
</:scriptlet>
====================================================================== View
: displayTime2.jsp Much like displayTime.jsp
, however youll see that timeByZone2.jsp is called at the top of the page. Notice that the scope of <jsp:useBean / has changed to >"request".
====================================================================== xml version
<=1.0"" ? > H1
<>Time JSP<H1> jsp
<:include page=timeByZone2.jsp"" / > jsp
<:useBean class=TimeBean"" id=tempTimeBean"" scope=request"" / > jsp
<:getProperty name=tempTimeBean"" property=hours"" >: jsp
<:getProperty name=tempTimeBean"" property=minutes"" >: jsp
<:getProperty name=tempTimeBean"" property=seconds"" > -- these would have printed
<!"null" if tempTimeBean was not instantiated by timeByZone2.jsp -->
====================================================================== In a system currently under construction
, weve made use of this method to create chains of classes, each responsible for its own processing. By identifying common presentation formats, weve created View objects that can be reused in yet higher level JavaServer Pages. Our goal is to create pages that are designed for reuse, and to reduce the number of presentation classes. Single Servlet Model
(A Model II Design) When I
ve had time to adequately research and implement this idea, Ill post something here.