電子產(chǎn)業(yè)一站式賦能平臺

PCB聯(lián)盟網(wǎng)

搜索
查看: 35|回復(fù): 0
收起左側(cè)

畢業(yè)設(shè)計(jì)So Easy:Java Vue SpringCloud實(shí)現(xiàn)博客系統(tǒng)

[復(fù)制鏈接]

601

主題

601

帖子

4762

積分

四級會員

Rank: 4

積分
4762
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2023-6-28 12:00:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
9 S) n( y0 U: K- i# N0 G
點(diǎn)擊上方藍(lán)色字體,關(guān)注我們
7 ^8 m: p6 M" ^. F8 F+ R很多計(jì)算機(jī)專業(yè)大學(xué)生經(jīng)常和我交流:畢業(yè)設(shè)計(jì)沒思路、不會做、論文不會寫、太難了....... b) n$ N1 c3 y4 ?. O

: x6 l$ d0 T8 d5 I9 s  c針對這些問題,決定分享一些軟、硬件項(xiàng)目的設(shè)計(jì)思路和實(shí)施方法,希望可以幫助大家,也祝愿各位學(xué)子,順利畢業(yè)!
( ]6 x# ?7 _+ w" [( K
/ l& ^, {9 S# T, G9 @8 x; [+ m
  d, b* D9 U8 }. k3 h( @8 ^+ N% ?2 j1 h0 l( P) \. F4 O0 f. Q) ]

7 h3 l% y/ R5 N1 |, [" ^! K8 a( ^# R對計(jì)算機(jī)技術(shù)感興趣的小伙伴請關(guān)注公眾號:美男子玩編程,公眾號優(yōu)先推送最新技術(shù)博文,創(chuàng)作不易,請各位朋友多多點(diǎn)贊、收藏、關(guān)注支持~0 T2 V2 f2 O" }9 u

