欢迎来到Srr的博客

结对作业二

这个作业属于哪个课程 2021春软件工程实践S班(福州大学)
这个作业要求在哪里 结对作业二
结对学号 221801108 、221801115
这个作业的目标 阅读《构建之法》第4章,将结对作业一的原型设计具体实现出来
其他参考文献 CSDN、博客园、《构建之法》

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
• Estimate • 估计这个任务需要多少时间 20 20
Development 开发 2775 2825
• Analysis • 需求分析 (包括学习新技术) 200 190
• Design Spec • 生成设计文档 80 120
• Design Review • 设计复审 15 15
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 30 20
• Design • 具体设计 60 30
• Coding • 具体编码 2000 2100
• Code Review • 代码复审 30 30
• Test • 测试(自我测试,修改代码,提交修改) 360 320
Reporting 报告 120 150
• Test Repor • 测试报告 30 70
• Size Measurement • 计算工作量 30 20
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 60 60
合计 2915 2995

git仓库链接

git仓库

代码规范链接

代码规范

项目地址

项目地址

成品展示

  • 输入部分信息进行模糊搜索,也可输入完整信息进行精确搜索

  • 点击论文列表查看论文详细信息,点击右上角按钮返回

  • 翻页功能

  • 对论文列表进行删除

  • 展示Top 10热词词云,动态展示20年三大顶会的热度走势,可以暂停或者调整进度 (PS:由于数据库信息过大,所以通过云服务器访问此页面显示大概需要5分钟,需要耐心等待)

结对讨论过程描述

讨论

设计实现过程

数据库

paper表:标题title, 摘要summary, 原文链接link, 关键词keywords, 发表年份year, 会议conference
database

前端

frontend

采用html+css的方式进行页面设计,paperList.jsp为论文列表界面,paper.jsp为论文详细信息界面,chartPage.jsp为热词研究界面,三个界面引用外部css文件实现具体样式。

后端

backend

功能结构图

功能结构图

代码说明

  • paperList.jsp代码,显示的是论文列表。该页面在点击搜索、上一页以及下一页按钮时,通过PaperListServlet从数据库取出相应数据并分页显示。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<% String path = request.getContextPath(); %>
<html>
<head>
    <title>Title</title>
    <link rel="stylesheet" href="css/paperList.css"/>
    <script type="text/javascript">
        function deletePaper(paperTitle) {
            var t = document.getElementById("query_text");
            var p = document.getElementById("pageNum");
            var c = document.getElementById("changeNum");
            var tv = t.getAttribute('value');
            var pv = p.getAttribute('value');
            var cv = c.getAttribute('value');
            if (window.confirm("是否删除此篇论文?")) {
                window.location.href = "<%=path%>/PaperListServlet?operation=deletePaper&paperTitle="
                    + paperTitle+ "&str=" + tv + "&pn=" + pv + "&cn=" + cv;
            }
        }

        function show(paperTitle) {
            window.location.href = "<%=path%>/PaperListServlet?operation=showPaper&paperTitle=" + paperTitle;
        }

        function changePage(num) {
            document.getElementById("changeNum").value = num;
            document.getElementById("queryForm").submit();
        }
    </script>
</head>
<body>

<div class="header" >
    <div class="logo_box">
        <img class="logo" src="./img/2.png" >
    </div>
    <div class="navigation_box">
        <div class="nav">
            <ul>
                <li class="nav_post"><a class="a1" href="<%=path%>/paperList.jsp" >论文列表</a></li>
                <li><a class="a2" href="<%=path%>/paperAnalysisPage/chartPage.jsp" >热门研究</a></li>
            </ul>
        </div>
    </div>


    <div id="div_paperQueryForm">
        <form action="<%=path%>/PaperListServlet" method="post" id="queryForm">
            <input type="text" name="query" id="query_text" value="${requestScope.info}">
            <button type="button" id="query_btn" onclick="changePage(0)">搜索</button>
            <input type="hidden" name="pageNum" id="pageNum" value="${requestScope.pageNum}" />
            <input type="hidden" id="changeNum" name="changeNum" value="" />
        </form>
    </div>
</div>
<div class="main">

    <div id="div_paperList">
        <table id="papertable">
            <tr>
                <th class="num">序号</th>
                <th class="title">论文题目</th>
                <th class="conference">会议</th>
                <th class="summary">摘要</th>
                <th class="link">原文链接</th>
                <th class="link">关键词</th>
                <th class="delete">操作</th>
            </tr>
            <c:forEach items="${requestScope.paperList}" var="pl" varStatus="vs">
                <tr>
                    <td class="num" onclick="show('${pl.title}')"> ${vs.index + 1}</td>
                    <td class="title" onclick="show('${pl.title}')"> ${pl.title} </td>
                    <td class="conference" onclick="show('${pl.title}')"> ${pl.conference} </td>
                    <td class="summary" onclick="show('${pl.title}')"> ${pl.summary} </td>
                    <td class="link" onclick="show('${pl.title}')"> <a href=${pl.link} >${pl.link}</a> </td>
                    <td class="link" onclick="show('${pl.title}')"> ${pl.keywords} </td>
                    <td class="delete"> <button type="button" id="delete_button" onclick="deletePaper('${pl.title}')"></button> </td>
                </tr>
            </c:forEach>
        </table>
        <div id="div_paging">
            <button id="btn_lastPage" type="button" onclick="changePage(-1)">上一页</button>
            当前第  <span class="page_num">${requestScope.pageNum}</span>  页  <button id="btn_nextPage" type="button" onclick="changePage(1)">下一页</button>  共 ${requestScope.totalPage} 页,共 ${requestScope.totalNum} 条记录
        </div>
    </div>

