對天乙社區bbscs8實現的詳細分析四

此文爲轉載:http://www.diybl.com/course/1_web/webjs/2007113/82989.html


接下來,看下BookMarkFactory接口,是個工廠接口.它只有一個一個公有方法, public BookMark getInstance(String userId);其實現爲BookMarkFactoryImp,它產生一個BookMark bean,不過是同步的! public synchronized BookMark getInstance(String userId) {
    return new BookMark();//返回的是com.laoer.bbscs.bean.BookMark
}
另有一個實現:BookMarksFactoryImp:(有個私有屬性:int modNum及其get/set方法)
public synchronized BookMark getInstance(String userId) {
    try {
      return (BookMark) Class.forName(BBSCSUtil.getClassName("BookMark", userId, this.getModNum())).
          newInstance();
    }
    catch (ClassNotFoundException ex) {
      logger.error(ex);
      return null;
    }
    catch (IllegalAccessException ex) {
      logger.error(ex);
      return null;
    }
    catch (InstantiationException ex) {
      logger.error(ex);
      return null;
    }

}
這裏用到了com.laoer.bbscs.common包中的工具類:BBSCSUtil.java
public static String getClassName(String className, String userID) {
int num = Math.abs(userID.hashCode());
className = Constant.BEANPERFIX + className + (num % 10);//public static String BEANPERFIX = "com.laoer.bbscs.bean.";
return className;
}

public static String getClassName(String className, String userID, int modnum) {
int num = Math.abs(userID.hashCode());
className = Constant.BEANPERFIX + className + (num % modnum);
return className; //應該返回是就是com.laoer.bbscs.bean.BookMark0~~~9之間的class了
}

public static String getClassName(String className, long bid, int modnum) {
className = Constant.BEANPERFIX + className + (bid % modnum);
return className;
}

而BookMarkService則完全負責這個業務!先看BEAN:
private String id;
private String userID;
private String bookMarkName;
private String url;
private String alt;
private int isShare;
private Date createTime;
//timestamp類型!

看service接口中的方法:
public BookMark findBookMarkByIDUserID(String id, String userID);
public BookMark saveBookMark(BookMark bm) throws BbscsException;
public long getBookMarkNumByUserID(String userID);
public PageList findBookMarks(String userID, Pages pages);
public PageList findBookMarksByUserIDShare(String userID, int isShare, Pages pages);
public void removeBookMark(BookMark bm) throws BbscsException;
public void removeBookMarkByIDUserID(String id, String userID) throws BbscsException;
我們看實現層:先注入BookMarkDAO對象.特別的是:
public PageList findBookMarks(String userID, Pages pages) {
    PageList pl = new PageList();
    if (pages.getTotalNum() == -1) {
      pages.setTotalNum(this.getBookMarkDAO().getBookMarkNumByUserID(userID));
    }
    pages.executeCount();

    List l = this.getBookMarkDAO().findBookMarks(userID, pages.getSpage(), pages.getPerPageNum()); //DAO層方法,Service層沒有
    pl.setObjectList(l);
    pl.setPages(pages);
    return pl;
}
和
public PageList findBookMarksByUserIDShare(String userID, int isShare, Pages pages) {
    PageList pl = new PageList();
    if (pages.getTotalNum() == -1) {
      pages.setTotalNum(this.getBookMarkDAO().getBookMarkNumByUserIDShare(userID, isShare));
    }
    pages.executeCount();

    List l = this.getBookMarkDAO().findBookMarksByUserIDShare(userID, isShare, pages.getSpage(),
        pages.getPerPageNum());//DAO層方法,Service層沒有
    pl.setObjectList(l);
    pl.setPages(pages);
    return pl;
}
這裏用到了2個分頁功能的類:它們都在com.laoer.bbscs.service.web包中,一個Page一個PageList;
兩個都是javaBEAN,不過可以帶少量的業務邏輯處理功能.先看Pages:
int page=1;//頁號
long totalNum=-1;//記錄總數
int perPageNum=1;//每頁顯示記錄數
int allPage=1;//總頁數
int cpage=1;//當前頁
int spage=1;//開始記錄數
String fileName="";
boolean useUrlRewirte=false;
public Pages(int page, long totalNum, int perPageNum) {
this.page = page;
this.totalNum = totalNum;
this.perPageNum = perPageNum;
this.executeCount();
}

