Spring学习笔记二(2006.1.4)

来源:互联网 发布:v2视频软件下载 编辑:程序博客网 时间:2024/04/30 09:09

Spring学习笔记二(2006.1.4)

1,配置文件的配置头
<?xml version="1.0" encoding="UTF-8"?>

<!--
  - Application context definition for JPetStore's business layer.
  - Contains bean references to the transaction manager and to the DAOs in
  - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
这样写才对

2,配置文件可以使用多个属性文件
<!-- Configurer that replaces ${...} placeholders with values from properties files -->
 <!-- (in this case, mail and JDBC related properties) -->
 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
   <list>
    <value>WEB-INF/mail.properties</value>
    <value>WEB-INF/jdbc.properties</value>
   </list>
  </property>
 </bean>
类是框架的。
里面包含两个属性文件,属性文件里都是“key=value”这种形式的。这样配置文件里就可以使用属性文件里的key,使用方法
${key},这样转移出属性设置,维护起来比较方便。

3,定义Validator供web层使用,自定义类。
<bean id="accountValidator" class="org.springframework.samples.jpetstore.domain.logic.AccountValidator"/>
类里面使用了ValidatorUtils系统类来进行处理。

4,服务层的定义。
 PetStoreImpl定义在配置文件中,是自己的类。
 所有的DAO都是它的属性,注意,DAO是interface,而不是class.
 PetStoreImpl中定义了所有的DAO接口作为属性,定义了他们的set方法,但是没有定义get方法。
 这样所有的业务操作就可以不用管DAO是如何实现的了,而只管使用这个PetStoreImpl就好了。

 DAO都是接口这种做法与平时开发不一样,我以前使用hibernate生成工具生成的dao都是默认好的实现类。
 而此处的DAO却都是接口。他们的实现方法是这样的:
 interface PetStoreFacade { } //定义所有的业务方法。
 interface AccountDao{} //定义所有帐户的业务方法。
 interface CategoryDao{} //定义类别的业务方法。
 interface ProductDao{} //定义产品的业务方法。
 。。。其他DAO接口,定义自己的业务方法。
 class PetStoreImpl implements PetStoreFacade //这个类就是一个javabean,操作的都是接口。
 //定义所有DAO接口当作自己的属性。
 //实现set方法
 //实现PetStoreFacade 定义的业务接口,实现的时候调用DAO接口的方法。

 如果是我自己,那么就会定义IDAO当作接口,因为hibernate插件自动生成dao类,容易混淆。
 
5,配置文件中定义dataSource
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
 </bean>
 可见,可以直接使用properties中的key。另外可以将数据库操作弄成另外一个配置文件。只要在web.xml中设置好就可以了,
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/dataAccessContext-local.xml  /WEB-INF/applicationContext.xml
  </param-value>
 </context-param>

6,配置文件中定义事务管理
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
 </bean>
 使用了数据源作为属性。

7,dao具体实现类。
 JPetStore使用ibatis作为ORM层。所以dao类的定义也都使用了ibatis。
 PetStoreImpl五个接口接受五个实现了对应接口的实现类。这里的实现类,
<bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
  <property name="accountDao" ref="accountDao"/>
  <property name="categoryDao" ref="categoryDao"/>
  <property name="productDao" ref="productDao"/>
  <property name="itemDao" ref="itemDao"/>
  <property name="orderDao" ref="orderDao"/>
 </bean>
 <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
  <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>
 实现类,使用ibatis。在配置文件中对英。
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao{
 //实现了业务接口,继承了ibatis基本类。
 }


8,ibatis基础类。
    <!-- SqlMap setup for iBATIS Database Layer -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
  <property name="dataSource" ref="dataSource"/>
 </bean>
 dao实现类都由他作属性。
    <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
  <property name="sqlMapClient" ref="sqlMapClient"/>
 </bean>

9,我竟然找不到action对应的mapping在什么地方定义的。
后来找到了是petstore-servlet.xml,by default defined in "{servlet-name}-servlet.xml"...
<!--
   - Spring web MVC servlet that dispatches requests to registered handlers.
   - Has its own application context, by default defined in "{servlet-name}-servlet.xml",
   - i.e. "petstore-servlet.xml" in this case.
   -
   - A web app can contain any number of such servlets.
   - Note that this web app has a shared root application context, serving as parent
   - of all DispatcherServlet contexts.
   -->
 <servlet>
  <servlet-name>petstore</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
 </servlet>
 原来是根据servlet名字命名影射文件的。
 影射文件和配置文件的结构完全一致,也是beans开头的。主要是web层的url影射,
 <beans>
 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/WEB-INF/jsp/spring/"/>
  <property name="suffix" value=".jsp"/>
 </bean>
 ....
 </beans>
 ok,现在把petstore-servlet.xml也放到SpringIDE里察看。

