1.1跟我学统一建模语言UML——MVC体系架构模式中的控制层的设计原则及示例
1.1.1MVC体系架构模式中的控制层的设计原则及示例
1、设计的原则和所需要达到的目标
在系统的控制层的设计中,一般应该将控制器拆分为前端控制器和后端控制器两个不同职责的控制器,设计的主要目标是要考虑如何降低与系统业务处理层组件的藕合度。2、系统控制器的主要实现形式
(1)前端控制器
可以将标准的J2EE 过滤器(Filter)组件或者Struts框架中的ActionServlet组件设计为系统的前端控制器。
(2)各种后端业务控制器
可将标准的J2EE Servlet组件或者Struts框架中的Action组件设计为系统后端业务控制器。
3、系统控制层设计中常应用的设计模式----命令设计模式
在基于Struts框架的应用系统项目中的Servlet组件的设计中,为了能够更好地对系统业务模型组件进行调度,一般可以采用命令(Command)设计模式。
通过命令设计模式实现把命令的请求和命令的具体执行的相关程序代码相互分离,对命令的请求者以统一的形式进行命令请求(功能调用)。下面为命令模式的调用示例代码:NetBookBussBean netBookBussBean=
NetBookCommander.produceCommandRequest(4,dataSource,enCoding,request);
boolean OKOrNot=
netBookBussBean.doNetBookModel(actionMapping,actionForm,request,
response);
4、编程实现线程安全的Servlet或者JSP程序类
(1)对控制器Servlet组件仅仅创建它的一个实例
为了能够使得控制器Servlet组件在一个多线程环境中正确运行,对控制器Servlet 组件仅仅创建它的一个对象实例,并用于所有的Web请求处理。而帮助线程安全编程的最重要的原则就是在Servlet程序类中仅仅使用局部变量而不应该使用实例变量——类中的成员变量。下图为线程不安全的Servlet程序代码示例:
因为局部变量的创建是在一个分配给每个Web请求线程的栈中,各个局部变量之间是相互隔离的,所以不会出现多线程方式下的同步冲突等问题。下图为使用局部变量或者使用类常量,而不使用类实例变量以避免产生线程不安全的Servlet程序代码示例:
(2)控制器Servlet(或者JSP)默认是以多线程方式执行的
由于标准的J2EE Servlet和JSP在默认方式下都是以多线程的方式执行的,这是JSP与ASP,PHP,PERL等脚本语言不一样的设计之处,也是JSP的主要优势之一。但如果不注意多线程中的同步共享等方面的问题,会使所写的Servlet或者JSP程序有难以发现的错误。
由于当客户端第一次请求某一个Servlet组件或者JSP页面文件时,服务器端的程序会
把该JSP页面中的各种脚本程序代码等编译成一个*.class的Java类文件,并创建一个该Servlet或者JSP程序类的实例,然后创建一个线程以处理Web浏览器客户端的Http请求。如果有多个客户端同时请求该Servlet或者JSP页面文件,则在Web服务器端的系统创建出多个不同的线程分别对Http请求进行处理。
每个Web浏览器客户端的请求对应一个服务器端的线程。以多线程的方式执行可大大地降低对应用系统的资源需求,提高应用系统的并发量及响应时间。
5、在JSP页面中可能应用的各种变量
(1)实例变量
实例变量是在堆中分配的,并被属于该实例的所有线程所共享,所以它们不是线程安全的。
(2)JSP系统中所提供的8个类变量
JSP页面中用到的out、request、response、session、config、page和pageContext 都是线程安全的,而内置对象application由于是在整个系统内被使用,所以它不是线程安全的。
(3)局部变量
局部变量在堆栈中分配,因为每个线程都有它自己的堆栈空间,所以是线程安全的。(4)静态类
由于静态类是不用被实例化的,就可直接使用,也不是线程安全的。
(5)外部资源
在程序中可能会有多个线程或进程同时操作同一个资源(比如多个线程或进程同时对一个文件进行写操作),此时也要注意线程同步的问题。
6、设计和编程实现Struts框架中的Action 程序类时所需要注意的设计要点
控制器Servlet(ActionServlet)组件仅仅创建一个Action 类的对象实例,并用于所有的Web请求。这样就需要编写对应的Action程序类以保证能够在一个多线程环境中正确地运行,就象必须安全地编程一个J2EE Servlet组件的 service() 方法一样。
帮助开发人员实现线程安全编程的最重要的设计原则就是在基于Struts框架的Action 程序类中仅仅使用局部变量而不是实例变量(类中的成员变量)。因为局部变量的创建是位于一个分配给每个请求线程的栈中,所以不会出现在多线程环境下的共享冲突等问题。