SSH combat OA 11: BBS module

The system management, permission management and other content of the "SSH OA" series of blogs will be added later. Let's continue with the third module: online communication module. There are two main needs for online communication: forum management and forum.

Some basic terms of BBS:

  1. Sections: Also known as "boards", "discussion boards", used to categorize posts
  2. Topic: Also called "Main Post", it means a new topic, there can be many replies, and it belongs to a certain section.
  3. Reply: Also called "Reply Post", "Talk Post", it belongs to a certain main post.

Function description of the forum module:

  1. browse
    • Plate list
    • Show a single section (list of topics)
    • Display a single topic (topic + list of replies)
  2. participate
    • post new
    • Reply
  3. Manage Articles
    • theme
      • set type
      • Move to another section
      • delete
      • Revise
    • Reply
  4. Section management
    • CRUD
    • Moving up and down

Section management

Section management
Let's take a look at the requirements of section management first. As can be seen from the above figure, the main requirements of section management include adding, deleting, modifying, listing, moving up, and moving down the sections. Then the corresponding Action method is as follows:

@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";
    }
}

Forum section ForumAction needs to inherit the basic Action abstract class 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的真实类型
            ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0];
            // 通过反射创建model的实例
            model = clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public T getModel() {
        return model;
    }
}

Without considering the association with other entities, our model class can be designed like this:

/**
 * @date 2017/05/06
 * @author shizongger
 * 论坛板块
 */
public class Forum {

    private Long id; //主键id

    private String name; //板块名称

    private String description; //板块描述

    private int position;  //板块所在位置

    //getter/settter
}

The previous articles mentioned that the primary key attribute id of the mapped pojo defaults to the Long type, and the forum attribute's own attributes include name, description, and position. name is used to record the name of the plate, description is the description of the plate, and position is the sorting position of the record plate, and the operation of moving up and down.

The Forum.hbm.xml file is as follows:

<?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 type mappings use Hibernate's default configuration. Don't forget to add the location of this file in the Hibernate configuration file hiberante.cfg.xml.
<mapping resource="com/shizongger/oa/domain/Forum.hbm.xml" />

Since I am currently using a two-layer architecture, the Merge and Serivce layer and the Dao layer, I abstract the basic additions, deletions, and changes to the database by the Dao layer into the DaoSupport abstract class. This is an abstract class of generic parameters. The specific type of the model type passed in is obtained through the java reflection mechanism in the constructor.

/**
 * @author shizongger
 * @param <T> 实际操作的daomain实体
 */
@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() {
        // 使用反射技术得到T的真实类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型
        this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
    }

    /**
     * 增加
     */
    @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);
    }

    /**
     * 根据id查询
     */
    @Override
    public T selectById(Long id) {
        return (T) getSession().get(this.clazz, id);
    }

    /**
     * 根据id数组查找对象集合
     * @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();
        }
    }

    /**
     * 根据id数组查询
     */
    @Override
    public List<T> selectAll() {
        List<T> list = getSession().createQuery("FROM " + this.clazz.getSimpleName()).list();

        return list;
    }

    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }
}

The service implementation class code of forum management is as follows:

@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();
    }

    /**
     * 上移当前板块forum的位置position值
     */
    @Override
    public void moveUp(Long id) {
        //获取当前板块
        Forum forum = selectById(id);
        //上一个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();
        //最上面的不能再往上移动
        if(prexForum == null) {
            return;
        }

        //交换当前和上一个的position
        int position = forum.getPosition();
        forum.setPosition(prexForum.getPosition());
        prexForum.setPosition(position);

        //更新两个对象到数据库中
        getSession().save(forum);
        getSession().save(prexForum);
    }

    /**
     * 向下移动当前板块
     */
    @Override
    public void moveDown(Long id) {
        //获取当前板块
        Forum forum = selectById(id);

        //下一个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;
        }

        //交换当前forum和下一个forum的position
        int position = nextForum.getPosition();
        nextForum.setPosition(forum.getPosition());
        forum.setPosition(position);

        //更新两个对象到数据库中去
        getSession().save(nextForum);
        getSession().save(forum);
    }
}

The function of adding, deleting, modifying and checking only needs to pass the model as Forum and call DaoSupport. The idea of ​​moving up and down is that jsp passes the forum in, and first obtains a forum object from the database. If it is moved up, get all the largest values ​​of position in the database that are smaller than this forum.position. Because as long as it is not the top plate, there may be multiple plates smaller than our own position, and we only need the largest one, that is, the plate just next to ourselves. Then swap the position values ​​of the two.

Front-end list list.jsp page

<%@ 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"><!--页面标题-->
            <img src="${pageContext.request.contextPath }/style/images/title_arrow.gif" width="13" height="13" border="0"> 版块管理
        </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>相关操作</td>
            </tr>
        </thead>

        <!--显示数据列表-->
        <tbody id="TableData" class="dataContainer" datakey="forumList">

        <!-- 遍历forumList -->
        <s:iterator value="#forumList" status="status">
            <tr class="TableDetail1 demodata_record">
                <td>${name }&nbsp;</td>
                <td>${description }&nbsp;</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>
                    <!-- 最下面的不能再往下移动 -->
                    <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"><img src="${pageContext.request.contextPath }/style/images/createNew.png"></a>
        </div>
    </div>
</div>

<div class="Description">
    说明:<br>
    1,显示的列表按其sortOrder值升序排列。<br>
    2,可以通过上移与下移功能调整顺序。最上面的不能上移,最下面的不能下移。<br>
</div>



</body></html>

New and Modified Pages

<%@ 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>
</head>
<body>

<!-- 标题显示 -->
<div id="Title_bar">
    <div id="Title_bar_Head">
        <div id="Title_Head"></div>
        <div id="Title"><!--页面标题-->
            <img src="${pageContext.request.contextPath }/style/images/title_arrow.gif" width="13" height="13" border="0"> 版块设置
        </div>
        <div id="Title_End"></div>
    </div>
</div>

<!--显示表单内容-->
<div id="MainArea">
    <s:form action="forumManage_%{id == null ? 'add' : 'edit'}">
        <!-- 隐藏表单内容 -->
        <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>

        <!-- 表单内容显示 -->
        <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);"><img src="${pageContext.request.contextPath }/style/images/goBack.png"></a>
        </div>
    </s:form>
</div>

<div class="Description">
    说明:<br>
    1,新添加的版块默认显示在最下面。<br>
</div>



</body></html>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325975747&siteId=291194637