站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2EE 专题Put JSF to work 3

Put JSF to work 3

摘要:
三,设计的实现
现在我们看看如何将所有的东西连接起来,实现JCatalog。你可以下载全部的源代码。
http://www.javaworld.com/javaworld/jw-07-2004/jsf/jw-0719-jsf.zip

数据库设计
我们为示例应用创建了一个名为Catalog的schema,它由4个表组成,如下图所示:
IMG ../upload/article/a200491145527.gif[/IMG]
类设计
下图是JCatalog的class图
IMG ../upload/article/200491145551.gif[/IMG]
面向接口的编程贯穿整个设计。在表示层,4个backing bean被使用:ProductBean, ProductListBean, UserBean,和MessageBean。业务逻辑层包含2个业务服务(CatalogService和UserService)和3个业务对象(Product, Category, User)。集成层包含2个DAO接口以及它们的Hibernate实现。Spring的application context连接和管理位于业务逻辑层和集成层的大部分对象bean。ServiceLocator将JSF和业务逻辑层结合起来。

将所有东西连接起来
由于文章篇幅所限,我们只分析一个use case。CreateProduct这个use case将向我们展示如何连接所有东西,创建应用程序。在我们深入细节之前,我们使用一个sequence图来示范所有层的集成:
IMG ../upload/article/200491145718.gif[/IMG]
现在我们来走一遍所有层,讨论如何实现CreateProduct的细节。
表示层
表示层的实现包括创建JSP页面,定义页面导航,创建和配置backing bean,以及结合JSF和业务逻辑层。
l JSP页面:createProduct.jsp是创建新产品的页面。它包含UI组件以及将组件连接到ProductBean。ValidateItemsRange这个自定义标签验证用户选择的种类数目。最后对于每一个新产品应该至少一个种类被选择。
l 页面导航(page navigateon):应用程序的导航定义在应用的配置文件faces-navigation.xml中。CreateProduct的导航规则为:


*

createProduct
/createProduct.jsp



/createProduct.jsp

success
/uploadImage.jsp


retry
/createProduct.jsp


cancel
/productList.jsp



l Backing bean:ProductBean不仅仅包含对应于页面上UI组件的属性,还包括了三个action: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中,一个Product业务对象(BO)基于ProductBean的属性而创建。ServiceLocator查找CatalogService。最后createProduct请求被代理给业务逻辑层的CatalogService。

l Managed-bean声明:ProductBean必须在JSF配置文件faces-managed-bean.xml中配置



Backing bean that contains product information.

productBean
catalog.view.bean.ProductBean
request

id
#{param.productId}


serviceLocator
#{serviceLocatorBean}



ProductBean别设置为request范围,这就意味着如果JSP页面中有引用到ProductBean,那么JSF就会为每一个request创建一个新的ProductBean。被管理的属性ID就会用request的参数productId来组装。JSF会从request得到parameter,然后把值设置给managed property。

l 表示层和业务逻辑层之间的连接:ServiceLocator抽象了查找service的逻辑。在示例中,ServiceLocator定义成一个接口。ServiceLocatorBean作为一个JSF managed bean实现了ServiceLocator接口,它从Spring的application context寻找service:

ServletContext context = FacesUtils.getServletContext();
this.appContext =
WebApplicationContextUtils.getRequiredWebApplicationContext(context);
this.catalogService =
(CatalogService)this.lookupService(CATALOG_SERVICE_BEAN_NAME);
this.userService = (UserService)this.lookupService(USER_SERVICE_BEAN_NAME);

ServiceLocator在BaseBean中作为一个属性而定义。继承自BaseBean的这些managed bean都可以通过它查找服务,并且,JSF的managed bean机制能够将ServiceLocator的具体实现连接给这些managed bean。

业务逻辑层
这一层的任务有:定义业务对象(BO),创建service接口以及它们的实现,使用Spring连接它们。(这里和后面我用了“连接”这个词,英文是wire,意思就是对象A中有对象B的属性,将一个特定的B对象指定给对象A,这也就是IoC容器做的事情)
l 业务对象(BO):因为需要Hibernate提供持久化,所以Product和Category这些业务对象需要为他们所有的字段提供getter/setter方法。
l 业务服务(Business service):CatalogService接口定义了所有与catalog管理相关的服务:

public interface CatalogService {
public Product saveProduct(Product product) throws CatalogException;
public void updateProduct(Product product) throws CatalogException;
public void deleteProduct(Product product) throws CatalogException;
public Product getProduct(String productId) throws CatalogException;
public Category getCategory(String categoryId) throws CatalogException;
public List getAllProducts() throws CatalogException;
public List getAllCategories() throws CatalogException;
}

CachedCatalogaServiceImpl是服务接口的实现,它包含了一个CatalogDao对象的setter方法。Spring会帮助我们完成CachedCatalogServiceImpl和CatalogDao对象的连接。因为我们仅仅是针对接口编码,我们不想与实现紧紧地结合。
l Spring配置:下面是CatalogService的Spring配置: