对天乙社区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();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章