《SSH實(shí)戰(zhàn)OA》系列博客的系統(tǒng)管理、權(quán)限管理等內(nèi)容后面再補(bǔ)上吧胎撇,先繼續(xù)第三個(gè)模塊:網(wǎng)上交流模塊贱傀。網(wǎng)上交流主要做兩個(gè)需求:論壇管理和論壇。
BBS的一些基本術(shù)語:
- 板塊:也叫做“版面”胎撤、“討論區(qū)”晓殊,用于對(duì)帖子進(jìn)行分類
- 主題:也叫做“主貼”,表示一個(gè)新的話題伤提,可以有很多回帖巫俺,屬于某個(gè)板塊。
- 回復(fù):也叫做“回帖”肿男、“跟帖”介汹,屬于某個(gè)主貼却嗡。
論壇模塊的功能說明:
- 瀏覽
- 板塊列表
- 顯示單個(gè)板塊(主題列表)
- 顯示單個(gè)主題(主題+回帖列表)
- 參與
- 發(fā)新帖
- 回帖
- 管理文章
- 主題
- 設(shè)置類型
- 移動(dòng)到其他板塊
- 刪除
- 修改
- 回復(fù)
- 主題
- 板塊管理
- 增刪改查
- 上下移動(dòng)
板塊管理
先來看看板塊管理的需求,由上圖可以看出嘹承,板塊管理主要的需求有板塊的新增窗价、刪除,修改叹卷,列表撼港,上移,下移這幾個(gè)需求骤竹。那么對(duì)應(yīng)的Action方法如下:
@Controller
@Scope("prototype")
public class ForumManageAction extends BaseAction<Forum> {
Log log = LogFactory.getLog(this.getClass());
/**
* @return 板塊列表
* @throws Exception
*/
public String list() throws Exception {
List<Forum> forumList = forumService.selectAll();
ActionContext.getContext().put("forumList", forumList);
return "list";
}
/**
* @return 新增頁面
* @throws Exception
*/
public String addUI() throws Exception {
return "saveUI";
}
/**
* @return 新增操作
* @throws Exception
*/
public String add() throws Exception {
forumService.add(model);
return "toList";
}
/**
* @return 刪除操作
* @throws Exception
*/
public String delete() throws Exception {
forumService.delete(model.getId());
return "toList";
}
/**
* @return 修改頁面
* @throws Exception
*/
public String editUI() throws Exception {
Forum forum = forumService.selectById(model.getId());
ActionContext.getContext().put("forum", forum);
return "saveUI";
}
/**
* @return 修改
* @throws Exception
*/
public String edit() throws Exception {
Forum forum = forumService.selectById(model.getId());
if(forum != null) {
forum.setDescription(model.getDescription());
forum.setName(model.getName());
forumService.update(forum);
}
return "toList";
}
/**
* @return 上移
* @throws Exception
*/
public String moveUp() throws Exception {
forumService.moveUp(model.getId());
return "toList";
}
/**
* @return 下移
* @throws Exception
*/
public String moveDown() throws Exception {
forumService.moveDown(model.getId());
return "toList";
}
}
論壇板塊ForumAction需要繼承基本Action抽象類BaseAction帝牡。
public abstract class BaseAction<T> extends ActionSupport implements ModelDriven<T>{
protected T model;
@Autowired
protected DepartmentService departmentService;
@Autowired
protected RoleService roleService;
@Autowired
protected UserService userService;
@Autowired
protected PrivilegeService privilegeService;
@Autowired
protected ForumService forumService;
public BaseAction() {
try {
// 通過反射獲取model的真實(shí)類型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0];
// 通過反射創(chuàng)建model的實(shí)例
model = clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public T getModel() {
return model;
}
}
在暫未考慮與其他實(shí)體關(guān)聯(lián)的提前下,我們的model類可以這樣設(shè)計(jì):
/**
* @date 2017/05/06
* @author shizongger
* 論壇板塊
*/
public class Forum {
private Long id; //主鍵id
private String name; //板塊名稱
private String description; //板塊描述
private int position; //板塊所在位置
//getter/settter
}
前幾篇文章提到映射的pojo的主鍵屬性id都默認(rèn)為L(zhǎng)ong型蒙揣,forum屬性自己的屬性有name,description,position靶溜。name用來記錄板塊名稱,description是對(duì)本板塊的描述懒震,而position是記錄板塊的排序位置罩息,方面上下移動(dòng)的操作。
Forum.hbm.xml文件如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.shizongger.oa.domain">
<class name="Forum" table="itcast_forum">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="description" />
<property name="position" />
</class>
</hibernate-mapping>
String類型的映射都用Hibernate默認(rèn)的配置个扰。別忘了在Hibernate的配置文件hiberante.cfg.xml添加本文件的位置瓷炮。
<mapping resource="com/shizongger/oa/domain/Forum.hbm.xml" />
由于目前我采用的是兩層架構(gòu),合并和Serivce層和Dao層锨匆,所以我把Dao層對(duì)數(shù)據(jù)庫基本增刪改查都抽象到DaoSupport抽象類里崭别。這是一個(gè)泛型參數(shù)的抽象類,具體傳遞進(jìn)來的model類型屬于什么類型是在構(gòu)造方法中通過java反射機(jī)制得到的恐锣。
/**
* @author shizongger
* @param <T> 實(shí)際操作的daomain實(shí)體
*/
@Transactional
@SuppressWarnings("unchecked")
public abstract class DaoSupportImpl<T> implements DaoSupport<T> {
private Log log = LogFactory.getLog(this.getClass());
/**
* sessionFactory工廠
*/
@Autowired
private SessionFactory sessionFactory;
private Class<T> clazz;
@SuppressWarnings("unchecked")
public DaoSupportImpl() {
// 使用反射技術(shù)得到T的真實(shí)類型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 獲取當(dāng)前new的對(duì)象的 泛型的父類 類型
this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 獲取第一個(gè)類型參數(shù)的真實(shí)類型
}
/**
* 增加
*/
@Override
public void add(T entity) {
log.info("add:" + entity.toString());
getSession().save(entity);
}
/**
* 刪除
*/
@Override
public void delete(Long id) {
Object object = selectById(id);
if(object != null) {
getSession().delete(object);
}
}
/**
* 修改
*/
@Override
public void update(T entity) {
getSession().update(entity);
}
/**
* 根據(jù)id查詢
*/
@Override
public T selectById(Long id) {
return (T) getSession().get(this.clazz, id);
}
/**
* 根據(jù)id數(shù)組查找對(duì)象集合
* @param ids id的列表
* @return
*/
@Override
public List<T> getByIds(Long[] ids) {
if (ids == null || ids.length == 0) {
return Collections.EMPTY_LIST;
} else {
return getSession().createQuery(//
"FROM " + clazz.getSimpleName() + " WHERE id IN (:ids)")//
.setParameterList("ids", ids)//
.list();
}
}
/**
* 根據(jù)id數(shù)組查詢
*/
@Override
public List<T> selectAll() {
List<T> list = getSession().createQuery("FROM " + this.clazz.getSimpleName()).list();
return list;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}
論壇管理的Service實(shí)現(xiàn)類代碼如下:
@Service
@Transactional
@SuppressWarnings("unchecked")
public class ForumServiceImpl extends DaoSupportImpl<Forum> implements ForumService {
Log log = LogFactory.getLog(this.getClass());
@Override
public void add(Forum forum) {
super.add(forum);
forum.setPosition(forum.getId().intValue());
}
@Override
public List<Forum> selectAll() {
return getSession()
.createQuery("FROM Forum f ORDER BY f.position")
.list();
}
/**
* 上移當(dāng)前板塊forum的位置position值
*/
@Override
public void moveUp(Long id) {
//獲取當(dāng)前板塊
Forum forum = selectById(id);
//上一個(gè)forum
Forum prexForum = (Forum)getSession()
.createQuery("FROM Forum f WHERE f.position < ? ORDER BY f.position DESC")
.setParameter(0, forum.getPosition())
.setFirstResult(0)
.setMaxResults(1)
.uniqueResult();
//最上面的不能再往上移動(dòng)
if(prexForum == null) {
return;
}
//交換當(dāng)前和上一個(gè)的position
int position = forum.getPosition();
forum.setPosition(prexForum.getPosition());
prexForum.setPosition(position);
//更新兩個(gè)對(duì)象到數(shù)據(jù)庫中
getSession().save(forum);
getSession().save(prexForum);
}
/**
* 向下移動(dòng)當(dāng)前板塊
*/
@Override
public void moveDown(Long id) {
//獲取當(dāng)前板塊
Forum forum = selectById(id);
//下一個(gè)forum
Forum nextForum = (Forum)getSession()
.createQuery("FROM Forum f WHERE f.position > ? ORDER BY f.position ASC")
.setParameter(0, forum.getPosition())
.setFirstResult(0)
.setMaxResults(1)
.uniqueResult();
//最下面的不能再往下移
if(nextForum == null) {
return;
}
//交換當(dāng)前forum和下一個(gè)forum的position
int position = nextForum.getPosition();
nextForum.setPosition(forum.getPosition());
forum.setPosition(position);
//更新兩個(gè)對(duì)象到數(shù)據(jù)庫中去
getSession().save(nextForum);
getSession().save(forum);
}
}
增刪改查功能只需要把model為Forum傳遞進(jìn)去調(diào)用DaoSupport就行了茅主,上移和下移的思路是jsp傳遞forum進(jìn)來,先從數(shù)據(jù)庫獲得一個(gè)forum對(duì)象土榴。如果是上移诀姚,則獲取數(shù)據(jù)庫中position所有小于本forum.position的那個(gè)最大的值。因?yàn)橹灰皇亲钌厦娴陌鍓K玷禽,小于自己position的板塊可能有多個(gè)赫段,而我們只需要最大的那個(gè),也就是僅僅挨著自己的那個(gè)板塊矢赁。然后交換兩者的position值糯笙。
前端列表list.jsp頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>版塊列表</title>
<%@ include file="/WEB-INF/jsp/public/commons.jspf" %>
<script type="text/javascript">
</script>
<style type="text/css">
.disabled{
color: gray;
cursor: pointer;
}
</style>
</head>
<body>
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--頁面標(biāo)題-->
![](${pageContext.request.contextPath }/style/images/title_arrow.gif) 版塊管理
</div>
<div id="Title_End"></div>
</div>
</div>
<div id="MainArea">
<table class="TableStyle" cellspacing="0" cellpadding="0">
<!-- 表頭-->
<thead>
<tr id="TableTitle" valign="MIDDLE" align="CENTER">
<td width="250px">版塊名稱</td>
<td width="300px">版塊說明</td>
<td>相關(guān)操作</td>
</tr>
</thead>
<!--顯示數(shù)據(jù)列表-->
<tbody id="TableData" class="dataContainer" datakey="forumList">
<!-- 遍歷forumList -->
<s:iterator value="#forumList" status="status">
<tr class="TableDetail1 demodata_record">
<td>${name } </td>
<td>${description } </td>
<td>
<s:a action="forumManage_delete?id=%{id}" onclick="return delConfirm()">刪除</s:a>
<s:a action="forumManage_editUI?id=%{id }">修改</s:a>
<!-- 最上面不能往上移 -->
<s:if test="#status.first">
<span class="disabled">上移</span>
</s:if>
<s:else>
<s:a action="forumManage_moveUp?id=%{id }">上移</s:a>
</s:else>
<!-- 最下面的不能再往下移動(dòng) -->
<s:if test="#status.last">
<span class="disabled">下移</span>
</s:if>
<s:else>
<s:a action="forumManage_moveDown?id=%{id }">下移</s:a>
</s:else>
</td>
</tr>
</s:iterator>
</tbody>
</table>
<!-- 其他功能超鏈接 -->
<div id="TableTail">
<div id="TableTail_inside">
<a href="forumManage_addUI.action">![](${pageContext.request.contextPath }/style/images/createNew.png)</a>
</div>
</div>
</div>
<div class="Description">
說明:<br>
1,顯示的列表按其sortOrder值升序排列撩银。<br>
2给涕,可以通過上移與下移功能調(diào)整順序。最上面的不能上移,最下面的不能下移够庙。<br>
</div>
</body></html>
新增和修改的頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>版塊設(shè)置</title>
<%@ include file="/WEB-INF/jsp/public/commons.jspf" %>
<script type="text/javascript">
</script>
</head>
<body>
<!-- 標(biāo)題顯示 -->
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--頁面標(biāo)題-->
![](${pageContext.request.contextPath }/style/images/title_arrow.gif) 版塊設(shè)置
</div>
<div id="Title_End"></div>
</div>
</div>
<!--顯示表單內(nèi)容-->
<div id="MainArea">
<s:form action="forumManage_%{id == null ? 'add' : 'edit'}">
<!-- 隱藏表單內(nèi)容 -->
<s:hidden name="id" value="%{#request.forum.id}"></s:hidden>
<div class="ItemBlock_Title1"><!-- 信息說明<DIV CLASS="ItemBlock_Title1">
<IMG BORDER="0" WIDTH="4" HEIGHT="7" SRC="${pageContext.request.contextPath }/style/blue/images/item_point.gif" /> 版塊信息 </DIV> -->
</div>
<!-- 表單內(nèi)容顯示 -->
<div class="ItemBlockBorder">
<div class="ItemBlock">
<table class="mainForm" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="100">版塊名稱</td>
<td><s:textfield name="name" cssClass="InputStyle" value="%{#request.forum.name}" > *</s:textfield></td>
</tr>
<tr>
<td>版塊說明</td>
<td><s:textarea name="description" cssClass="TextareaStyle" value="%{#request.forum.description}"></s:textarea></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- 表單操作 -->
<div id="InputDetailBar">
<input src="${pageContext.request.contextPath }/style/images/save.png" type="image">
<a href="javascript:history.go(-1);">![](${pageContext.request.contextPath }/style/images/goBack.png)</a>
</div>
</s:form>
</div>
<div class="Description">
說明:<br>
1恭应,新添加的版塊默認(rèn)顯示在最下面。<br>
</div>
</body></html>