大三寒假赋闲在家,闲来无事,用了5天时间做了一个在线学习的小网站,一鼓作气部署上线,制作的过程比较坎坷。内心经历过奔溃,也经历过狂喜。
按照惯例先放出网址,欢迎大家来访问学习:www.pbjlovezjy.com
我采用的技术栈是:SpringBoot + MySQL + Mybatis + Vue.js + Redis
虽然最开始有想过用微服务来做,但后来考虑到这只是一个小网站,秉持着杀鸡焉用牛刀的原则,就直接采用前后端分离的架构来做了。
做这个网站的浅层目的:主要是提供一些能够在线学习的资料,比如之前在复习新思想、毛中特这些思政课的时候,会发现找不到课后题的答案,最后花费了很多时间,东拼西凑,才最终找齐,感觉很浪费时间。
同时资料也很难做到随时随地背诵,有时候上厕所想背一下,都要把电脑上的PDF传到QQ里,才能打开看看,而且字体很小,看着很累人。
所以我就做了一个能够在线学习的网站,同学们不论是走路、坐车、吃饭还是睡觉,只需要打开网页,然后想看哪章点哪章就能在线复习了,简直就是懒人福音,非常nice。
做这个网站的深层目的:是为了能够给更多的大学生提供便捷的资源获取渠道,网络上的那些资料质量参差不齐,像我以前年少、涉世未深的时候也经常被骗,所以不希望有同学被一些不良商家割了韭菜,无情坑骗,买到不适合的资料。
下面言归正传:
我主要想说开发过程中3件令我感觉比较崩溃的事情:
第1件事,让我足足奔溃了1个晚上——数据录入。没错就是数据录入,整个网站虽然只有2张表,但content这张表却让我足足录入了6个小时...
起初我是想把数据直接写在html中,但这样写死之后后期不方便维护,所以我就想:通过搭建一个html模板来实时获取数据库中的数据,对数据进行展示。这样后期需要改动的时候,我只需要打开数据库进行修改就好。html框架如下:
<template>
<div class="app sidebar-mini" id="app">
<div :style="{ marginLeft: this.$store.getters.status ? '70px' : '240px', width:'84%' , marginTop: '60px' }">
<div class="tile mb-4" >
<h2 id="typography">第一章:新时代坚持和发展中国特色社会主义</h2>
</div>
<div v-for="(section, index) in sections" :key="index">
<div class="tile mb-4">
<h4>{{section.title}}</h4>
<div v-for="(part,index) in section.content" :key="index">
<p style="text-align: left;font-size: 18px;line-height: 1.9;text-indent: 2em;">{{part}}</p>
</div>
</div>
</div>
</div>
</div>
</template>
但是数据录入数据库的过程真的很枯燥繁琐,我也没想到有什么好方法能一次性把数据录入。
就拿新思想来举例,一门新思想课程分为17个大章节,在每个大章节里面还有4-5个问题,这样一门课下来要录入6、7十条的数据,一方面录入的数量很多,另一方面还要考虑分段和展示的问题,所以要求录入很精细,速度很慢,加上做的是重复动作,因此感觉很疲劳崩溃。
甚至有那么一瞬间,我似乎明白了程序员为啥会戏称自己为码农了。。
第2件事,让我整整难受了1天。那当属用拦截器来做权限的管理。
之所以在我的这个网站中需要做权限的管理,主要是为了区分出3类用户:1.未登录用户。2.已登录用户,但未付费。3.已付费用户。
不同类型的用户只能访问资源的不同章节,比如未登录用户只能访问前10%的章节,已登录但未付费用户,只能访问前30%的章节,只有付费用户才能访问全部章节。
之所以不敢让未登录用户访问太多章节的原因是,怕出现安全问题。比如不排除某些“坏人”,会通过疯狂访问公共资源来破坏数据库,使其过负载。
有人可能会说你可以把公共资源放到redis缓存里呀,这样你就不用害怕“坏人”DOS攻击了(但很显然我想到了,现在还没来得及这么做,不过后面应该会做)。
因此我选择仅开放一部分的资源,另一部分资源用拦截器拦截下来,避免对数据库造成冲击。
下面给大家简单看一下拦截器:
实话说代码并不复杂, 但逻辑比较复杂。比如JwtTokenAdminInterceptor这个拦截器主要是拦截未登录的用户,放行公共资源。然后TestInterceptor这个拦截器主要是为了拦截未付费用户,放行已登录用户能访问的所有资源。
然而这里面还有更复杂的,比如用户购买2门课程,可以是毛中特和新思想,也可以是近纲和马原。
一开始我觉得这是一个排列组合的问题,一个人在5门课中,可以选择只买1门,也可以选择全买,也可以选择买2门或者3门或者4门。这样子的话组件的情况会变得非常多,差不多是22种情况,难道每种情况都要写一个拦截器吗?
但经过我的苦思冥想(实则是GPT给我的思路),我采用了一个string来模拟bitmap,当某1位上为5代表用户没购买,当某1位上为1代表用户购买,只需要把为5的资源对应的请求地址加入到拦截器中即可,这样就可以实现只拦截用户没购买的资源。
之所以我最开始没想到这点,还是因为对拦截器的性质不太熟练。
具体实现可以详见上面的代码。
第3件事,让我整整难受了3天。那当属网站上线后改前端的界面和BUG。
因为在电脑上看页面屏宽很宽,可以显示完全,如下图:
但因为手机屏幕的宽度只有450作用,所以PC端看上去好好的界面,一到手机上就会变成一坨*。
此时有2种解决方案:
1.单独设置css样式PC端和移动端的代码,使得用一套代码来实现2种页面效果。
2.写2套代码,2套界面,通过地址访问不同的界面。这种一般是早期的做法,工作量太大。
秉持敏捷开发的原则,我舍弃了第2种方法,采用了第1种方法。
然后涉及到几个问题:
比如学习制作自适应页面代码的语法,然后一步步调试。
还有在一些不熟悉的css组间中反复挣扎,一会儿组间要横向摆放,比如“资源付费”界面,一会儿要竖向摆放;一会儿这个组件消失了,一会儿那个组件被遮挡了,要调位置还要调优先级。
一会儿这里好了,一会儿那里出问题了,在崩溃和喜悦之间反复横跳。
这里的过程就不多说了,实在是辛酸的血泪史。
中间还有一些插曲,比如说我的导航栏和侧栏是单独放在App.vue里的,然后主体界面是在vuews里面,就会涉及到不同组件之间共享变量的调用问题。
所以我感觉最难的根本不是后端代码,而是前端代码。。。
好了好了,接下来就说一些值得开心和喜悦的事吧。
第1件事,当然是独立部署上线了一个网站,能够让亲朋好友们在线访问,跟他们说这是我的网站,真心有满满的自豪感啊。
第2件事,攻克了很多的困难,从0-1搭建了一个网站,包括后端和前端,把一些学习到的知识现学现用,活学活用,加深了对知识的理解,在过程中也很享受改BUG的过程,当一切都基本完成之后,心中的喜悦明显会居多。
下面是一些代办事项,看着一件件待办事项被完成、划掉,内心充满自豪感。
但是不可否认的是网站当前还存在有一些问题,比如但不仅限于如下:
1.没有把公共资源缓存到Redis中;
2.SSL证书还没有办理,导致网站属于不安全状态;
3.数据库的设计不太合理,不符合第3范式。
4.界面上仍旧有需要改进的地方,比如在移动端显示下登录栏和注册栏时常会“分家”,一个掉到下面,一个挂在上面;
5.还有登录和注册的安全机制仍旧有待加强,比如还没有限制1人1手机只能注册1个账号;登录的时候也没有验证码,无法防止机器人恶意登录;登录校验也没有用更安全的Spring Security,仅仅只用了一个JWT的Token校验。
综上:我想说的是,尽管世界就像代码一样,仍旧有许多不完美的地方,但我相信在新的一年,会通过你我的共同努力,让其慢慢变得更好。
在此祝新老粉丝朋友们,新的一年心想事成,万事如意,龙年大吉。