欢迎使用我的 在线工具

小D

读历史、看小说、写程序都是我所爱。技术不好,头脑不灵光,靠的是兴趣。
随笔 - 35, 文章 - 25, 评论 - 13, 引用 - 0
数据加载中……

petclinic阅读笔记

1 Web 程序的设计原则:

The following items should be noted regarding the web application implementation design:

  1. all JSP's are stored under /WEB-INF/jsp except for index.jsp which is the configured "welcome-file"
  2. The use of JSP technology in the application is not exposed to the user, i.e., the end user never sees a URL ending in ".jsp".
  3. By convention, all URL's in the application ending in ".do" are handled by web application controllers. Static html pages ending in ".html", such as Javadoc, will be directly served to the end user.
  4. The results of all form entries are handled using browser round trip redirection to minimize possible end user confusion.
  5. All pages are extremely simple JSP implementations that focus only on providing the necessary functionality.
  6. References to Entity objects are passed around in the application by supplying the object's ID as a request parameter.

下面的几项应该在 Web 程序的设计实现中被关注:

1.      除了处理 index.jsp 这个被被配置为欢迎页面的页面外,所有的 JSP 页面放置在 /WEB-INF/jsp 下面。

2.      这样的使用 JSP 技术是不被用户接受的,所以,最终用户永远也不应该看到 URL ".jsp " 结尾。

3.      根据协议,在程序的所有 URL 都以 ".do" 结尾以便于被 web 程序 controllers 处理。静态 html 页面以 ".html" 结尾,例如 Javadoc, 将直接对最终用户服务。

4.      对于被浏览器处理的所有的表单实体对象的结果的往返传递应该尽可能地降低用户理解的混乱。

5.      所有的页面尽可能的简单, JSP 的实现集中在仅仅提供必须的功能。

6.      对于实体对象的引用应该是将对象 ID 作为 request 参数在应用程序中的传递来提供的。

 

2 JNDI Dababase connections pools 技术

我使用 PetClinic Tutorial 中介绍的方法根本不能实现。我想应该是 Tutorial 中介绍的不全面或者是我有什么地方不正确,这里先留着,等以后能上网后在搞定,后面使用 Tomcat 推荐的方式来实现。

context.xml 中作如下配置:

<Resource name="jdbc/petclinicMYSQL" auth="Container" type="javax.sql.DataSource" maxActive="50"

maxIdle="10" maxWait="10000" removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"

      driverClassName="org.gjt.mm.mysql.Driver" username="pc" password="pc"

      url="jdbc:mysql://localhost:3306/petclinic?autoReconnect=true"/>

 

web.xml 中作如下配置:

              <resource-ref>

              <res-ref-name>jdbc/petclinicMYSQL</res-ref-name>

              <res-type>javax.sql.DataSource</res-type>

              <res-auth>Container</res-auth>

       </resource-ref>

声明那个你将要请求的使用的 JNDI 的名称。

 

3 Spring2.0 几个 annotation 支持

1 )、 @Service

org.springframework.stereotype.Service      

指明一个被注解的类是一个“ Service ( 例如 . 一个业务服务门面 )

这个 annotation 当作一种特性的 @Component 被使用,允许 classpath 扫描自动探测。

2 )、 @ManagedResource

org.springframework.jmx.export.annotation.ManagedResource

JDK 1.5+ 类库级别的 annotaion 用来指明注册一个使用了 JMX 服务器和 ManagedResource 属性通信的类的实例。

 

4 Spring2.0 JDBC 支持

1 )、 org.springframework.jdbc.core.support.JdbcDaoSupport

DAO 的便利的父类。需要一个 javax.sql.DataSource ,通过 getJdbcTemplate() 方法提供一个 org.springframework.jdbc.core.JdbcTemplate 给子类。

这个基础类主要供 JdbcTemplate 使用,但是它也可以在一个直接连接或者使用 org.springframework.jdbc.object 包中的类操作对象。

这个类也就是给实现 DAO 的提供了一个模版。

 

       2 )、 org.springframework.jdbc.object.MappingSqlQuery

一个有用的查询工具类其具体的子类必须实现 abstract mapRow(ResultSet ,int) 方法去将 JDBCResultSet 的每一行转换为一个对象。

通过减少参数和上下文信息简化了 MappingSqlQueryWithParameters API 。绝大多数的子类不用关心参数。如果你不使用上下文相关的信息,这个子类将取代 MappingSqlQueryWithParameters

org.springframework.jdbc.object.RdbmsOperation.compile() 编译这个 Query 语句,忽略以后的编译。做的其实就是设置 preparedStatementFactory 的参数,为该查询语句的查询做好准备。必须在构造方法中编译,否则无法生成指定的 PreparedStatement

 

3 )、 org.springframework.jdbc.core.SqlParameter

代表一个 SQL 参数定义的对象。

参数可以是匿名的,如 ”name” 属性可以是 null 。但是,所有的参数必须一个根据 java.sql.Types 定义了 SQL 类型。

 

4 )、 org.springframework.jdbc.object.SqlUpdate

