重读Jive之一 Global.jsp
Author: Hfree ( 转贴请注明出处 )
最近重读Jive, 确实是温故知新, 打算写一系列, 虽然网上不乏相关说明, 但把自己的体会写下来, 毕竟是自己的, 或者对别人也是一种帮助, 故有此文, 这是第一篇. Global.jsp
一 ForumFactory, ForumFactoryProxy, DbForumFactory
ForumFactory是抽象工厂, 定义了一系列的abstract方法, 其中只有一个static方法getInstance(), 这正是整个Jive的入口. ForumFactoryProxy是DbForumFactory的代理类,ForumFactoryProxy在其getter方法中, 把相应的DbObject全部封装到DbOjbectProxy中,将相应的代理权限交给相应的代理管理, 从这一点上看来, ForumFactoryProxy是一个Proxy的dispatcher! DbForumFactory是真正与数库据交互的Factory, 整个Jive的控制中心就是此类. DbForumFactory与数据库交互, 而且维护着一个缓存池, 以及包含对各类对象的Manager类. 具体如下.
public DatabaseCacheManager cacheManager;
protected UserManager userManager;
protected DbGroupManager groupManager;
private DbSearchManager searchManager;
private DbFilterManager filterManager;
protected DbPermissionsManager permissionsManager;
protected DbWatchManager watchManager;
protected DbRewardManager rewardManager;
ForumFactory , ForumFactoryProxy, DbFourmFactory 这三个类的关系异常巧妙.
ForumFactory.getinstantce( Authorization ) 根据Authorization创建一个DbFourmFactory, 此处创建的DbfourmFactory使用了Singleton模式. 再者, 当getInstance返回时, 再把此DBForumFactory封装到一个ForumFactoryProxy中, 并传入相应的Authorization, Permission作为参数. 这样, 当user使用getInstance得到的其实是一个FourmFactoryProxy代理, 此代理根据用户的权限, 把用户的操作分发到相应的Proxy.来进处代理处理.
二 Authorization
就我个人来讲, 这一部份使我更深刻的理解Factory模式.这一部分完全可以从整个Jive中独立出来, 你也完全可以把它做为一杯香浓无比的Cofe, 细细品味位.
OK, 回归正题, 这一部份其实包括四个类.Authroization, DbAuthorization, AuthorizationFactory, DbAuthorizationFactory.
按我个人看法, 从这一部份, 其实已经可以看得出Jive设计上的一些特点. 就是工厂模式和接口的大量使用( 可惜这里看不到iterator,cache,和proxy )
接口, 在jive中, 每一个实际的值(其实不完全是值,因为包括了对DB的一系列与该类相关的操作以及对自身field的操作)对象,都有一个接口与其对应, 实际的值对象(暂且这样说)总是以Db开头.其对应的接口总是省去Db二字.像上面,Authorization就是一个接口, 而DbAuthorization就是一个值对象. 工厂也是一样.像DbAuthorizationFactory才是干活的工厂.
OK, 现在开始看一下接口Authorization.Authorization的作用就是获得进入论坛用户的ID,根据这一个ID, 以后可以进行一系列的权限按制. 如果是匿名用户, 默认的ID是-1
public interface Authorization {
public long getUserID();
public boolean isAnonymous();
}
再看一下DbAuthorization
public final class DbAuthorization implements Authorization, Serializable { private long userID;
protected DbAuthorization(long userID) {
this.userID = userID;
}
public long getUserID() {
return userID;
}
public boolean isAnonymous() {
return userID == -1;
}
}
使用接口的好处就不用多说啦.接下来看一下精彩的Factory.
public abstract class AuthorizationFactory {
private static String className =
"com.jivesoftware.forum.database.DbAuthorizationFactory";
private static AuthorizationFactory factory = null;
public static Authorization getAuthorization(String username,
String password) throws UnauthorizedException
{
loadAuthorizationFactory();
return factory.createAuthorization(username, password);
}
public static Authorization getAnonymousAuthorization() {
loadAuthorizationFactory();
return factory.createAnonymousAuthorization();
}
protected abstract Authorization createAuthorization(String username, String password) throws UnauthorizedException;
protected abstract Authorization createAnonymousAuthorization();
private static void loadAuthorizationFactory() {
if (factory == null) {
//Use className as a convenient object to get a lock on.
synchronized(className) {
if (factory == null) {
//See if the classname has been set as a Jive property.
String classNameProp = JiveGlobals.getJiveProperty(
"AuthorizationFactory.className");
if (classNameProp != null) {
className = classNameProp;
}
try {
Class c = Class.forName(className);
factory = (AuthorizationFactory)c.newInstance();
}
catch (Exception e) {
System.err.println("Exception loading class: " + e);
e.printStackTrace();
}
}
}
}
}
}
这里,最精彩的地方有三个!
1, 自然就是loadAuthorizationFactory(),这里,使用了单态模式来创建一个AuthorizationFactory,当然,这里实际上创建的是其子类.使用单态模式,保证了整个jive只有一个全局入口.
2, 良好的扩展性. className默认是DbforumFactory,在类加载的时候, 先查看XML文件, 看用户是否指定了相应的Factory Class,如果有,则用用户的Class ,而不是用默认的DbFourmFactory,这里,使得扩展jive的时候可以在不必改动整个jive源文件的情况下扩展jive.
3, 抽象方法的使用. 这里,注意两个静态方法和两个抽象方法
先看两个抽象方法
createAuthorization 和 createAnonymousAuthorization();这两个方法交由继承AuthorizationFactory的方法来实现.
两个静态方法
public static Authorization getAuthorization(String username,
String password) throws UnauthorizedException
{
loadAuthorizationFactory();
return factory.createAuthorization(username, password);
}
public static Authorization getAnonymousAuthorization() {
loadAuthorizationFactory();
return factory.createAnonymousAuthorization();
}
这两个静态方法经过初始化后, 便把一切具体的实现都交给相应的抽象方法使用, 至于子类是怎样实现的, 无所谓啦. 只要结果是对的就OK啦.
三 相应代码研究
1. Authorization
Authorization authToken = SkinUtils.getUserAuthorization(request, response);
if (authToken == null) {
authToken = AuthorizationFactory.getAnonymousAuthorization();
isGuest=true;
}
2. Factory
<jsp:useBeanid="myEnv" scope="application" class="com.jdon.web.UserEnvFront"/>
myEnv.registeUserInit(authToken);
精彩的地方来啦, 看这一段代码
public void registeUserInit(Authorization authToken){
try{
this.forumFactory = ForumFactory.getInstance(authToken);
this.pageUser=this.forumFactory.getUserManager().getUser(authToken.getUserID());
}catch(Exception ex){ }
}
注意斜体字这一段代码
由刚才分析知道, 这时的forumFactory其实是ForumFactoryProxy,看FourmFactoryProxy.getUserManager()
public UserManager getUserManager() {
UserManager userManager = factory.getUserManager();
return new UserManagerProxy(userManager, authorization, permissions);
}
此处的factory其实就是DbFourmFactory, 刚才说到DBFourmFactory包含对各类对象的Manager类,此处, 把DBForumFactory的DbUserManager封装到一个UserManagerProxy. 再根据Authorization来getUser.
public User getUser(long userID) throws UserNotFoundException {
User user = userManager.getUser(userID);
ForumPermissions userPermissions = user.getPermissions(authorization);
ForumPermissions newPermissions =
new ForumPermissions(permissions, userPermissions);
return new UserProxy(user, authorization, newPermissions);
}
这里, 返回的,其实并非是一个DbUser,而是一个UserProxy
To Be Continue...