</div>
</body>
</html>
  • PaperListServlet的doGet方法通过jsp传来的参数判断要执行的操作。
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String oper = "";
        if(req.getParameter("operation") != null)
            oper = req.getParameter("operation");
        switch (oper) {
            case "deletePaper":
                deletePaper(req, resp);
                break;
            case "showPaper":
                showPaper(req, resp);
                break;
            case "queryKeyPaper":
                queryKeyPaper(req, resp);
                break;
            default:
                queryPaper(req, resp);
                break;
        }
    }

    /* 模糊查询论文并分页 */
    public void queryPaper(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String str = req.getParameter("query");
        String pageNum = req.getParameter("pageNum");
        String changeNum = req.getParameter("changeNum");
        //linesPerPage:每页行数, page:当前页码, change:页码要改变的数量, totalNum:总论文数
        int linesPerPage = 20, page = 1, change = 0, totalNum = paperDAO.getTotal(str);
        //totalPage:总页数
        int totalPage = totalNum / linesPerPage + (totalNum % linesPerPage == 0 ? 0 : 1);

        if (totalPage == 0) {
            totalPage = 1;
        }
        if (pageNum != null && !"".equals(pageNum)) {
            page = Integer.parseInt(pageNum);
        }
        if (changeNum != null && !"".equals(changeNum)) {
            change = Integer.parseInt(changeNum);
        }
        if (!(page == 1 && change == -1) && !(page == totalPage && change == 1)) {
            page += change;
        }
        if (page > totalPage) {
            page = totalPage;
        }

        ArrayList<Paper> paperList = paperDAO.list(str, page, linesPerPage);
        req.setAttribute("info", str);
        req.setAttribute("pageNum", page);
        req.setAttribute("totalPage", totalPage);
        req.setAttribute("totalNum", totalNum);
        req.setAttribute("paperList", paperList);
        req.getRequestDispatcher("/paperList.jsp").forward(req,resp);
    }

    /* 删除论文 */
    public void deletePaper(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {...}

    /* 查询单篇论文详细信息 */
    public void showPaper(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {...}

    /* 通过关键词字段查询论文 */
    public void queryKeyPaper(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {...}

  • PaperDAO的函数
public interface PaperDAO {
    
    /* 返回模糊查询到的论文总数 */
    int getTotal(String str);
    
    /* 根据论文题目删除对应论文 */
    void delete(String title);
    
    /* 模糊查询分页用 */
    ArrayList<Paper> list(String str, int pageNum, int lineNum);
    
    /* 根据论文题目返回对应论文 */
    Paper get(String title);
    
}
  • KeywordDAOImpl函数
public class KeywordDAOImpl implements KeywordDAO{

    /* 返回关键词内含有keyword的论文数 */
    public int getTotal(String keyword) {...}

    /* 根据关键词返回包含该关键词的论文列表 */
    public ArrayList<Paper> keyList(String keyword,int pageNum, int lineNum) {...}

    /* 根据关键词、年份、会议查询论文,返回查询总数 */
    public int keyListNum(String keyword, int year, String conference) {...}

    /* 按着频率大小返回频率最高的十个关键词 */
    public ArrayList<Keyword> GetTop10Keywords() {...}

    /* 返回十大关键词在该会议每年的频率列表 */
    public ArrayList<YearFrequency> getKeywordFrequencyEachYear(String conference) {
        ArrayList<YearFrequency> yearFrequencyList = new ArrayList<>();
        ArrayList<Keyword> kwList = GetTop10Keywords();
        YearDAO yearDAO = new YearDAOImpl();
        ArrayList<Integer> years = yearDAO.getYears();

        for (int y:years) {
            YearFrequency yf = new YearFrequency();
            yf.setYear(y);
            ArrayList<Integer> frequency = new ArrayList<>();

            for (int i = 0; i < 10; i++) {
                frequency.add(keyListNum(kwList.get(i).getName(), y, conference));
            }

            yf.setFrequency(frequency);
            yearFrequencyList.add(yf);
        }

        return yearFrequencyList;
    }

}
  • YearDAOImpl函数
public class YearDAOImpl implements YearDAO{

    /* 返回数据库中论文所有的发表年份 */
    public ArrayList<Integer> getYears() {
        ArrayList<Integer> years = new ArrayList<>();
        Connection conn = null;
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try{
            conn = DBUtil.getConnection();
            pstm = conn.prepareStatement("select year from paper group by year order by year");
            rs = pstm.executeQuery();

            while (rs.next()) {
                years.add(rs.getInt(1));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(rs, pstm, conn);
        }
        return years;
    }

}

心路历程和收获

  • Srr(221801108):

这次结对编程是第一次从需求分析开始,到设计方案,原型创作,再到具体实现功能,最后把项目部署到服务器上,让项目投入使用,这么一个较为完整的项目流程。说实话一开始也有怀疑能不能完成这个任务,后来摸索着配置服务器从Linux到放弃转用Windows也很痛苦,好在最终还是顺利结束了,中间还经历了一次团队合作,这十来天可以说是过的非常充实了。实践出真知,这次的结对编程不仅是一次了解项目流程的实战经历,也将之前学的web知识和还在学习的JavaEE知识整合巩固了一遍,收获不小。

  • Lmh(221801115):

本次结对编程负责的是实现后端的任务,一开始的几天通过看b站视频学习了servlet、jsp的知识,非常大的帮助了之后的后端代码实现。在写代码过程中遇到了很多困难,一开始大多是数据传输的问题,后面熟悉了以后写代码也就容易了起来。在此期间也看了不少相关的视频来学习,比如分页功能就是看视频写的。

评价结对队友

  • 宋日荣(221801108)对林明昊(221801115)的评价:

队友很靠谱,对待任务也很认真负责,作业一发布就马上进行讨论以及任务的分配,在具体实现功能的过程中出现的问题,能够及时地查找资料找出解决方法。和队友沟通很融洽,很好地发挥出1+1>2的效果,是一个很好的结对伙伴。

  • 林明昊(221801115)对宋日荣(221801108)的评价:

队友很用心地一起讨论一起完成任务,对待工作也很认真。分配的任务能够很好地完成,工作起来井井有条,和他交流很愉快也很高效,面对问题也很有见解。

posted @ 2021-04-01 00:35  Srr  阅读(80)  评论(0编辑  收藏  举报