public void executeCount() {
this.allPage = (int) Math.ceil((this.totalNum + this.perPageNum - 1) / this.perPageNum);
int intPage = this.page;
if (intPage > this.allPage) { // pages == 0
   this.cpage = 1;
} else {
   this.cpage = intPage;
}
this.spage = (this.cpage - 1) * this.perPageNum;
}
而PageList包括一個pages和List類型的objectList 及其set/get方法

public PageList() {
}
我們回到findBookMarks,先得到totalNum,再執行executeCount(),設置其值後,用this.getBookMarkDAO().findBookMark(userID,pages.getspage,pages.getPerPageNum())得到後賦給PageList的objectList和page對象.這樣,就可以給web層用List去遍歷了,當然也要配合page.
我們直接進入DAO接口層:(其實它完全爲service層服務,整體上差不多不過有些方法卻不一樣)
public BookMark saveBookMark(BookMark bm);
public BookMark findBookMarkByIDUserID(String id,String userID);
public long getBookMarkNumByUserID(String userID);
public List findBookMark(final String userID,final int firstResult,final int maxResults);
public long getBookMarkNumByUserIDShare(String userID, int isShare);
public List findBookMarksByUserIDShare(final String userID, final int isShare, final int firstResult,final int maxResults);//final int類型,方法體裏不可改變
public void removeBookMark(BookMark bm);
public void removeBookMarkByIDUserID(String id, String userID);
看它的實現BookMarkHibernateDAO.java:(private static final String類型)
private static final String LOAD_BY_ID_USERID = "from BookMark where id = ? and userID = ?";
private static final String GET_NUM_BY_USERID = "select count(*) from BookMark where userID = ?";
private static final String LOADS_BY_USERID =
      "from BookMark where userID = ? order by createTime desc";
private static final String REMOVE_BY_ID_USERID =
      "delete from BookMark where id = ? and userID = ?";
private static final String GET_NUM_BY_USERID_ISSHARE =
      "select count(*) from BookMark where userID = ? and isShare = ?";
private static final String LOADS_BY_USERID_ISSHARE =
      "from BookMark where userID = ? and isShare = ? order by createTime desc";
我們看其中的一些方法(根據UserID取得BookMark數量)
public long getBookMarkNumByUserID(String userID) {
    List l = this.getHibernateTemplate().find(GET_NUM_BY_USERID, userID);
    if (l == null || l.isEmpty()) {
      return 0;
    }
    else {
      return ( (Long) l.get(0)).longValue();
    }
}
另外一個方法:(根據UserID和isShare取得BookMark列表)
public List findBookMarksByUserIDShare(final String userID, final int isShare,
                                         final int firstResult,
                                         final int maxResults) {
    return getHibernateTemplate().executeFind(new HibernateCallback() {
      public Object doInHibernate(Session s) throws HibernateException, SQLException {
        Query query = s.createQuery(LOADS_BY_USERID_ISSHARE);
        query.setString(0, userID);
        query.setInteger(1, isShare);
        query.setFirstResult(firstResult);
        query.setMaxResults(maxResults);

        List list = query.list();
        return list;
      }
    });
}

我們看下CommendService:(推薦)

先看bean:
private String id;
private long boardID;//版區ID
private String boardName;
private String postID;
private String postMainID;
private String userID;
private String userName;
private long commendBoardID;//推薦頂層版區ID
private int commendTop;//是否推薦到首頁
private String title;//帖子標題
private long createTime;//創建時間