6 H1 S1 F3 Y. D項(xiàng)目專欄:https://blog.csdn.net/m0_38106923/category_11085518.html
- f& \! c, u; `3 l* H) x* U博客是互聯(lián)網(wǎng)的一種分享類型的技術(shù)產(chǎn)物,但是如何留著用戶才是重要的,并不都是所有的功能都會涉及到“高并發(fā)”,博客的功能多樣性會增強(qiáng)用戶的體驗(yàn),讓用戶對博客的使用產(chǎn)生依賴性,利用從眾心態(tài)合理地開發(fā)增值功能。
) m; N6 \: k& o0 Y: d( f& T' A+ z' M3 U# j* z$ }; m
本次系統(tǒng)的開發(fā)采用了主流的微服務(wù)架構(gòu)方式,所以把控每個微服務(wù)的功能相互獨(dú)立和完整是“微服務(wù)”系統(tǒng)的關(guān)鍵。由于博客的實(shí)現(xiàn)比較簡單,所以只有涉及到“高并發(fā)”的時候需要斷點(diǎn)分析即可,下面將介紹博客系統(tǒng)的一些功能。! N1 u0 P" L" F  ]# R$ T& Z
$ a. X) I; R# S5 Y. l7 ]
項(xiàng)目工程資源請參見:https://download.csdn.net/download/m0_38106923/87849577
7 S: ]  {# J# m: \8 Q  J1  \- e( G: D7 v5 Q
項(xiàng)目功能6 }) t% ~6 i" e7 {$ B" Z
博客基本的功都具備,例如博客的核心功能:博客的發(fā)表,刪除,瀏覽,評論,點(diǎn)贊等。除了這些,還可以每天定時簽到提升博客的等級,充值會員提升使用體驗(yàn)。
5 o! x/ N- q" L$ q# a
$ C5 Q7 m* w! |8 E2 Q個人的安全信息也非常重要,所以我單獨(dú)劃分一個微服務(wù)中心來實(shí)現(xiàn)。同樣我在每行重要的代碼上都增加了明顯的注釋,這對于我以后的維護(hù)和擴(kuò)充博客功能可以打下堅(jiān)實(shí)的基礎(chǔ),盡可能地符合軟件設(shè)計(jì)開發(fā)原則。
$ O4 X: m* |0 n$ `. k
  r9 ~- f1 w: \6 H' ~3 _關(guān)于博客的功能一共涉及到8個微服務(wù)中心:
  • 用戶的個人中心:包含登錄、注冊、智能驗(yàn)證。
  • 用戶的安全中心:安全信息、手機(jī)與郵箱的基本功能和安全認(rèn)證的接口。
  • 用戶的博客中心:發(fā)表和管理個人的博客,游客可以瀏覽公開的博客。
  • 用戶的文件中心:發(fā)表博客需要用到的圖片和個人用戶的頭像。
  • 用戶的簽到中心:博客的簽到累計(jì)的經(jīng)驗(yàn)值和簽到獎勵。
  • 用戶的會員中心:包含普通會員和超級會員。
  • 用戶的支付中心:VIP的充值功能,個人錢包功能,賬單等。
  • 用戶的搜索中心:根據(jù)摘要或者文章標(biāo)題的關(guān)鍵字搜索指定的博客。1 ~6 d4 |  ]5 ~% z
    [/ol]
    $ @. s7 H/ |% a3 V6 D1 F2
    . p4 p8 W5 D, Y' z. z2 Q/ q& u1 \項(xiàng)目架構(gòu)設(shè)計(jì)
    : ^5 v0 T, R$ U% a  r# U  b
    / S; {- B7 c& c5 A
    # r6 V& ^) L/ b/ }) l從宏觀設(shè)計(jì)來說,各個微服務(wù)中心都是一個moudle,需要注冊到一個高可用的微服務(wù)注冊中心上保證機(jī)器信息的正確性。
    3 S, W3 z0 c8 \) u' B2 l# L
    3 T8 h) W% l7 _從微觀運(yùn)行來說,用戶的請求API都經(jīng)過Zuul,再由Zuul負(fù)載均衡分配給需要的微服務(wù)中心,所以Zuul也需要高可用保證用戶流量可以得到回應(yīng)。通過zuul網(wǎng)關(guān)后,請求通過Feign實(shí)現(xiàn)微服務(wù)之間數(shù)據(jù)的交互。
    , t, i5 V$ a  K  H' \
    2 @0 L0 k" c8 K7 v4 b- Y當(dāng)發(fā)生錯誤運(yùn)行時,利用Hystrix的回退機(jī)制保護(hù)系統(tǒng)的穩(wěn)定運(yùn)行,不會發(fā)生級聯(lián)占用效應(yīng),保證每一個請求API都可以得到響應(yīng)。當(dāng)發(fā)生網(wǎng)絡(luò)不可用的情況下,需要觸發(fā)用戶的補(bǔ)償機(jī)制,當(dāng)出現(xiàn)不可知的錯誤時,也可以直接管理機(jī)器的集群來維護(hù)系統(tǒng)的穩(wěn)定運(yùn)行。
    8 M9 e& B& {. V( q* I/ [30 h. r# O! E* b2 E
    項(xiàng)目數(shù)據(jù)庫設(shè)計(jì)
    1 G7 [9 z& I8 Q( t2 f對于用戶來說,需要輸入賬號和密碼,若是不存在可以注冊自己的賬號和密碼。注冊的時候提供30分鐘填寫博客信息的有效時間,不填寫則直接登錄。需要設(shè)置個人的手機(jī)和郵箱來綁定安全認(rèn)證,若想要開通我的錢包則需要實(shí)名注冊,同樣也包含校園認(rèn)證。丟失了個人信息,則可以用身份證申訴。每天凌晨開始可以開始簽到,根據(jù)會員的不同增益不同,簽到的持續(xù)天數(shù)不同經(jīng)驗(yàn)值累加也不同。會員的開通只包含支付寶,賬單是每筆消費(fèi)的記錄。核心表是用戶博客之類的表,文章均存在數(shù)據(jù)庫,不過ElasticSearch也保存了文章的標(biāo)題和摘要。每個用戶可以評論他人的文章,私密的文章不會出現(xiàn),會員的文章會出現(xiàn)在會員專區(qū)。
    2 G" f: |, @. {: z) r9 N3 y: `' N/ ^# q. w* w
    博客一共含有8個主功能,所以一共涉及用戶表,用戶信息表,安全表,頭像表,簽到表,簽到獎勵表(兩種獎勵),會員表,錢包表,訂單表,博客表,博客分類表,博客標(biāo)簽表,博客圖片表,博客的評論表,點(diǎn)贊表和收藏表17個表。
    . j/ U* I- U+ A. _: l4 I6 ]4 }  H% r# _! u
    # N! R6 U/ V6 G' @# n( `. G

    / T  q3 q) j3 x2 l( G" X4# O, B5 i% N+ H
    項(xiàng)目架構(gòu)實(shí)現(xiàn)
    ( ?0 J: L& ^9 ?4 E4.1、Vue架構(gòu)的實(shí)現(xiàn)
    6 q7 M4 A" x' S2 z6 y. e前端IDE采用的是WebStorm,博客的Vue主要分布如下圖所示:
      b6 e2 z5 \7 e' Z* S, Y. X8 V" U5 e$ g
    # w7 c8 \9 y$ Y" T- }
    5 G& S5 ~8 b4 `* @1 [8 n; R
    Alert.js是自定義重構(gòu)代碼的漂亮提示框。axios.js是封裝好的axios請求HTTP函數(shù),components是Vue文件存儲位置,也是Vue的組件,index.js是管理前端路由url的跳轉(zhuǎn),利用components組件與url的控制。store.js是組件狀態(tài)管理的文件,由于采用的LocalStorage本地存儲所以并不是主用。main.js是全局文件也是最重要的文件,管理Vue的全局配置。static/img中保存的是博客所用的圖片。
    9 c9 v  ]8 Y/ `  ?& R  Y, b不管是用IDE創(chuàng)建的項(xiàng)目還是采用常規(guī)腳手架創(chuàng)建的vue項(xiàng)目,其項(xiàng)目都會在根目錄生成一個package.json文件,這個文件與后端的“pom”相似,這個文件包含所需要的各種包,還包含項(xiàng)目的配置的名稱與版本對應(yīng)。
    9 a+ A3 z( q: R+ E3 p  z4 O+ v; v
    博客項(xiàng)目中的package的完整dependencies代碼如以下所示:+ _+ S! c- c# j! u1 g1 H
    8 |; r' p" S- s' u6 R) A" c% S
  • "dependencies": {    "axios": "^0.19.0",    "bootstrap": "^3.3.7",    "echarts": "^4.6.0",    "element-ui": "^2.12.0",    "font-awesome": "^4.7.0",    "github-markdown-css": "^4.0.0",    "highlight.js": "^9.18.1",    "jquery": "^3.4.1",    "marked": "^0.8.0",    "mavon-editor": "^2.7.7",    "popper.js": "^1.12.5",    "showdown": "^1.9.1",    "v-charts": "^1.19.0",    "view-design": "^4.0.2",    "vue": "^2.5.2",    "vue-drag-verify": "^1.0.6",    "vue-nocaptcha": "^0.2.8",    "vue-puzzle-vcode": "^1.1.2",    "vue-qr": "^2.2.1",    "vue-router": "^3.0.1",    "vue-schart": "^2.0.0",    "vue-splitpane": "^1.0.6",    "vuex": "^3.1.2" }
    : w0 I! V6 }$ r" W, A4.2、SpringCloud架構(gòu)的實(shí)現(xiàn)! s7 a* z- q* k& H! i/ o
    博客Maven的整體微服務(wù)中心實(shí)現(xiàn)的結(jié)構(gòu)圖如下所示:
    , a, f$ @7 i! E+ H  R8 K
    8 g3 O) Y! b4 Q  N9 l; E
    ; V( F" r. `; B
    " m! e  d1 R: f5 k  s4 |6 ^$ ySpringCloud是基于Java語言的工具集,SpringCloud具備拿來就用的特性,可以節(jié)省開發(fā)的配置時間,它可以在Docker等云環(huán)境中開發(fā)和部署。SpringCloud的組件比較豐富,博客使用了Eureka,Zuul,F(xiàn)eign,Htsrrix,trubine,Zipkin微服務(wù)組件。組件可以自由地選擇,不過需要解決SpringBoot與SpringCloud之間的版本依賴才能使用。博客涉及到的Java的JDK版本是1.8,SpringBoot的版本是Spring Boot 1.5.9.RELEASE,SpringCloud的版本是Edgware SR4。后端的IDE采用的是IDEA,Maven的版本為3.6.1,任何一個版本的更改都可能會導(dǎo)致兼容不一致。
      w/ ?7 Z! r: s% ^' O" w% P# L6 D' s  ~" w( k, M
    4.3、博客的高可用的實(shí)現(xiàn)
    ) a1 k4 L# n9 l& c6 h+ J+ p2 r博客使用了兩個Zuul并且注冊到高可用的服務(wù)發(fā)現(xiàn)中心來構(gòu)造Zuul高可用集群。Eureka是所有微服務(wù)的注冊中心,并且自己本身也是微服務(wù)不過需要禁止自我注冊。Eureka注冊中心包含每個微服務(wù)的名稱,IP,端口等,由于因?yàn)榈膯蝹節(jié)點(diǎn)的微服務(wù)可能會發(fā)生不可用的情況下導(dǎo)致系統(tǒng)發(fā)生停機(jī),所以采用高可用的微服務(wù)注冊中心。讓兩個(多個)服務(wù)發(fā)現(xiàn)組件相互注冊以達(dá)到可以保持其它微服務(wù)的調(diào)用,維持整個系統(tǒng)的高可用性,整個博客的Eureka服務(wù)注冊中心圖如下圖所示:
    - d3 o# h/ s5 D  A. D. ?
    9 O" {  y" ~9 o2 }/ t! M& L * f5 ~5 S" U9 Z: a6 j0 n4 H, X; J

    ) Z8 }- t6 w/ \# A' B" W" a5 jDS Replicas代表兩個模塊加載模擬單機(jī)代替高可用的實(shí)現(xiàn),不過需要修改本地Host來模擬真實(shí)多機(jī)高可用的效果。每個微服務(wù)都具有自己的虛擬主機(jī)名以及狀態(tài)來描繪微服務(wù)的顯示情況。每個微服務(wù)之間通過與服務(wù)注冊中心每30S心跳傳遞保證服務(wù)可用性。默認(rèn)90S沒有收到心跳則會注銷該微服務(wù)。EurekaServerOne與EurekaServerTwo為兩個微服務(wù)注冊中心,兩者相互注冊到對方的服務(wù)中心上來保證Eureka的高可用穩(wěn)定,從而使每一個博客的請求都可以得到響應(yīng)。7 z6 U, T9 c, d: J8 c& o- U
    5 g: ~0 \; k5 c4 Q; n7 C- I
    5( }' U: j! _1 L& N2 P+ l, L/ o% e
    用戶的個人中心, f  J4 n; a- g% f6 g+ J) t
    用戶的個人中心相當(dāng)于博客的大門,用戶的首次流量都經(jīng)過此處,首次負(fù)載均衡調(diào)用也是基于這個中心開始,主要涉及到用戶的登錄與注冊的基本功能,在登錄上排除惡意的攻擊與干擾,保證博客登錄的穩(wěn)定,從而保證系統(tǒng)的穩(wěn)定。這個中心核心功能就是權(quán)限驗(yàn)證,保持登錄的標(biāo)志,它是保持業(yè)務(wù)穩(wěn)定的重要因素,后續(xù)的實(shí)現(xiàn)會在以上所述的三個重要功能展開來講。
    . V: Y8 L; N% v9 L1 b
    / j' ~, k$ Q+ C5.1、登錄的智能驗(yàn)證) B- d5 F* I  ^
    Vue整合阿里云智能驗(yàn)證時,需要注冊布局組件來動態(tài)加載JavaScript文件,不然無法使用阿里云的智能組件,前端登錄智能驗(yàn)證的核心代碼如以下所示:9 |5 d- I. M6 i2 [

    6 s* m. h2 a5 ~: m
  • //動態(tài)加載阿里云的JavaScript文件src="//g.alicdn.com/sd/nvc/1.1.112/guide.js" @loaded="initCaptcha">
    1 a5 [8 F/ l7 i  k//注冊局部組件來加載阿里云的JavaScript文件components: {            "remote-js": {                render(createElement) {                    const self = this;                    return createElement("script", {                        attrs: { type: "text/javascript", src: this.src },                        on: {                            load() {                                self.$emit("loaded");                            }                        }                    });                },                props: {                    src: { type: String, required: true }                }            }        },
    5 G/ o, j) `- f* N. ~- g  G* |//點(diǎn)擊智能驗(yàn)證的封裝函數(shù)            initCaptcha() {                let _this=this;                let ic = new smartCaptcha({                    renderTo: '#sc',                    width: 350,                    height: 42,                    default_txt: "請點(diǎn)擊驗(yàn)證按鈕",                    success_txt: "博客登錄驗(yàn)證成功",                    fail_txt: "點(diǎn)擊按鈕重新刷新登錄驗(yàn)證",                    scaning_txt: "智能檢測中",                    success: function (data) {                        console.log(NVC_Opt.token);                        console.log(data.sessionId);                        console.log(data.sig);                        _this.aliToken=NVC_Opt.token;                        _this.sessionId=data.sessionId;                        _this.sig=data.sig;                    },                });                ic.init(); },/remote-js/ i! ]. X' B7 _0 Z- V+ v
    5.2、博客的登錄注冊7 w& ?# ~: @2 a# R
    登錄是一個系統(tǒng)的重要的功能,也是個人隱私的重要體現(xiàn),拿常見的登錄有郵箱,手機(jī),賬號或,語音或者二維碼登錄,不過不管通過哪種登錄,個人信息的安全都應(yīng)該得到保護(hù),保護(hù)個人隱私重要的是從個人做起,拒絕非法點(diǎn)擊與輸入。
    5 Y8 e  R- I) _# j& F) u( t; ~( K) R6 R) O6 f% Y) ]# _6 G
    拿本次博客的登錄來說只需要驗(yàn)證賬號和密碼就行,個人登錄是不會進(jìn)行權(quán)限驗(yàn)證。注冊成功會保持30分鐘的權(quán)限驗(yàn)證,關(guān)于權(quán)限驗(yàn)證會在標(biāo)題5-2-3中提到,以便后面的博客信息的操作,超過則需要重新登錄去博客的個人中心填寫博客信息。% e4 I6 G9 i' x9 |2 H- E% Q3 b: @) d
    博客的登錄與注冊的頁面如下圖所示:# e. o, J% r0 y! G" W, E4 e

    3 w" u3 n! |5 e
    $ @7 P% _1 ~& a' _1 y
    ) {8 y  t4 u7 [6 i博客登錄的用戶名需要以英文子母開頭,用戶名和密碼均不可以超過16位,注冊保證兩次登錄密碼正確就可,在此不再貼出圖片累述。- W- c! b$ ~% v- ^

    " y4 y# s* ~% J7 e1 G5.3、登錄的權(quán)限驗(yàn)證+ G- ]# }: ^* l; y& S
    登陸權(quán)限控制是每個系統(tǒng)都應(yīng)必備的功能,是保持登錄狀態(tài)的重要實(shí)現(xiàn)。微服務(wù)所有的權(quán)限驗(yàn)證均在一個module上,Token消時則直接回退給前端status 404失敗碼,成功則是執(zhí)行對應(yīng)的業(yè)務(wù)邏輯,注意登錄的博客是不需要權(quán)限驗(yàn)證。* U* ^! U$ Z9 w/ j6 b' i( J
    ( m; F# P" y" c% Z, i) F/ U
    博客使用了前后端攔截器攔截Token(登錄成功的認(rèn)證碼),所以后端需要定義一個token驗(yàn)證注解,用攔截器攔截系統(tǒng)的url請求,再進(jìn)行攔截用戶的API請求,最后再驗(yàn)證傳過來的token與Redis中token值是否一致,效驗(yàn)通過才可以正常訪問。當(dāng)用戶登錄成功博客后,后端返回token數(shù)據(jù)。token具有存在時間,如果用戶一段時間后不在線或者操作的話,則token會失效,用戶保持登錄時,則不會過期。
    $ M  X  {8 Y2 f. I4 z$ u" q. T
    0 L3 G. H& D, `) J. i: ]4 O6 mRedis中會以用戶的登錄賬號作為與token關(guān)聯(lián)的認(rèn)證,有效的token碼可以取出用戶的賬號,然后再進(jìn)行業(yè)務(wù)邏輯。這些redis中的key都可以自行設(shè)置一些時間,不過前端只保存token值,二次登錄會覆蓋Redis中的token值。
    / Y3 B9 s+ g3 X- Y: i; i
    ( w1 w- s8 F6 `! a) P% |; i . o" @3 O5 W" |# I

    ) e! [( x+ v+ F權(quán)限驗(yàn)證相當(dāng)于系統(tǒng)的第一道大門,如今的安全框架越來越豐富,例如SpringSecurity,Shiro,OAuth等,shiro->security->oauth的上手難度逐漸提升。若是需要對密碼加密的,可以需根據(jù)個人開發(fā)自行配置使用對應(yīng)的安全框架。2 N5 r. _" G9 ~& K# O: F% S/ a
    6
    3 d; d# p& D& H" M* c用戶的安全中心- w( E$ c+ B: R1 N: k. ~% G
    6.1、用戶的安全布局; n8 I3 E( {6 ^& t
    安全中心包含郵箱,手機(jī),身份證,校園認(rèn)證和其它微服務(wù)中心需要用到的認(rèn)證接口。郵箱采用QQ郵箱,開啟smtP 587端口發(fā)送郵箱驗(yàn)證碼。手機(jī)采用阿里云短信API服務(wù)。兩者的驗(yàn)證碼存在的時間均為1次失效且存在10分鐘。身份證需要手機(jī)號的驗(yàn)證。校園認(rèn)證的名字需要和身份證的名字一致。除了綁定一些安全的服務(wù),還包括三種修改密碼的方式,原始密碼修改新密碼,郵箱重置密碼,手機(jī)重置密碼,身份證重置密碼。個人申述包括手機(jī)號重置郵箱,舊手機(jī)更換新手機(jī),身份證重置手機(jī)。
    ) g4 D4 h6 C* [$ R/ A' E: Z, Y) X+ E
    ) K4 L0 R; k7 M* V5 ?, }! v

    . S  ?) N5 `5 f2 x4 r安全中心包括用戶的規(guī)則規(guī)章,博客旨在分享自己的動態(tài)和經(jīng)驗(yàn)給他人,不可以辱罵他人,以及不遵守國家的法律法規(guī)。本次博客的其它微服務(wù)中心所需要的手機(jī)認(rèn)證接口均由這個微服務(wù)中心提供。7 A: K, z0 }, K& J' K, {- q2 G

    ; i) L7 n( R8 e/ k6.2、用戶的郵箱注冊
    . Y& z4 r8 b* \3 L  a! Q1 \5 A博客采用的是免費(fèi)的QQ郵箱,郵箱的yml配置如下:" o" l# N1 L0 F$ a  M# H* T' x

    " J7 l1 v' h* U0 N2 I- o# A
  • mail:    host: smtp.qq.com    port: 465或587    protocol: smtp    username: 個人的郵箱    password: 郵箱的SMTP的密碼,可在郵箱的賬戶中開啟SMTP服務(wù)    default-encoding: UTF-8    properties:      mail:       debug: true   #控制臺開啟運(yùn)行日志/ R  W" b& E& L' A7 |
    QQ郵箱(郵箱與手機(jī)的六位驗(yàn)證碼共用)發(fā)送驗(yàn)證碼按鈕的原代碼如以下所示:
    * ^4 d4 A, H+ p' X. a- |" [8 i/ `, h/ G3 Y
  • //自動生成的驗(yàn)證碼,驗(yàn)證碼的位數(shù)可以自己設(shè)定    public static String generateVerifyCode(int verifySize, String sources){        if(sources == null || sources.length() == 0){            sources = EMAIL_CODES;}        int codesLen = sources.length();        Random rand = new Random(System.currentTimeMillis());        StringBuilder verifyCode = new StringBuilder(verifySize);        for(int i = 0; i             verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));}        return verifyCode.toString();}: |, N" b: J4 K+ j% q8 w, i% e
    綁定QQ郵箱JavaScript的代碼如以下所示:
    ; ^$ f! B4 n& [8 `  H' e; ~9 f2 B+ ^# @3 i
  • //綁定郵箱的發(fā)送registerEmail(){let emailPatter=/[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/;if (this.email=== '' || !emailPatter.test(this.email) || this.emailYzm === ''){this.$message.error('輸入內(nèi)容不能為空且郵箱要符合格式')              }else {      this.$http.post('/whc/blog-customer-user/emailButtonRegister',{                      email: this.email,                      emailYzm: this.emailYzm,                  }).then(res=>{                      console.log(res);                      if (res.data.success === true){                          this.$notify({                              title: '成功',                              message: '郵箱綁定成功',                              type: 'success',                          });                  window.localStorage.setItem('myEmail',res.data.message);                          this.reload();                          //this.$router.go(0);                      }else {                          this.$message.error(res.data.message);                      }                  })              }          }! E* n* g- q# Z1 U
    后端發(fā)送QQ郵箱注冊的驗(yàn)證碼如以下所示:$ V; D% O1 p4 k

    + W2 M* W' t" Q
  • //后端QQ郵箱發(fā)送驗(yàn)證碼的按鈕服務(wù)@Override@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)public void sendEmailCode(String email) {    //生成郵箱隨機(jī)的6位驗(yàn)證碼    String emailYzm= generateVerifyCode(6, EMAIL_CODES);
    1 ?4 h) D0 W. {9 g! X//From-to,主題和信息.    SimpleMailMessage simpleMailMessage = new SimpleMailMessage();    simpleMailMessage.setFrom(FORM);    simpleMailMessage.setTo(email);    simpleMailMessage.setSubject(SUBJECT);    simpleMailMessage.setText("你的郵箱驗(yàn)證碼是: "+emailYzm+"本次驗(yàn)證碼    會在10分鐘后失效,請立馬使用。");    //發(fā)送郵箱驗(yàn)證碼       javaMailSender.send(simpleMailMessage);6 l; p% E# X% b
        //開啟Redis存入email和yzm    Jedis jedisEmail = new Jedis("localhost", 6379);    //設(shè)置郵箱(key)-驗(yàn)證碼(value)的綁定,秒為單位,存在時間為10分鐘。    jedisEmail.set(email,emailYzm);    jedisEmail.expire(email,600);    //設(shè)置驗(yàn)證碼(key)-郵箱(value)的綁定,秒為單位,存在時間為10分鐘。(雙向綁定可以判斷失敗存入的驗(yàn)證碼,雙向保險)    jedisEmail.set(emailYzm,email);    jedisEmail.expire(emailYzm,600);}
    3 w* j. m2 X5 u1 n6.3、用戶的手機(jī)注冊
    8 g" |( W5 u" R. s7 q9 H發(fā)動短信的前端JavaScript的代碼如以下所示:
    7 s9 ~+ }2 c; g- ?3 A7 u
  • //前端綁定手機(jī)phoneRegister(){ let phonePatterRegister=/^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;             if (this.phone === '' || this.phoneYzm === '' || !phonePatterRegister.test(this.phone)){                  this.$message.error('手機(jī)或者驗(yàn)證碼不符合規(guī)則');              }else {                  this.$http.post('/whc/blog-customer-user/phoneRegisterButton',{                      phone: this.phone,                      phoneYzm: this.phoneYzm,                  }).then(res =>{                      console.log(res);                      if (res.data.success === true){                          this.$notify({                              title: '成功',                              message: '手機(jī)綁定成功',                              type: 'success',});                         window.localStorage.setItem('myPhone',res.data.message);                          this.reload();                          //this.$router.go(0);                      }else {                          this.$message.error(res.data.message);}})}}' o$ h; c9 n! ?# ~: d
    ) T( N  v5 s, P8 M' u
    后端發(fā)送驗(yàn)證碼的代碼如以下所示:
    ) K7 ]6 b, |0 F7 m: p; c2 K# G9 u9 C
  • //生成手機(jī)的驗(yàn)證碼        String phoneYzm= generateVerifyCode(6, EMAIL_CODES);        //阿里云發(fā)送短信的API        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "個人隱私",                "個人隱私");        IAcsClient client = new DefaultAcsClient(profile);        CommonRequest request = new CommonRequest();        request.setMethod(MethodType.POST);        request.setDomain("dysmsapi.aliyuncs.com");        request.setVersion("2017-05-25");        request.setAction("SendSms");        request.putQueryParameter("RegionId", "cn-hangzhou");        request.putQueryParameter("PhoneNumbers", phone);        request.putQueryParameter("SignName", "個人隱私");        request.putQueryParameter("TemplateCode", "個人隱私");        request.putQueryParameter("TemplateParam", "{\"codeab\":\""+phoneYzm+"\"}");        //發(fā)送注冊手機(jī)的驗(yàn)證碼        try { CommonResponse response = client.getCommonResponse(request);            System.out.println(response.getData());        } catch (ServerException e) {            e.printStackTrace();        } catch (ClientException e) {            e.printStackTrace();}        //開啟Redis存入phone和yzm        Jedis jedisPhone = new Jedis("localhost", 6379);        //設(shè)置手機(jī)(key)-驗(yàn)證碼(value)的綁定,秒為單位,存在時間為10分鐘。        jedisPhone.set(phone,phoneYzm);        jedisPhone.expire(phone,600);        //設(shè)置驗(yàn)證碼(key)-手機(jī)(value)的綁定,秒為單位,存在時間為10分鐘。(雙向綁定可以判斷失敗存入的驗(yàn)證碼,雙向保險)        jedisPhone.set(phoneYzm,phone);        jedisPhone.expire(phoneYzm,600);}3 @4 N8 R6 U1 N
    6.4、用戶的安全認(rèn)證
    3 ?$ ?6 ^! `; |2 b8 K+ a提供安全的認(rèn)證有身份認(rèn)證與校園認(rèn)證,當(dāng)然只是表單的提交,真實(shí)的認(rèn)證需要有關(guān)部門的配合,在此只是用來模擬,校園認(rèn)證需要與身份證的名字保持一致,否則無法通過。
    3 l# p* @' R, x8 _3 y3 |  p. b5 k) n1 g3 @
    - x: ], ~1 n2 R+ W0 M4 {: \8 ^  ~
      w, h& I8 S5 M9 L$ Z: u5 H

    % M  i8 Y9 K8 j+ a
    , k6 p" D! M+ a9 Z# M* a3 s% q
    : v- }; `- w$ e, ~6.5、用戶的密碼安全, [! x0 ?( E: Y$ j
    當(dāng)個人安全賬號發(fā)生異常,可以提供修改密碼,也可以重置密碼。
    ! {8 D- F9 r3 Z* e8 z6 F: n* q) B! C: `6 t
    $ K+ j/ ]$ t2 @4 d! Z

    & _  ]$ r5 X) ?5 ]$ I$ M
    % G. E, V9 T3 Q3 w6 H  f0 o& v8 q
    & r# V4 F! U: Y, g" G7 @- ?
    ) j- T# U$ R) Y, k0 ~6 \7 \& K6.6、用戶的賬號申訴
    $ c# n/ _: K0 X, \6 I; e3 d: n$ e可以使用手機(jī)號重置郵箱,也可以使用舊手機(jī)號更換新手機(jī)號。如果個人博客的手機(jī)號安全信息被盜取,手機(jī)號也可以被重置,但是需要借助身份證申訴,不過一天只可以成功申訴一次。
    & d& G3 @" |* t; n
    2 j/ ]+ S& A: k/ V7 ^  ` ' ?$ W0 I2 Y4 n6 W( y

    1 q! t# J$ [9 h0 E# c7& i: k5 h0 W- _$ I
    用戶的文件中心
    ; i4 A& o+ w- B3 i7.1、用戶的頭像存儲& m/ ~2 x* ?) \0 |) G
    當(dāng)用戶注冊的時會需要選擇個人的頭像,上傳的頭像只能是JPG格式且大小不能超過2MB,且上傳前會先查詢數(shù)據(jù)庫中的頭像圖片名是否已經(jīng)存在,存在的話直接會先刪除OSS中舊圖片,再插入新圖片,如果不存在的話,直接插入到OSS文件服務(wù)器中。頭像的存儲流程由前端發(fā)起file傳給后端,后端接受file頭像,利用二進(jìn)制傳給OSS文件服務(wù)器。服務(wù)器再傳過來頭像的外網(wǎng)URL地址,此時修改顯示時間為10年再返還給用戶,最后把頭像外網(wǎng)URL地址保存到自己的LocalStorage本地。9 e: s$ l7 U) S; K

    ; m1 r  d9 t9 U* l7 a) ?, o 3 t/ J$ r& j: P; y) Q- C

    - p. n) i7 K+ l* c5 x8 S7.2、博客的圖片存儲
    $ f9 `$ T" q0 M+ x( T: N, \3 Y% \發(fā)表博客時文章中會包含圖片,前端獲取后端的博客圖片url綁定在前端文章中顯示,同樣url也在文章內(nèi)容中一起保存到數(shù)據(jù)庫中。上傳圖片和上傳頭像不同,文章需要用到的圖片可以有多張,不存在覆蓋問題。需要根據(jù)個人的文件服務(wù)器的存儲量來權(quán)衡上傳圖片大小。
    ( A9 R) K0 p/ ~  u& ^: u+ `: x* ~( i1 M! m8 y
    $ D4 c- x1 t! R/ f* P6 Y

    : k. l! ^& M  X5 y% d& ?$ T
    : x  X9 j8 \: l+ |* a# d! w, u! L8
    ) X5 J9 m) D* z6 u用戶的簽到中心6 E+ @& p+ Z; D* {' m' w; _
    用戶的簽到等級代表用的可以使用的權(quán)限,當(dāng)簽到累計(jì)天數(shù)和連續(xù)天數(shù)達(dá)到獎勵階段時觸發(fā)一鍵領(lǐng)取獎勵按鈕,每次獎勵每個賬號只可以領(lǐng)取一次。整個簽到的等級由經(jīng)驗(yàn)值決定,但是每天獲得經(jīng)驗(yàn)值為1500。簽到的經(jīng)驗(yàn)值還會進(jìn)行快速排序排名返還給前端,提升競爭效果,同時會員增益機(jī)制也會導(dǎo)致不同的疊加效果。" C$ R( T: J, r0 s: p0 R/ s
    " F: D) L4 E  D8 C0 g
    每天0點(diǎn)之前只能簽到一次,過完0點(diǎn)后Redis中限時憑證失效既可以再次簽到,簽到的經(jīng)驗(yàn)值采用二分查找和快速排序算法進(jìn)行計(jì)算最后的排名返還給用戶。
    3 w4 v/ _6 E; w3 C3 I# ]& a# p* D1 `4 y' J
    簽到按鈕的計(jì)算代碼如以下所示:
    " C& Z1 Q% e- {2 n
      B; h0 Y9 W/ O) E
  • //先判定是否redis中是否存在限時憑證        Jedis jedis = new Jedis("localhost", 6379);        if (jedis.get(id.toString()) == null) {            //獲取明天0點(diǎn)的時間并且設(shè)置限時憑證            try {                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設(shè)置日期格式                Calendar cal = Calendar.getInstance();                cal.add(Calendar.DATE, 1);//這里改為1                Date time = cal.getTime();                String tomorrow = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(time);                String now = df.format(new Date());                Date d1 = df.parse(now);                Date d2 = df.parse(tomorrow);                //小時和分鐘和秒相減                Long hour = ((d2.getTime() - d1.getTime()) / (60 * 60 * 1000));                Long minute = ((d2.getTime() - d1.getTime()) / (1000 * 60));                Long second = ((d2.getTime() - d1.getTime()) / 1000);                //最后存在的秒時間        int total = (hour.intValue()) * 3600 + (minute.intValue()) * 60 + second.intValue();                //控制臺觀看                logger.info(tomorrow + "/n" + now + "/n" + total);                //設(shè)置redis中的簽到過期時間                jedis.set(id.toString(), "今天簽到已經(jīng)完成!");                jedis.expire(id.toString(), total);                return SUCCESS;            } catch (ParseException e) {                e.printStackTrace();}        }        return FAILED;
    ) h) z7 n  E% H5 q' E3 K$ b$ @經(jīng)驗(yàn)值的排名的代碼如以下所示:" O2 u0 M! u- O1 ?
    6 |. f. M! m  u; _" I; ^
  • //先查詢所有的經(jīng)驗(yàn)值        ListexAll=userSignMapper.selectExperience();        //先將List集合轉(zhuǎn)為Long[]數(shù)組        Long[] a=exAll.stream().toArray(Long[]::new);        //可以使用轉(zhuǎn)換工具類,也可以自己動手寫Long數(shù)組的轉(zhuǎn)換        long[] quickSort = ArrayUtils.toPrimitive(a);        //快速排序排序成從小到大的順序        sortService.quickSort(quickSort,0,quickSort.length-1);        //利用二分查找算法查找經(jīng)驗(yàn)值所在的索引位置        int position=sortService.binarySearch(quickSort,myExperience);        //最終排名,倒序輸出。        int lastPosition=quickSort.length-position;        //控制條輸出你的排名        logger.info("你在經(jīng)驗(yàn)值排行榜中的名次是:"+lastPosition);        //返回給前端的排名        return lastPosition;
    , p+ q' O% }, u) R1 f9 W# f, V* `9
    - t* j/ ?. ?' z5 [用戶的會員中心( ^& v% C' g$ D$ X' D2 F+ B
    由于會員中心與支付中心聯(lián)系比較密切,所以兩者的中心可以結(jié)合起來看作一個中心來觀看。用戶的會員中心包括普通會員和超級會員,每種方式存在三種收益方式,年費(fèi)季費(fèi)和月費(fèi),支付成功后均由負(fù)載均衡執(zhí)行業(yè)務(wù)邏輯。由于支付不屬于這個module中,所以這個module只是由其它微服務(wù)調(diào)用直接完成業(yè)務(wù)邏輯。5 U* ]' q# W! I" j% x) U; B
    / V( J9 r) }" b/ B

    2 s! K, z9 f' t' C/ G) k' f) j0 }
    $ P9 A) B5 O4 g* }10, ^$ l4 y  s, p9 W9 v
    用戶的支付中心
    , V5 a/ @3 o! K1 _* E/ W. c未完成實(shí)名認(rèn)證時頁面會轉(zhuǎn)到實(shí)名認(rèn)證中,當(dāng)完成實(shí)名認(rèn)證時,首次進(jìn)入我的錢包中心會觸發(fā)設(shè)置支付密碼,當(dāng)設(shè)置成功后,支付以及綁定個人銀行卡均需要用到支付密碼?梢杂门f支付密碼修改新密碼,也可以手機(jī)重置手機(jī)密碼。還可以綁定自己的銀行卡,需要有關(guān)部門的配合。本次博客只允許建設(shè)銀行,工商銀行和中國銀行,且每張銀行卡只允許綁定一張。利用v-charts組件把個人的時間段的消費(fèi)情況以條形圖展現(xiàn)給用戶觀看。* W% z% M2 N( i1 b+ a8 P
    ( @% H+ q& I& k4 a4 y6 {! k
    : a! t& u$ d2 a
    4 b3 @; f" E; r, b2 a3 y$ Y
    . o* F; Q3 y9 [& i" F
    " r8 a0 U( b' n; j# O, e

    9 S$ n% c# q* [$ T當(dāng)用戶開通了我的錢包后,可以選擇是否進(jìn)行余額充值,賬戶余額暫時只可以用支付寶充值。所有關(guān)于金額的操作均需要在后端安全操作,前端只用來顯示數(shù)據(jù),必須使用數(shù)據(jù)庫中的金額。' K7 T6 h5 X- a( x. X. o/ }& q
    8 D2 X  h7 t! T! i# I/ T

    - o, a1 e% x  e* u: W
    ; o- K! x. e: S  L, I. U- l: \1 o& O6 J( F, m

    & C- w% x& n' u' I- X$ d密碼為6位有效數(shù)字,可以使用原密碼更換新支付密碼。
    6 H4 }! w( {. [4 b
    2 S" v; J' i) I7 r" Y
    / R  `) m: m& C2 T
    . q1 h- `$ N4 _  T
    , [/ F3 G* @( k8 X9 f& E  t( R# h  L: j2 s$ j3 @

    3 M- K! Q$ N/ n! |9 ?8 ?# P8 U% U銀行卡姓名需要與實(shí)名認(rèn)證的姓名一致。
    - P. h# l! `( y! O( n1 _
    5 F! Q% n( q. J" T$ V9 M+ e0 b* q  K: K+ p
    8 `4 K6 o! l. v  A. o) e

    & Q( {( Z9 l0 z4 z+ K# D7 ~
    2 a; q* j6 j* e% H7 q* U7 [- p! q* l! X5 G( ?! l2 ~9 H
    - r; U+ H: L$ \
    ) d$ @4 \# p" [' D3 }1 d5 P; T

    " E" D9 g' `- r2 L1 q支付中心包含普通會員和超級會員,由于普通會員采用支付寶原始的方式,而超級會員采用支付寶的二維碼方式,所以兩者會在調(diào)用的時候會有所不用。. P" N: d+ l. }# e9 u
    2 n2 k8 }' N8 h7 m

    ) R5 \4 k. I! {- X: k& g' w5 _* n7 |" W; h8 g
    賬單中心是分頁展示給用戶觀看,提供當(dāng)前頁面,月份和全部的賬單打印Csv。前端可以直接把后端的數(shù)據(jù)直接打包Csv,也可以自行后端打包Csv數(shù)據(jù)到本地。
    * @3 U: \4 j/ E/ o7 d/ t# s7 `) x4 o$ C, b! t

    # m  H% e+ |& ~. |$ {+ [& ^9 }1 C) X: a! b

    + Z0 ~$ q6 }( f, u5 }* q9 `
    2 m9 g$ u6 q, x- [6 ]8 y$ |2 P/ a1 u& S9 k
    11
    0 I* t7 b' n$ ^( O1 j" C4 n用戶的博客中心" D/ D9 T) c6 L
    11.1、用戶的訪問主頁0 w  _' F8 t7 k
    編寫博客是一個展示自我的機(jī)會,通過這個機(jī)會,可以增強(qiáng)個人的表達(dá)能力,還會結(jié)識一些五湖四海的博友。通過他人文章的學(xué)習(xí),我們還可以增強(qiáng)個人的知識度和眼界。綜上所述,用戶的博客中心是博客系統(tǒng)的最核心功能。
    5 A, @6 X- D) v# E7 p# S6 o8 P* {- @1 v1 P' X* R  r( z
    用戶可以分享自己的博客動態(tài),博客旨在分享自己所學(xué)所知給他人,或者解決他人的困難。博客中心包含發(fā)表博客,查看個人博客,刪除博客,更新個人博客。非本人也可以觀看他人的博客,也可以評論他人的博客,所以需要用到分頁功能和輪滑加載功能配合前端展示不是私密的博客給他人觀看。每個用戶所看到的博客都是最新發(fā)的博客,可以與他人進(jìn)行學(xué)習(xí)交流。每個發(fā)表者要尊重他人的知識勞動成果,切勿抄襲并且發(fā)表不適當(dāng)?shù)奈恼,做一名合格的博友?font class="jammer">" h4 @8 c: v. r0 B# h# |( E  h/ N& k

    # x; f* T) U: m% L- \當(dāng)用戶輸入賬號密碼登錄后,可以看到博客的主頁如下圖所示,主頁面可以看到發(fā)表人和發(fā)表的文章,點(diǎn)擊文章可以進(jìn)入文章的主頁面進(jìn)行學(xué)習(xí)交流。
    / G7 M& e& B5 P3 h9 B# i/ q4 b: B" p' g3 L  ^: e

    $ Q9 i8 n6 W# a6 H
    3 [( T, H+ @6 X11.2、用戶的文章中心
    + d* M. r7 c: N4 f3 b5 L用戶的文章微服務(wù)中心的功能包含發(fā)表,查看,修改,刪除,用戶可以控制自己發(fā)表過的每一篇文章。
    9 m. t- {& M3 D0 {5 ?" `* X. l6 t. J$ d! [, G  u% o

    ' `7 h: O4 y+ z+ P8 _0 v9 J  P* `0 {
    關(guān)于文章的增刪改會在后續(xù)標(biāo)題中得到詳解,在此只放出用戶的個人文章中心由圖可以看出是用戶發(fā)表過的全部文章,后端利用的是先分頁后List方式,最終傳送前端進(jìn)行ListItem遍歷顯示即可。
    ' G+ w7 P3 O4 }/ R2 r
    & P1 l# d4 Y+ _由于也使用了Elasticsearch把文章分類作為存儲索引,但是重要的文章信息均放在數(shù)據(jù)庫中,在此只提一下,到后續(xù)的分類搜索中會詳細(xì)說明。; {* _% O+ W( y. I$ d$ N

    / x; |- j' j& A( ~  u11.3、發(fā)表個人的博客
    7 T6 n9 J  k; i$ j文章的的發(fā)布有許多選擇,自己可以選擇文章的分類和文章的標(biāo)簽,同樣也可以設(shè)置文章的可見性。用戶可以設(shè)置文章的標(biāo)簽,標(biāo)簽用來顯示給游客看,用來文章的標(biāo)識認(rèn)證,還可以設(shè)置文章的分類,類型和保密性,每種文章的分類會發(fā)布到那個分類的專區(qū)。文章類型有三種,若是轉(zhuǎn)載和翻譯他人的文章需要著名地址,保護(hù)他人的知識勞動成果。只有具備會員資格才可以發(fā)送到會員專區(qū),但是轉(zhuǎn)載的文章不可以發(fā)送到會員專區(qū),發(fā)表文章時可參考紅字注意事項(xiàng)。. }- e! T7 j$ X. X1 _
    ; {5 Y. u  x, O, ~# f: r
    # E6 Y$ u; T/ x# A# M
    $ z: L) C8 g. _. c
    博客的發(fā)表的核心原代碼如以下所示:
    $ ?  k/ [$ N! g6 [+ W+ U% m& I, n4 }: j* W) j" S
  • //獲取文章的摘要markdown格式-html-summaryString words= StringFromHtmlUtil.getString(MDTool.markdown2Html(blogFrontPublish.getArticleContent()));//獲取文章的摘要且摘要長度為255個字符String summary = words.length() > 240 ? words.substring(0, 240) + "......" : words;//去除轉(zhuǎn)換后存在的空格String tagTar = blogFrontPublish.getArticleTag().replaceAll(" ", "");//將文章的分類寫入分類表然后再插入整篇文章UserArticleCategory userArticleCategory=userArticleCategoryMapper.findAllByCategoryName(blogFrontPublish.getArticleCategory());if (userArticleCategory==null){    userArticleCategory=new UserArticleCategory();    userArticleCategory.setCategoryArticles("");  userArticleCategory.setCategoryName(blogFrontPublish.getArticleCategory());//返回獲取到的自增ID    userArticleCategoryMapper.insert(userArticleCategory);}//把標(biāo)簽寫入數(shù)據(jù)庫for (String tag :tagTar.split(",")) {    if (tag.replaceAll(" ", "").length() == 0) {        //單個標(biāo)簽只含空格        continue;}    UserArticleTag userArticleTag = userArticleTagMapper.findAllByTagName(tag);    if (userArticleTag==null){        userArticleTag=new UserArticleTag();        userArticleTag.setTagName(tag);        userArticleTag.setTagArticles("");        userArticleTagMapper.insert(userArticleTag);}//轉(zhuǎn)換后的值再更新得到文章表的主鍵   userArticleTag.setTagArticles(userArticleTag.getTagArticles()+userArticle.getId()+",");  userArticle.setArticleTagsId(userArticle.getArticleTagsId()+userArticleTag.getId()+",");   userArticleTagMapper.updateTagNameAndTagArticlesById(userArticleTag.getTagName(),userArticleTag.getTagArticles(),userArticleTag.getId());}; q6 D+ H( O  Z5 u/ m% _- I4 B& V
    11.4、修改個人的博客
    7 |1 Y3 X& D0 P若是需要修改個人的博客,需要進(jìn)入圖5-33的個人博客中心,查看發(fā)表的指定文章進(jìn)入到指定文章的頁面,點(diǎn)擊編輯按鈕,不是本人的文章不會出現(xiàn)編輯按鈕,博客的編輯按鈕效果圖如下圖所示:) K0 B( ~% K( m- W0 Y+ E! I

    ) X# B9 q6 k  i& h  y
    % f. M( l$ |2 `5 f5 p2 N) [2 z" x* o% m  D
    可以修改文章的所有的條件與內(nèi)容。
    - ^& m- F& P  V' m$ p) f  m3 E( k7 o& S, U9 p, g% x
    + R2 {% ]0 v- f4 l: f/ y/ V
    # u4 e4 h/ d3 u5 f4 q8 `( U
    文章的發(fā)表與修改的源碼不同在于要刪除之前的原屬文章的分類Id與標(biāo)簽Id的關(guān)聯(lián),再進(jìn)入文章的插入,不過文章的修改也會觸發(fā)在搜索引擎上的文章信息修改,搜索引擎上的文章信息也會跟著更新,保持搜索到最新的數(shù)據(jù)。
    6 T+ w: q+ v% U/ K' s1 |# W0 u2 v* Z, `# M  n1 e  t9 v5 @
    11.5、刪除個人的博客
    ' }+ Y+ W1 p" v+ p( D刪除個人的博客需要刪除數(shù)據(jù)庫和搜索引擎上的文章,刪除文章后不可恢復(fù)。; O& D. U0 g- ?( ]7 O
    * D. I; I- @1 N' X
    6 d* k0 [' }' @

    % p! e3 ?+ C, y2 |+ m4 K11.6、用戶的文章布局- Y" @* C4 {: E% F; ]2 \
    完整博客的顯示方式是采用GitHub的代碼高亮布局,可以是用戶看到自己的博客是嵌入式的面板,可以給予人一種清爽的感覺。由于采用Vue,可以不用動態(tài)渲染html,使用v-html命令就可以把后端傳過來的數(shù)據(jù)利用showdown轉(zhuǎn)換器轉(zhuǎn)換給html直接顯示給用戶看。5 u, s$ a; h) C: c' E$ o; U

    . Q. E% ~6 t# A# O( W' B# Q' d0 g  f. |

      q( ]8 P+ P6 Z, h% m' P11.7、點(diǎn)贊用戶的文章, p/ @3 M5 ^. n7 m) s
    互聯(lián)網(wǎng)時代每個人都或許都點(diǎn)贊過他人分享的文章,本次設(shè)計(jì)是博客所以會涉及到點(diǎn)贊,當(dāng)用戶太多時需要考慮到高并發(fā)的情況。正常情況的點(diǎn)贊并不會給后端造成多大的負(fù)載壓力,如果是熱門的文章博客,用戶點(diǎn)贊與取消點(diǎn)贊,評論,分享等,對于后端來說這些都會帶來巨大的流量,如果后端接口支撐不住,前端得不到響應(yīng),前端無法響應(yīng)就會返回404,會導(dǎo)致用戶體驗(yàn)極差。6 c+ x4 X" q: S4 S
    9 M' s7 p& d2 C+ B
    ) N( B/ B" g6 B0 y, Z

    2 a& }. ~$ j. {  T3 p' A由上圖可知,核心的模塊就是點(diǎn)贊與取消點(diǎn)贊,利用Redisson把多個用戶的請求利用分布式鎖分開請求,利用“緩存”保護(hù)數(shù)據(jù)庫。若用戶點(diǎn)贊微博,則后端會先查詢是否存在點(diǎn)贊記錄,當(dāng)存在點(diǎn)贊記錄時,分析是否是完成點(diǎn)贊還是已經(jīng)取消了點(diǎn)贊。若沒存在點(diǎn)贊記錄,則完成數(shù)據(jù)庫中的點(diǎn)贊記錄更新,再把點(diǎn)贊結(jié)果“緩存”到Redis中,若是取消點(diǎn)贊,則直接會在“緩存”中刪除,更新數(shù)據(jù)庫中的結(jié)果。每一篇文章的點(diǎn)贊總數(shù)都是利用“緩存”計(jì)算得到一篇文章的結(jié)果發(fā)送給前端顯示。前面的操作都是利用Redisson操作的,所以當(dāng)高并發(fā)多線程請求時,分布式鎖就會控制資源的并發(fā)訪問,避免出現(xiàn)文章數(shù)據(jù)不一致的情況。) e+ K  C  T9 L2 [8 N
    8 M2 e+ o! H$ _2 B
    11.8、收藏用戶的文章+ D2 Q% L" L" @1 [, S6 w3 ]# A
    用戶允許收藏自己的文章,收藏的功能也借用了Redisson的分布鎖來控制收藏的緩存,收藏與博客的點(diǎn)贊功能相似。) |1 l* V1 l4 B3 B  o2 C
    2 N7 D! }' k( J5 p5 N/ o. \4 q9 k3 n

    + S5 `$ r. t5 r! e5 g4 j! z& |$ i( ?% |6 A0 K& h
    % ~: I( H3 V8 G6 W, m6 L
    ; m8 d, m& m. k) F* L

    % Q) ~4 H- o1 U5 _! N% F3 N2 {11.9、評論用戶的文章
    4 D  U' [; a" ^% v. T8 Z評論的實(shí)現(xiàn)比較簡單,一級評論的用戶的Id為父Id,只含有一級評論與二級評論,分頁直接查看文章的所有評論。- F! a6 C+ n7 \- V
    2 ?9 v5 t- G4 X+ S% \3 D
    8 j& `# ~0 b( \6 M, b; o
    1 U3 \2 y$ o4 C6 e) e- p8 G
    11.10、博客的文章排行榜# Y5 a5 `9 }; r6 k4 D
    文章排行榜采依舊是利用了Redisson,排行榜與標(biāo)題3-7-4的點(diǎn)贊關(guān)聯(lián)緊密,“點(diǎn)贊”會導(dǎo)致熱流,形成短時間內(nèi)的超高人氣,把文章的排行榜放給用戶看,可以增強(qiáng)用戶的體驗(yàn)。不是所有的功能都要用分布式鎖,排行榜不需要用到分布式鎖,也不需要控制非常高的高并發(fā)流量,對于后端來說控制排行榜比較簡單。
    ' W8 t* w- S9 t9 d1 `2 J1 R; |; B& ^1 t" B; e6 g
    2 Y8 q) a2 ]9 w7 V6 Z9 {6 R
    ( t( P' H( G! ^. l/ E/ t% a( x0 w
    排行榜需要保證查詢數(shù)據(jù)庫的點(diǎn)贊表的SQL正確,SQL錯誤之后的所有操作都是白費(fèi)力氣,這個要設(shè)置一定的范圍與時間差來確保文章的間斷實(shí)時性,最后要把數(shù)據(jù)庫中的數(shù)據(jù)放到緩存中。對于緩存的操作,用戶的點(diǎn)贊與取消點(diǎn)贊都會觸發(fā)緩存中的排行榜排序。用戶請求后,會查到緩存中的排行榜點(diǎn)贊數(shù)最多的前10篇文章,利用List的文章Id找到文章的信息,最后打包傳給前端顯示。排行榜算是一種實(shí)時性要求不算很高的,可以使用定時的方式主動更新緩存中排行榜記錄。
    1 |+ s8 K. i1 F, [1 g
    # l6 C2 W' v; J9 Q! n( g, Q% I1 v- B# y2 p, x' w6 k% ~9 X

    ! {2 p+ V) m. }. _& E5 D( s) O. i5 A* @/ k3 e, z. }; ]
    12
    7 G% z& ]/ u; K1 j, g( L博客的搜索中心' H$ i8 J. o2 d8 {1 @
    12.1、搜索引擎的應(yīng)用
    9 _- d$ q$ T5 I) r! N' x當(dāng)微服務(wù)整合Zipkin時,運(yùn)行系統(tǒng)會產(chǎn)生大量的API運(yùn)行指標(biāo),而Elasticsearch(ES)作為一種存儲方式,可以把那些運(yùn)行API指標(biāo)存儲到ES中。. e8 D- f! L! ]  z
    0 b4 F" W$ g5 i% Y, N
    + `" h' D/ p: x9 {% f/ J

    6 ]. I7 i" z. x9 ZElasticsearch的index是文檔索引,與數(shù)據(jù)庫的“庫”相似,type是文檔類型,與數(shù)據(jù)庫中的“表”相似,id是一個字段作為主鍵。3 U9 x! n- J! ]" S. B
    ' }. \- Z8 n& e' P2 n
    12.2、博客的分類搜索0 w  k) H$ ^) f6 n$ k5 c2 z
    博客的搜索中心包含文章的顯示的信息,例如標(biāo)題和文章內(nèi)容的摘要,由于把文章的整篇內(nèi)容均放到數(shù)據(jù)庫中,所以搜素引擎上的文章是負(fù)載均衡保存提示的信息,用戶可以根據(jù)搜索界面的搜索框查詢Elasticsearch上文章,根據(jù)的是文章的分類的區(qū)域和關(guān)鍵字,后端判關(guān)鍵字是否符合且存在,然后把結(jié)果傳給前端顯示。
    % o+ ?1 r9 _- r3 A# C! C# F& N, N4 I7 A" @5 ~# k9 T$ m
    " Q# K* I- Q: u. @6 [& [

    ) ], e- B/ d7 r
    0 J9 P2 Z5 S8 x* ^, k1 {, D
    ( Z5 f: s7 q8 N% ]* C: s
    ; z+ E6 W/ v# r* g8 \; v. B* A12.3、博客的分類主頁/ J/ W9 k  b/ U4 u
    博客的分類主頁是利用Elasticsearch上的文章信息進(jìn)行遍歷,用戶發(fā)表的博客時候選擇的分類作為Elasticsearch索引的名負(fù)載均衡到Elasticsearch,分類中心的文章每次選擇20篇最新的文章傳給給用戶觀看。3 o1 V% Q3 I3 p/ w
    $ I  Z; e- Y' k' l+ U

    0 G6 X' Q- Z/ J8 {: Z6 i; `, m" L; c9 u% n( k& D
    13
    ( N+ N) {% C5 B博客的測試分析
    0 a' e  f- q  |$ o2 ~13.1、博客的請求抗壓性分析
    ' t- |/ D0 d8 e" ]8 ]; K2 x0 k' C. z! A博客采用的是前后端的分離模式,所以對于前端傳過來的Token,后端只要鑒定Redis中存在Token即放行API的請求,同時前端可以防止表單的多次提交,前端可以增加JS監(jiān)聽Button的提交,也可以使用session鑒定請求的時間間隔。不過博客大多采用Axios的異步提交,http成功時可以把Button設(shè)置為true或者直接局部刷新網(wǎng)頁重置數(shù)據(jù)。對于博客中的支付中心,另起線程中需要防止出現(xiàn)業(yè)務(wù)出現(xiàn)錯誤,或者網(wǎng)絡(luò)錯誤導(dǎo)致負(fù)載均衡出現(xiàn)中斷錯誤,所以需要catch防止程序出現(xiàn)錯誤,同樣還必須保存支付寶異步通知的結(jié)果防止另起線程中出現(xiàn)異常。對于每個用戶的請求,可以采用服務(wù)器的限制流量,限制的方向可由個人選擇,需要在服務(wù)器的圖形化界面中可以設(shè)置。0 J3 t$ l4 M. }7 w, @4 x

    ( {. {9 [  Q* |' o# ], ?
    4 X' J$ g: J) n& N. P4 r9 }0 i# n4 Q$ n1 O
    13.2、博客的功能擴(kuò)展性分析
    6 X" L  z% [, \  h( \* X( s博客的前端容易擴(kuò)展,由于Vue本身具有的實(shí)用的數(shù)據(jù)綁定優(yōu)勢,所以前端只要時間充足就可以隨意擴(kuò)展,還有一個很重要的原因是安全是后端來控制的。博客后端的每一個微服務(wù)的中心承擔(dān)著一個功能模塊,若是發(fā)生不同功能的擴(kuò)充則需要多添加一個微服務(wù)的中心。當(dāng)功能相同只是擴(kuò)展當(dāng)前的功能,則可以直接在某個微服務(wù)中心增加代碼即可。編寫博客時遵守了Java代碼的規(guī)范,為以后的擴(kuò)充打下堅(jiān)實(shí)的基礎(chǔ)。本次博客各個中心均遵守了Java的代碼規(guī)范,微服務(wù)中的module劃分清晰,功能擴(kuò)充方便。
    " [" b# A' F  W! {- I1 |* i3 ]. r4 j( i0 V6 ], _
    Pom文件中的module劃分如下圖所示:* D+ S' |+ U, w+ t# `; z* _7 [

    6 X3 ?6 \  Z0 @' l1 ?
    ) y7 Z5 ]% L7 {% ~
    3 Y) O- G1 K) a. L& I項(xiàng)目工程資源請參見:https://download.csdn.net/download/m0_38106923/87849577
    3 E5 E* `' \+ _, `, B" }
    ) f0 v; }# H. M+ U% {9 Q; a, \. r- W0 M) Q- d7 y; A8 k5 y
    往期推薦畢業(yè)設(shè)計(jì)So Easy:Java MySQL智能報紙閱讀器APP應(yīng)用
    1 E+ ]  S" i* O/ g畢業(yè)設(shè)計(jì)So Easy:基于C++實(shí)現(xiàn)網(wǎng)絡(luò)掃描器  ?" h, d. G% ?3 W) d% s2 |( |6 J
    畢業(yè)設(shè)計(jì)So Easy:基于Java Web學(xué)生選課系統(tǒng)* y- V; D* ?- |- f
    畢業(yè)設(shè)計(jì)So Easy:基于Java語言西餐廳點(diǎn)餐系統(tǒng): X+ w; t" K2 O* M% Z
    畢業(yè)設(shè)計(jì)So Easy:珠穆朗瑪FM音頻電臺APP, x/ j3 T) ~' @9 }; ~2 D

    * H0 Q% H4 G& s% ]
    9 u7 \+ K7 s3 E9 b' e- w' U& V
    4 \7 I# k0 s' r: i% R點(diǎn)擊閱讀原文,更精彩~
  • 回復(fù)

    使用道具 舉報

    發(fā)表回復(fù)

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表