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

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


現在,讓我們看一下最複雜的一個業務對象,forum,它是一個論壇的核心部分,貼子(其實這個單詞是論壇的意思)當然其關係到的業務邏輯及其它東東也最多了!我們從BEAN開始研究:(右邊爲一條數據庫表的記錄,注意其中有許多Default值)
        private String id;       //主鍵   402881e513bdc8550113bdefb43c0014
private String parentID; //父級ID NULL值
private String mainID;   //MainID 402881e513bdc8550113bdefb43c0014
private long boardID;    //版區ID 2
private String boardName;           java
private int reNum; //回覆數       0
private int face;   //表情        0
private String userID; //用戶ID    4028818208ed006b0108ed020bd50001
private String userName;       webmaster
private String nickName;       webmaster
private String title; //標題   dffdsfds
private String detail;//文件名稱 P_2_402881e513bdc8550113bdefb43c0014.txt
private String sign;//簽名     NULL
private int artSize;//字數     58
private int click;//點擊數     5
private long postTime;//發貼時間 1184302609453
private long lastTime;//最後回覆時間 1184302609453
private String ipAddress;//IP地址   127.0.0.1
private int isNew;//是否是主貼(這個取名有點問題) 1
private long elite;//是否精華   0
private long eliteID;//精華目錄ID 0
private int agree;//贊成    0
private int beAgainst;//反對 1
private int canNotDel;不是水貼標誌 0
private int delSign;//刪除標誌   0 
        private String delUserID;//刪除者   NULL
private String delUserName;   NULL
private long delTime;     0
private String delIP;    NULL
private String amend;//刪除附加信息   NULL
        private String doEliteName;//加入精華者用戶名   NULL
private long doEliteTime;//加入精華時間    0
private int haveAttachFile;//是否有附件   0
private List attachFileName = new ArrayList();//附件文件名列表 NULL
private String lastPostUserName;//最後回覆用戶名 ---
private String lastPostTitle;//最後回覆帖子標題 NULL
private String lastPostNickName;    ---
private long isTop;//置頂標誌   0
private int isLock;//鎖定標誌   0
private int auditing;//審覈標誌   0
        private int auditingAttachFile;//附件審覈標誌 0
private int isVote;//是否投票貼標誌 0
private int isHidden;//是否隱藏貼標誌 0
private int editType;//編輯器類型   0
private String quoteText;//引用文字   NULL
private int postType;//發貼類型    0
private int titleColor;//標題color   5
private int canNotRe;//已經是否回覆標誌         0
private long commend;//推薦標誌            0
private int isHiddenValue;//隱藏貼參數    0
private int userBlog;//加入個人文集標誌   0
private int indexStatus;//索引標誌       0
private int quoteEditType;//引用文字編輯器類型 0
private int emailInform;//通知發信到哪裏(不用) 0
private int msgInform;//消息到誰(不用)    0
private String voteID;//投票ID   NULL
private String tagID;//版區Tag   0 
private String tagName;//版區Tag名稱   NULL
        private int isGuest;//是否遊客發貼     0
private int previewAttach;//附件預覽標誌     1
對於ForumMain-mysql.hbm.xml,
    