可重用的操作对象代表了一个 SQL undate

这个类提供一个许多的 update 方法,就类似于 query 对象中的 execute 方法。

这个类是具体的。尽管它可以被子类化 ( 例如去增加一个自定义的 update 方法 ) ,但是能很容易的通过设置 SQL 语句和声明参数来参数化。

就像所有装载在 Spring 框架中的 RdbmsOperation 类一样, SqlQuery 实例在其初始化完成后是线程安全的。准确的说,在它们通过它们的 setter 方法构造和配置后,它们能在多线程中安全使用。

       5 )、 HibernateTemplate merge 方法。

       注意: Hibernate3 merge 操作不能在当前的 HibernateSession 中再次组合 entity 。作为替代,它将总是拷贝状态到一个注册了的这个 entity 的代表。新的 entity 它将会注册一个拷贝,但是将不会更新传递进来的对象的 id 。为了仍然更新原始的 object id ,我们需要在我们的 SessionFactory 中注册一个 Spring IdTransferringMergeEventListener

典型的使用情况是,将 IdTransferringMergeEventListener 作为一个 entry ,使用“ merge ”键值,配置到 LocalSessionFactoryBean ”eventListeners” Map 中。

5 Spring2.5 Annotation 支持

         1 )、 @Repository
org.springframework.stereotype.Repository

       指出一个注解的类是“ Repository (仓库)”(或者“ DAO ”)。

       一个这样注解的类是能够使用 Spring org.springframework.dao.DataAccessException 处理异常合格的类了。注解过的类也能够作为整个程序体系的工具类使用,例如 aspects 等等。

       Spring2.5 为止,这个 annotation 也能够作为一个特殊的 @Component 来使用。允许使注解过的类通过 classpath 扫描来自动装配。

2 )、 @Transactional
org.springframework.transaction.annotation.Transactional

       在一个方法或类上描述事务属性。

       这个注解类型一般能够直接与 Spring org.springframework.transaction.interceptor.RuleBasedTransactionAttribute 相比较,而且实际上 AnnotationTransactionAttributeSource 也能够直接将数据转换成接下的类,因此 Spring 的事务支持代码不必要去了解 annotations 。假如没有 exception 相关的规则,它将会当作 org.springframework.transaction.interceptor.DefaultTransactionAttribute (在运行时异常发生的时候回滚)。

3 )、 @Autowired

org.springframework.beans.factory.annotation.Autowired

         标记一个构造器,域, setter 方法或者配置方法能够被 Spring 依赖注入的工具自动绑定。

       任何给定的类最多只有一个构造器可能带有该注解,标志这个类作为一个 Spring bean 使用时,标志这个构造器自动绑定。这样的构造器不必一定是 public 的。

       域在一个 bean 构造器调用后,所有的配置方法被调用前,被注入。这样的配置域不必一定是 public 的。

       配置方法可以拥有任意的名字和任意数量的参数;那些参数中的每一个将在 Spring 容器中匹配的 bean 自动绑定。 Bean 属性 setter 方法是一个特殊的配置方法。这样的配置方法不必一定是 public 的。

       在多参方法的情况下,‘ required ’属性可应用到所有的参数中。

       在一个依赖 java.util.Collection 或者 java.util.Map 的情况下,这个容器将自动绑定所有的 bean 并匹配声明的值类型。当 Map 的情况下, key 必须是 String 类型的并且将会解析成相应的 bean 的名字。

       请考虑阅读 AutowiredAnnotationBeanPostProcessor ( 默认,检查这个 annotation 是否存在 ) javadoc

4 )、 @ Controller

org.springframework.stereotype.Controller

       指出一个注解的泪是一个“ Controller ( 一个 Web 控制器 )

       这个 annotation 作为一个特殊的 @Component 使用,允许实现类通过 classpath 扫描自动发现。典型的使用是,结合基于 org.springframework.web.bind.annotation.RequestMapping 注解的注解的处理器方法。

5 )、 @RequestMapping

org.springframework.web.bind.annotation.RequestMapping

       映射 web 请求到特殊处理器类及(或)处理方法。在 Servlet Portlet 环境中提供一致的方式,通过语义结合具体的环境。

       注意:方法级别的映射仅仅允许缩小类级别的映射表达。 HTTP paths/portlet modes 需要唯一地映射到特殊的处理 bean ,所有给定的 path/mode 仅允许被映射成一个特殊的处理器 bean (不会延伸过多处理器 bean )。强烈的推荐将彼此相关的处理方法放到相同 bean 中。使用该注解注解过的处理方法被允许拥有灵活的签名。它们可以拥有任意排列的如下类型的参数 ( 除了验证结果外,如果需要,它们需要验证相关的 command 对象正确 )  

·        请求及 / 或响应对象( Servlet API 或者 Portlet API )。你可以选择任何特殊的 request/response 类型,例如 javax.servletRequest/javax.servlet.http.HttpServletRequest 或者 javax.portlet.PortletRequest / javax.portlet.ActionRequest / javax.portlet.RenderRequest 。注意 Portlet 情况下,一个明确的声明为 action / render 参数也能用作映射特殊的 request 类型成一个处理器方法。(以防,没有其它给定的 action render 请求的区别的信息)。

