结对作业(2/2)

结对作业(2/2)

这个作业属于哪个课程 <2021春软件工程实践|S班>
这个作业要求在哪里 <结对作业二>
结对学号 <221801324><221801319>
这个作业的目标 GitHub ,结对编程 ,web项目 ,结对作业一原型设计的实现
其他参考文献 CSDN、简书、博客园等

目录:

GitHub仓库链接和代码规范链接

GitHub仓库地址:https://github.com/Tom-502/PairProject
GitHub仓库地址:https://github.com/Zhengkaixin/PairProject
代码规范地址:https://github.com/Tom-502/PersonalProject-Java/blob/main/221801324/codestyle.md

项目链接

链接:http://1.15.178.163:8081
用户名:yrc
密码:yrc123
验证码区分大小写

PSP表格

叶睿操

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 50
• Estimate • 估计这个任务需要多少时间 30 50
Development 开发 1235 1200
• Analysis • 需求分析 (包括学习新技术) 45 60
• Design Spec • 生成设计文档 30 30
• Design Review • 设计复审 30 35
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 30 20
• Design • 具体设计 150 160
• Coding • 具体编码 700 670
• Code Review • 代码复审 100 80
• Test • 测试(自我测试,修改代码,提交修改) 120 150
Reporting 报告 95 125
• Test Report • 测试报告 20 30
• Size Measurement • 计算工作量 25 35
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 50 60
合计 1278 1330

郑宏骏:

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 50
• Estimate • 估计这个任务需要多少时间 40 60
Development 开发 1235 1200
• Analysis • 需求分析 (包括学习新技术) 50 50
• Design Spec • 生成设计文档 30 30
• Design Review • 设计复审 30 35
• Coding Standard • 代码规范 (为目前的开发制定合适的规范) 30 20
• Design • 具体设计 150 160
• Coding • 具体编码 700 670
• Code Review • 代码复审 90 100
• Test • 测试(自我测试,修改代码,提交修改) 120 150
Reporting 报告 95 125
• Test Report • 测试报告 20 30
• Size Measurement • 计算工作量 25 35
• Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 50 60
合计 1300 1350

产品展示

  • 登录界面:(有验证码功能,首页可以中英文切换)


  • 注册界面(有正则验证邮箱,密码用户名查重)

  • 用户密码找回(通过邮箱发重置密码页面到用户邮箱)

  • 修改密码

  • 修改邮箱

  • 主页面

  • 论文列表(支持分页查询与分页显示,点击删除可以删除该论文)

  • 论文搜索(模糊查询)

  • 图表


  • 图表互动(点击图标的条子,可以直接搜索该条子关键词的论文)

设计思路

