虽然对 Spring 不熟悉,又不懂 iBatis ,而且对模式的概念还没有弄清楚,但也硬着头皮去读 Spring 包自带的 Jpetstore 经典 J2EE 例子。
可以肯定, Jpetstore 是按照 MVC 模式设计的。持久化层用 iBatis (这个我不懂,我希望是用 Hibernate ), web 层控制器的 servlet 有两个选择,一个是用 Struts ,另一个是 Spring 的 MVC 。
以下是自己的阅读体会,也许分析不当或描述不清,但也算初步尝试,所以记下来了。
一,分层结构 <?XML:NAMESPACE PREFIX = O /?>
Jpetstore 使用了门面模式、单例模式, DAO 模式。
1. 门面模式
门面接口的实现类: PetStoreImpl
public class PetStoreImpl implements PetStoreFacade, OrderService
{
private AccountDao accountDao;
private CategoryDao categoryDao;
private ProductDao productDao;
private ItemDao itemDao;
private OrderDao orderDao;
// ----------------------------------------------------------------
// Setter methods for dependency injection
// ----------------------------------------------------------------
public void setAccountDao(AccountDao accountDao)
{
this.accountDao = accountDao;
}
// 省略余下的四个setter
// -------------------------------------------------------------------------
// Operation methods, implementing the PetStoreFacade interface
// -------------------------------------------------------------------------
public Account getAccount(String username)
{
return this.accountDao.getAccount(username);
}
public Account getAccount(String username, String password)
{
return this.accountDao.getAccount(username, password);
}
public void insertAccount(Account account)
{
this.accountDao.insertAccount(account);
}
public void updateAccount(Account account)
{
this.accountDao.updateAccount(account);
}
// 省略其它的crud方法
}
暂时先不管 OrderService 这个接口。
PetStoreImpl 的那些 setter 方法正是 spring 的注入方法。
在配置文件中:
< 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 >
2. 单例模式
单例模式中,我们一般把类的构造方法设置为 private ,提供静态工厂方法给外界返回唯一的实例,但在这里,它不是这样做的,因为有了 Spring 。有了 Spring 的 BeanFactory 管理,可以轻易配置实现单例。看看作者的注释。
There is one instance of this class in the JPetStore application. In Spring terminology, it is a "singleton". This means a per-Application Context singleton. The factory creates a single instance; there is no need for a private constructor, static factory method etc as in the traditional implementation of the Singleton Design Pattern.
单例的 PetStoreImpl
在 Struts 当控制器时,它这样做:为整个应用程序编写一个继承自 Action 的 BaseAction 基础类。
public abstract class BaseAction extends Action
{
private PetStoreFacade petStore;
public void setServlet(ActionServlet actionServlet)
{
super.setServlet(actionServlet);
if (actionServlet != null)
{
ServletContext servletContext = actionServlet.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext);
this.petStore = (PetStoreFacade) wac.getBean("petStore");
}
}
protected PetStoreFacade getPetStore()
{
return petStore;
}
}
3.DAO 模式
ORM 工具用 iBatis ,在领域模式层使用了粗粒度对象。下面是 AccountDao 的配置。
< select id ="getAccountByUsername" resultMap ="result">
select
signon.username as userid,
account.email,
account.firstname,
account.lastname,
account.status,
account.addr1,
account.addr2,
account.city,
account.state,
account.zip,
account.country,
account.phone,
profile.langpref,
profile.favcategory,
profile.mylistopt,
profile.banneropt,
bannerdata.bannername
from account, profile, signon, bannerdata
where account.userid = #value#
and signon.username = account.userid
and profile.userid = account.userid
and profile.favcategory = bannerdata.favcategory
</ select >