10,配置文件petstore-servlet.xml
 viewResolver,定义了一个表现层的基本配置,此bean名字固定。
 属性viewClass使用了jstl技术。
 <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/WEB-INF/jsp/spring/"/>
  <property name="suffix" value=".jsp"/>
 </bean>

11,配置文件petstore-servlet.xml
 defaultHandlerMapping使用默认的BeanNameUrl影射,具体不太明白。
 <bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

12,配置文件petstore-servlet.xml
 定义*.do
<bean name="/shop/addItemToCart.do" class="org.springframework.samples.jpetstore.web.spring.AddItemToCartController">
  <property name="petStore" ref="petStore"/>
 </bean>
 属性petStore是在applicationContext.xml里定义的,看来这里也可以使用其他<beans>定义的bean。

13,*.do类研究
 实现了Controller,接口public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
 有一个属性petstore,是一个接口PetStoreFacade,包括全部业务逻辑接口。
 
14,首页index
 在mapping文件里定义了系统ParameterizableViewController,相当于forwardAction。
 <bean name="/shop/index.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
  <property name="viewName" value="index"/>
 </bean>
 而首页里大量使用了jstl语言,最重要的地方是所有 a href=, action=,处都使用了<c:url value="/xxxx"/>
 这样的定义,这样换域名或者设置虚拟目录名,就会运行正常了。例如,
<center>
<a href="<c:url value="/shop/viewCategory.do?categoryId=FISH"/>">
<img border="0" src="../images/sm_fish.gif" /></a>
<img border="0" src="../images/separator.gif" />
<a href="<c:url value="/shop/viewCategory.do?categoryId=DOGS"/>">
<img border="0" src="../images/sm_dogs.gif" /></a>
<img border="0" src="../images/separator.gif" />
<a href="<c:url value="/shop/viewCategory.do?categoryId=REPTILES"/>">
<img border="0" src="../images/sm_reptiles.gif" /></a>
<img border="0" src="../images/separator.gif" />
<a href="<c:url value="/shop/viewCategory.do?categoryId=CATS"/>">
<img border="0" src="../images/sm_cats.gif" /></a>
<img border="0" src="../images/separator.gif" />
<a href="<c:url value="/shop/viewCategory.do?categoryId=BIRDS"/>">
<img border="0" src="../images/sm_birds.gif" /></a>
</center>

15, 进入首页后点左边的链接都指向同一个viewCategory.do,
 <bean name="/shop/viewCategory.do" class="org.springframework.samples.jpetstore.web.spring.ViewCategoryController">
  <property name="petStore" ref="petStore"/>
 </bean>
 类研究:
 ViewCategoryController implement Controller
 里面只使用了PetStore实现类的方法,并没有DAO对象。只有Domain对象。
 很好,把主要的和业务相关的东西都在Controller中展现出来了,其他辅助的东西都被隐藏了,使得Controller非常简洁。
 另外,在业务PetStoreImp类中,使用了DAO,这样就使得后台程序也开始分层了。
 
 |--层Controller及使用的daomain对象 /// 第一层
            |----层PetStoreFacade 接口及他的实现类PetStoreImpl //第二层
   |-------- 层DAO接口 ,DAO接口实现类,//第三层
    |------------实现类中使用的ORM类  //第四层
 层次非常的分明。
    
 daomain符合javabean规范,并且有些javabean还有自己的public方法。大多数javabean没有必要有public方法。

16, 点击分类后,显示分类中的items,点items可以进入viewProduct.do?productId=xxx,来观看产品。
 <bean name="/shop/viewProduct.do" class="org.springframework.samples.jpetstore.web.spring.ViewProductController">
  <property name="petStore" ref="petStore"/>
 </bean>
 这是一个翻页功能的Controller。
 没弄清楚成功后跳转到什么地方? return new ModelAndView("Product", model);没有理解。
 
public class ModelAndViewextends ObjectHolder for both Model and View in the web MVC framework. Note that these are entirely distinct. This class merely holds both to make it possible for a controller to return both model and view in a single return value.

Class to represent a model and view returned by a handler used by a DispatcherServlet. The view can take the form of a reference to a View object, or a String view name which will need to be resolved by a ViewResolver object. The model is a Map, allowing the use of multiple data objects keyed by name.