我們看下這個另外的hibernate自定義類型類,它與SplitList類似......
而在數據庫中:(請多看看數據庫中的數據)
PRIMARY KEY (`ID`),
UNIQUE KEY `ID` (`ID`),
KEY `MainID` (`MainID`),
KEY `BoardID` (`BoardID`), 
KEY `LastTime` (`LastTime`),
KEY `PostTime` (`PostTime`),
KEY `UserID` (`UserID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
進入到forumservice中,有一大堆方法:(不加javadoc的話應該不會有100個吧!嚇人!)
public Forum saveOrUpdateForum(Forum forum) throws BbscsException;
public Forum saveForum(Forum forum) throws BbscsException;
public Forum updateForum(Forum forum) throws BbscsException;
public Forum findForumByID(String id);
public Forum findForumByID(String id, long bid);//根據ID,Bid取得Forum對象
public long getForumNum(long bid, int isNew, int delSign, int auditing, int auditingAttachFile);//取得帖子數量
public long getForumNum(long bid);//取得正常帖子數量
public long getForumMainNum(long bid);//取得主帖數量
public long getForumDelNum(long bid);//取得已刪除帖子數量
public long getForumAuditingNum(long bid);//取得未審覈帖子數量
public long getForumTopicNum(long bid, String mainID, int delSign, int auditing);//取得同一主題帖子數量
public long getForumTopicNum(long bid, String mainID);//取得一個主題的帖子數量(正常的)
public long getForumTopicDelNum(long bid, String mainID);//取得一個主題已刪除帖子數量
public long getForumTopicAuditingNum(long bid, String mainID);//取得一個主題未審覈帖子數量
public List findForums(long bid, int isNew, int delSign, int auditing, OrderObj[] oo);//取得帖子列表
public PageList findForums(long bid, int isNew, int delSign, int auditing, int auditingAttachFile, OrderObj[] oo,
   Pages pages);
public PageList findForumsMainWWW(long bid, Pages pages);//取得主帖分頁列表(WWW方式,發帖時間排序)
public PageList findForumsMainLastRe(long bid, Pages pages);//取得主帖分頁列表(頂帖方式,回覆時間排序)
public PageList findForumsAll(long bid, Pages pages);//取得正常帖子分頁列表,不分主從
public PageList findForumsDel(long bid, Pages pages);// 取得已刪除帖子分頁列表
public PageList findForumsAuditing(long bid, Pages pages);// 取得未審覈帖子分頁列表
public PageList findForumsTopic(long bid, String mainID, int delSign, int auditing, OrderObj[] oo, Pages pages);//取得同一主題帖子分頁列表
public PageList findForumsTopic(long bid, String mainID, Pages pages);
public List findForumsTopicAll(long bid, String mainID, int delSign, int auditing, OrderObj[] oo);
public List findForumsTopicDel(long bid, String mainID);//取得已刪除同一主題帖子列表
public List findForumsTopicAuditing(long bid, String mainID);取得未審覈同一主題帖子列表
public List findForumsElite(long bid, long elite, long eliteId);取得精華帖列表
public long getSearchNum(long bid, String con, String text, int delSign, int auditing);取得搜索帖子數量
public PageList getSearchList(long bid, String con, String text, int delSign, int auditing, String orderby,
   int ascOrDesc, Pages pages);取得搜索結果分頁列表
public long getSearchNum(long bid, String con, String text);取得搜索帖子數量(不帶條件)
public PageList getSearchList(long bid, String con, String text, Pages pages);
public long getForumOwnerNum(String userID);取得自己的帖子數量
public PageList findForumsOwner(String userID, int isNew, Pages pages);取得自己的帖子分頁列表
public void removeForum(String id, long bid) throws BbscsException;刪除Forum對象
public void removeForum(String id) throws BbscsException;
public void removeForum(Forum forum) throws BbscsException;
public Forum createForum(Forum forum) throws BbscsException;發帖
public Forum createForum(Forum forum, Board board, UserInfo ui, UploadFile uploadFile) throws BbscsException;
public Forum createReForum(Forum forum, Forum mainForum, Board board, UserInfo ui, UploadFile uploadFile,
   boolean isQuote) throws BbscsException;回帖
public Forum createForumUpFile(Forum forum, UploadFile uploadFile) throws BbscsException;
public Forum editForum(Forum forum) throws BbscsException;帖子修改
public long getForumNumCommend(long bid, long commen);
public long getForumNumCommend(long commend);
public PageList findForumsCommend(long bid, long commen, Pages pages);
public PageList findForumsCommend(long commend, Pages pages);
public boolean isReedUser(long bid, String mainID, String userID);
public void delaPost(Forum forum, Board board, UserInfo ui) throws BbscsException;刪除一個帖子
public void savePostElite(Forum forum, UserInfo ui) throws BbscsException;
public void saveForums(List forums) throws BbscsException;
public void saveForumsEliteDel(List forums) throws BbscsException;
public Forum createVoteForum(Forum forum, Board board, Vote vote, UserInfo ui,String voteItem) throws BbscsException;
public long getForumOwnerNum(long bid, String userID, String mainID);摟主帖子數
public PageList findForumsOwner(long bid, String userID, String mainID, Pages pages);只看樓主
public void removeAttachFile(Forum forum, List fileNames) throws BbscsException;刪除附件
public void removeAllAttachFile(Forum forum) throws BbscsException;刪除某個帖子所有附件
public void delForumsNotAuditingAttachFile(List ids) throws BbscsException;刪除未通過審覈的帖子附件
public long getForumNumHotTopic(long bid, int reNum, int click);
public PageList findForumsHotTopic(long bid, int reNum, int click, Pages pages);
public void removeToHistory(long atime) throws BbscsException;
public void delPosts(List forums, Board board) throws BbscsException;
public List findForumsInIds(long bid, List ids);
public List findForumsInIds(List ids);
public void delPostReal(Forum forum) throws BbscsException;
public void delPostsReal(List ids) throws BbscsException;
public void delWastePost(long bid) throws BbscsException;
public PageList findForumsAllManage(long bid, Pages pages);
public void saveForumsResume(List ids, Board board) throws BbscsException;
public void saveForumsAuditingAttachFile(List ids) throws BbscsException;
public long getForumsAuditingAttachFileNum(long bid);
public PageList findForumsAuditingAttachFile(long bid, Pages pages);
public List findForumsTopicAuditingAttachFile(long bid, String mainID);
public void saveForumChangeUser(Forum forum, int[] titleType, int[] values) throws BbscsException;
public void saveForumChangeUser(Forum forum, int titleType, int values) throws BbscsException;
public void createCommendPage(long commend) throws BbscsException;
public void saveForumCommend(int createOrDel, Board board, Forum forum) throws BbscsException;
public List findForumsByIndexStatus(int indexStatus);
public List findForumsAllNew(int num);
public List findForumsAllNewCache(int num);
public PageList findForumsAll(long bid, String tagID, Pages pages);
public PageList findForumsMainWWW(long bid, String tagID, Pages pages);
public PageList findForumsMainLastRe(long bid, String tagID, Pages pages);
public void saveForumBuy(long bid, String postId, Forum f, UserInfo buyFromUi) throws BbscsException;
public long getForumBuyNumByPostId(String postId);
public ForumBuy findForumBuyByPostIdFromId(String postId, String fromId);
public Forum saveEditForum(Forum forum) throws BbscsException;
public void saveMoveForum(Forum forum, Board toboard) throws BbscsException;
public void saveMoveForum(long frombid, String mainid, Board toboard) throws BbscsException;
public String getForumDetail(Forum forum, boolean forcefromfile);
我們進入ForumServiceImp類:
首先它注入了許多DAO和其它服務,如:forumDAO,userInfoDAO,forumUploadFile,sysListObjCache,sysConfig,userInfoFileIO,subscibeFactory,subscibeDAO,boardDAO,subscibeQueue,forumBuyDAO,voteDAO,voteItemDAO,commendDAO,commendFileIO,forumHistoryDAO,forumConfig,postCache....當然,還有logger,真得太嚇人了,太多東東了!
public Forum createForum(Forum forum) throws BbscsException {
Board board = this.getBoardDAO().getBoardByID(forum.getBoardID());//得到版區
UserInfo ui = this.getUserInfoDAO().findUserInfoById(forum.getUserID());//得到用戶信息
return createForum(forum, board, ui, null);//讓別人去完成!
}
@SuppressWarnings("unchecked") //因爲有些非JDK5.0的開源庫如hibernate, 函數返回的一定是List,而不會是List,這時候IDE就會爆出很多warning。用SuppressWarning("unchecked")可以讓IDE安靜一些。
public Forum createForum(Forum forum, Board board, UserInfo ui, UploadFile uploadFile) throws BbscsException {
try {
   if (Constant.POST_STORAGE_MODE == 0) {//貼子存儲方式,其實在web.xml中有設定
    forum = this.getForumDAO().saveOrUpdateForum(forum);
   } else {
    String detail = forum.getDetail();//現在用這種方式
    forum = this.getForumDAO().saveOrUpdateForum(forum);

    String postFileName = "P_" + forum.getBoardID() + "_" + forum.getId() + ".txt";//可見safe文件夾下的post下的....
    File postFile = new File(this.getForumConfig().getForumPath(forum.getBoardID(), forum.getPostTime())
      + postFileName);
    FileUtils.writeStringToFile(postFile, detail, Constant.CHARSET);//寫入文件
    forum.setDetail(postFileName);//而寫入數據庫的只是文件名
   }

   if (uploadFile != null) {
    String fileName = "File_" + forum.getId() + "_" + System.currentTimeMillis()//當前時間 + "."
      + FilenameUtils.getExtension(uploadFile.getFileName());//文件後綴
    String toFilePath = BBSCSUtil.getUpFilePath(forum.getBoardID(), forum.getPostTime());//以前講過的,應該生成safe/upload/...
/**
public static String getUpFilePath(long bid, long adate) {
StringBuffer sb = new StringBuffer();
sb.append(Constant.ROOTPATH);
sb.append(getUpFileWebPath(bid, adate));
File ft = new File(sb.toString());
if (!ft.exists()) {
   ft.mkdirs();
}
return sb.toString();
}

public static String getUpFileWebPath(long bid, long adate) {
StringBuffer sb = new StringBuffer();
sb.append("upload/");
sb.append((bid % 20));
sb.append("/");
sb.append(bid);
sb.append("/");
sb.append(Util.formatDate4(new Date(adate)));
sb.append("/");
return sb.toString();
}
*/
    this.getForumUploadFile().saveUploadFile(toFilePath + fileName, uploadFile, this.getSysConfig());//帖子上傳文件
    forum.setHaveAttachFile(1);//有附件
    forum.getAttachFileName().add(fileName);//List里加入內容!
    if (board.getAuditAttach() == 1) {
     forum.setAuditingAttachFile(1);
    }
   }
   forum.setMainID(forum.getId());
   forum = this.getForumDAO().saveOrUpdateForum(forum);//刷新一下
   if (board.getAuditPost() == 0 && board.getAddUserPostNum() == 1) { // 不需要審覈,並且版區爲增加用戶發帖數量
    ui.setArticleNum(ui.getArticleNum() + 1);
    ui.setExperience(ui.getExperience() + 2); // 發帖增加經驗值2點。
    ui = this.getUserInfoDAO().saveUserInfo(ui);//用戶信息更新
    this.getUserInfoFileIO().writeUserFile(ui);//用戶信息寫入文件!見safe/user
   }
   if (forum.getEmailInform() != 0 || forum.getMsgInform() != 0) {
    if (this.getSubscibeDAO().findSubscibeByPostID(forum.getId(), ui.getId(), forum.getBoardID()) == null) {
     Subscibe subs = this.getSubscibeFactory().getInstance(forum.getBoardID());
     subs.setBoardID(forum.getBoardID());
     subs.setCreateTime(new Date());
     subs.setEmailinform(forum.getEmailInform());
     subs.setMsginform(forum.getMsgInform());
     subs.setNickName(ui.getNickName());
     subs.setPostID(forum.getId());
     subs.setPostTitle(forum.getTitle());
     subs.setUserEmail(ui.getEmail());
     subs.setUserID(ui.getId());
     subs.setUserName(ui.getUserName());
     subs.setUserLocale(ui.getUserLocale());
     this.getSubscibeDAO().saveSubscibe(subs);//訂閱服務!
    }
   }

   this.getSysListObjCache().remove(Constant.FORUM_NEW_CACHE_NAME);//文章Cache,remove方法來自Cache接口!
   return forum;
} catch (Exception ex) {
   logger.error(ex);
   throw new BbscsException(ex);
}
}
我們看下ForumConfig的getForumPath:(注意:forum.getBoardID()--->bid,forum.getPostTime()-->adate)
這個服務類注入的是private String safePath;
public String getSafePath() {
return safePath;
}
public void setSafePath(String safePath) {
this.safePath = safePath;
}
它有兩個方法:getForumPathOld與getForumPath其實完全一樣!555
public String getForumPath(long bid, long adate) {
StringBuffer sb = new StringBuffer();
sb.append(this.getSafePath());
if (!this.getSafePath().endsWith("/")) {
   sb.append("/");
}
sb.append("post/");
sb.append(bid % 20); //bid%20的餘數 2
sb.append("/"); 
sb.append(bid);   //2
sb.append("/");
sb.append(Util.formatDate4(new Date(adate)));//20070713
sb.append("/");
sb.append(adate % 100);//餘數 53
sb.append("/");
File ft = new File(sb.toString());
if (!ft.exists()) {
   ft.mkdirs();
}
return sb.toString();
}
這裏有個Util:來自com.laoer.bbscs.comm包,裏面有許多格式時間的方法:
public static String formatDateTime(Date date) {
SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return outFormat.format(date);
}
public static String formatDate2(Date myDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
String strDate = formatter.format(myDate);
return strDate;
}
        public static String formatDate3(Date myDate) {
SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm");
String strDate = formatter.format(myDate);
return strDate;
}
public static String formatDate4(Date myDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String strDate = formatter.format(myDate);
return strDate;
}//用的是這個囉!
public static String formatDate5(Date myDate) {
String strDate = getYear(myDate) + "-" + getMonth(myDate) + "-" + getDay(myDate);
return strDate;
}
public static String formatDate6(Date myDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String strDate = formatter.format(myDate);
return strDate;
}
而另外一個是文件上傳操作!貼子附件上傳和用戶信息寫入文件兩種:它們都在com.laoer.bbscs.fio中,有三個接口:CommendFileIO,ForumUploadFile,UserInfoFileIO,另外,這個包裏也提供了一個javabean:UploadFile,有兩個上傳文件需要用到的屬性fileName和InputStream類型的inputStream,它們提供了對外實用方法..我們一個一個看它們的實現過程,CommendFileIO是推薦內容,我們曾講過,safe/include/...兩個文件,而本forum用到的是另外兩個:
ForumUploadFile中有
public void saveUploadFile(String toFileName, UploadFile uploadFile, SysConfig sysConfig) throws IOException; //sysConfig用於獲得系統的配置參數!,這裏也用到了UploadFile這個javabean!
public void delUploadFile(Forum f) throws IOException;
public List delUploadFile(Forum f, List fileNames) throws IOException;
public void moveUploadFile(Forum forum, long tobid) throws IOException;
public void delDetailFile(Forum forum) throws IOException;
我們看它的實現,由於實現它是通過spring注入的!

這個類也先使用了forumConfig及其getter/setter!(不過怎麼沒注入呢)我們看其:
public void saveUploadFile(String toFileName, UploadFile uploadFile, SysConfig sysConfig) throws IOException {
OutputStream bos = new FileOutputStream(toFileName);
IOUtils.copy(uploadFile.getInputStream(), bos);
if (sysConfig.isAttachImg(uploadFile.getFileName()) && sysConfig.getReduceAttachImg() == 1) {
   ImgUtil.reduceImg(toFileName, toFileName + Constant.IMG_SMALL_FILEPREFIX, sysConfig
     .getReduceAttachImgSize(), sysConfig.getReduceAttachImgSize(),1);//縮微圖的生成,同目錄內!public static String IMG_SMALL_FILEPREFIX = "_Small";
}
---------->
public boolean isAttachImg(String fileName) {
return FilenameUtils.isExtension(fileName, getAttachImgTypes());
}
public String[] getAttachImgTypes() {
String[] types = getAttachImgType().split(","); 
if (types == null || types.length == 0) { //提供默認值!
   types = new String[3];
   types[0] = "gif";
   types[1] = "jpg";
   types[2] = "jpeg";
}
return types;
}
public String getAttachImgType() {
return this.getStringValue("AttachImgType");
}
public int getReduceAttachImg() {
return this.getIntValue("ReduceAttachImg", 1);
}
是圖片且系統允許生成!
public int getReduceAttachImgSize() {
return this.getIntValue("ReduceAttachImgSize", 200);
}//長寬都用這個
注意我們將繼續深入下去:
FilenameUtils是org.apache.common.io下的!而ImgUtil.reduceImg則是com.laoer.bbscs.comm包裏的工具類:(這個類就只有一個方法),我們摘入主要的一段:
public static void reduceImg(String imgsrc, String imgdist, int widthdist, int heightdist, int benchmark) {

// int benchmark說明:0,長寬哪個長,以哪個爲標準;1,以寬爲基準;2,以高爲基準
try {
   File srcfile = new File(imgsrc);
   if (!srcfile.exists()) {
    return;
   }
   Image src = javax.imageio.ImageIO.read(srcfile);
   int width = src.getWidth(null);
   int height = src.getHeight(null);

   if (width <= widthdist && height <= heightdist) {
    // SysUtil.cpoyFile(imgsrc, imgdist);
    FileUtils.copyFile(new File(imgsrc), new File(imgdist));
    return;
   }
// 寬度除以高度的比例
   float wh = (float) width / (float) height;
if(benchmark==0) {
...
}
if (benchmark == 1) {
    float tmp_heigth = (float) widthdist / wh;
    BufferedImage tag = new BufferedImage(widthdist, (int) tmp_heigth, BufferedImage.TYPE_INT_RGB);
    tag.getGraphics().drawImage(src, 0, 0, widthdist, (int) tmp_heigth, null);
    FileOutputStream out = new FileOutputStream(imgdist);
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
    encoder.encode(tag);
    out.close();
   }
...主要還是BufferedImage和JPEGCodec.createJPEGEncoder!
對於ForumUploadFileImp中的其它方法我們在用到的時候在來考慮之.
好,我們看看UserInfoFileIO的writeUserInfo(ui),對於這個文件的效果見:safe/user目錄下!我們首先注入的是userConfig和sysConfig兩個配置服務!下面是某用戶文件中的內容:
402881e513bdc8550113bdf70a1b0019|1184303089000|1184303117000|0|0|0|0|100|0|0|0|0|-|本機地址|
用戶ID|註冊時間|登錄時間|文章數|精華文章數|用戶頭銜|用戶生命值(不一定)|積分|......|社區幣|是否有相片|(有的話,圖片名,無 爲"-")|(有的話,用戶來自)|
我們看其中的一段代碼:
if (StringUtils.isBlank(userInfo.getUserFrom())) {
   sb.append("-");
} else {
   sb.append(userInfo.getUserFrom());
}
sb.append("|");
File usrfile = new File(this.getUserConfig().getUserFilePath(userInfo.getId()) + Constant.USER_PROFILE);//public static final String USER_PROFILE = "UserProFile.txt";
FileUtils.writeStringToFile(usrfile, sb.toString(), Constant.CHARSET);
//關於userConfig其實與sysConfig和ForumConfig類似,提供的是簡單的配置方法:
注入了safePath:(以前講過,這裏重複一次)
public String getUserFilePath(String userID) {
StringBuffer sb = new StringBuffer();
int num = Math.abs(userID.hashCode());
sb.append(this.getSafePath());
if (!this.getSafePath().endsWith("/")) {
   sb.append("/");
}
sb.append("user/");
sb.append(num % 100);
sb.append("/");
sb.append(userID);
sb.append("/");
File ft = new File(sb.toString());
if (!ft.exists()) {
   ft.mkdirs();
}
return sb.toString();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章