这个作业属于哪个课程 | 福州大学-202302软件工程实践 |
---|---|
这个作业要求在哪里 | 结对第二次作业–编程实现 |
结对学号 | 222100224、222100225 |
这个作业的目标 | 学习前端页面的编写、JSON数据处理、页面渲染、前后端信息传输 |
其他参考文献 | 《构建之法》 |
文章目录
一、 Gitcode地址
二、PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Analysis | 需求分析 | 60 | 40 |
Learning | Vue/Springboot框架学习 | 200 | 200 |
Discussion | 结对讨论/接口设计 | 60 | 40 |
Design | Vue前端页面设计 | 400 | 400 |
Create | Springboot后端实现 | 300 | 300 |
Test & Improve | 前后端联调 | 120 | 120 |
Server deployment | 服务器部署 | 180 | 200 |
Postmortem | 总结 | 20 | 20 |
Blog writing | 博客编写 | 50 | 50 |
合计 | 1390 | 1370 |
三、项目访问链接
四、项目展示
- 具体效果请点击跳转网页查看
4.1 首页
- 首页在页头的基础上添加一个轮播图,展示了有关比赛的一些图片。
4.2 每日赛事
- 根据导航栏所选择的比赛类型,展示比赛时间,支持点击跳转查看详细赛事。
4.3 详细赛况
- 根据导航栏选择的比赛类型,展示该分类下包含的赛事。
- 进一步点击赛事折叠面板查看详细比赛结果。
- 比赛结果分为半决赛,总决赛等多种,支持赛程切换。
4.4 选手信息
- 根据比赛类型展示本类型的参赛选手信息,包括国籍、性别、出生日期。支持切换比赛类型查看不同比赛的选手信息。
4.5 奖牌榜
- 根据最终排名顺序展示国家获奖情况;展示各个国家的总奖牌数、金牌、银牌、铜牌的数量。
4.6 了解更多
- 展示有关本次赛事的信息;末尾提供本次赛事官网跳转链接以便用户查看更多信息。
五、结对讨论描述
-
(1)首先确定使用的框架以及技术,springboot框架先前已有所涉猎;故本次作业主要问题在于前端的技术实现,最终在宿舍里商讨决定使用Vue框架配合Element组件进行前端页面的制作,再通过后端Springboot传递数据给前端页面进行渲染。
-
(2)第二步是需求分析与设计接口,先初步分析需要的数据,根据作业要求设计接口文档,在编写过程中进一步优化与联调。
-
交流截图(Gitcode分支;初步接口文档;联调URL):
-
(3)接口文档最终在Swagger上呈现,前后端联调只需要连接同一个局域网,并访问对方的IP地址及端口即可连接到队友,通过这种方式进行联调并查看Swagger上的接口文档。
-
Swagger上的接口文档截图:
-
(4)各自编写代码,在同一局域网下只需开启服务器就可以相互进行联调测试,逐步修改bug完善项目。
-
(5)服务器部署,参照网上服务器部署教学资源学习服务器部署,选用阿里云的服务器,最终成功部署前后端。
-
前后端分别部署在两台服务器上,互相给出服务器IP地址,连接对方服务器。
-
(6)结对讨论:实际上为舍友,直接了当的语言沟通。
六、实现过程&功能结构图
-
开发具体步骤如下:
-
前端开发(使用Vue和Element组件):
- 创建首页及通用页头ElementView。
- 创建选手信息页面:展示所有选手的信息,使用Element的el-table组件实现表格展示。
- 创建每日赛况页面:创建一个比赛列表,展示比赛的名称及日期,对于决赛加粗并红色突出显示,el-table的点击事件完成赛事的点击查看详细情况。
- 创建详细赛况页面:展示比赛的名称在折叠面板el-collapse上,点击可下拉展示详细内容;点击下拉后可以通过el-tags组件选择赛程并通过el-table组件展示其比赛结果,包括选手排名,比赛积分,落后积分等信息。
- 创建奖牌榜页面:展示各个参赛国的获奖情况,直观展示国家排名与各个国家奖牌的获取情况。
- 创建了解更多页面:展示一些有关本次比赛的信息,并在最后提供官网链接以便查看更多相关信息。
-
后端开发(Springboot框架)
- 创建选手信息API:实现获取所有选手信息的接口,包括Country,Athlete,Gender,DOB等信息,封装后返回给前端。
- 创建每日赛况API:实现获取每日赛事的接口,根据比赛类型分类,封装比赛时间、比赛进程等信息给前端渲染。
- 创建详细赛况API:第一个接口根据用户选择的赛事类别,封装本赛事类别下的所有赛事给前端渲染,供用户选择查看哪一个具体赛事;第二个接口根据用户点击的具体赛事的折叠面板,前端传来具体赛事名称,根据赛事名称提取该赛事的选手排名、比赛积分、落后积分等比赛信息,封装完成后返回前端。
- 创建奖牌榜API:提取各个参赛国获得的奖牌情况与奖牌数量排名进行封装后返回前端渲染。
-
开发完成后进行前后端联调与服务器部署:
- 前后端联调在同一局域网下互相访问即可联调。
- 服务器部署在初始化服务器后将后端jar包与前端打包完的dist包上传到服务器,修改配置后启动nginx渲染前端,启动jar包运行后端即可正常访问页面。
-
功能结构图:
七、关键代码展示
7.1前端关键代码
1.请求事件
使用element组件需要编写一些点击事件从后端接受数据并渲染。
export default {
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
//Tabs点击事件
tabHandleClick() {
axios
.get(MyUrl.urlDetail, {
params: { event: this.activeName },
})
.then((result) => {
this.items = result.data.data;
});
},
//折叠面板点击事件
handleChange() {
this.tabActiveName2 = "Finals";
if (this.collapseActiveName != null && this.collapseActiveName != "") {
axios
.get(MyUrl.urlDetails, {
params: {
event: this.activeName,
sportsName: this.collapseActiveName,
},
})
.then((result) => {
this.tabItems = result.data.data.map((item) => item.phaseName);
this.result2 = result.data.data;
this.tableData2 = this.result2.filter(
(item) => item.phaseName === this.tabActiveName2
)[0].players;
console.log(
this.tabActiveName2 + "tableData21->" + this.tableData2
);
});
}
},
//tab2点击事件
tabHandleClick2() {
this.tableData2 = this.result2.filter(
(item) => item.phaseName === this.tabActiveName2
)[0].players;
console.log(this.tabActiveName2 + "tableData22->" + this.tableData2);
},
},
//钩子方法
mounted() {
axios
.get(MyUrl.urlDetail, {
params: { event: this.activeName },
})
.then((result) => {
this.items = result.data.data;
});
},
};
</script>
2.页面代码
页面的制作需要注意其格式排版,不断微调以达到最好的展示。以下是一小部分页面绘制的代码:
<!-- 折叠面板 -->
<el-collapse
v-model="collapseActiveName"
accordion="true"
@change="handleChange"
style="margin-left: 200px; margin-right: 200px"
>
<el-collapse-item
v-for="(item, index) in items"
:key="index"
:title="item"
:name="item"
style="margin-left: 20px; margin-top: 15px"
><template #title>
<span
style="
color: #3299cc;
font-weight: bold;
font-size: 1.5em;
padding-left: 110px;
"
>{{ item }}</span
>
</template>
<!-- 折叠面板内部标签 -->
<el-tabs
v-model="tabActiveName2"
@tab-click="tabHandleClick2"
style="position: relative; width: 380px; left: 30%; top: -10px"
>
<el-tab-pane
v-for="(item, index) in tabItems"
:key="index"
:label="item"
:name="item"
></el-tab-pane>
</el-tabs>
<!-- 内层表格渲染 -->
<el-table
:data="tableData2"
border
style="
margin-left: 110px;
margin-top: 10px;
padding-top: 10px;
"
>
<el-table-column prop="overallRank" label="选手排名" width="200px">
</el-table-column>
<el-table-column prop="fullName" label="参赛选手" width="200px">
</el-table-column>
<el-table-column
prop="points"
label="比赛积分/比赛用时"
width="200px"
>
</el-table-column>
<el-table-column prop="pointsBehind" label="落后积分" width="200px">
</el-table-column>
</el-table>
</el-collapse-item>
</el-collapse>
7.2后端关键代码
1封装文件操作代码
1.1文件提取:
以下两个为示例:主要就是根据传递进来的参数值去访问不同的文件,然后返回一个流,便于后续将json文件转为字符串
@ApiOperation("传入赛事类别,获取选手信息文件")
public static InputStream getAthletesFile(String event){
String fileName = event + "/athletes.json";
InputStream input = ClassUtils
.getDefaultClassLoader()
.getResourceAsStream("results/athletes/" + fileName);
return input;
}
@ApiOperation("获取项目文件")
public static InputStream getSportsDetailsFile(String event,String sportsName){
String fileName = event + "/" + sportsName + ".json";
InputStream input = ClassUtils
.getDefaultClassLoader()
.getResourceAsStream("results/events/" + fileName);
return input;
}
1.2将json文件转为字符串:
利用流读取文件,将其拼接在StringBuffer对象后面,再利用toString方法进行转换
@ApiOperation("将json文件转为字符串")
public static String JSONToString(InputStream inputStream) {
String finalStr = "";
StringBuffer jsonStrBuffer = new StringBuffer();
try{
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
int data;
if(bufferedInputStream != null){
while((data = bufferedInputStream.read()) != -1){
jsonStrBuffer.append((char) data);
}
finalStr = jsonStrBuffer.toString();
}
bufferedInputStream.close();
}
catch (FileNotFoundException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
return finalStr;
}
2.网页接口编写
这里根据前端页面主要分为4个部分,选手信息、国家奖牌、赛事详情、赛事时间表这几个功能,每个功能编写一个接口,这里就展示一个接口。
public List<MatchSchedule> showEventSchedule(String event) {
String jsonStr = fileUtils.JSONToString(fileUtils.getTimeScheduleFile(event));
JSONArray jsonArray = JSON.parseArray(jsonStr);
List<MatchSchedule> matchSchedules = new ArrayList<>();
for(int i = 0; i < jsonArray.size(); i++){
JSONObject object = jsonArray.getJSONObject(i);
MatchSchedule matchSchedule = new MatchSchedule();
matchSchedule.setDisciplineName(object.get("DisciplineName").toString());
matchSchedule.setDate(object.get("Date").toString());
matchSchedule.setPhaseName(object.get("PhaseName").toString());
matchSchedules.add(matchSchedule);
}
return matchSchedules;
}
这是时间表接口里面的展示时间表接口,主要就是根据传过来的json字符串,根据格式,提取所需要的信息,将其封装,返回给前端。
3.返回数据格式封装
由于返回给前端的数据格式比较统一,故封装成一个类,之后调用类里面的静态方法传递数据。
这里偷了个懒,只处理了成功数据的返回
public class R<T> {
private String msg;
private Integer code;
private T data;
public static <T> R success(T data){
return new R("操作成功",200,data);
}
}
八、总结收获&评价队友
后端开发(222100225_林璞):
8.1.1后端开发总结收获
本次结对编程,我们组是采用前后端分离的模式,后端数据存储是直接爬取json数据,保存在本地,没有封装到数据库里,有点像第二次作业的文件读取 ,后端提取完数据后,再根据前端所需,传递相应封装好的数据。
其实后端接口基本编写是很快的,因为不需要去跟数据库做交互,实际上没有什么接口。很大一部分时间都是花在调试上面。将java项目导成jar包后,部署到了服务器后,很多文件读写的操作都会报错。
就比如上面这个函数,是去文件中读取对应的赛事详情,一开始是采用File类,根据路径得到相应文件,再将文件内容传给处理接口去处理,在本地调试很顺利,一遍就成功了,在部署到服务器上后,疯狂报错… 之后便是“面向CSDN编程‘,上网查询资料,整合大家踩过的坑,最后决定采用读取文件流的形式,这样子就不需要得到文件的具体路径了,直接通过流传递文件,排除了bug。
此外,在这次开发过程中,我们小组使用了swagger + knife4j去生成接口文档,该文档集成了接口参数说明,接口请求路径说明等等,此外还有在线api调试功能,给我们前后端联调提供了很多帮助(虽然一开始老是找不到自己的ip地址罢了)。
在部署服务器方面,感谢阿里云的学生免费服务器以及其配套的配置教程,部署起来非常快,也很方便。由于这个项目比较基础,所以跟着网上教程配置,很快就完成了项目的部署。
总而言之,本次结对编程还是学到了很多东西,尤其是linux的指令操作,掌握一些常用的指令,然后对java文件流操作也更加熟练了,除此之外,自己整合资料的能力也得到了锻炼(网上七七八八的解决方案看的头疼…)。总的来说,还算是一次收获颇多的编程作业。
8.1.2对队友的评价
在前后端联调的过程中,我这边接口有的地方没写清楚,及时与我沟通,解决问题,积极参与讨论功能点的设计和实现,代码编写遵守代码规范,代码提交遵守规定时间,不拖拉。
前端开发(222200224_林然鹏):
8.2.1前端开发总结收获
这次开发,同样是有不少的困难。首先难点在于前端知识的匮乏,先前学过的SpringBoot框架主要是基于后端的开发,对前端的认知还停留于传统三大件,为了完成本次作业,临时加班学习了Vue框架的使用以及部署,在NPM安装Vue的过程中也有一些小问题需要解决,学习完了Vue后再尝试使用Element组件,利用组件绘制页面并不断调整页面样式,较花时间。
页面绘制完成后,还需要根据接口文档编写一系列的事件响应接收参数,对于后端传来的数据,如果结构稍微复杂一点,就需要在方法中进行分析拆解,容易混淆。
最后是服务器的部署,因为是第一次部署服务器,需要一点一点看文档学习部署,并且使用的是一点页不熟悉的Linux指令,操作起来有些许困难,进度缓慢。
本次作业收获不少,尝试了Vue绘制前端页面,尽管很花时间进行美观调整;也学习了有关服务器部署的步骤,是一次很宝贵的开发经验。
8.2.2对队友的评价
编写了较完善的接口文档,方便前端阅读,积极参与讨论功能点的设计和实现,代码编写遵守代码规范,代码提交遵守规定时间。