CommendServie接口中有以下主要方法:
public Commend saveCommend(Commend commend) throws BbscsException;
public int getCommendNumByCommendBoardID(long commendBoardID);
public PageList findCommendsByCommendBoardID(long commendBoardID, Pages pages);
public int getCommendNumByCommendTop(int commendTop);
public void removeCommend(long commendBoardID, List ids) throws BbscsException;
public void createCommendTopFile(int num) throws BbscsException;
public List findCommendsByCommendTopCache(int commendTop, int num);
而其實現層大多方法給DAO去實現之.下面爲其中的幾個方法:
public PageList findCommendsByCommendBoardID(long commendBoardID, Pages pages) {
PageList pl = new PageList();
if (pages.getTotalNum() == -1) {
   pages.setTotalNum(this.getCommendDAO().getCommendNumByCommendBoardID(commendBoardID));//DAO實現
}
pages.executeCount();
List l = this.getCommendDAO().findCommendsByCommendBoardID(commendBoardID, pages.getSpage(),
    pages.getPerPageNum());
pl.setObjectList(l);
pl.setPages(pages);
return pl;
}
下面是從頂層版區刪除推薦....
public void removeCommend(long commendBoardID, List ids) throws BbscsException {
List l = this.getCommendDAO().findCommendsInIds(ids);
try {
   for (int i = 0; i < l.size(); i++) {
    Commend c = (Commend) l.get(i);//取出
    Forum f = this.getForumDAO().findForumByID(c.getPostID(), c.getBoardID());
    f.setCommend(0);//修改是否推薦標誌
    this.getForumDAO().saveOrUpdateForum(f);
    this.getCommendDAO().removeCommend(c);
   }
   List commendList = this.getCommendDAO().findCommendsByCommendBoardID(commendBoardID, 0, 10);
   this.getCommendFileIO().saveCommendInReadPageFile(commendBoardID, commendList);//寫入推薦文件中!!!!
} catch (Exception ex) {
   logger.error(ex);
   throw new BbscsException(ex);
}
}
public void createCommendTopFile(int num) throws BbscsException {
List l = this.getCommendDAO().findCommendsByCommendTop(0, 0, num);
try {
   this.getCommendFileIO().saveCommendInReadPageFile(0, l);
} catch (IOException ex) {
   logger.error(ex);
   throw new BbscsException(ex);
}
}
而findCommendByCommendTopCache爲從SysListObjCache中獲得10條推薦信息!
public List findCommendsByCommendTopCache(int commendTop, int num) {
List l = (List) this.getSysListObjCache().get(Constant.COMMEND_CACHE_NAME);//public static final String COMMEND_CACHE_NAME = "CommendSceipt";
if (l == null) {
   l = this.getCommendDAO().findCommendsByCommendTop(commendTop, 0, num);
   this.getSysListObjCache().add(Constant.COMMEND_CACHE_NAME, l);
}
return l;
}
我們來分析下commendFileIO:

