结对作业(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是如何使得页面样式改变的。有困难马上就可以讨论,在百度、博客中寻找答案。一起解决问题。
骏是一个助人为乐的队友,经验也丰富,和他一起讨论问题很快乐,学到了很多前端知识,获得了很多的经验,找到了许多问题的答案。