![img](file:///F:\qq记录\Tencent Files\1315740835\Image\C2C\150DECB1A3805DFF0FB0506E339A1415.png)

采用:springboot+thymlf+echarts+html+mybatis+js+css+PageHelper

  • 数据库表设计

  • 一人前端一人后端

  • 最后把前端页面给后端,用springboot+thymlf整合

讨论过程

  • 上次结对因为没有开学,都是线上讨论,比较不太方便。这次线下,我们两个人线下交流,课后一起讨论功能与样式,明天都有1-2个小时的固定时间来进行讨论,设计接口与页面样式,明天相互汇报进度与困难,一起攻克。
  • 根据每天的课程时间来安排讨论与代码的时间,课少多写,课多少写一些。
  • 我们先注重完善基本功能,再实现拓展功能。
  • 我们这次比较注重用户的体验,所以用户方面的基本功能写的比较多。
  • 遇到了比较大的困难,相互打气,去百度,请教同学等,直到问题被解决。

关键代码展示

  • mybatis的数据库操作(查询。模糊查询。删除)
<mapper namespace="com.yrc.mapper.PaperMapper">

    <select id="querypaperList" resultType="com.yrc.pojo.paper">
        select * from paper
    </select>


        <select id="search_by_gjc" resultType="com.yrc.pojo.paper" parameterType="String">
        select * from paper where keywords  LIKE '%${gjc}%'
    </select>


    <delete id="delete_paper" parameterType="int">
        delete from paper  where id=#{id}
    </delete>

</mapper>
  • controller层的搜索接口(PageHelper分页)

    @RequestMapping(value = "/search")
    public String search(Model model,@RequestParam(defaultValue = "1") int pageNum,
                         @RequestParam(defaultValue = "10") int pageSize,
                          @RequestParam("gjc") String gjc) {
        PageHelper.startPage(pageNum,pageSize);
        System.out.println(gjc);
        PageInfo pageInfo1=new PageInfo(paperMapper.search_by_gjc(gjc));
        model.addAttribute("pageInfo1",pageInfo1);
        model.addAttribute("gjc",gjc);
        return "lunwen/list1";
    }
    
  • controller的删除接口(PageHelper分页)

    @RequestMapping("/delete/paper/{id}")
    public String delete(HttpSession session, Model model,@RequestParam(defaultValue = "1") int pageNum,
                         @RequestParam(defaultValue = "10") int pageSize,
                         @PathVariable("id") int id){
        paperMapper.delete_paper(id);
        PageHelper.startPage(pageNum,pageSize);
        PageInfo pageInfo=new PageInfo(paperMapper.querypaperList());
        model.addAttribute("pageInfo",pageInfo);
        return "lunwen/论文列表";
    }
    
  • 用户的登录验证码检验与密码加盐

if (!CodeUtil.checkVerifyCode(request)) {
    System.out.println("验证码错误");
    model.addAttribute("msg", "验证码错误");
    return "index";
}
Subject subject = SecurityUtils.getSubject();
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());//密码MD5加密
//2.封装用户数据
UserToken token = new UserToken(username, md5Password,"User");
try {
    subject.login(token);//执行登录方法
  • 防止XSS注入
/**
 * 拦截防止xss注入
 * 通过Jsoup过滤请求参数内的特定字符
 * @author yangwk
 */
public class XssFilter implements Filter {
    private static final Logger logger = LogManager.getLogger();

    /**
     * 是否过滤富文本内容
     */
    private static boolean IS_INCLUDE_RICH_TEXT = false;

    public List<String> excludes = new ArrayList<>();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,ServletException {
        if(logger.isDebugEnabled()){
            logger.debug("xss filter is open");
        }

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        if(handleExcludeURL(req, resp)){
            filterChain.doFilter(request, response);
            return;
        }

        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request,IS_INCLUDE_RICH_TEXT);
        filterChain.doFilter(xssRequest, response);
    }
  • 图表显示部分代码
<script type="text/javascript">
//定义echart对象
    var myChart = echarts.init(document.getElementById('main'));
    //设置option参数
    option = {
       // backgroundColor:'#323a5e',
       grid:{
            left:'4%',
            right:'4%',
            bottom:'4%',
            top:'4%',
            containLabel:true
       },
       tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'shadow',
                animation: true
            },
            triggerOn: "mousemove",
            alwaysShowContent: true,
            position: function(pt) {
            return [pt[0], 130];
            }
            
        },
       legend :{
            data:['CVPR'],
            right:100
       },
        yAxis: {
            type: 'category',
            name:'keywords',
            data: ['learning (artificial intelligence)', 'feature extraction ', 'training ', 'image reconstruction', 'neural nets', 'task analysis', 'computer vision','cameras','object detection','image segmentation'],//横轴
            axisLine:{
                show:true,
                LineStyle:{
                    color:'red'
                }
            },
  • 论文列表显示部分代码
<tr>
    <th>title||</th>
    <th>typeandyear||</th>
    <th>keywords||</th>
    <th>releasetime</th>
    <th>link</th>
</tr>
</thead>
<tbody>
<tr th:each="paper:${pageInfo.list}" id="tableInfo">
    <td th:text="${paper.getTitle()}"></td>
    <!--新增--><td th:text="${paper.getTypeandyear()}"></td>
    <td th:text="${paper.getKeywords()}"></td>
    <td th:text="${paper.getReleasetime()}"></td>
    <td      >
        <a th:href="${paper.getLink()}">
            论文链接点此
        </a>
    </td>
    <td>
        <a class="btn btn-sm btn-danger" th:href="@{/delete/paper/}+${paper.getId()}">删除</a>
    </td>
  • 登录注册等验证码工具
public class CodeUtil {  //验证码工具
//    /**
//     * 将获取到的前端参数转为string类型
//     * @param request
//     * @param key
//     * @return
//     */
    public static String getString(HttpServletRequest request, String key) {
        try {
            String result = request.getParameter(key);
            if(result != null) {
                result = result.trim();
            }
            if("".equals(result)) {
                result = null;
            }
            return result;
        }catch(Exception e) {
            return null;
        }
    }
//    /**
//     * 验证码校验
//     * @param request
//     * @return
//     */
    public static boolean checkVerifyCode(HttpServletRequest request) {
        //获取生成的验证码
        String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
        //获取用户输入的验证码
        String verifyCodeActual = CodeUtil.getString(request, "verifyCodeActual");
        if(verifyCodeActual == null ||!verifyCodeActual.equals(verifyCodeExpected)) {
            return false;
        }
        return true;
    }
}

心路历程

  • ZHJ:这是第一次合作写前端页面,以前只有在web课上学过,但是当时用的是框架,样式基本都用它自带的,然后基本不太需要自己打,然后这次是比较完整的写前端,感觉很新,也是第一次接触layui,vue还有echarts。这次使用标签语言,刚开始上手感觉有点难受,然后通过慢慢地查看官方文档,测试实例,不断学习,在一些代码上修改测试,不断懂得一些原理,开始慢慢实践。在写的过程中,一步一步地将页面完善起来,将一个个组件组合起来形成一个页面,还是挺有成就感的。做的时候和队友讨论样式的布局和一些观点,编写文档,调用接口都让我学到了新的知识,让实力得到了提高。

  • YRC:这是我第三次写后端,但是之前太久没写了springboot有些前后端交互的数据传输不熟练了。传值函数与一些规范格式忘的比较多,比如mybatis中的mapper因为多写了一个;使得一直报错,让我改了一晚上。有一些页面跳转也变得有些不熟练。但是通过去研究之前自己写的项目,慢慢的重新学习,使得数据库等操作都变的得心应手,把一个一个零散的页面与后端结合起来,再组成一个完整的项目,挺有趣的。使我的能力有了较大的提高。

相互评价

  • ZHJ:第二次和RC结对合作,从寒假线上语音交流的不方便,到现在在一个宿舍,随时都能够交流。由于我没有做过前后端合作的项目,这次在RC的帮助下理解了很多概念,懂得接口到底是什么,懂得如何调用传递参数。在宿舍,有时候想到点子就能立马交流,大家在交流的过程中会发现到一些对方的盲点,并相互帮助,合作解决问题。
    RC是一个乐于助人的队友,经验比我丰富,愿意带着我学习,和他合作得到了很多经验,获得了成长。

  • YRC:这是第二次与骏合作,之前线上交流不便,隔着一个屏幕,有苦说不出。这次在一个宿舍里,随时都可以交流,十分愉快。在骏的交流下,知道了前端的js与css是如何使得页面样式改变的。有困难马上就可以讨论,在百度、博客中寻找答案。一起解决问题。

    骏是一个助人为乐的队友,经验也丰富,和他一起讨论问题很快乐,学到了很多前端知识,获得了很多的经验,找到了许多问题的答案。

posted @ 2021-03-31 22:56  boynextdoor♂  阅读(173)  评论(5编辑  收藏  举报