由於service實現層用的是fio接口層,實際注入的卻是fil.imp裏面的東西:
public interface CommendFileIO {
public void saveCommendInReadPageFile(long commendid, List commendList) throws IOException;//只有一個方法
}
看其實現,裏面用了BBSCSUtilTextUtils工具類,它其實寫了2個文件!!!前一個在貼子顯示時用到,後一個可見www.laoer.com斑主推薦部分!
public void saveCommendInReadPageFile(long commendid, List commendList) throws IOException {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < commendList.size(); i++) {
      Commend commend = (Commend) commendList.get(i);
      sb.append("·");
      sb.append("");
      sb.append(TextUtils.htmlEncode(commend.getTitle()));
      sb.append("
"); } File commendFile = new File(BBSCSUtil.getIncludePath() + "Commend_" + commendid + ".html"); FileUtils.writeStringToFile(commendFile, sb.toString(), Constant.CHARSET); commendFile = null; sb = null; sb = new StringBuffer(); //int counter = 0; for (int i = 0; i < commendList.size(); i++) { Commend c = (Commend) commendList.get(i); sb.append(""); sb.append(""); sb.append(""); sb.append(c.getTitle()); sb.append(""); sb.append("["); sb.append(c.getBoardName()); sb.append("]"); sb.append(""); sb.append(""); } commendFile = new File(BBSCSUtil.getIncludePath() + "ForumCover_Commend_" + commendid + ".html"); FileUtils.writeStringToFile(commendFile, sb.toString(), Constant.CHARSET); } BBSCSUtil中的方法:(前面的一些的分析) getUserWebFilePath()返回一個本地的用戶資料文件路徑,絕對的(加了ROOTPATH) getUserWebPath()相對的... getWebRealPath()返回URL(一級) getUpFilePath和getUpFileWebPath類似與上getUserWebFilePath getIncludePath()返回本地的路徑/include/ 對於BBSCSUtil.getActionMappingURLWithoutPrefix("forum?action=index&bid=" + c.getBoardID()),用了工具類封裝了真實的網頁後綴! public static String getActionMappingURLWithoutPrefix(String action) { //action="forum?action=index&bid=" + c.getBoardID() StringBuffer value = new StringBuffer(); // Use our servlet mapping, if one is specified String servletMapping = Constant.SERVLET_MAPPING;//*.bbscs if (servletMapping != null) { String queryString = null; int question = action.indexOf("?");//6 if (question >= 0) { queryString = action.substring(question);//"action=index&bid="+c.getBoardID() } String actionMapping = getActionMappingNameWithoutPrefix(action);//forum if (servletMapping.startsWith("*.")) { value.append(actionMapping);//forum value.append(servletMapping.substring(1));//forum.bbscs } else if (servletMapping.endsWith("/*")) { value.append(servletMapping.substring(0, servletMapping.length() - 2)); value.append(actionMapping); } else if (servletMapping.equals("/")) { value.append(actionMapping); } if (queryString != null) { value.append(queryString);//value="forum.bbscs?action=index&bid="+c.getBoardID() } } return (value.toString()); } public static String getActionMappingNameWithoutPrefix(String action) { String value = action;////action="forum?action=index&bid=" + c.getBoardID() int question = action.indexOf("?");//6 if (question >= 0) { value = value.substring(0, question);//value="forum" } int slash = value.lastIndexOf("/");//slash=0;如果是main/forum.bbscs的話slash=4 int period = value.lastIndexOf(".");//period=0;.....................period=9 if ((period >= 0) && (period > slash)) { value = value.substring(0, period);//value=0....perod main/forum } return (value); //forum } 接下來,我們看CommendDAO,這個接口中提供瞭如下方法: public Commend saveCommend(Commend commend); public Commend findCommendByID(String id); public Commend findCommendByPostID(String postID); public int getCommendNumByCommendBoardID(long commendBoardID); public List findCommendsByCommendBoardID(long commendBoardID, final int firstResult, final int maxResults); public int getCommendNumByCommendTop(int commendTop); public List findCommendsByCommendTop(int commendTop, final int firstResult, final int maxResults); public List findCommendsInIds(List ids); public void removeCommend(Commend commend); public void removeCommend(String postID); 看實現: private static final String LOADS_IN_IDS = "from Commend where id in (:ids)"; public List findCommendsInIds(final List ids) { return getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session s) throws HibernateException, SQLException { Query query = s.createQuery(LOADS_IN_IDS); query.setParameterList("ids", ids);//List!!!final List ids List list = query.list(); return list; } }); } ConfigService用於配置服務:(它有兩個屬性:id,confContext其hbm.xml 有public Config updateConfig(Config config) throws BbscsException; public Config findConfigByID(String id); public List findConfigs(); public void updateAllConfigs(HashMap configs) throws BbscsException; 其實現: public void updateAllConfigs(HashMap configs) throws BbscsException { Iterator it = configs.values().iterator(); try { while (it.hasNext()) { Config config = (Config) it.next(); this.getConfigDAO().updateConfig(config); } } catch (Exception ex) { logger.error(ex); throw new BbscsException(ex); } } 由於比較簡單,直接PASS: public List findConfigs() { return this.getHibernateTemplate().find(LOAD_ALL); } 看EliteService,其對應的BEAN有以下屬性: private Long id; private long boardID;//版區ID private long parentID; //父ID private List parentIDs;//你級ID列表,用","分開 private String eliteName;//精華目錄名稱 private String createUser;//創建者 private long eliteTime;//創建時間 private int orders;//序 //自動增長 //自定義類型 進行方法中: public Elite createElite(Elite elite) throws BbscsException; public Elite saveElite(Elite elite) throws BbscsException; public Elite findEliteByID(long id); public List findElitesByPidBid(long pid, long bid); public void removeElite(Elite elite) throws BbscsException; public List findElitesInIds(List ids); 它首先注入了DAO:eliteDAO和forumDAO;需要注意的是: public Elite createElite(Elite elite) throws BbscsException { Elite pElite = this.getEliteDAO().findEliteByID(elite.getParentID()); if (pElite != null) { List pElites = new ArrayList(); pElites.addAll(pElite.getParentIDs()); pElites.add(pElite.getId()); elite.setParentIDs(pElites);//構造一下其ParentIDs } try { return this.getEliteDAO().saveElite(elite); } catch (Exception ex) { logger.error(ex); throw new BbscsException(ex); } } public void removeElite(Elite elite) throws BbscsException { try { List l = this.getForumDAO().findForumsElite(elite.getBoardID(), elite.getBoardID(), elite.getId().longValue()); for (int i = 0; i < l.size(); i++) { Forum forum = (Forum) l.get(i); forum.setEliteID(elite.getParentID());//改變之 this.getForumDAO().saveOrUpdateForum(forum); } this.getEliteDAO().removeElite(elite); } catch (Exception ex) { logger.error(ex); throw new BbscsException(ex); } } 我們直接看DAO: public Elite saveElite(Elite elite); public Elite findEliteByID(long id); public List findElitesByPidBid(long pid, long bid); public void removeElite(Elite elite); public List findElitesInIds(List ids); 對於具體地實現我們PASS.
發佈了76 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章