当前位置 博文首页 > 适己而忘人者,人之所弃;克己而立人者,众之所戴。:知识积累(
实现设计
??????? 现在,让我把每件事情都串起来,实现JCatalog项目。你可以冲资源列表中下载应用程序的完整源代码。
数据库设计
我们为例子应用程序创建指定目录的结构,它包含4个表,如图5:
? ?
?
?
图5 数据结构图
?
类设计
图6图解了JCatalog项目的类图
?
?
?
图6 类图
?
面向接口编程贯穿于整个设计。在表现层,四个bean被使用:ProductBean, ProductListBean, UserBean和 MessageBean。业务逻辑层包含两个服务(CatalogService and UserService)和三个业务对象(Product, Category, and User)。集成层包括两个DAO接口和它们的Hibernate实现。Spring application contexts 包含和管理业务逻辑层和集成层的很多object beans。ServiceLocator使JSF和业务逻辑层结合到一起。
?
Wire everything up
因为这篇文章篇幅的限制,我们只看一个用例。CreateProduct用例示范了怎样将每件事情串起来建造应用程序。深入细节以前,让我们使用一个序列图(图7)示范所有层端到端的整合:
?
?
图7 CreateProduct用例的序列图
?
现在,让我们通过对每一层的介绍讨论如何实现CreateProduct用例的更多细节。
?
表现层
表现层的实现包括创建JSP页面,定义页面导航,创建和配置backing beans,将JSF与业务逻辑层结合。
?
JSP page:createProduct.jsp是创建新产品的页面。它包括UI组件和捆绑这些组件的ProductBean。ValidateItemsRange自定义标签检验用户选择目录的数目。每个新产品至少有一个目录被选择。
?
Page navigation:应用程序的导航定义在应用程序的配置文件里面,faces-navigation.xml。CreateProduct定义的导航规则是:
<navigation-rule>
?? <from-view-id>*</from-view-id>
?? <navigation-case>
????? <from-outcome>createProduct</from-outcome>
?? ???<to-view-id>/createProduct.jsp</to-view-id>
?? </navigation-case>
</navigation-rule>
<navigation-rule>
?? <from-view-id>/createProduct.jsp</from-view-id>
?? <navigation-case>
????? <from-outcome>success</from-outcome>
????? <to-view-id>/uploadImage.jsp</to-view-id>
?? </navigation-case>
?? <navigation-case>
????? <from-outcome>retry</from-outcome>
????? <to-view-id>/createProduct.jsp</to-view-id>
?? </navigation-case>
?? <navigation-case>
????? <from-outcome>cancel</from-outcome>
????? <to-view-id>/productList.jsp</to-view-id>
?? </navigation-case>
</navigation-rule>
?
Backing bean: ProductBean不仅包含了页面中UI组件与数据映射的属性,也包含三个actions:createAction,editAction和deleteAction。这是createAction()方法的代码:
?
public String createAction() {
?? try {
????? Product product = ProductBeanBuilder.createProduct(this);
?
????? //Save the product.
????? this.serviceLocator.getCatalogService().saveProduct(product);
?
????? //Store the current product id inside the session bean.
????? //For the use of image uploader.
????? FacesUtils.getSessionBean().setCurrentProductId(this.id);
?
????? //Remove the productList inside the cache.
????? this.logger.debug("remove ProductListBean from cache");
????? FacesUtils.resetManagedBean(BeanNames.PRODUCT_LIST_BEAN);
?? } catch (DuplicateProductIdException de) {
????? String msg = "Product id already exists";
????? this.logger.info(msg);
????? FacesUtils.addErrorMessage(msg);
?
????? return NavigationResults.RETRY;
?? } catch (Exception e) {
????? String msg = "Could not save product";
????? this.logger.error(msg, e);
????? FacesUtils.addErrorMessage(msg + ": Internal Error");
?
????? return NavigationResults.FAILURE;
?? }
?? String msg = "Product with id of " + this.id + " was created successfully.";
?? this.logger.debug(msg);
?? FacesUtils.addInfoMessage(msg);
?
?? return NavigationResults.SUCCESS;
}
??????? 在这个action里面,基于ProductBean的一个Product业务对象被建立。ServiceLocator查询CatalogService。最后,createProduct的请求被委派给业务逻辑层的CatalogService。
?
Managed-bean declaration: ProductBean必须在JSF的配置资源文件faces-managed-bean.xml中配置:
?
<managed-bean>
?? <description>
????? Backing bean that contains product information.
?? </description>
?? <managed-bean-name>productBean</managed-bean-name>
?? <managed-bean-class>catalog.view.bean.ProductBean</managed-bean-class>
?? <managed-bean-scope>request</managed-bean-scope>???
?? <managed-property>
????? <property-name>id</property-name>
????? <value>#{param.productId}</value>
?? </managed-property>
?? <managed-property>