·          Session 对象( Servlet API 或者 Portlet API ): javax.servlet.http.HttpSession 或者 javax.portlet.PortletSession 。一个这样类型的参数将强迫相应类型的 session 的存在。结果,这样一个参数将不能使 null 。注意 session 的访问可能不是线程安全的,特别是一个 servlet 环境:考虑改换 ”synchronizeOnSession” 标记为 ”true” 假如多重请求容许同时访问一个 session

·        略。

 

6 )、 @SessionAttributes

org.springframework.web.bind.annotation.SessionAttributes

       指出一个特殊的处理器使用的 session 属性的注解。这个将列出将被透明的存储在 session 或者一些对话存储中的 model 属性的名字,作为 form-backing bean 使用。在类级别使用中,应用为注解过的处理类操作的 model 属性。

       注意:使用这个 annotation Session 属性是满足一个特殊处理器 model 属性需要的。

透明的存储在一个对话 session 中。那些属性将会在完成处理器的需要后从 session 中删除。因此,在一个特殊的处理器对话期间内,使用这个工具操作被期望临时存储在 session 中的会话属性。

       要用到永久的 session 属性,例如,一个用户鉴定对象,请使用传统的 session.setAttribute 方法代替。可选择地,考虑使用 org.springframework.web.context.request.WebRequest 接口的属性管理功能。

6 Spring2.5 新加的 schema tag

       1 )、 Context tags 用来处理涉及到 plumbing ApplicationContext 配置。也就是说,不是通常的对于终端用户重要的 bean ,而是是处理许多 Spring 中日常事务的更重要的 Bean ,例如 BeanfactoryPostProcessor 。下面是使 context 命名空间对你起作用的正确的 schema 片段。

						
								               <?xml version="1.0" encoding="UTF-8"?>
				

<beans xmlns="http://www.springframework.org/schema/beans"

                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                  xmlns:context="http://www.springframework.org/schema/context"

                  xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

 

<!-- <bean/> definitions here -->

                                                                      注意:该 tag Spring2.5 中才起作用。

 

<context:property-placeholder location="classpath:jdbc.properties"/>    这个元素通过指定的属性文件的地址,使替代标识 ${…}placeholders 得以活动。这个元素是一个方便的机制,它通过建立一个 PropertyPlaceholderConfigurer 给你提供一个方便的机制;如果你需要更多的控制 PropertyPlaceholderConfigurer ,那么你自己建一个吧。

<context:annotation-config/> 使 Spring 基础组织中的能够自动侦查 bean 类的各种 annotations Spring @Required @Autowired ,还有 JSR 250 规范中的 @PostConstruct @PreDestroy @Resource (如果可用的话)还有 JPA @PersistenceContext @PersistenceUnit (如果可用的话)。作为选择,你可以选择使用单独的 BeanPostProcessors 来处理那些 annotations

注意:这个元素不能激活对 Spring @Transactional annotation 的处理。请使用 <tx:annotation-driven/> 元素来达到目的。

<context:component-scan base-package="org.springframework.samples.petclinic.web"/>

       这个元素能够扫描并自动侦测到指定的包中的标识为 @Components 的类。            -

总结

petclinic Spring 组织给出的 Spring 使用的示例程序。

         该程序未将领域对象和其它的业务类没严格分开(没有明确的分包来标识),而且 Business 层和持久层更是根本混合一起,不是很好的实践,因为持久层的类,竟然是从 Business 层的类继承而来,比如 SimpleJdbcClinic HibernateClinic 都是继承至 Clinic 这个核心业务的 DAO ( 很显然混合就是从这里开始了 )

在手册中提到,该程序主要是用来展示各种的 Spring 数据访问策略,而仅带有极其简单的业务逻辑,所有为了开发效率将业务层和持久层混合一起。很显然,这里如果我们改变业务方法的话,就需要几乎修改所有的持久化类了。

我想更好的方式是将持久类对象 Bean 注入到业务类中。因为组合永远优于继承,并且如果使用 Spring 进行依赖注入的话会更优良。

使用 Spring MVC 框架,这是一个很优良的框架,比 Struts1.X 要强很多。

使用了 Spring JMX 支持 API JMX 是一个基于 RMI JNDI Java 管理扩展 API

使用了 Spring 的声明式事务管理 API

使用 apache DBCP 数据库连接池技术。

petclinic2.5 版中,使用了 annotation 方式进行各种 Spring 配置。 Annotation 方式虽然提高了学习成本,但是无疑是比描述文档更优的策略,因为它减少了程序员的编写描述文件成本,而且能提供编译器的检查,程序员不用再去编写可能使我们头脑炸掉的 XML 描述文档。

Spring AOP 支持,虽然这个程序中使用了几个很无聊的切面。

 

 

posted on 2009-11-04 21:15 vagasnail 阅读(783) 评论(0)  编辑  收藏 所属分类: Java Web


只有注册用户登录后才能发表评论。


网站导航: