JSP/Servlet开发——第五章 使用分层实现业务处理
1、JNDI(Java Naming and Directory Interface)Java命名和目录接口:
●JNDI:是一个有关应用序设计的 API 为开发人员提供了查找和访问各种命名和目录服务的通用、 统一的接口; |
●JNDI的作用与优点: ★在应用与Java对象或资源之间建立松耦合的逻辑关联,简化应用对于资源的配置及维护工作; ★可以在更大范围、不同应用之间共享资源; |
●JNDI 简单地理解为是一种将对象和名字绑定的技术,即指定一个资源名称,将该称与某一资源或服务相关联,当需要访问其他组件和资源时,就需要使用 JNDI 服务进行定位. 应程序可以通过名字获取对应的对象或服务; |
●JNDI 可以访问的目录及服务很多,eg:DNS、文件服务、数据库等; |
●eg:在 Tomcat 中发布一条信息供所有的 Web 应用程序使用; 分析:Tomcat 根目录\conf\context.xml 文件为全局的上下文配置文件,所有的 Web 应用有效。所将要发布的信息配置在此文件中,再通过 JNDI 来查找信息; 步骤1:在 Tomcat 中发布一条信息,修改context . xml 文件,代码如下: <Context> <Environment name="tjndi" value="hello JNDI" type="java.lang.String" /> </Context> 注:< EnviTonment >元素用于配置命名的值, 所配置的值作为环境条目资源, 对整个 Web 应用可见。它包含的属性:name、type、value; ◆name:环境条目的名称,相对于 java:comp/env 的名称; ◆type: 环境条目的 Java 类名的全称; ◆value: 通过JNDI context 请求时,返回给应用的参数值,该值必须转换成 type 属性定义Java 类型; 步骤2:编写 JSP 代码 , 通过 JNDI 访问环境条目,代码如下: <body> <%@ page import="javax.naming.*" %> <% //javax.naming.Context提供了查找JNDI Resource的接口 Context ctx = new InitialContext(); //初始化Context对象 //java:comp/env/为前缀 String testjndi = (String) ctx.lookup("java:comp/env/tjndi"); //调用lookup()方法 out.print("test jndi:" + testjndi); %> </body> 注:◆java. naming包下的Context 接口表示命名上下文,它由一组名称到对象的绑定组成。 ◆InitialContext是 Context接口的实现类; ◆Object lookup(String name) 方法根据名称检索指定对象, ◆为了避免 JNDI命名空间中的资源名称互相冲突. 并且避免可移植性问题 Java EE 应用程序中的所有名称应该以字串“java:comp/env”作为前缀;在上面的示例中:前缀后面的 'tjndi " 则对应着 context. xml 文件中< EnviTonment >元素的 name 属性; |
●使用 JNDI 的步骤如下: (1)配置资源; (2) 通过 Context 的 lookup()方法查找资源; |
●使用application 应该也能满足上述需求,但是 application 对象只能个 Web 应用程序中使用;使用 JNDI 发布的信息是对服务器上所有的 Web 应用程序都可见的,JNDI不只完成这种简单的需求,它还提供了对其他资源的引用; |
2、 连接池(Connection Pool ):
●传统数据库连接技术:
◆传统数据库连接方式的不足: 1、需要经常与数据库建立连接,在访问结束后必须关闭连接释放资源; 2、当并发访问数量较大时,执行速度受到极大影响; 3、系统的安全性和稳定性相对较差; |
●数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。 ●数据库连接池:数据库连接池负责分配、管理和释放数据库连接; ★它允许应用程序重复使用一个现有的数据连接,而不再是重新建立一个; ★释放那些空闲时间超过最大空闲时间的数据库连接,以避免由于有释放数据库连接而引起的数据库连接泄露; ★能明显地提高对数据库操作的性能; eg:日常生活中经常拨打热线电话 (如 10086热线电话对外是相同的号码. 但是因为有多接线员 . 所以允许同时接A 多个电话。当然 ,如果所有的接线员都在工作,再有电话打入时就要进行等待,直到其中有接线员出现空闲; |
●数据库连接池在初始化时将创建一定数量的数椐库连并放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接否被使用,连接池都将确保至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求被加入等待队列中; |
●连接池是如何管理连接的: 对于连接的管理可使用空闲池,即把巳经创建但尚未分配出去的连接存放到一个空闲池中;每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接,如果有就分配一个连接给用户;如果没有则检查当前连接池是否达到连接池所允许的最大连接数。如果没有达到,就新建一个连接。如杲已经达到,就等待一定的间。如果在等待的时间内有连接被释放出来,就可以把这个连接分配给等待的用户;如果等待时间超过预定时间,则返回空值 (null),系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池; |
3、数据源与连接池:
●数据源:数据源是在 JDBC 2. 0中引入的一个概念,在 JDBC 扩展包中定义了 javax.sql .DataSource 接口,它有一组特性用于确定和描述它所表示的现实存在的数据源,配置好的数据库连接池也是DataSource 的形式存在,其实现类负责建立与数据库的连接,在应用程序中访问数据库时不必编写接数据库的代码,可以直接从数据源获得数据库连接; |
●javax.sql.DataSource接口的实现类: 1、负责管理与数据库的连接; 2、以连接池的形式对数据库连接进行管理; |
●在 DataSaice 中事先建立多个数据库连接, 这些数据库连接保存在座接池中。Java 程序访问数锯库时只需从连接池中取出空闲状态的数据库连接,当程序访问数据库结束时,再将数据库连接返回给接池. 这样做可以提高访问数据库的效率. 以上过程如下图:
|
经验:在传统模式下,数据库连接使用完毕后,需要将其关闭,释放资源。而在连接池中,使用数据源获得数据库连接对象,在调用 close()方法时并不会真正地关闭连接,而仅仅实現了断开应用程序与连接池之间的联系,即将连接的使用权归还给连接池; |
4、数据源与JNDI资源:
●如果将一个数据源实例发布在 Tomcat 环境中,那么Web 应用就可以通过 JNDI 进行访问,通该数据源实例为 Web 应用提供数据库连接的管理机制,从而简化 Web 应用的数据库连接管理问题; |
●DataSource 对象是由Web容器 (Tomcat ) 提供的,因此不能在程序中采用创建一个实例的方生成 DataSource对象,而需要通过 JNDI 来获取: ★通过javax.naming.Context 的lookup()方法查找 JNDI Resource 的接口; eg:可以通过以下代码获得名称为 jdbc/news 的数据源: //初始化上下文 Context ctx =new InitialContext(); //获取与逻辑名相关联的数据源对象 DataSource ds=(DateSources)ctx.lookup("java:comp/env/jdbc/news”); ★Tomcat把 DataSouce作为一种可配置的JNDI 资源来处理,假定配置了一个 DataSource , 数据源名称为jdbc/news,应用程序访问名为 jdbc/news的 DataSource 的过程如下:
★得到DateSource对象后,可以通过 DataSource 的getConnection ( ) 方法来获得数据库连接对象; Connection conn=ds.getConnection(); ★当程序结束数据库访问后,应该调用 Connection 的 close ( ) 方法及时将 Connection 返回给数据连接池 . 使 Comection 恢复空闲状态; |
5、数据源的配置(下面以Tomcat为例讲解如何配置数据源):
●使用连接池实现数据库连接: 1、配置context.xml文件; 2、配置web.xml文件; 3、添加数据库驱动文件; 4、进行代码编写,查找并使用lookup()方法获取数据源对象; |
||||||||||||||||||||||
★Tomcat的conf/context.xml文件的配置: ◆上面JNDI时学习了如何在 context . xml 文件中增加<Environment>元素配置公共资源,而配数据源时需在<Context>节点下添加<Resource>元素; eg: <Context> <Resource name="jdbc/news" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="newsu" password="123456" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/newsmanagersystem? useUnicode=true&characterEncoding=utf-8" /> </Context> 注:对于url中出现的“&”,应将其替换为对应的实体“&” ▲Resource元素的属性配置数据库连接池的参数:
◆不同的Web 服务器,配置数据源的方式也是不一样的,需要根据服务器提供的助文档进行配置; |
||||||||||||||||||||||
★配置应用程序的web.xml文件:在web.xml中配置<resource-ref>: eg: <web-app> <resource-ref> <description>news DataSource</ description > <res-ref-name>jdbc/news</res-ref-name> // jdbc/news:指定JNDI的名字,与<Resource>元素中的name一致 <res-type>javax.sql.DataSource</res-type> // javax.sql.DataSource:指定引用资源的类名,与<Resource>元素中的type一致 <res-auth>Container</res-auth> // Container:指定管理所引用资源的Manager与<Resource>元素中的auth一致 </resource-ref> <!—省略其他配置信息--> < /web-app > ▲resource-ref元素的属性:
◆<resource-ref>元素包含一个对外部资源的引用,它包含一个可选的description、一个引用资源的名称(相对于java:comp/env环境的JDNI名)、资源类型、验证方式; |
||||||||||||||||||||||
★添加数据库驱动文件:把数据库驱动jar文件,加入到Tomcat的lib中 |
||||||||||||||||||||||
★进行代码编写,查找并使用lookup()方法获取数据源对象: importjavax.naming.Context; importjavax.naming.InitialContext; importjavax.naming.NamingException; importjavax.sql.DataSource; publicclass BaseDao { public Connection getConnection () { Connection conn = null; try { //获取与逻辑名相关联的数据源对象 Context ctx = new InitialContext(); DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/news"); conn = ds.getConnection(); } catch (SQLException exception) { exception.printStackTrace(); } catch (NamingException namingException) namingException.printStackTrace(); } return conn; } } |
||||||||||||||||||||||
●经验:还有一种配置数据源方式,只需要在 WebRoot 目录下的 META-NF 目录中创建一个context.xml文件,添加<Context>节点,然后在<Context>节点中添加<Resource>元素内容; |
||||||||||||||||||||||
●数据源配置完毕,要通过数据源访问数据库,还要添加数据库驱动文件. 由于数据源由 Tomcat创建并维护,所以必须把数据库驱动文件放到 Tomcat 的 lib 目录下; |
6、 常见错误:
●错误提示: Cannot load JDBC driVer class (不能加载驱动类); 错误原因及解决方案:通过数据源访问数据库,数据源由 Tomcat创建 , 应该把 JDBC 驱程序的 jar 文件复制到 Tomcat 的 jib 目录下; |
●常见错误Cannot create JDBC driver of class ‘ ' for connect URL 'null' (由于连接路径为null. 不能创建驱动 ); 错误原因及解决方案 : 此类错误多在数椐库驱动或者在连接错误时出现,解决的方法是检查 context . xml 文件中数据源配置的文件信息,确保配置信息完全正确; |
●错误信息:Name [news] is not bound in this Context (jdbc 名称没有绑定到当前上下文) 错误原因及解决方案 : ◆在使用lookup()方法查找数据源时,如果数据源名称与配置中的名称不一致,则程序运时会报此错误。解决方法是确保context. xml 文件中指定的数据源名称与代码中所要访问数据源名称一致; ◆在程序中调用 lookup()方法查找数据源时,没有使用前缀 (java:comp/env/) +数据源名称,则程序运行时会报此错误。解决方法是在使用 lookup()查找数据源时, 使用前缀(java:comp/env/) +数据源名称的形式; |
7、 软件分层模式:
●JSP开发时分两层的弊端
|
●分层模式是最常见的一种架构模式;甚至可以说分层模是很多架构模式的基础; ●分层模式是将解决方案的组件分隔到不同的层中,每一层中的组件应保内聚性,每一层都应与其下面的各层保持松耦合,对于一个小型系统一般三层就足够了; |
●三层架构:三层指的是:表示层、业务逻辑层、数据访问层;
◆表示层:位于最外层 ( 最上层 ),使用户能够直接访问,用于显示数据和接收用户输入的数据,为用户提供一种交互式操作界面。在 Web 应用程序中,表示层一般以 JSP 文件、HTML文件为主; ◆业务逻辑层:其主要功能是提供对业务逻辑处理的封装,在业务逻辑层中,通常会定义些接口,表示层通过调用业务逻辑层的接口实现各种操作,如数据有效性的检验. 业务辑描述等相关功能,业务逻辑层经常放在 service 包或 biz 包下,btz 是英文 buslness 的缩写,意思是 '业务逻辑"; ◆数据访问层:该层实现对数据的保存和读取操作。数据访问,可以访问关系数椐库、文件或 XML 文档等。数据访问层通常放在 dao 包下,DAO 是英文 Data Access Object 的缩写,意思是 "数据访问对象 "; |
●层与层之间的关系: ◆在三层架构中各层之间相互依赖。表示层依赖于业务逻辑层,业务逻辑层依赖于数据访层,各层之间的数据传递方向分为请求与晌应两个方向; ★如图:
◆表示层根据用户的操作,将请求提交给业务逻辑层 ;业务辑层收到请求,首先对请求数据进行必要的审核和处理,然后请求通知数据访问层或直接将处理结果返回表示层,数据访问层收到业务逻辑层的调用后便开始访问数据库; ◆业务逻辑层在体系架构中的位置非常关键,起到数据交换承上启下的作用。理想的分层式架构. 应该是一个支持可抽取可替换的 “抽屉” 式架构。 业务逻辑层的设计对于一个支持可展的架构尤为关键,因为它扮演了两个不同的角色。对于数据访问层而言,他是调用者,对于表示层而言,它却是被调用者。 ◆数据访问层通过对数据库的访问得到请求结果,并把请求结果通知业务逻辑层;业务逻辑层到请求结果,可以对请求结果进行必要的审核和处理,然后将请求结果通知表示层;表示层收到求结果,并把结果展示给用户。 |
●分层原则: 1、上一层依赖其下一层、依赖关系不跨层: ★上一层调用下一层所得到的执行结果完全取决于下一层中的代码实现,上一层无法进行控; 2.下一层不能调用上一层: ★上一层调用下一层功能,下一层不能调用上一层功能。下一层为上一层提供服务,而不使用上一层提供的服务; 3.下一层不依赖上一层: ★下一层的代码实现决定了上一层获得的内容,所以说上一层依赖下一层,从另一个角度来说,上一层不管如何发生改变. 对于其调用下一层的业务是不会发生变化的,因此对于下一层来说,上一层的改变不会对其产生任何影响; 4.在上一层中不能出现下一层的概念: ★使用分层架构的一个优点是在系统中各个功能分工明确,在某一层中不会出现其下一层的任内容,简单地说就是在业务逻辑层中. 只能有用于业务逻辑控制的代码,而不能出现数据库访问层中才有的 SQL 语句 , 确保层次间的关系很清晰; |
8、使用三层架构开发的特点和优势:
●使用三层开发的特点: ★下层不知上层的存在; ★每一层仅知它下一层的存在,而不知另外的下层; ★上层使用下层提供的服务,并为下层提供数据; |
●分层思想:就是指这样一种分工,它将系统按不同职责组织成有序的层次。其中,除最上层外,每一层仅提供若干服务供其相邻的上层使用,但不上层的存在;除了最下层外,每一层仅调用其临近下层的服务; |
●分层的优点: ★职责划分清晰; ◆由于某一层仅仅调用其相邻下一层所提供的服务, 所以,只要本层的实现和相邻下一层的实现定义完整,开发人员在开发某一层时就可以将关注集中于这一层所用的思想、模式、技术,而无需关心其他层的具体实现; ★利用面向对象的特性迸行无损替换; ★复用代码; ◆例如:铁路局制作发布了一个 “ Business Service' , 用于提供火车车次预告信息,这样火车票代售网站就可以利用这个服务层提供的服务制作火车票信息页面,而无须再重新实现获取信息的功能; ★降低了系统内部的依赖程度: ◆例如:在三层架构中,表示层只与业务逻辑层联系,而对业务逻辑层下还有哪些层并不关心,表示层只依赖于业务逻辑; |
●分层的弊端: ★例如,原本很直接的操作,现在要通过层层传递,势必造成性能的下降; ★另外,虽然分层架构可以降低层内变化的成本,但对于功能定义 (接口定义)变化非常敏感;功能定义的变动对于分层架构是致命的,修改起来难度非常大。所以,一个简单的判断法则是,如果系统层内实现频繁变动 (甚至整层替换) 的可能性很大,而功能定义变动的可性很小,就使用分层; |
9、附加:
●JSP三层架构:当不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,现在通过中间层来完成影响系统性能; ●使用三层架构,分别是表示层、业务逻辑层、数据访问层,各层之间分工明细,职责划分非常的清晰,而且代码的重用性也提高了很多,同事也降低了系统内部的依赖程度,实现无损替换,构建松耦合架构。 |
●三层开发的优势包括松耦合、重用性高、生命周期成本低、可维护性高。 ●三层分别为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。 作用: 1.解耦。 2.简化复杂问题。 3.便于系统维护/升级。 4.逻辑复用。 5.便于团队开发。 6.方便部署。 |
●业务逻辑层访问数据访问层,数据访问层执行对数据库的访问,并将请求结果通知业务逻辑层,业务逻辑层再将结果通知表示层,注意:业务逻辑层不直接对数据库访问。上一层依赖其下一层、依赖关系不跨层; |
●MVC是由三部分组成: 表示层、视图层(VIEW)JSP,主要做页面的显示效果,用于显示以及获取界面的数据; 控制层(控制器)(Controller)Servlet,主要做接受请求和响应的、控制页面跳转等; 模型层(Model)JavaBean:主要做业务处理,处理上层传递来的数据以及从数据库获取的数据的; |
●MVC是复合模式,结合了观察者模式、策略模式和组合模式。模型使用Observer,控制器是视图的策略,视图使用组合模式实现用户界面。适配器是使用MVC时,经常附带用到的技巧:使用适配器将模型适配成符合现有视图和控制器的需要的模型。 ●MVC 和Model2的区别:Model 2架构中呈现视图的技术并没有限制 |
MVC架构也可以应用于3-tier的网络架构中,其中模型通知视图时,可以透过Socket联机来进行。 |
●maxWait: 最大等待秒数, 单位为 ms, 超过时间会丟出错误信息,-1为无限制;
|
数据库连接池技术:
|
●动态include用jsp:include动作实现 <jsp:include page=included.jsp flush=true />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数; 静态include用include伪码实现,不会检查所含文件的变化,适用于包含静态页面 <%@ include file=included.html %> |
●Name jdbc is not bound in this Context。这种错误是因为根据JNDI名称查找数据源的时候出现错误,可能的错误原因如下:
|
●由于数据源由Tomcat 维护,所以在程序中要获取DataSource对象,需要通过JNDI来获取数据源,不能采用创建一个实例的方式来生成。
|