public ModelAndView(String viewName,
                    Map model)Creates new ModelAndView given a view name and a model.

Parameters:
viewName - name of the View to render, to be resolved by the DispatcherServlet
model - Map of model names (Strings) to model objects (Objects). Model entries may not be null, but the model Map may be null if there is no model data.

这样viewName就知道了,返回给DispatcherServerlet,再根据viewResolver中的定义,就可以知道是/jsp/spring/Product.jsp了。
也就是说,viewName也就是jsp文件的名字。

17,ModelAndView传递给页面之后页面如何使用其中的数据 ?
 Controller传递的model是一个map,一共传递了两个key-value对。
 model.put("itemList", itemList);
 model.put("product", product);
 ok,看jsp页面。<c:out value="${product.name}"/>
<c:forEach var="item" items="${itemList.pageList}">
  <tr bgcolor="#FFFF88">
  <td><b>
  <a href="<c:url value="/shop/viewItem.do"><c:param name="itemId" value="${item.itemId}"/></c:url>">
    <c:out value="${item.itemId}"/>
  </a></b></td>
  <td><c:out value="${item.productId}"/></td>
  <td>
    <c:out value="${item.attribute1}"/>
    <c:out value="${item.attribute2}"/>
    <c:out value="${item.attribute3}"/>
    <c:out value="${item.attribute4}"/>
    <c:out value="${item.attribute5}"/>
    <c:out value="${product.name}"/>
  </td>
  <td><fmt:formatNumber value="${item.listPrice}" pattern="$#,##0.00"/></td>
  <td><a href="<c:url value="/shop/addItemToCart.do"><c:param name="workingItemId" value="${item.itemId}"/></c:url>">
    <img border="0" src="../images/button_add_to_cart.gif"/>
  </a></td>
  </tr>
</c:forEach>
原来是把key当作attributename放到了request范围内了。这样就ok了,model的key实际上就是request的属性名字啊。
 model的value就是request的属性值。jstl真正发挥简洁的威力了。

18,viewProduct.do里还有一个翻页的逻辑,没看明白怎么回事。


19,viewProduct.do之后再点链接就进入了viewItem.do,相对简单。不用看了。
PagedListHolder itemList = new PagedListHolder(this.petStore.getItemListByProduct(productId));
java.lang.Object
  org.springframework.beans.support.PagedListHolder
PagedListHolder is a simple state holder for handling lists of objects, separating them into pages. Page numbering starts with 0.
Constructor Summary
PagedListHolder()
          Create a new holder instance.
PagedListHolder(List source)
          Create a new holder instance with the given source list, starting with a default sort definition (with "toggleAscendingOnProperty" activated).
PagedListHolder(List source, SortDefinition sort)
          Create a new holder instance with the given source list.
 boolean isFirstPage()
          Return if the current page is the first one.
 boolean isLastPage()
          Return if the current page is the last one.
 void nextPage()
          Switch to next page.
 void previousPage()
          Switch to previous page.
 可以排序。可以设置页数。
这个类明显是把所有的结果一次性查询出来后,设定每页个数,之后再把当页数据发送给页面。虽然不是把全部数据发送给页面由页面来分页,但是一次把全部数据都查询出来的做法只适合少量数据。如果多量数据几万条的话同时查出来,存放到session,用不了多久服务器的内存就被耗光了。
还不太清楚放到session中的对象什么时候被晴空,好像只有在退出的时候才晴空一次。

20,addItemToCart.do?workingItemId=EST-11,代码很清楚。有两点主意:
 一,webUtil org.springframework.web.util.webUtil提供了有限的几个方法。
 二,return new ModelAndView("Cart", "cart", cart); // Cart.jsp , key ,value
 因为不熟悉ibatis所以ORM层的代码都没有阅读,也就是PetsoreImpl实现类的各个DAO实例都没有阅读。

    removeItemFromCart.do?workingItemId=EST-11 也是同一页面上的购物车操作 ,过于简单。略
 updateCartQuantities.do //更新的是内存中的数据,所以没有什么技术。

21,checkout.do有一点需要注意,别的Controller没有传入viewName。它传了,
 <bean name="/shop/checkout.do" class="org.springframework.samples.jpetstore.web.spring.ViewCartController">
  <property name="successView" value="Checkout"/>
 </bean>
 Controller中:
 private String successView;

 public void setSuccessView(String successView) {
  this.successView = successView;
 }
 最后return new ModelAndView(this.successView, "cart", cart);

原创粉丝点击