版塊列表 1(個請求)javascript
ForumAction.list()css
顯示單個版塊(主題列表) 1html
ForumAction.show()java
------瀏覽器
發新帖 2dom
TopicAction.addUI()eclipse
TopicAction.add()jsp
顯示單個主題(主帖+回帖列表) 1編輯器
TopicAction.show()ide
------
回帖 2
ReplyAction.addUI()
ReplyAction.add()
步驟:建立Actionà寫裏面的方法(方法名,返回值) à建立頁面à配置(Action註釋和struts.xml)à建立serviceà配置(ServiceImpl註釋和在BaseAction中注入service) à寫具體的Action方法和service方法à套用靜態頁面
1.先實現版塊列表功能:
(這裏ForumAction和ForumManageAction公用service)
ForumAction:
import cn.itcast.oa.base.BaseAction; import cn.itcast.oa.domain.Forum; @Controller @Scope("prototype") public class ForumAction extends BaseAction<Forum>{
/** 版塊列表 */ public String list() throws Exception { List<Forum> forumList = forumService.findAll(); ActionContext.getContext().put("forumList", forumList); return "list"; }
/** 顯示單個版塊(主題列表) */ public String show() throws Exception { return "show"; } } |
TopicAction:
@Controller @Scope("prototype") public class TopicAction extends BaseAction<Topic>{
/** 顯示單個主題 */ public String show() throws Exception { return "show"; }
/** 發新帖頁面*/ public String addUI() throws Exception { return "addUI"; }
/** 發新帖 */ public String add() throws Exception { return "toShow"; //轉到當前這個 新主題的頁面 } } |
ReplyAction:
@Controller @Scope("prototype") public class ReplyAction extends BaseAction<Reply>{
/** 發表回覆頁面 */ public String addUI() throws Exception { return "addUI"; }
/** 發表回覆 */ public String add() throws Exception { return "toTopicShow"; //轉到當前回覆所屬的主題顯示頁面 } } |
(ForumAction對應的)list.jsp:
<div class="ForumPageTableBorder" style="margin-top: 25px;"> <s:iterator value="forumList"> <table width="100%" border="0" cellspacing="0" cellpadding="0">
<!--表頭--> <tr align="center" valign="middle"> <td colspan="3" class="ForumPageTableTitleLeft">版塊</td> <td width="80" class="ForumPageTableTitle">主題數</td> <td width="80" class="ForumPageTableTitle">文章數</td> <td width="270" class="ForumPageTableTitle">最後發表的主題</td> </tr> <tr height="1" class="ForumPageTableTitleLine"><td colspan="9"></td></tr> <tr height="3"><td colspan="9"></td></tr>
<!--版面列表--> <tbody class="dataContainer" datakey="forumList"> <tr height="78" align="center" class="template"> <td width="3"></td> <td width="75" class="ForumPageTableDataLine"> <img src="${pageContext.request.contextPath}/style/images/forumpage3.gif" /> </td> <td class="ForumPageTableDataLine"> <ul class="ForumPageTopicUl"> <li class="ForumPageTopic"> <s:a cssClass="ForumPageTopic" action="forum_show?id=%{id}">${name}</s:a></li> <li class="ForumPageTopicMemo">${description}</li> </ul> </td> <td class="ForumPageTableDataLine"><b>${topicCount}</b></td> <td class="ForumPageTableDataLine"><b>${articleCount}</b></td> <td class="ForumPageTableDataLine"> <ul class="ForumPageTopicUl"> <li><font color="#444444">┌ 主題:</font> <s:a cssClass="ForumTitle" action="topic_show?id=%{lastTopic.id }">${lastTopic.title}</s:a> </li> <li><font color="#444444">├ 做者:</font> ${lastTopic.author.name}</li> <li><font color="#444444">└ 時間:</font> <s:date name="lastTopic.postTime" format="yyyy年MM月dd日 HH:mm:ss"/></li> </ul> </td> <td width="3"></td> </tr> </tbody> <!-- 版面列表結束 -->
<tr height="3"><td colspan="9"></td></tr> </table> </s:iterator> </div> |
Struts.xml:
<!-- 論壇:版塊相關 --> <action name="forum_*" class="forumAction" method="{1}"> <result name="list">/WEB-INF/jsp/forumAction/list.jsp</result> <result name="show">/WEB-INF/jsp/forumAction/show.jsp</result> </action>
<!-- 論壇:主題相關 --> <action name="topic_*" class="topicAction" method="{1}"> <result name="show">/WEB-INF/jsp/topicAction/show.jsp</result> <result name="addUI">/WEB-INF/jsp/topicAction/addUI.jsp</result> <result name="toShow" type="redirectAction">topic_show?id=${id}</result> </action>
<!-- 論壇:回覆相關 --> <action name="reply_*" class="replyAction" method="{1}"> <result name="addUI">/WEB-INF/jsp/replyAction/addUI.jsp</result> <result name="toTopicShow" type="redirectAction">topic_show?id=${id}</result> </action> |
效果:
2.再實現單個版塊(主題列表)功能:(暫時不作分頁)
ForumAction:
@Controller @Scope("prototype") public class ForumAction extends BaseAction<Forum>{
/** 版塊列表 */ public String list() throws Exception { List<Forum> forumList = forumService.findAll(); ActionContext.getContext().put("forumList", forumList); return "list"; }
/** 顯示單個版塊(主題列表) */ public String show() throws Exception { //準備數據:forum Forum forum = forumService.getById(model.getId()); ActionContext.getContext().put("forum", forum);
//準備數據:topicList List<Topic> topicList = topicService.findByForum(forum); ActionContext.getContext().put("topicList", topicList); return "show"; } } |
topicServiceImpl:
@Service @Transactional @SuppressWarnings("unchecked") public class TopicServiceImpl extends DaoSupportImpl<Topic> implements TopicService{
/** * 查詢指定版塊的主題列表,最新狀態的排到前面,置頂帖排到最前面 */ public List<Topic> findByForum(Forum forum) { return getSession().createQuery(// "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc")// .setParameter(0, forum)// .list(); } } |
其中Topic.java是這樣的:
/** * 實體:主貼 * @author Tan * */ public class Topic extends Article{
/** 普通貼 */ public static final int TYPE_NORMAL = 0; /** 精品貼 */ public static final int TYPE_BEST = 1; /** 置頂貼 */ public static final int TYPE_TOP = 2;
private String title; //標題 private int type; //類型 private int replyCount; //回覆數量 private Date lastUpdateTime; //最後文章的發表時間
private Forum forum; //版塊 主貼與版塊:多對一 private Set<Reply> replies = new HashSet<Reply>(); //回覆 主貼與回覆:多對一 private Reply lastReply; //最後回覆 …… } |
Topic還繼承了Article.java:
/** * 實體:文章 * @author Tan * */ public abstract class Article {
private Long id; private String content; //內容(TEXT類型) private Date postTime; //發表時間 private String ipAddr; //ip地址
private User author; //做者 …… |
需求頁面是這樣的:
ForumAction中的show.jsp:
<!-- 標題顯示 --> <div id="Title_bar"> <div id="Title_bar_Head"> <div id="Title_Head"></div> <div id="Title"><!--頁面標題--> <img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/>【${forum.name }】中的主題列表 </div> <div id="Title_End"></div> </div> </div>
<div id="MainArea"> <div id="PageHead"></div> <center> <div class="ItemBlock_Title1" style="width: 98%;"> <font class="MenuPoint"> > </font> <s:a action="forum_list">論壇</s:a> <font class="MenuPoint"> > </font> ${forum.name } <span style="margin-left:30px;"><a href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"> <img align="absmiddle" src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png"/></a> </span> </div>
<div class="ForumPageTableBorder"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <!--表頭--> <tr align="center" valign="middle"> <td width="3" class="ForumPageTableTitleLeft"> <img border="0" width="1" height="1" src="${pageContext.request.contextPath}/style/images/blank.gif" /> </td> <td width="50" class="ForumPageTableTitle"><!--狀態/圖標--> </td> <td class="ForumPageTableTitle">主題</td> <td width="130" class="ForumPageTableTitle">做者</td> <td width="100" class="ForumPageTableTitle">回覆數</td> <td width="130" class="ForumPageTableTitle">最後回覆</td> <td width="3" class="ForumPageTableTitleRight"> <img border="0" width="1" height="1" src="${pageContext.request.contextPath}/style/images/blank.gif" /> </td> </tr> <tr height="1" class="ForumPageTableTitleLine"><td colspan="8"></td></tr> <tr height=3><td colspan=8></td></tr>
<!--主題列表--> <tbody class="dataContainer" datakey="topicList"> <s:iterator value="topicList"> <tr height="35" id="d0" class="template"> <td></td> <td class="ForumTopicPageDataLine" align="center"><img src="${pageContext.request.contextPath}/style/images/topicType_${topic.type}.gif" /></td> <td class="Topic"><s:a cssClass="Default" action="topic_show?id=%{id}">${title}</s:a></td> <td class="ForumTopicPageDataLine"> <ul class="ForumPageTopicUl"> <li class="Author">{author.name}</li> <li class="CreateTime"><s:date name="postTime" format="yyyy年MM月dd日 HH:mm:ss"/> </li> </ul> </td> <td class="ForumTopicPageDataLine Reply" align="center"><b>${replyCount}</b></td> <td class="ForumTopicPageDataLine"> <ul class="ForumPageTopicUl"> <li class="Author">${lastReply.author.name }</li> <li class="CreateTime"><s:date name="lastReply.postTime" format="yyyy年MM月dd日 HH:mm:ss"/></li> </ul> </td> <td></td> </tr> </s:iterator> </tbody> <!--主題列表結束--> |
效果頁面:
以前已經實現了版塊列表和單個版塊展現(主題列表)的功能,由於尚未數據,因此主題展現的功能暫且不作,先作主題添加的功能(發新帖).
添加頁面:
發新帖的請求是從版塊的單個版塊展現(主題列表)發出的:
還要修改一下ForumAction對應的show.jsp中的連接地址:
<div class="ItemBlock_Title1" style="width: 98%;"> <font class="MenuPoint"> > </font> <s:a action="forum_list">論壇</s:a> <font class="MenuPoint"> > </font> ${forum.name } <span style="margin-left:30px;"> <s:a action="topic_addUI?forumId=%{#forum.id }"> <img align="absmiddle" src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png"/> </s:a> </span> </div> |
這裏要將forum的id傳遞給TopicAction.雖然本頁面是ForumAction對應的show.jsp頁面,但由於此連接要轉到TopicAction,而此id並非Topic的id,因此要寫成forumId,毫不能寫成Id. forumId.%{#forum.id}這是OGNL表達式,加#是由於在ForumAction,forum被put進了map域中.
Forum forum = forumService.getById(model.getId()); ActionContext.getContext().put("forum", forum); |
相應的,在TopicAction中要用屬性驅動的方式封裝這個參數
@Controller @Scope("prototype") public class TopicAction extends BaseAction<Topic>{
private Long forumId;
/** 顯示單個主題 */ public String show() throws Exception { return "show"; }
/** 發新帖頁面*/ public String addUI() throws Exception { //準備數據:forum Forum forum = forumService.getById(forumId); ActionContext.getContext().put("forum", forum); return "addUI"; }
/** 發新帖 */ public String add() throws Exception { return "toShow"; //轉到當前這個 新主題的頁面 } //----------------------------------- public Long getForumId() { return forumId; }
public void setForumId(Long forumId) { this.forumId = forumId; } } |
TopicAction對應的add UI.jsp:
…… <!--顯示錶單內容--> <div id="MainArea"> <s:form action="topic_add" cssStyle="margin: 0; padding: 0;"> <s:hidden name="forumId"></s:hidden> <div id="PageHead"></div> <center> <div class="ItemBlock_Title1"> <div width=85% style="float:left"> <font class="MenuPoint"> > </font> <s:a action="forum_list">論壇</s:a> <font class="MenuPoint"> > </font> <s:a action="forum_show?id=%{#forum.id}">${forum.name}</s:a> <font class="MenuPoint"> >> </font> 發表新主題 </div> </div> <div class="ItemBlockBorder"> <table border="0" cellspacing="1" cellpadding="1" width="100%" id="InputArea"> <tr> <td class="InputAreaBg" height="30"><div class="InputTitle">標題</div></td> <td class="InputAreaBg"><div class="InputContent"> <s:textfield name="title" cssClass="InputStyle" cssStyle="width:100%"/></div> </td> </tr> <tr height="240"> <td class="InputAreaBg"><div class="InputTitle">內容</div></td> <td class="InputAreaBg"><div class="InputContent"><s:textarea name="content" cssStyle="width:600px;height:200px"></s:textarea></div></td> </tr> <tr height="30"> <td class="InputAreaBg" colspan="2" align="center"> <input type="image" src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" style="margin-right:15px;"/> <a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/style/blue/images/button/goBack.png"/></a> </td> </tr> </table> </div> </center> </s:form> …… |
同理,這裏要將forum的id傳遞給ForumAction對應的show(),雖然本頁面是TopicAction對應的addUI頁面,但由於此連接要轉到ForumAction,而此id這好是forum的id,因此寫成id便可,不用再寫成forumId了. %{#forum.id}這是OGNL表達式,加#是由於在TopicAction中forum被put進了map域中.
Forum forum = forumService.getById(forumId); ActionContext.getContext().put("forum", forum); |
在發表新主題的同時,版塊的一些屬性也會受到影響,因此還要維護版塊的某些屬性.
特殊屬性的說明
Forum |
topicCount |
主題數量 |
articleCount |
文章數量(主題+回覆) |
|
lastTopic |
最後發表的主題 |
|
Topic |
replyCount |
回覆數量 |
lastReply |
最後發表的回覆 |
|
lastUpdateTime |
最後更新時間(主題發表的時間或最後回覆的時間) |
特殊屬性的維護
發表新主題 |
發表新回覆 |
||
Forum |
topicCount |
加1 |
|
articleCount |
加1 |
加1 |
|
lastTopic |
更新爲當前的新主題 |
||
Topic |
replyCount |
0 |
加1 |
lastReply |
null |
更新爲當前的新回覆 |
|
lastUpdateTime |
本主題的發表時間 |
更新爲當前新回覆的發表時間 |
TopicAction:
@Controller @Scope("prototype") public class TopicAction extends BaseAction<Topic>{
private Long forumId;
/** 顯示單個主題 */ public String show() throws Exception { return "show"; }
/** 發新帖頁面*/ public String addUI() throws Exception { //準備數據:forum Forum forum = forumService.getById(forumId); ActionContext.getContext().put("forum", forum); return "addUI"; }
/** 發新帖 */ public String add() throws Exception { //封裝對象 Topic topic = new Topic(); //須要在action中封裝的數據: //>>a.表單中的參數 topic.setTitle(model.getTitle()); topic.setContent(model.getContent()); topic.setForum(forumService.getById(forumId));//addUI.jsp表單中的隱藏域,把forumId傳遞過來了 //>>b.在顯示層才能得到的數據 topic.setAuthor(getCurrentUser()); //當前登陸的用戶 topic.setIpAddr(getRequestIp()); //客戶端的IP地址
//調用業務方法 topicService.save(topic);
return "toShow"; //轉到當前這個新主題的頁面 } … } |
Tips:
在action中就封裝這些屬性便可:表單中的參數和在顯示層才能獲取到的數據,其餘數據到業務層再設置.看需求頁面分析從頁面傳遞過來的值:
GetCurrentUser()和getRequestIp()比較經常使用,因此封裝到BaseAction中比較好.
//--------------------工具方法---------------- /** * 獲取當前用戶 */ public User getCurrentUser() throws Exception { return (User) ActionContext.getContext().getSession().get("user"); }
/** * 獲取客戶端的ip地址 */ public String getRequestIp() throws Exception { return ServletActionContext.getRequest().getRemoteAddr(); } |
TopicServiceImpl:
@Service @Transactional @SuppressWarnings("unchecked") public class TopicServiceImpl extends DaoSupportImpl<Topic> implements TopicService{
/** * 查詢指定版塊的主題列表,最新狀態的排到前面,置頂帖排到最前面 */ public List<Topic> findByForum(Forum forum) { return getSession().createQuery(// "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc")// .setParameter(0, forum)// .list(); }
/** * 重寫save() */ public void save(Topic topic) { //設置屬性並保存 topic.setType(topic.TYPE_NORMAL); //普通帖 topic.setReplyCount(0); topic.setLastReply(null); topic.setPostTime(new Date()); //當前時間 topic.setLastUpdateTime(topic.getPostTime()); //默認爲主題的發表時間
getSession().save(topic);
//更新相關信息 Forum forum = topic.getForum(); forum.setTopicCount(forum.getTopicCount()+1); //主題數量 forum.setArticleCount(forum.getArticleCount()+1); //回覆數量(主題+回覆) forum.setLastTopic(topic); //最後發表主題
getSession().update(forum); } } |
由於topicaction中的show()和對用的頁面還沒寫,因此發完新帖後提交,顯示的是空白頁面,此時在空白頁面中右鍵屬性:
Id爲空值,因此要在TopicAction中傳id過去:
…… /** 發新帖 */ public String add() throws Exception { //封裝對象 Topic topic = new Topic(); //須要在action中封裝的數據: //>>a.表單中的參數 topic.setTitle(model.getTitle()); topic.setContent(model.getContent()); topic.setForum(forumService.getById(forumId)); //>>b.在顯示層才能得到的數據 topic.setAuthor(getCurrentUser()); //當前登陸的用戶 topic.setIpAddr(getRequestIp()); //客戶端的IP地址
//調用業務方法 topicService.save(topic);
ActionContext.getContext().put("topicId", topic.getId()); return "toShow"; //轉到當前這個新主題的頁面 } |
Struts.xml:
<!-- 論壇:主題相關 --> <action name="topic_*" class="topicAction" method="{1}"> <result name="show">/WEB-INF/jsp/topicAction/show.jsp</result> <result name="addUI">/WEB-INF/jsp/topicAction/addUI.jsp</result> <result name="toShow" type="redirectAction">topic_show?id=${#topicId}</result> </action> |
這樣再提交時,便有了id值:
顯示置頂帖,精華帖,普通貼圖標的小技巧:
將相應圖片名稱改爲相應type值:
在ForumAction對應的show.jsp頁面中引入圖片時便可這麼寫:
<img src="${pageContext.request.contextPath}/style/images/topicType_${type}.gif" /> |
效果圖:
TopicAction:
…… public class TopicAction extends BaseAction<Topic>{ …… /** 顯示單個主題 */ public String show() throws Exception { //準備數據:topic Topic topic = topicService.getById(model.getId()); ActionContext.getContext().put("topic", topic);
//準備數據:replyList List<Reply> replyList =replyService.findByTopic(topic); ActionContext.getContext().put("replyList", replyList);
return "show"; } …… } |
ReplyServiceImpl:
public class ReplyServiceImpl extends DaoSupportImpl<Reply> implements ReplyService{ …… /** * 查詢指定主題的回覆,最新回覆排到最後 */ public List<Reply> findByTopic(Topic topic) { return getSession().createQuery(// "from Reply r where r.topic = ? order by r.postTime")// .setParameter(0, topic)// .list(); } …… } |
對應靜態頁面:
TopicAction對應的show.jsp:
…… <!--內容顯示--> <div id="MainArea"> <div id="PageHead"></div> <center> <div class="ItemBlock_Title1" style="width: 98%"> <font class="MenuPoint"> > </font> <s:a action="forum_list">論壇</s:a> <font class="MenuPoint"> > </font> <s:a action="forum_show?id=%{#topic.forum.id}">${topic.forum.name }</s:a> <font class="MenuPoint"> >> </font> 帖子閱讀 <span style="margin-left:30px;"><s:a action="topic_addUI?forumId=%{#topic.forum.id}"> <img align="absmiddle" src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png"/></s:a> </span> </div>
<div class="ForumPageTableBorder dataContainer" datakey="replyList">
<!--顯示主題標題等--> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr valign="bottom"> <td width="3" class="ForumPageTableTitleLeft"> </td> <td class="ForumPageTableTitle"><b>本帖主題:${topic.title }</b></td> <td class="ForumPageTableTitle" align="right" style="padding-right:12px;"> <s:a class="detail" action="reply_addUI?topicId=%{#topic.id}"><img border="0" src="${pageContext.request.contextPath}/style/images/reply.gif" />回覆</s:a> <a href="moveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />移動到其餘版塊</a> <a href="#" onClick="return confirm('要把本主題設爲精華嗎?')"><img border="0" src="${pageContext.request.contextPath}/style/images/forum_hot.gif" />精華</a> <a href="#" onClick="return confirm('要把本主題設爲置頂嗎?')"><img border="0" src="${pageContext.request.contextPath}/style/images/forum_top.gif" />置頂</a> <a href="#" onClick="return confirm('要把本主題設爲普通嗎?')"><img border="0" src="${pageContext.request.contextPath}/style/images/forum_comm.gif" />普通</a> </td> <td width="3" class="ForumPageTableTitleRight"> </td> </tr> <tr height="1" class="ForumPageTableTitleLine"><td colspan="4"></td></tr> </table>
<!-- ~~~~~~~~~~~~~~~ 顯示主帖 ~~~~~~~~~~~~~~~ --> <div class="ListArea"> <table border="0" cellpadding="0" cellspacing="1" width="100%"> <tr> <td rowspan="3" width="130" class="PhotoArea" align="center" valign="top"> <!--做者頭像--> <div class="AuthorPhoto"> <img border="0" width="110" height="110" src="${pageContext.request.contextPath}/style/images/defaultAvatar.gif" onerror="this.onerror=null; this.src='${pageContext.request.contextPath}/style/images/defaultAvatar.gif';" /> </div> <!--做者名稱--> <div class="AuthorName">${topic.author.name }</div> </td> <td align="center"> <ul class="TopicFunc"> <!--操做列表--> <li class="TopicFuncLi"> <a class="detail" href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />編輯</a> <a class="detail" href="#" onClick="return confirm('肯定要刪除本帖嗎?')"><img border="0" src="${pageContext.request.contextPath}/style/images/delete.gif" />刪除</a> </li> <!-- 文章標題 --> <li class="TopicSubject"> <s:property value="#topic.title" escape="true"/> </li> </ul> </td> </tr> <tr><!-- 文章內容 --> <td valign="top" align="center"> <div class="Content">${topic.content }</div> </td> </tr> <tr><!--顯示樓層等信息--> <td class="Footer" height="28" align="center" valign="bottom"> <ul style="margin: 0px; width: 98%;"> <li style="float: left; line-height:18px;"><font color=#C30000>[樓主]</font> <s:date name="#topic.postTime" format="yyyy-MM-dd HH:mm:ss"/> </li> <li style="float: right;"><a href="javascript:scroll(0,0)"> <img border="0" src="${pageContext.request.contextPath}/style/images/top.gif" /></a> </li> </ul> </td> </tr> </table> </div> <!-- ~~~~~~~~~~~~~~~ 顯示主帖結束 ~~~~~~~~~~~~~~~ -->
<!-- ~~~~~~~~~~~~~~~ 顯示回覆列表 ~~~~~~~~~~~~~~~ --> <s:iterator value="replyList" status="status"> <div class="ListArea template"> <table border="0" cellpadding="0" cellspacing="1" width="100%"> <tr> <td rowspan="3" width="130" class="PhotoArea" align="center" valign="top"> <!--做者頭像--> <div class="AuthorPhoto"> <img border="0" width="110" height="110" src="${pageContext.request.contextPath}/style/images/defaultAvatar.gif" onerror="this.onerror=null; this.src='${pageContext.request.contextPath}/style/images/defaultAvatar.gif';" /> </div> <!--做者名稱--> <div class="AuthorName">${author.name }</div> </td> <td align="center"> <ul class="TopicFunc"> <!--操做列表--> <li class="TopicFuncLi"> <a class="detail" href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />編輯</a> <a class="detail" href="#" onClick="return confirm('肯定要刪除本帖嗎?')"><img border="0" src="${pageContext.request.contextPath}/style/images/delete.gif" />刪除</a> </li> <%-- <!-- 文章表情與標題 --> <li class="TopicSubject"> <img width="19" height="19" src="${pageContext.request.contextPath}/style/images/face/${reply.faceIcon}"/> ${reply.title} </li> --%> </ul> </td> </tr> <tr><!-- 文章內容 --> <td valign="top" align="center"> <div class="Content">${content}</div> </td> </tr> <tr><!--顯示樓層等信息--> <td class="Footer" height="28" align="center" valign="bottom"> <ul style="margin: 0px; width: 98%;"> <li style="float: left; line-height:18px;"><font color=#C30000>[${status.count}樓]</font> <s:date name="postTime" format="yyyy-MM-dd HH:mm:ss"/> </li> <li style="float: right;"><a href="javascript:scroll(0,0)"> <img border="0" src="${pageContext.request.contextPath}/style/images/top.gif" /></a> </li> </ul> </td> </tr> </table> </div> </s:iterator> <!-- ~~~~~~~~~~~~~~~ 顯示回覆列表結束 ~~~~~~~~~~~~~~~ --> </div>
<div class="ForumPageTableBorder" style="margin-top: 25px;"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr valign="bottom"> <td width="3" class="ForumPageTableTitleLeft"> </td> <td class="ForumPageTableTitle"><b>快速回復</b></td> <td width="3" class="ForumPageTableTitleRight"> </td> </tr> <tr height="1" class="ForumPageTableTitleLine"> <td colspan="3"></td> </tr> </table> </div> </center>
<!--快速回復--> <div class="QuictReply"> <form action=""> <div style="padding-left: 3px;"> <table border="0" cellspacing="1" width="98%" cellpadding="5" class="TableStyle"> <!-- <tr height="30" class="Tint"> <td width="50px" class="Deep"><b>標題</b></td> <td class="no_color_bg"> <input type="text" name="title" class="InputStyle" value="回覆:昨天發如今表單裏刪除的圖片" style="width:90%"/> </td> </tr> --> <tr class="Tint" height="200"> <td valign="top" rowspan="2" class="Deep"><b>內容</b></td> <td valign="top" class="no_color_bg"> <textarea name="content" style="width: 95%; height: 300px"></textarea> </td> </tr> <tr height="30" class="Tint"> <td class="no_color_bg" colspan="2" align="center"> <input type="image" src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" style="margin-right:15px;"/> </td> </tr> </table> </div> </form> </div> </div> …… |
Tips: <s:property value="#topic.title" escape="true"/>
escape="true"這是轉義的意思.
主題顯示頁面的頂部,有快速回復的按鈕:
相應連接action="reply_addUI?topicId=%{#topic.id}
既然是回覆,就要指定要回復的主題.因此要傳遞topicId.在ReplyAction中以屬性驅動的方式封裝該參數:
private Long topicId; public Long getTopicId() { return topicId; }
public void setTopicId(Long topicId) { this.topicId = topicId; } |
回覆和發帖差很少.
ReplyAction:
@Controller @Scope("prototype") public class ReplyAction extends BaseAction<Reply>{
private Long topicId;
/** 發表回覆頁面 */ public String addUI() throws Exception { //準備數據 Topic topic = topicService.getById(topicId); ActionContext.getContext().put("topic", topic); return "addUI"; }
/** 發表回覆 */ public String add() throws Exception { Reply reply = new Reply(); //封裝對象 //a.表單中的參數 reply.setContent(model.getContent()); reply.setTopic(topicService.getById(topicId));
//b.在顯示層才能獲取的信息 reply.setAuthor(getCurrentUser()); //當前登陸的用戶 reply.setIpAddr(getRequestIp()); //客戶的ip地址
//調用業務方法 replyService.save(reply);
return "toTopicShow"; //轉到當前回覆所屬的主題顯示頁面 }
//--------------------- public Long getTopicId() { return topicId; }
public void setTopicId(Long topicId) { this.topicId = topicId; } } |
ReplyServiceImpl:
@Service @Transactional public class ReplyServiceImpl extends DaoSupportImpl<Reply> implements ReplyService{
/** * 重寫save(),處理特殊屬性 */ public void save(Reply reply) { reply.setPostTime(new Date()); //發表時間爲當前時間 reply.setDeleted(false); //默認爲未刪除
getSession().save(reply); //處理Forum和Topic中的特殊屬性 Topic topic = reply.getTopic(); Forum forum = topic.getForum();
forum.setArticleCount(forum.getArticleCount()+1); //版塊的文章數量(主題+回覆)
topic.setReplyCount(topic.getReplyCount()+1); //主題回覆數量 topic.setLastReply(reply); //主題的最後回覆 topic.setLastUpdateTime(reply.getPostTime()); //主題的最後更新時間 默認爲最後回覆時間
getSession().update(forum); getSession().update(topic); } } |
頁面需求: (其中表情和標題是不須要的)
ReplyAction對應的addUI.jsp:
…… <!--顯示錶單內容--> <div id="MainArea"> <s:form action="reply_add" sccStyle="margin: 0; padding: 0;"> <s:hidden name="topicId"></s:hidden> <div id="PageHead"></div> <center> <div class="ItemBlock_Title1"> <div width=85% style="float:left"> <font class="MenuPoint"> > </font> <s:a action="forum_list">論壇</s:a> <font class="MenuPoint"> > </font> <s:a action="forum_show?id=%{#topic.forum.id}">${topic.forum.name }</s:a> <font class="MenuPoint"> >> </font> 帖子回覆 </div> </div> <div class="ItemBlockBorder"> <table border="0" cellspacing="1" cellpadding="1" width="100%" id="InputArea"> <tr> <td class="InputAreaBg" height="30"><div class="InputTitle">帖子主題</div></td> <td class="InputAreaBg"><div class="InputContent">${topic.title }</div></td> </tr> <tr height="240"> <td class="InputAreaBg"><div class="InputTitle">內容</div></td> <td class="InputAreaBg"><div class="InputContent"><s:textarea name="content" cssStyle="width:650px;height:200px;"></s:textarea></div></td> </tr> <tr height="30"> <td class="InputAreaBg" colspan="2" align="center"> <input type="image" src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" style="margin-right:15px;"/> <a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/style/blue/images/button/goBack.png"/></a> </td> </tr> </table> </div> </center> </s:form> </div> …… |
在主題展現列表頁面的底部,有快速回復的功能,因此得修改TopicAction對應的show.jsp:
<!--快速回復--> <div class="QuictReply"> <s:form action="reply_add?topicId=%{#topic.id}"> <div style="padding-left: 3px;"> <table border="0" cellspacing="1" width="98%" cellpadding="5" class="TableStyle"> <tr class="Tint" height="200"> <td valign="top" rowspan="2" class="Deep"><b>內容</b></td> <td valign="top" class="no_color_bg"> <s:textarea name="content" cssStyle="width: 95%; height: 300px"></s:textarea> </td> </tr> <tr height="30" class="Tint"> <td class="no_color_bg" colspan="2" align="center"> <input type="image" src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" style="margin-right:15px;"/> </td> </tr> </table> </div> </s:form> </div> |
Struts.xml:
<!-- 論壇:主題相關 --> <action name="topic_*" class="topicAction" method="{1}"> <result name="show">/WEB-INF/jsp/topicAction/show.jsp</result> <result name="addUI">/WEB-INF/jsp/topicAction/addUI.jsp</result> <result name="toShow" type="redirectAction">topic_show?id=${#topicId}</result> </action>
<!-- 論壇:回覆相關 --> <action name="reply_*" class="replyAction" method="{1}"> <result name="addUI">/WEB-INF/jsp/replyAction/addUI.jsp</result> <result name="toTopicShow" type="redirectAction">topic_show?id=${topicId}</result> </action> |
Tips: topic_show?id=${#topicId}
這兩個模塊,發帖和發表回覆的請求發出時,頁面跳轉的過程是同樣的:addUI.jspàaction中的add()àshow.jsp
最後跳轉到show.jsp時,都須要topic的id值.
當發表新主題時,從addUI.jsp開始,就一直沒有將topic的id值傳遞過來(傳遞的是forumId),因此纔在TopicAction中將topicId給put進map域中,因此取出時要加#;
而發表回覆時,從addUI.jsp開始,就傳遞了topicId,因此直接取出來就好,不須要加#.
小技巧:eclipse有自動編譯的功能,但有時候會失靈.所以某些時候,看着代碼沒錯,但頁面顯示就是不對.這時能夠在代碼中空白位置加個空格再保存,目的是讓eclipse再次自動編譯,而後刷新頁面就能夠看到效果了.
在線編輯器:
老版:FCKeditor(Html + Css + JavaScript + Servlet處理上傳的文件)
新版:CKeditor
就是用JS實現的一個網頁版的html代碼生成器,最終的結果是一段html代碼。
原理是動態生成html代碼。
使用步驟:
1.導入fckeditor.js文件à2.顯示文本域à3.顯示爲FCKeditor
測試_20130706.html:
<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8">
<!-- 1,導入js文件 --> <script type="text/javascript" src="fckeditor.js"></script>
</head> <body>
<!-- 2,顯示文本域 --> <form action=""> <textarea name="content"> </textarea>
<!-- 3,顯示爲FCKeditor --> <script type="text/javascript"> var oFCKeditor = new FCKeditor( 'content' ) ; // 參數就是提交表單時的參數名(name的值)
// 必需要指定的屬性。 //用於指定fckeditor的核心文件的存放路徑(editor文件夾所在的路徑)。 // 要求必定要以'/'結尾。 oFCKeditor.BasePath = "./";
// 一些配置 oFCKeditor.Height = 300 ; oFCKeditor.Width = 700 ; //oFCKeditor.Value = 'itcast' ; oFCKeditor.ToolbarSet = "bbs"; // 提定工具欄的功能項配置,默認是Default
// oFCKeditor.Create() ; // 建立FCKeditor並在當前位置顯示出來。 oFCKeditor.ReplaceTextarea(); // 替換指定的textarea爲FCKeditor </script>
<br><input type="submit" value="提交"> </form> <hr> <a href="#">return</a> </body> </html> |
效果以下:
Tips:FCKeditor有本身默認的配置文件,要修改一些屬性(好比功能選項,表情等)的話,一般都要採用這樣的方式:本身建一個配置文件,如myconfig.js,在默認配置文件fckconfig.js中聲明還要加載myconfig.js,而後再把想要修改的配置寫到
myconfig.js中(不想改的不寫),就行了.
原理:默認先加載默認配置文件,聲明後還會加載本身寫的配置文件,這時前面加載的配置會被後面加載的相同的配置所覆蓋.
在默認配置文件中聲明還要加載本身寫的配置文件:
myonfig.js:
// 1. 自定義 ToolbarSet FCKConfig.ToolbarSets["simple"] = [ ['Bold','Italic','Underline'], ['Link','Unlink'], ['Image','Smiley','SpecialChar'], ['FontName'], ['FontSize'], ['TextColor','BGColor'], ] ;
FCKConfig.ToolbarSets["bbs"] = [ ['NewPage','RemoveFormat'], ['Bold','Italic','Underline'], ['Subscript','Superscript'], ['JustifyLeft','JustifyCenter','JustifyRight'], ['Link','Unlink'], ['Image','Smiley','SpecialChar'], ['Table'], ['OrderedList','UnorderedList','-','Outdent','Indent'], ['FontName'], ['FontSize'], ['TextColor','BGColor'], ['FitWindow'] ] ;
FCKConfig.ToolbarSets["admin"] = [ ['Source','DocProps','-','Save','NewPage','Preview','-','Templates'], ['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'], ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'], ['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'], ['OrderedList','UnorderedList','-','Outdent','Indent','Blockquote','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'], ['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'], ['Link','Unlink','Anchor'], ['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak'], ['Style','FontFormat','FontName','FontSize'], ['TextColor','BGColor'], ['FitWindow','ShowBlocks','-','About'] // No comma for the last row. ] ;
// 是否開啓簡單功能與高級功能顯示 if(typeof(FCKConfig.EnableAdvanceTable) == "undefined"){ // 在頁面中調用fckeditor時指定的 EnableAdvanceTable 的值會先被調用。 FCKConfig.EnableAdvanceTable = false; // 默認爲false } FCKConfig.AdvanceTableNum = 0; FCKConfig.AdvanceTable = [1,3,7,8,9,12];
// 2. 添加中文字體與大小 FCKConfig.FontNames ='宋體;楷體_GB2312;黑體;隸書;Times New Roman;Arial' ; FCKConfig.FontSizes ='9/最小;12/較小;16/中等;20/較大;36/最大;54/更大;';
// 3. 修改 "回車" 和 "shift + 回車" 的樣式 FCKConfig.EnterMode = 'br' ; // p | div | br FCKConfig.ShiftEnterMode = 'p' ; // p | div | br
// 4. 更換表情圖片 FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/wangwang/' ; // 表情圖片所在的文件夾 // 列出表情圖片的文件名 FCKConfig.SmileyImages = ['0.gif','1.gif','2.gif','3.gif','4.gif','5.gif','6.gif','7.gif','8.gif','9.gif','10.gif','11.gif','12.gif','13.gif','14.gif','15.gif','16.gif','17.gif','18.gif','19.gif','20.gif','21.gif','22.gif','23.gif','24.gif','25.gif','26.gif','27.gif','28.gif','29.gif','30.gif','31.gif','32.gif','33.gif','34.gif','35.gif','36.gif','37.gif','38.gif','39.gif','40.gif','41.gif','42.gif','43.gif','44.gif','45.gif','46.gif','47.gif','48.gif','49.gif','50.gif','51.gif','52.gif','53.gif','54.gif','55.gif','56.gif','57.gif','58.gif','59.gif','60.gif','61.gif','62.gif','63.gif','64.gif','65.gif','66.gif','67.gif','68.gif','69.gif','70.gif','71.gif','72.gif','73.gif','74.gif','75.gif','76.gif','77.gif','78.gif','79.gif','80.gif','81.gif','82.gif','83.gif','84.gif','85.gif','86.gif','87.gif','88.gif','89.gif','90.gif','91.gif','92.gif','93.gif','94.gif','95.gif','96.gif','97.gif','98.gif','test.gif'] ; FCKConfig.SmileyColumns = 8 ; FCKConfig.SmileyWindowWidth = 668 ; FCKConfig.SmileyWindowHeight = 480 ;
// 5. 設置容許上傳的圖片類型的擴展名列表 FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png|bmp)$" ; // empty for all
// 其它須要修改的配置 ... FCKConfig.LinkDlgHideTarget = true; // false ; FCKConfig.LinkDlgHideAdvanced = true; // false ;
FCKConfig.ImageDlgHideLink = true; // false ; FCKConfig.ImageDlgHideAdvanced = true; // false
FCKConfig.LinkUpload = false; |
這是老師寫好的myconfig.js,能夠用現成的,還想要修改字體,圖片等的話能夠在裏面自行修改.
將整個fckedit文件拷貝到WebContent根目錄下:
而後打開topicAction對應的addUI.jsp(發帖頁面) ,show.jsp(主題展現頁面的底部有快速回復功能) 和replyAction對應的addUI.jsp(發表回覆頁面),在這三個頁面的頂部加入下面這些代碼:
<%-- 使用FCKeditor --%> <script type="text/javascript" src="${pageContext.request.contextPath}/fckeditor/fckeditor.js"></script> <script type="text/javascript"> $(function() { var oFCKeditor = new FCKeditor('content'); // 參數就是提交表單時的參數名 // 必需要指定的屬性。用於指定fckeditor的核心文件的存放路徑(editor文件夾所在的路徑)。要求必定要以'/'結尾。 oFCKeditor.BasePath = "${pageContext.request.contextPath}/fckeditor/"; oFCKeditor.Width = "90%";//指定寬度 oFCKeditor.ToolbarSet = "bbs"; // 提定工具欄的功能項配置,默認是Default oFCKeditor.ReplaceTextarea(); // 替換指定的textarea爲FCKeditor }); </script> |
Tips:這三個頁面的文本域的name值都爲content;
這段代碼原本是必定要出如今文本域以後的,否則會提示找不到name值爲content的文本域.之因此能這麼作,是由於加了$(function(){});代表等頁面加載完成以後再執行這些代碼.
在eclipse自帶的瀏覽器中顯示不出來--.
效果以下:
他沒給演示數據….本身手動添加,,,,,-------…