javascript
5w 字 | 172 图 | 超级赛亚级 Spring Cloud 实战
點擊上方?好好學java?,選擇?星標?公眾號
重磅資訊、干貨,第一時間送達今日推薦:硬剛一周,3W字總結,一年的經驗告訴你如何準備校招!
個人原創100W+訪問量博客:點擊前往,查看更多一、PassJava 項目簡介
-
PassJava 是一款 Java 面試刷題 的開源系統,可以用零碎時間利用小程序查看常見面試題,夯實 Java 基礎。
-
PassJava 項目可以教會你如何搭建 SpringBoot 項目,Spring Cloud 項目
-
采用流行的技術,如 SpringBoot、MyBatis、Redis、 MySql、 MongoDB、 RabbitMQ、Elasticsearch,采用 Docker 容器化部署。
項目地址
-
[后臺平臺] https://github.com/Jackson0714/PassJava-Platform
-
[后臺管理] https://github.com/Jackson0714/PassJava-Portal
-
[學習教程] https://github.com/Jackson0714/PassJava-Learning
項目演示
-
后臺管理系統
-
小程序
PassJava 中使用的技術
SpringBoot、MyBatis、Redis、 MySql、 MongoDB、 RabbitMQ、Elasticsearch
PassJava 實現的功能概覽
PassJava 數據庫表概覽
數據庫表前綴說明
-
ums_*:會員模塊相關表
-
cms_*:內容管理模塊相關表
-
qms_*:題目模塊相關表
-
chms_*:渠道模塊相關表
-
sms_*:學習模塊相關表
二、項目微服務架構圖
微服務架構圖
三、項目前置要求
“由于 PassJava 項目涉及到很多知識點,希望大家先補下功課,推薦的書籍如下。
”推薦資料
IDEA
《IntelliJ-IDEA-Tutorial》:https://github.com/judasn/IntelliJ-IDEA-Tutorial
Spring
《Spring 實戰(第 4 版)》:https://book.douban.com/subject/26767354/
SpringBoot
《Spring Boot 實戰》:https://book.douban.com/subject/26857423/
MyBatis
《MyBatis 從入門到精通》:https://book.douban.com/subject/27074809/
MySql
《深入淺出 MySQL》:https://book.douban.com/subject/25817684/
Linux
《循序漸進 Linux(第 2 版)》:https://book.douban.com/subject/26758194/
Elasticsearch
《Elasticsearch 權威指南》:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
《Elasticsearch 技術解析與實戰》:https://book.douban.com/subject/26967826/
Mongodb
《MongoDB 實戰 (第二版)》:https://book.douban.com/subject/27061123/
Docker
《Spring Cloud 與 Docker 微服務架構實戰》:https://book.douban.com/subject/27028228/
四、環境搭建篇
4.1 Vagrant 快速搭建 Ubuntu 虛擬機環境
1. 開啟虛擬機服務
Windows 啟動配置:Intel Virtualization Technology -> Enabled
2. 下載安裝 VirtualBox
VirtualBox:虛擬機管理軟件
https://www.virtualbox.org/wiki/Downloads
3. 下載安裝 Vagrant
Vagrant:創建和管理虛擬機
Vagrant 軟件:https://www.vagrantup.com/downloads.html
Vagrant 官方鏡像:https://app.vagrantup.com/boxes/search
-
check 是否安裝好了 vagrant
命令行輸入 vagrant
vagrant4. 安裝 vagrant ubuntu 國內鏡像
#?ubuntu?18.04?LTS: vagrant?box?add?https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/bionic/current/bionic-server-cloudimg-amd64-vagrant.box?--name?ubuntu18# ubunt 16.04 LTS: vagrant?box?add?https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/xenial/current/xenial-server-cloudimg-amd64-vagrant.box?--name?ubuntu16# ubuntu14: vagrant?box?add?https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box?--name?ubuntu14安裝 ubuntu 18
vagrant?box?add?https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/bionic/current/bionic-server-cloudimg-amd64-vagrant.box?--name?ubuntu18-
創建 vagrant 配置文件
-
打開 C:\Users\Administrator\Vagrantfile 文件
5. 啟動虛擬機
vagrant?up6. 連接虛擬機
vagrant?ssh7. 配置密碼登錄
-
配置密碼登錄 vagrant
-
安裝 XShell 工具和 XFTP 工具
-
XShell 連接虛擬機
賬號:root
密碼:vagrant
4.2 配置虛擬機網絡
1.查看VirtualBox Host-Only Network
本地VirtualBox 網絡地址 192.168.56.1,則修改虛擬機IP地址為同一個網段下,比如192.168.56.10
2.配置虛擬機IP地址
打開Vagrant 配置文件 C:\Users\Administrator\Vagrantfile
# config.vm.network "private_network", ip: "192.168.33.10" 修改為 config.vm.network "private_network", ip: "192.168.56.10"3.重新加載虛擬機
vagrant?reload4.查看虛擬機IP地址
虛擬機IP地址:192.168.56.10,和配置文件中的一致
5.測試本機是否可以ping通虛擬機
ping 192.168.56.10,可以ping通
6.測試虛擬機是否可以ping通本機
ping 192.168.10.160,可以ping通
4.3 安裝docker
https://docs.docker.com/engine/install/ubuntu/
1.卸載老版本docker
sudo?apt-get?remove?docker?docker-engine?docker.io?containerd?runc2.設置倉庫
//?命令1 $?sudo?apt-get?install?\apt-transport-https?\ca-certificates?\curl?\gnupg-agent?\software-properties-common //?命令2 curl?-fsSL?https://download.docker.com/linux/ubuntu/gpg?|?sudo?apt-key?add?-//?命令3 sudo?apt-key?fingerprint?0EBFCD88//?命令4 sudo?add-apt-repository?\"deb?[arch=amd64]?https://download.docker.com/linux/ubuntu?\$(lsb_release?-cs)?\stable"3.安裝docker
sudo?apt-get?update sudo?apt-get?install?docker-ce?docker-ce-cli?containerd.io4.測試安裝成功
sudo?docker?run?hello-world5.設置開機自啟動
sudo systemctl enable docker
6.配置鏡像加速
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
sudo?mkdir?-p?/etc/docker sudo?tee?/etc/docker/daemon.json?<<-'EOF' {"registry-mirrors":?["您的專屬加速器地址"] } EOF sudo?systemctl?daemon-reload sudo?systemctl?restart?docker7. 免sudo使用docker命令
當以普通用戶身份去使用docker images時,出現以下錯誤:
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied 可以看都,最后告知我們時權限的問題。那么在linux文件權限有三個數據左右drwxrwxrwx,
img其中第一為d代表該文件是一個文件夾 前三位、中三位、后三位分別代表這屬主權限、屬組權限、其他人權限。如圖,其中 第三列、第四列分別代表文件的屬主、屬組。
上圖是報錯文件的權限展示,可以看到其屬主為root,權限為rw,可讀可寫;其屬組為docker,權限為rw,可讀可寫。如果要當前用戶可直接讀取該文件,那么我們就為當前用戶添加到docker屬組即可。
如果還沒有 docker group 就添加一個:
sudo?groupadd?docker將用戶加入該 group 內。然后退出并重新登錄就生效啦。 sudo?gpasswd?-a?${USER}?docker重啟?docker?服務 sudo?service?docker?restart切換當前會話到新?group?或者重啟?X?會話 newgrp?-?docker注意:最后一步是必須的,否則因為 groups 命令獲取到的是緩存的組信息,剛添加的組信息未能生效,所以 docker images 執行時同樣有錯。8. apt-get update更新慢
Ubantu 18.04 apt-get update 無法更新,更新慢的問題 https://blog.csdn.net/stopping5/article/details/80493643
sudo?cp?/etc/apt/sources.list?/etc/apt/sources.list.old sudo?vim?/etc/apt/sources.list 替換成阿里源#阿里源: deb?http://mirrors.aliyun.com/ubuntu/?trusty?main?restricted?universe?multiverse deb?http://mirrors.aliyun.com/ubuntu/?trusty-security?main?restricted?universe?multiverse deb?http://mirrors.aliyun.com/ubuntu/?trusty-updates?main?restricted?universe?multiverse deb?http://mirrors.aliyun.com/ubuntu/?trusty-proposed?main?restricted?universe?multiverse deb?http://mirrors.aliyun.com/ubuntu/?trusty-backports?main?restricted?universe?multiverse deb-src?http://mirrors.aliyun.com/ubuntu/?trusty?main?restricted?universe?multiverse deb-src?http://mirrors.aliyun.com/ubuntu/?trusty-security?main?restricted?universe?multiverse deb-src?http://mirrors.aliyun.com/ubuntu/?trusty-updates?main?restricted?universe?multiverse deb-src?http://mirrors.aliyun.com/ubuntu/?trusty-proposed?main?restricted?universe?multiverse deb-src?http://mirrors.aliyun.com/ubuntu/?trusty-backports?main?restricted?universe?multiverse其他命令
docker update redis --restart=always 虛擬機重啟后,redis自動啟動
docker update mysql --restart=always 虛擬機重啟后,mysql自動啟動
4.4 docker 安裝mysql
1.下載鏡像
sudo?docker?pull?mysql:5.7 ubuntu@VM-0-13-ubuntu:~$?sudo?docker?pull?mysql:5.7 5.7:?Pulling?from?library/mysql c499e6d256d6:?Pull?complete? 22c4cdf4ea75:?Pull?complete? 6ff5091a5a30:?Pull?complete? 2fd3d1af9403:?Pull?complete? 0d9d26127d1d:?Pull?complete? 54a67d4e7579:?Pull?complete? fe989230d866:?Pull?complete? 466a91a95e2f:?Pull?complete? 3e4554c238f1:?Pull?complete? 603b48ead88c:?Pull?complete? 1e86a9aa7171:?Pull?complete? Digest:?sha256:fbaeced79cfdae5d3c8d4a8c41e883f254f72ed7428c6b93a498824b76d97121 Status:?Downloaded?newer?image?for?mysql:5.7 docker.io/library/mysql:5.72.查看下載的鏡像
sudo?docker?images3.創建mysql實例并啟動
-
創建mysql實例并啟動
-
查看docker容器
mysql容器已啟動
4.連接數據庫
-
用Workbench連接數據庫
-
查看數據庫
5.進入mysql 容器
sudo?docker?exec?-it?mysql?/bin/bash6.查看虛擬機映射文件
cd?/mydata/mysql ls7.修改mysql賬號密碼
1.進入mysql容器 docker?exec?-it?mysql?/bin/bash2.登錄mysql mysql?-u?root?-p 輸入密碼:root3.切換數據庫 use?mysql4.查詢root用戶 select?*?from?user?where?user?=?root;5.修改密碼 update?user?set?authentication_string?=?password('新的密碼'),?password_expired?=?'N',?password_last_changed?=?now()?where?user?=?'root';6.這條命令暫不清楚 update?user?set?plugin="mysql_native_password";7.刷新權限 flush?privileges;8.退出 quit;9.重新登錄 mysql?-u?root?-p?輸入新的密碼,登錄成功8.其他命令
-
設置容器在機器重啟后自動啟動
4.5 docker安裝redis
1.下載鏡像
-
下載鏡像
-
查看下載的鏡像
2.啟動redis
-
創建redis.conf 配置文件
-
啟動redis
3.連接redis
sudo?docker?exec?-it?redis?redis-cli4.測試redis
設置a=100,返回OK
set?a?100獲取a的值,返回"100"
get?a5.設置redis持久化存儲
-
修改虛擬機映射的redis配置文件
-
檢查是否生效
6.安裝redis可視化工具
-
安裝redis可視化工具
redis-desktop-manager
-
連接redis
-
查看redis數據庫
4.6 本地開發環境配置
1. 本地環境安裝Java
我本地環境的java版本 1.8.0_131
java?-versionjava安裝和環境變量配置:https://www.cnblogs.com/jackson0714/p/6591942.html
2.本地環境配置Maven
(1)下載Maven,拷貝文件夾到C盤
C:\apache-maven-3.6.2
(2)添加到環境變量
cmder里面 執行命令 mvn -v
如果報錯命令不存在,則重新啟動cmder
(3)設置Maven代理
阿里云代理 https://maven.aliyun.com/mvn/view
點擊使用指南,拷貝配置指南
<mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共倉庫</name><url>https://maven.aliyun.com/repository/public</url> </mirror>(4)配置jdk1.8編譯項目
<profiles><profile><id>jdk-1.8</id><activation><activeByDefault>true</activeByDefault><jdk>1.8</jdk></activation><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion></properties></profile> <profiles>3.IDEA Maven構建工具配置
-
Maven配置
-
字符集配置
4. IDEA 安裝Lombok插件
Lombok:簡化JavaBean的開發
5. IDEA 安裝mybatisx 插件
mybatisx:mybatis plus開發的一個插件,從mapper方法快速定位到xml文件
6.安裝VSCode
https://code.visualstudio.com/
7.添加VSCode插件
-
Auto Close Tag 自動加上關閉標簽
-
Auto Rename Tag 自動命名配對標簽
-
Chinese 中文簡體包
-
ESLint 語法檢查
-
HTML CSS Support 幫助CSS開發
-
HTML Snippets 幫忙HTML開發
-
JavaScript (ES6) 幫助JavaScript開發
-
Liver Server 啟動一個本地服務
-
open in browser 用瀏覽器打開文件
-
Vetur ?幫助Vue開發
-
minapp 幫助小程序開發
問題
1.新項目導入main1,main2
刪除main1.iml,main2.iml
4.7 配置Git
1.配置git 用戶名和郵箱
git?config?--global?user.name?"jackson0714" git?config?--global?user.email?"jackson0585@163.com"2.生成ssh key
ssh-keygen?-t?rsa?-b?4096?-C?"jackson0585@163.com"3.設置ssh key
-
打開文件
C:\Users\Administrator.ssh\id_rsa.pub
-
拷貝里面的內容
-
打開這個鏈接
https://github.com/settings/ssh/new
-
粘貼已拷貝的內容
-
保存ssh key
4.遇到的問題
如果遇到Fatal: HttpRequestException encountered問題
則下載這個安裝包解決:
Git Credential Manager for Windows v1.20
鏈接:https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/
git每次提交都需要輸入用戶名和密碼
解決辦法:git config --global credential.helper store
下次提交輸入用戶名和密碼后就會記住了
5.讓一個項目同時提交到碼云和GitHub兩個倉庫
在項目目錄里找到.git文件夾然后找到config文件。
打開這個文件后找到下面的代碼
[remote?"origin"]url?=?git提交地址fetch?=?+refs/heads/*:refs/remotes/origin/*將其改成
[remote?"origin"]url?=?碼云Git提交地址url?=?GitHub提交地址fetch?=?+refs/heads/*:refs/remotes/origin/*問題:
c731c6f..69bae9b ?master -> master To https://gitee.com/jayh2018/passjava-portal.git ! [rejected] ? ? ? ?master -> master (fetch first) error: failed to push some refs to 'https://gitee.com/jayh2018/passjava-portal.git' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
4.8 Windows安裝mysql
1.安裝截圖
2.遇到的問題 1
windows用syslog連接本地mysql數據庫,提示 plugin caching_sha2_password
解決方案:
ALTER?USER?'root'@'%'?IDENTIFIED?WITH?mysql_native_password?BY?'123';2.遇到的問題 2
Host is not allowed to connect to this MySQL server
使用遠程連接mysql的時候碰到這樣的錯誤:
Host is not allowed to connect to this MySQL server。
簡單的解決方式如下:
(1)修改表。可能是你的帳號不允許從遠程登陸,只能在localhost。這個時候只要在localhost的那臺電腦,登入mysql后,更改 "mysql" 數據庫里的 "user" 表里的 "host" 項,從"localhost"改稱"%"
mysql -u root -p
按照提示輸入密碼
mysql>use mysql;
mysql>update user set host = '%' where user = 'root';
(2)修改完后執行如下SQL命令
flush privileges
五、PassJava 基礎實踐篇
5.1 初始化項目和添加微服務
1.GitHub上創建一個空的倉庫
2.從GitHub上引入空的項目
3.添加內容服務
passjava-content
| 1 | group | com.jackson0714.passjava |
| 2 | Artifact | passjava-content |
| 3 | Name | passjava-content |
| 4 | Description | 佳必過-內容服務 |
| 5 | Package | com.jackson0714.passjava.content |
-
添加依賴組件SpringWeb, OpenFeign
3.添加其他微服務
| 1 | 內容微服務 | passjava-content |
| 2 | 會員微服務 | passjava-member |
| 3 | 題目微服務 | passjava-question |
| 4 | 學習微服務 | passjava-study |
| 5 | 渠道微服務 | passjava-channel |
4.PassJava-Platform添加Pom.xml文件
<?xml?version="1.0"?encoding="UTF-8"?> <project?xmlns="http://maven.apache.org/POM/4.0.0"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.jackson0714.passjava</groupId><artifactId>passjava</artifactId><version>0.0.1-SNAPSHOT</version><name>passjava</name><description>佳必過-聚合服務</description><packaging>pom</packaging><modules><module>passjava-content</module><module>passjava-member</module><module>passjava-question</module><module>passjava-study</module><module>passjava-channel</module></modules> </project>5.添加根目錄Maven 配置
Maven操作根項目就可以了,試下clean
6. 配置.gitignore文件
提交代碼時,忽略某些文件
###?gradle?### .gradle /build/ !gradle/wrapper/gradle-wrapper.jar###?STS?### .settings/ .apt_generated .classpath .factorypath .project .settings .springBeans bin/###?IntelliJ?IDEA?### .idea *.iws *.iml *.ipr rebel.xml###?NetBeans?### nbproject/private/ build/ nbbuild/ dist/ nbdist/ .nb-gradle/###?maven?### target/ *.war *.ear *.zip *.tar *.tar.gz **/mvnw **/mvnw.cmd **/.mvn###?logs?#### /logs/ *.log###?temp?ignore?### *.cache *.diff *.patch *.tmp *.java~ *.properties~ *.xml~###?system?ignore?### .DS_Store Thumbs.db Servers .metadata upload gen_code###?database?###db/db_back_dir/###?redis?### /redis/刪除子項目的.gitignore文件
7.提交代碼
可以用IDEA的git工具提交,也可以用git bash命令行提交
git?add?. git?commit?-m?'xxx' git?push?origin?master5.2 初始化數據庫和表
用PowerDisigner工具創建數據庫
-
用PowerDisigner工具創建數據庫
總共有5個微服務數據庫:內容、學習、渠道、用戶、題目
5個數據庫-
內容微服務的數據庫
-
學習微服務的數據庫
-
渠道微服務的數據庫
-
用戶微服務的數據庫
-
題目微服務的數據庫
SQL文件在這個項目里面:https://github.com/Jackson0714/PassJava-Platform.git
SQL文件5.3 搭建管理后臺
“管理后臺使用人人開源的后臺管理框架,完成快速搭建。
”1.下載人人開源后臺管理框架
-
renren-fast
https://gitee.com/renrenio/renren-fast.git
-
renren-fast-vue
https://gitee.com/renrenio/renren-fast-vue.git
2.添加人人開源后端代碼
PassJava項目
拷貝文件夾renren-fast到PassJava根目錄
POM文件 添加依賴
<module>renren-fast</module>3.初始化后臺管理數據庫
-
創建數據庫:passjava_admin
-
執行renren-fast/db/mysql.sql腳本
4.修改renren-fast 服務的配置文件
文件路徑:src/main/resources/application-dev.yml
-
修改數據庫連接為自己的mysql數據庫連接
5.啟動renren-fast服務
-
配置SDK為1.8
-
-
運行renren-fast后臺
出現錯誤:com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large...
解決方案:修改mysql容器的配置文件
cd?/mydata/mysql/conf sudo?vim?my.cnf添加配置,[mysqld_safe]如果有,則不需要添加 [mysqld_safe] max_allowed_packet=32M-
執行結果
-
測試服務運行狀態
瀏覽器輸入:http://localhost:8080/renren-fast/
顯示結果:
{"msg":"invalid?token","code":401}結果如上所示,則表示服務運行正常。另外結果里面的invalid token說明權限不足,不是指服務不正常。
6.啟動前端項目
-
配置cnpm
npm?install?-g?cnpm?--registry=https://registry.npm.taobao.org -
安裝node_modules依賴包
cnpm?install -
打包前端項目
npm?run?dev -
瀏覽后臺
http://localhost:8002
7.前后端聯調登錄
-
登錄后臺
賬號:admin
密碼:admin
登錄成功
-
查看后端服務日志
說明前端登錄請求發送到了后端服務,并驗證了用戶名和密碼是否正確。
5.4 自動生成前后端代碼
1.下載代碼生成器框架
git?clone?https://gitee.com/renrenio/renren-generator.git2.添加人人開源后端代碼
PassJava項目
拷貝文件夾renren-fast到PassJava根目錄
POM文件 添加依賴
<module>renren-generator</module>3.修改renren-generator服務的配置文件
(1)修改數據庫鏈接 src/main/resources/application-dev.yml
-
修改數據庫連接為自己的mysql數據庫連接
-
數據庫名改為要生成代碼的服務,如passjava_qms數據庫
url:?jdbc:mysql://129.211.188.xxx:3306/passjava_qms?useUnicode=true&characterEncoding=UTF-8&useSSL=false username:?root password:?root
(2)修改屬性配置文件 src/main/resources/generator.properties
# 以question微服務為例 mainPath=com.jackson0714 package=com.jackson0714.passjava moduleName=question author=jackson0714 email=jackson0585@163.com tablePrefix=qms_(3)修改controller 模板文件
src/main/resources/template/Controller.java.vm
刪除引入的包,后面再引入
import?org.apache.shiro.authz.annotation.RequiresPermissions;注釋RequiresPermissions注解,后面再引入
@RequiresPermissions("${moduleName}:${pathName}:list")4.啟動代碼生成器服務
啟動代碼生成器服務瀏覽器打開localhost,可以看到數據庫qms的兩張表已經顯示在后臺了
5.生成代碼
-
生成代碼
-
拷貝main文件夾到question模塊src目錄
-
刪除前端代碼passjava-question\src\main\resources\src目錄
-
代碼結構
生成的代碼包含controller,dao層,實體類,接口實現類,mapper映射文件
6.添加common 模塊
因為自動生成的代碼引用了一些工具類,而我們的項目中沒有,所以需要加個common模塊添加一些工具類
引用工具類報錯 選擇Maven-
添加passjava-common
New Module: 選擇Maven
Name: passjava-common
添加common模塊7.question模塊添加common模塊依賴
pom文件添加依賴
<dependency><groupId>com.jackson0714.passjava</groupId><artifactId>passjava-common</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>8.common模塊添加依賴
-
MyBatis-Plus
<!--mybatis-plus?DAO層工具?https://mp.baomidou.com/--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.2.0</version> </dependency> -
lombok依賴
<!--lombok?不需要寫getter,setter方法了--> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version> </dependency> -
httpcore依賴
<!--httpcore?依賴--> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.12</version> </dependency> -
commons-lang依賴
<!--commons-lang?依賴?--> <dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version> </dependency> -
servlet依賴
<!--??導入servlet-api?依賴??--> <dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope> </dependency>
9.common模塊添加工具類
-
添加包com.jackson0714.common.utils
-
從renren-fast項目copy文件
Constans.java、PageUtils.java、Query.java、R.java、RRException.java
-
添加包com.jackson0714.common.xss
-
從renren-fast項目copy文件
HTMLFilter.java、SQLFilter.java
5.5 整合MyBatis-Plus實現CRUD
1.添加Mybatis-Plus依賴
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version> </dependency>2.配置數據源
-
導入數據庫的驅動
-
查看mysql版本 5.7.29
-
到maven倉庫查看適用的mysql驅動,5.7的沒有,8.0兼容5.7的,所以選擇8.0的驅動
<!--添加mysql驅動--> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.17</version> </dependency>3.配置MyBatis-Plus
配置mabatis-plus時的智能提示-
添加application.yml 文件配置數據源
文件路徑:/passjava-question/src/main/resources/application.yml
spring:datasource:driver-class-name:?com.mysql.cj.jdbc.Driverurl:?jdbc:mysql://129.211.188.xxx:3306/passjava_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername:?rootpassword:?xxx -
配置mapper映射文件路徑
mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: auto -
添加MapperScan注解
@MapperScan("com.jackson0714.passjava.question.dao") @SpringBootApplication public?class?PassjavaQuestionApplication?{public?static?void?main(String[]?args)?{SpringApplication.run(PassjavaQuestionApplication.class,?args);} }
4.測試mybatis-plus的CRUD方法
創建類型為javaBasic的type表數據 更新id=1的表數據-
創建類型為javaBasic的type表數據
@Autowired TypeService?typeService;//?創建題目類型 @Test void?testCreateType()?{TypeEntity?typeEntity?=?new?TypeEntity();typeEntity.setType("javaBasic");typeService.save(typeEntity);System.out.println("創建成功"); } -
更新id=1的表數據
//?更新type=jvm @Test void?testUpdateType()?{TypeEntity?typeEntity?=?new?TypeEntity();typeEntity.setId(1L);typeEntity.setType("jvm");typeService.updateById(typeEntity);System.out.println("修改成功"); } -
查詢id=1的表數據
//?查詢題目類型 @Test void?testSelectType()?{List<TypeEntity>?typeEntityList?=?typeService.list(new?QueryWrapper<TypeEntity>().eq("id",1L));typeEntityList.forEach((item)->?{System.out.println(item);});System.out.println("查詢成功"); }
-
刪除id=1的表數據
//?刪除題目類型記錄 @Test void?testRemoveType()?{typeService.removeById(1L);System.out.println("刪除成功"); }
5.6 生成所有微服務的CRUD代碼
1. 修改代碼生成器配置文件
(1)\renren-generator\src\main\resources\generator.properties
mainPath=com.jackson0714 package=com.jackson0714.passjava moduleName=channel author=jackson0714 email=jackson0585@163.com tablePrefix=chms_(2)\renren-generator\src\main\resources\application.yml
修改連接的數據庫:passjava_chms
2.生成渠道微服務代碼
啟動服務,打開瀏覽器:http://localhost:8003/#generator.html
注意:端口地址默認是8080,我配置成了8003。
生成渠道微服務代碼3.添加生成的代碼
-
刪除自動生成的代碼中的文件夾:main\resources\src
-
拷貝main文件夾到channel模塊src目錄下
4.配置渠道微服務
-
pom.xml引入common模塊
<dependency><groupId>com.jackson0714.passjava</groupId><artifactId>passjava-common</artifactId><version>0.0.1-SNAPSHOT</version> </dependency> -
添加application.yml
spring:datasource:driver-class-name:?com.mysql.cj.jdbc.Driverurl:?jdbc:mysql://129.211.188.xxx:3306/passjava_chms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername:?rootpassword:?xxxmybatis-plus:mapper-locations:?classpath:/mapper/**/*.xmlglobal-config:db-config:id-type:?auto -
5.測試channel服務接口
訪問:http://localhost:8000/channel/channel/list
返回:
{"msg":"success","code":0,"page":{"totalCount":0,"pageSize":10,"totalPage":0,"currPage":1,"list":[]}}
5.生成所有微服務的CRUD代碼
生成所有微服務代碼6.配置微服務端口
passjava-channel??端口8000 passjava-content??端口9000 passjava-member?端口10000 passjava-question?端口11000 passjava-study?端口12000所有微服務都啟動成功并測試接口通過
http://localhost:8000/channel/channel/list http://localhost:9000/content/banner/list http://localhost:10000/member/member/list http://localhost:11000/question/question/list http://localhost:12000/study/studytime/list5.7 管理后臺-題目類型功能
1.環境準備
-
代碼準備
將renren-fast-vue代碼copy到自己的前端項目中
-
安裝node_module
-
啟動前端portal
-
登陸后臺
1.啟動RenrenAplication
2.輸入用戶名和密碼登陸
2. 添加目錄和菜單
-
添加題目中心目錄(一級菜單)
刷新頁面,就可以看到題目中心菜單
-
添加題目類型維護菜單(二級菜單)
可以看到數據庫新增了兩條記錄,分別對應兩個菜單
sys_menu表點擊類型維護菜單,打開了鏈接:http://localhost:8002/#/question-type,頁面顯示空白頁面.
3.自動生成前端頁面
用renren-generator自動生成前端代碼,可以參考這篇:13.SpringCloud實戰項目-自動生成前后端代碼
拷貝question目錄到前端目錄 \src\views\modules
自動生成前端代碼 前端Vue頁面4. 測試類型維護功能
點擊類型維護菜單,可以看到請求報404
http://localhost:8080/renren-fast/question/type/list?t=1587825969456&page=1&limit=10&key=
“因為頁面的請求都訪問到renren-fast服務了,所以要修改為訪問題目微服務。但是前端有很多請求訪問的是不同的服務,所以我們可以通過網關來作為請求的入口,然后將不同的請求路由到不同的服務。
”SpringCloud整合網關可以看之前寫的一篇文章:20.SpringCloud整合Gateway網關
5.配置請求到網關
文件:\static\config\index.js
api接口請求地址替換為gateway的地址
window.SITE_CONFIG['baseUrl']?=?'http://localhost:8080/renren-fast'; 替換為 window.SITE_CONFIG['baseUrl']?=?'http://localhost:8060';?//?網關地址刷新頁面,發現會回到登錄頁面,而且驗證碼獲取不到,F12調試工具可以看到驗證碼請求發送到網關上,而網關上找不到這個請求地址(http://localhost:8060/captcha.jpg),所以報404。其實驗證碼請求應該訪問renren-fast服務,所以我們要將驗證碼請求通過網關轉發到renren-fast服務(http://localhost:8080/renren-fast/captcha.jpg)。
#?驗證碼請求: GET?http://localhost:8060/captcha.jpg?uuid=1ce21f53-1866-40b1-8b20-2f4515d59f0d?404?(Not?Found) 獲取驗證碼報404 “可以將renren-fast注冊到注冊中心,然后通過網關將請求轉發到renren-fast服務。
”6.注冊renren-fast服務
-
renren-fast項目添加common依賴
-
配置注冊中心地址
-
配置應用程序的名稱
-
應用類添加@EnableDiscoveryClient注解
-
查看服務是否注冊成功
7. 添加網關路由規則
-
配置路由規則
passjava-gateway項目中application.yml文件配置路由規則,并重啟passjava-gateway服務
spring:cloud:gateway:routes:-?id:?route_portal?#?路由規則iduri:?lb://renren-fast?#?負載均衡,renren-fast服務predicates:?#?斷言-?Path=/api/**?#?如果前端請求路徑包含?api,則應用這條路由規則filters:?#過濾器-?RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}?#?將訪問路徑中包含的api替換成renren-fast,但是替換的url不會在前端顯示,還是網關的訪問路徑。這里不是跳轉到新的路徑,而是轉發請求。-
修改前端請求路徑
文件:\static\config\index.js
請求路徑添加api
?window.SITE_CONFIG['baseUrl']?=?'http://localhost:8086';替換為window.SITE_CONFIG['baseUrl']?=?'http://localhost:8060/api';?//?添加api-
刷新登錄頁面,可以正常獲取驗證碼,請求路徑為網關地址 + /api/captcha
前端將請求發送到網關http://localhost:8060/api/captcha.jpg,網關將請求轉發到http://localhost:8060/api/renren-fast/captcha.jpg。
”-
登錄,報跨域問題
登錄頁面url:http://localhost:8002,點擊登錄訪問的請求url:http://localhost:8060/api/sys/login,兩個url的端口號不一樣,產生了跨域問題。
”8.跨域問題
跨域場景-
跨域資源共享(CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被準許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。
-
比如,站點 http://domain-a.com 的某 HTML 頁面通過 ?的 src 請求 http://domain-b.com/image.jpg。網絡上的許多頁面都會加載來自不同域的CSS樣式表,圖像和腳本等資源。
-
出于安全原因,瀏覽器限制從腳本內發起的跨源HTTP請求。例如,XMLHttpRequest和Fetch API遵循同源策略。這意味著使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非響應報文包含了正確CORS響應頭。
9.解決跨域問題
-
添加響應頭,配置當次請求允許跨域
-
Access-Control-Allow-Origin:支持哪些來源的請求跨域
-
Access-Control-Allow-Methods:支持哪些方法跨域
-
Access-Control-Allow-Credentials:跨域請求默認不包含cookie,設置為true可以包含cookie
-
Access-Control-Expose-Headers:跨域請求暴露的字段CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
-
Access-Control-Max-Age:表明該響應的有效時間為多少秒。在有效時間內,瀏覽器無 須為同一請求再次發起預檢請求。請注意,瀏覽器自身維護了一個最大有效時間,如果 該首部字段的值超過了最大有效時間,將不會生效。
-
-
添加跨域配置
passjava-gateway應用中添加配置類PassJavaCorsConfiguration.java
-
注釋renren-fast里面的跨域配置
文件路徑:src/main/java/io/renren/config/CorsConfig.java
-
登錄成功
可以看到login請求的響應報文中包含了已配置的CORS響應頭
10.配置題目服務的路由規則
我們訪問題目中心的類型頁面,發現還是報404找不到資源
所以我們需要配置題目服務的路由規則,將題目中心的頁面請求經網關轉發到題目服務。
spring:cloud:gateway:routes:-?id:?route_question?#?題目微服務路由規則uri:?lb://passjava-question?#?負載均衡,將請求轉發到注冊中心注冊的renren-fast服務predicates:?#?斷言-?Path=/api/question/**?#?如果前端請求路徑包含?api/question,則應用這條路由規則filters:?#過濾器-?RewritePath=/api/(?<segment>.*),/$\{segment}?#?將跳轉路徑中包含的api替換成question “注意:若predicates的Path更精確,則將路由規則放到更上面,優先命中更上面的路由規則。
”11.測試類型維護功能
類型維護頁面 修改類型logo-
數據庫插入3條測試數據
-
測試查詢列表,可以看到有三條記錄查詢出來了
-
測試修改一條數據,可以看到數據庫里面記錄更新為23了
-
測試刪除一條數據,可以看到界面和數據庫都刪除了一條數據
12.打開新增和批量刪除功能
注釋權限判斷,默認返回true
//?src\utils\index.js /***?是否有權限*?@param?{*}?key*/ export?function?isAuth?(key)?{//?return?JSON.parse(sessionStorage.getItem('permissions')?||?'[]').indexOf(key)?!==?-1?||?falsereturn?true } 新增和批量刪除按鈕5.8 管理后臺-題目維護功能
1.配置邏輯刪除
-
所有表字段添加del_flag字段
del_flag?tinyint(1)?DEFAULT?0?COMMENT?'刪除標記(0-正常,1-刪除)', -
MyBatisPlus配置邏輯刪除
-
log中打印查詢SQL語句
-
log打印刪除SQL語句
2.快速顯示開關
想要將是否顯示改為快速開關
-
自定義列模板
1.通過 Scoped slot 可以獲取到 row, column, $index 和 store(table 內部的狀態管理)的數據
2.使用Switch開關
添加更新方法
//?更新題目是否顯示 updateQuestionStatus(data)?{console.log(data)let?{id,?enable}?=?datathis.$http({url:?this.$http.adornUrl('/question/question/update'),method:?'post',data:?this.$http.adornData({id,?enable},?false)}).then(({?data?})?=>?{this.$message({type:"success",message:?"狀態更新成功"})}); },3.前端字段校驗
對排序字段限制:必須為正整數
dataRule: {displayOrder: [{validator: (rule, value, callback) => {if (value == "") {callback(new Error("排序字段必須填寫"));} else if (!Number.isInteger(value) || value<0) {callback(new Error("排序必須是一個大于等于0的整數"));} else {callback();}},trigger: "blur"}] }4.后端字段校驗
-
實體類字段上添加注解@Positive必須是大于0的數字
-
API 添加注解@Valid
測試結果
后端字段校驗-1,0,0.2 不通過
測試1,1.2通過
5.模糊查詢題目列表
修改實現類QuestionServiceImpl的queryPage方法
原方法:
public?PageUtils?queryPage(Map<String,?Object>?params)?{IPage<QuestionEntity>?page?=?this.page(new?Query<QuestionEntity>().getPage(params),new?QueryWrapper<QuestionEntity>());return?new?PageUtils(page); }修改后:
@Override public?PageUtils?queryPage(Map<String,?Object>?params)?{//1.get?keyString?key?=?(String)?params.get("key");QueryWrapper<QuestionEntity>?queryWrapper?=?new?QueryWrapper<>();if?(!StringUtils.isEmpty(key))?{queryWrapper.eq("id",?key).or().like("title",?key).or().like("answer",?key);}IPage<QuestionEntity>?page?=?this.page(new?Query<QuestionEntity>().getPage(params),queryWrapper);return?new?PageUtils(page); }6.添加分頁插件
沒有分頁插件顯示共0條添加分頁插件
package?com.jackson0714.passjava.question.config;import?com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import?org.mybatis.spring.annotation.MapperScan; import?org.springframework.context.annotation.Bean; import?org.springframework.context.annotation.Configuration; import?org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration @EnableTransactionManagement?//開啟事務 @MapperScan("com.jackson0714.passjava.question.dao") public?class?MyBatisConfig?{//引入分頁插件@Beanpublic?PaginationInterceptor?paginationInterceptor()?{PaginationInterceptor?paginationInterceptor?=?new?PaginationInterceptor();//?設置請求的頁面大于最大頁后操作,?true調回到首頁,false?繼續請求??默認falsepaginationInterceptor.setOverflow(true);//?設置最大單頁限制數量,默認?500?條,-1?不受限制paginationInterceptor.setLimit(1000);return?paginationInterceptor;} }添加分頁插件后的顯示
配置了分頁插件的顯示六、PassJava 高級實踐篇
6.1 Spring Cloud Alibaba 組件簡介
1.SpringCloud Alibaba概述
“Spring Cloud Alibaba 致力于提供微服務開發的一站式解決方案。此項目包含開發分布式應用微服務的必需組件,方便開發者通過 Spring Cloud 編程模型輕松使用這些組件來開發分布式應用服務。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以將 Spring Cloud 應用接入阿里微服務解決方案,通過阿里中間件來迅速搭建分布式應用系統。
”Github:https://github.com/alibaba/spring-cloud-alibaba
Spring Cloud的幾大痛點
-
部分組件停止維護和更新,有問題也不易解決
-
部分環境搭建起來比較復雜,沒有非常友好的可視化界面
-
配置相對來說復雜,需要較高的學習成本
Spring Cloud Alibaba的優勢
-
阿里經歷過了時間的考驗
-
設計合理
-
擁有不錯的可視化界面,方便運維監控和排查問題
-
環境搭建和配置簡單,學習成本低
PassJava項目搭配SpringCloud Alibaba技術的搭配方案
| 服務發現組件 | Eureka(停止維護)服務發現組件 | Nacos 注冊中心 | Spring Cloud Alibaba - Nacos |
| 配置中心組件 | Spring Cloud Config 配置中心 | Nacos 配置中心 | Spring Cloud Alibaba - Nacos |
| 斷路保護組件 | Hystrix 斷路保護 | Sentinel 服務容錯 | Spring Cloud Alibaba - Sentinel |
| 鏈路追蹤組件 | Sleuth 調用鏈監控 | / | Spring Cloud - Sleuth |
| 負載均衡組件 | Ribbon | / | Spring Cloud - Ribbon |
| 遠程調用組件 | OpenFeign (HTTP+JSON) | Dubbo(RPC框架) | Spring Cloud - OpenFeign |
| 分布式事務 | / | Seata 分布式事務 | Spring Cloud Alibaba - Seata |
| API 網關 | Gateway | / | Spring Cloud - Gateway |
最后技術選型:
Spring?Cloud?Alibaba?-?Nacos?實現注冊中心 Spring?Cloud?Alibaba?-?Nacos?實現配置中心 Spring?Cloud?Alibaba?-?Sentinel??實現服務容錯 Spring?Cloud?Alibaba?-?Seata?實現分布式事務Spring?Cloud?-?Ribbon?實現負載均衡 Spring?Cloud?-?Feign?實現遠程調用 Spring?Cloud?-?Gateway?API網關 Spring?Cloud?-?Sleuth?實現調用鏈監控2.Spring Cloud Alibaba版本
項目的版本號格式為 x.x.x 的形式,其中 x 的數值類型為數字,從 0 開始取值,且不限于 0~9 這個范圍。項目處于孵化器階段時,第一位版本號固定使用 0,即版本號為 0.x.x 的格式。
由于 Spring Boot 1 和 Spring Boot 2 在 Actuator 模塊的接口和注解有很大的變更,且 spring-cloud-commons 從 1.x.x 版本升級到 2.0.0 版本也有較大的變更,因此阿里采取跟 SpringBoot 版本號一致的版本:
-
1.5.x 版本適用于 Spring Boot 1.5.x
-
2.0.x 版本適用于 Spring Boot 2.0.x
-
2.1.x 版本適用于 Spring Boot 2.1.x
-
2.2.x 版本適用于 Spring Boot 2.2.x
Spring Cloud Alibaba 版本和Spring Cloud 和Spring Boot 版本兼容性列表
| Spring Cloud Hoxton.SR3 | 2.2.x.RELEASE | 2.2.x.RELEASE |
| Spring Cloud Greenwich | 2.1.x.RELEASE | 2.1.x.RELEASE |
| Spring Cloud Finchley | 2.0.x.RELEASE | 2.0.x.RELEASE |
| Spring Cloud Edgware | 1.5.x.RELEASE | 1.5.x.RELEASE |
我們采用Spring Cloud Hoxton.SR3, Spring Cloud Alibaba 2.2.0.RELEASE, Spring Boot 2.2.6 RELEASE
PassJava-Common的pom.xml文件引入Spring Cloud Alibaba依賴
<dependencyManagement><dependencies><!--??Spring?Cloud?Alibaba?依賴??--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.0.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies> </dependencyManagement>6.2 SpringCloud整合Alibaba-Nacos組件
“Nacos 是阿里巴巴開源的一個更易于構建云原生應用的動態服務發現、配置管理和服務管理平臺。
”1.引入Nacos 服務發現組件
passjava-common模塊的pom.xml文件引入Nacos 服務發現組件
<!--?nacos?discovery?服務發現組件--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>2.下載Nacos Server并啟動
-
下載Nacos Server 壓縮包
https://github.com/alibaba/nacos/releases
啟動 Server,進入解壓后文件夾或編譯打包好的文件夾,找到如下相對文件夾 nacos/bin,并對照操作系統實際情況之下如下命令。
Linux/Unix/Mac 操作系統,執行命令 sh startup.sh -m standalone
Windows 操作系統,執行命令 cmd startup.cmd
windows執行startupm.cmd遇到問題:
λ?startup.cmd??????????????????????????????????????????????????????Please?set?the?JAVA_HOME?variable?in?your?environment,?We?need?java(x64)!?jdk8?or?later?is?better!?解決方案:
修改startup.cmd文件中的%JAVA_HOME%
%JAVA_HOME%?替換為?C:\Program?Files\Java\jdk1.8.0_131啟動成功:
3.每個微服務都配置Nacos Server 地址
-
配置Nacos Server 地址
在passjava-question、passjava-channel、passjava-content、passjava-member、passjava-study 應用的 /src/main/resources/application.yml配置文件中配置 Nacos Server 地址
spring:cloud:nacos:discovery:server-addr:?127.0.0.1:88484.添加注解
為每個服務使用 @EnableDiscoveryClient 注解開啟服務注冊與發現功能
@EnableDiscoveryClient @MapperScan("com.jackson0714.passjava.question.dao") @SpringBootApplication public?class?PassjavaQuestionApplication?{public?static?void?main(String[]?args)?{SpringApplication.run(PassjavaQuestionApplication.class,?args);}}5.配置微服務的名稱
spring:application:name:?passjava-question6.訪問nacos server后臺
-
登錄后臺
http://localhost:8848/nacos/index.html#/login
用戶名:nacos
密碼:nacos
-
查看已注冊的服務
passjava-channel?渠道微服務 passjava-member?用戶微服務 passjava-study?學習微服務 passjava-question?問題微服務 passjava-content?內容微服務
6.3 SpringCloud整合OpenFeign遠程調用
1.Feign 概述
-
Feign聲明式客的HTTP客戶端,讓遠程調用更簡單。
-
提供了HTTP請求的模板,編寫簡單的接口和插入注解,就可以定義好HTTP請求的參數、格式、地址等信息
-
整合了Ribbon(負載均衡組件)和Hystix(服務熔斷組件),不需要顯示使用這兩個組件
-
Spring Cloud Feign 在Netflix Feign的基礎上擴展了對SpringMVC注解的支持
2. 遠程調用示例
“示例:查詢用戶的學習時長
”用戶微服務passjava-member調用學習微服務passjava-study的方法
2.1 引入openfeign依賴
passjava-member和passjava-study項目的pom文件引入openfeign依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>2.2 StudyTimeController定義遠程調用測試方法
返回某個用戶學習題目的總時長
@RequestMapping("/member/list/test") public?R?memberStudyTimeTest()?{StudyTimeEntity?studyTimeEntity?=?new?StudyTimeEntity();studyTimeEntity.setTotalTime(100);?//?學習時長:100分鐘studyTimeEntity.setQuesTypeId(1L);?//?題目類型:1 (javaBasic)return?R.ok().put("studyTime",?Arrays.asList(studyTimeEntity)); }2.3 member目錄下創建feign service
接口測試結果-
創建package: com.jackson0714.passjava.member.feign
-
創建StudyTimeFeignService接口
-
添加注解@FeignClient。顯示聲明這個接口用來遠程調用study服務。
@FeignClient("passjava-study") public?interface?StudyTimeFeignService?{} -
添加遠程調用方法
public?R?memberStudyTime(); -
給方法添加要遠程調用的方法的路徑study/studytime/member/list/test
@RequestMapping("study/studytime/member/list/test") public?R?getMemberStudyTimeListTest(); -
添加注解@EnableFeignClients開啟遠程調用服務。
給類PassjavaStudyApplication.java添加注解@EnableFeignClients。
basePackages代表自動掃碼指定路徑下所有帶有@FeignClient注解的接口。
@EnableFeignClients(basePackages?=?"com.jackson0714.passjava.member.feign") @EnableDiscoveryClient @MapperScan("com.jackson0714.passjava.member.dao") @SpringBootApplication public?class?PassjavaMemberApplication?{public?static?void?main(String[]?args)?{SpringApplication.run(PassjavaMemberApplication.class,?args);}} -
測試接口
studytime和member都有數據,學習時長:100分鐘,昵稱:悟空聊架構
-
啟動passjava-member和passjava-study服務
-
用postman工具或瀏覽器輸入請求地址
http://localhost:10000/member/member/studytime/list/test
-
返回結果如下圖
-
2.4 測試OpenFeign傳參
示例:用戶id作為參數在服務間傳遞
MemberController
@RequestMapping("/studytime/list/test/{id}") public?R?getMemberStudyTimeListTest(@PathVariable("id")?Long?id)?{//mock數據庫查到的會員信息MemberEntity?memberEntity?=?new?MemberEntity();memberEntity.setId(id);?//?學習時長:100分鐘memberEntity.setNickname("悟空聊架構");//遠程調用拿到該用戶的學習時長(學習時長是mock數據)R?memberStudyTimeList?=?studyTimeFeignService.getMemberStudyTimeListTest(id);return?R.ok().put("member",?memberEntity).put("studytime",?memberStudyTimeList.get("studytime")); }StudyTimeFeignService
@FeignClient("passjava-study") public?interface?StudyTimeFeignService?{@RequestMapping("study/studytime/member/list/test/{id}")public?R?getMemberStudyTimeListTest(@PathVariable("id")?Long?id); }StudyTimeController
@RequestMapping("/member/list/test/{id}") public?R?memberStudyTimeTest(@PathVariable("id")?Long?id)?{StudyTimeEntity?studyTimeEntity?=?new?StudyTimeEntity();studyTimeEntity.setTotalTime(100);?//?學習時長:100分鐘studyTimeEntity.setQuesTypeId(1L);?//?題目類型:1 (javaBasic)return?R.ok().put("studytime",?Arrays.asList(studyTimeEntity)); }請求地址和參數:http://localhost:10000/member/member/studytime/list/test/1
執行結果:
執行結果2.5 總結FeignClient使用方法
-
引入OpenFeign依賴
-
定義FeignClient接口類(注解@FeignClient),聲明這個接口類是用來遠程調用其他服務的
-
接口類中定義要遠程調用的接口方法,指定遠程服務方法的路徑
-
Controller類中調用接口方法
-
開啟遠程調用(注解@EnableFeignClients)
-
遠程調用的流程:
-
@RequestBody將這個對象轉為json
-
找到passjava-study服務,給study/studytime/member/list/test服務發送請求
-
將json放到請求體里面,發送請求
-
對方服務收到請求,請求體里有json數據
-
將請求體中的json數據轉換成對方服務的參數類型。只需要兩邊的字段名稱和類型是一致的。
-
6.4 Spring Cloud 整合 Nacos配置中心
1.傳統配置方式
-
application.properties文件中定義兩個配置:
-
示例控制器中定義私有變量nickname和age,@value代表從配置中取值
-
示例控制器中定義方法:獲取nick和age的值
-
測試結果
總結:從配置文件中獲取配置。
這種方式的缺點是什么呢?如果要修改配置參數,則需要重新啟動服務。如果服務很多,則需要重啟所有服務,非常不方便。
有沒有什么辦法不停服務修改配置而且使其生效呢?
答案:有的,用Spring Cloud Alibaba的Nacos 組件就可以完成。
2.引入Nacos依賴
PassJava-Common項目的pom.xml文件引入Spring Cloud Alibaba Nacos Config依賴
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>3.配置Nacos元數據
-
passjava-member 添加 /src/main/resources/bootstrap.properties 配置文件(注意:bootstrap.properties 優先級高于其他配置文件)
-
配置 Nacos Config 元數據
4.Nacos后臺新增配置
Data ID: passjava-member.properties
Group: DEFAULT_GROUP
配置格式:
member.nick="悟空" member.age=10 Nacos后臺新增配置5.開啟動態刷新配置功能
添加注解@RefreshScope開啟動態刷新配置功能
@RefreshScope @RestController @RequestMapping("member/sample") public?class?SampleController?{}可以從控制臺看到日志信息:
Refresh keys changed: [member.age] 2020-04-19 23:34:07.154 INFO 8796 --- [-127.0.0.1_8848] c.a.nacos.client.config.impl.CacheData : [fixed-127.0.0.1_8848] [notify-ok] dataId=passjava-member.properties, group=DEFAULT_GROUP, md5=df136e146c83cbf857567e75acb11e2b, listener=com.alibaba.cloud.nacos.refresh.NacosContextRefresher$1@4f49b78b 2020-04-19 23:34:07.154 INFO 8796 --- [-127.0.0.1_8848] c.a.nacos.client.config.impl.CacheData : [fixed-127.0.0.1_8848] [notify-listener] time cost=529ms in ClientWorker, dataId=passjava-member.properties, group=DEFAULT_GROUP, md5=df136e146c83cbf857567e75acb11e2b, listener=com.alibaba.cloud.nacos.refresh.NacosContextRefresher$1@4f49b78bmember.age 更新了,通知了member服務,刷新了配置。對應的配置id為passjava-member.properties,分組為DEFAULT_GROUP。監聽器為com.alibaba.cloud.nacos.refresh.NacosContextRefresher
6.測試結果
訪問:http://localhost:10000/member/sample/test-local-config
結果:nickname和age和Nacos后臺配置一致
結論:只用在Nacos后臺改配置即可實時修改配置。
注意:Nacos的配置項優先級高于application.propertite里面的配置。
測試結果7.命名空間
我們現在有5個微服務,每個微服務用到的配置可能都不一樣,那不同微服務怎么樣獲取自己微服務的配置呢?
這里可以用到命名空間,我們針對每個微服務,都創建一個命名空間。
創建命名空間-
創建命名空間
-
命名空間下創建配置
我們打開配置列表菜單,可以看到有五個命名空間。
選中passjava-channel命名空間,然后新增配置項,與之前新增配置的步驟一致,也可以通過克隆命名空間來克隆配置。
克隆配置 passjava-member.properties-
修改指定的命名空間
bootstrap.properties配置命名空間
spring.cloud.nacos.config.namespace=passjava-member -
測試配置是否生效
修改passjava-member.properties的配置內容
重啟member服務
訪問方法:/member/sample/test-local-config
執行結果:
{"msg":?"success","code":?0,"nickname":?"\"悟空member\"","age":?30 }說明獲取的是passjava-member命名空間的配置
8.分組
如果我們有多套環境,比如開發環境,測試環境,生產環境,每一套環境的配置參數不一樣,那配置中心該如何配置呢?
我們可以使用配置中心的分組功能。每一套環境都是一套分組。
-
首先創建一套dev環境配置項,然后克隆配置到test和prod環境
-
bootstrap.properties配置當前使用的分組:prod
-
測試獲取生產環境配置
{"msg":?"success","code":?0,"nickname":?"\"悟空-prod\"","age":?10 }可以看到獲取到的是prod分組的配置
9.多配置集
我們可以將application.yml文件中的datasource、mybatis-plus等配置進行拆解,放到配置中心。group可以創建3套,dev/test/prod。
1.配置中心新建datasource.yml 配置
datasource.yml 配置2.配置中心新建mybatis.yml 配置
mybatis.yml配置3.配置中心新建more.yml 配置
more.yml配置4.克隆dev環境配置到test和prod環境
5.bootstrap.properties增加nacos配置,application.yml注釋配置
spring.application.name=passjava-member spring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.cloud.nacos.config.namespace=passjava-member spring.cloud.nacos.config.group=prodspring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml spring.cloud.nacos.config.extension-configs[0].group=dev spring.cloud.nacos.config.extension-configs[0].refresh=truespring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml spring.cloud.nacos.config.extension-configs[1].group=dev spring.cloud.nacos.config.extension-configs[1].refresh=truespring.cloud.nacos.config.extension-configs[2].data-id=more.yml spring.cloud.nacos.config.extension-configs[2].group=dev spring.cloud.nacos.config.extension-configs[2].refresh=true6.測試配置是否生效
-
測試passjava-member.properties和more.yml配置是否生效
請求url:http://localhost:10000/member/sample/test-local-config
返回配置的nick和age,且端口是10000,且member服務注冊到注冊中心
{"msg":?"success","code":?0,"nickname":?"\"悟空-prod1\"","age":?22 }-
測試datasource.yml和mybatis.yml配置是否生效
請求url:http://localhost:10000/member/member/list
返回數據庫查詢結果
{"msg":?"success","code":?0,"page":?{"totalCount":?0,"pageSize":?10,"totalPage":?0,"currPage":?1,"list":?[]j} }說明以上配置都生效了。
更多配置項
| 服務端地址 | spring.cloud.nacos.config.server-addr | ||
| DataId前綴 | spring.cloud.nacos.config.prefix | spring.application.name | |
| Group | spring.cloud.nacos.config.group | DEFAULT_GROUP | |
| dataID后綴及內容文件格式 | spring.cloud.nacos.config.file-extension | properties | dataId的后綴,同時也是配置內容的文件格式,目前只支持 properties |
| 配置內容的編碼方式 | spring.cloud.nacos.config.encode | UTF-8 | 配置的編碼 |
| 獲取配置的超時時間 | spring.cloud.nacos.config.timeout | 3000 | 單位為 ms |
| 配置的命名空間 | spring.cloud.nacos.config.namespace | 常用場景之一是不同環境的配置的區分隔離,例如開發測試環境和生產環境的資源隔離等。 | |
| AccessKey | spring.cloud.nacos.config.access-key | ||
| SecretKey | spring.cloud.nacos.config.secret-key | ||
| 相對路徑 | spring.cloud.nacos.config.context-path | 服務端 API 的相對路徑 | |
| 接入點 | spring.cloud.nacos.config.endpoint | UTF-8 | 地域的某個服務的入口域名,通過此域名可以動態地拿到服務端地址 |
| 是否開啟監聽和自動刷新 | spring.cloud.nacos.config.refresh-enabled | true |
10.使用Nacos總結
-
1.引入Nacos依賴
-
2.配置Nacos數據源
-
3.配置中心配置數據集DataId和配置內容
-
4.開啟動態刷新配置@RefreshScope
-
5.獲取配置項的值@value
-
6.優先使用配置中心的配置
-
7.使用命名空間namespace來創建各服務的配置
-
8.使用分組group來區分不同環境
-
9.使用多配置集extension-configs區分不同類型的配置
6.5 SpringCloud整合Gateway網關
1.Gateway網關介紹
-
網關:流量的入口
-
網關常用功能:路由轉發,權限校驗,限流控制
-
Spring Cloud Gateway是Spring Cloud官方推出的第二代網關框架
-
Spring Cloud Gateway取代了netflix的Zuul網關
2.Gateway原理
PassJava項目中,小程序和管理后臺請求先訪問到API網關.
API網關通過注冊中心實時感知微服務的狀態的路由地址,準確地將請求路由到各個服務.
Spring Cloud Gateway官方文檔:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/
Gateway原理-
請求到達網關后,先經過斷言Predicate,是否符合某個路由規則
-
如果符合,則按路由規則路由到指定地址
-
請求和響應都可以通過過濾器Filter進行過濾
3.創建Gateway 模塊
-
適用Spring 初始化器創建Gateway module
-
創建module
-
選擇Gateway依賴
-
引入Gateway模塊
4.配置Gateway
-
引入Nacos組件
因common模塊引入了nacos注冊中心組件,所以我們可以直接引用common模塊
<dependency><groupId>com.jackson0714.passjava</groupId><artifactId>passjava-common</artifactId><version>0.0.1-SNAPSHOT</version> </dependency>-
應用類上添加注解@EnableDiscoveryClient
5.使用Gateway demo
-
新建application.yml文件
spring:cloud:gateway:routes:-?id:?route_qquri:?http://www.qq.compredicates:-?Query=url,qq-?id:?route_baiduuri:?http://www.baidu.compredicates:-?Query=url,baidu第一條路由規則:當請求路徑中包含url=qq,則跳轉到http://www.qq.com
第二條路由規則:當請求路徑中包含url=baidu,則跳轉到http://www.baidu.com
后續在PassJava項目中使用Gateway的強大功能.
6.6 整合OSS對象存儲
1.緣起
“文件上傳在系統中用的很頻繁,所以我們需要將上傳的文件進行存儲,傳統的將文件上傳到本機已不適用分布式系統。自己搭建文件服務器有復雜性和維護成本。所以我們可以采用市面上成熟的文件存儲服務,如阿里云的OSS對象存儲服務。
” 上傳圖片每個 OSS 的用戶都會用到上傳服務。Web 端常見的上傳方法是用戶在瀏覽器或 APP 端上傳文件到應用服務器,應用服務器再把文件上傳到 OSS。具體流程如下圖所示。
和數據直傳到 OSS 相比,以上方法有三個缺點:
-
上傳慢:用戶數據需先上傳到應用服務器,之后再上傳到OSS。網絡傳輸時間比直傳到OSS多一倍。如果用戶數據不通過應用服務器中轉,而是直傳到OSS,速度將大大提升。而且OSS采用BGP帶寬,能保證各地各運營商之間的傳輸速度。
-
擴展性差:如果后續用戶多了,應用服務器會成為瓶頸。
-
費用高:需要準備多臺應用服務器。由于OSS上傳流量是免費的,如果數據直傳到OSS,不通過應用服務器,那么將能省下幾臺應用服務器。
2.技術方案
2.1 服務端簽名后直傳
2.1.1 背景
采用JavaScript客戶端直接簽名(參見JavaScript客戶端簽名直傳)時,AccessKeyID和AcessKeySecret會暴露在前端頁面,因此存在嚴重的安全隱患。因此,OSS提供了服務端簽名后直傳的方案。
2.1.2 原理介紹
原理介紹服務端簽名后直傳的原理如下:
用戶發送上傳Policy請求到應用服務器。
應用服務器返回上傳Policy和簽名給用戶。
用戶直接上傳數據到OSS。
3.實現案例
3.1 開通阿里云OSS
-
登錄阿里云官網
https://www.aliyun.com/sale-season/2020/procurement-new-members?userCode=thp9caen
-
創建Bucket 存儲桶
-
獲取accesskey id和secret
-
分配權限
分配 管理對象存儲服務(OSS)權限
3.2 使用OSS SDK
3.2.1 安裝SDK
在Maven項目中加入依賴項
https://help.aliyun.com/document_detail/32009.html?spm=a2c4g.11186623.6.769.2c5145dc4TUgTa <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.0</version> </dependency>3.2.2 ?上傳文件到OSS
@Test void?testUploadByOss()?throws?FileNotFoundException?{// Endpoint以杭州為例,其它Region請按實際情況填寫。String?endpoint?=?"http://oss-cn-beijing.aliyuncs.com";//?阿里云主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建并使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創建RAM賬號。String?accessKeyId?=?"xxxx";String?accessKeySecret?=?"xxxx";String?bucketName?=?"passjava";//?<yourObjectName>上傳文件到OSS時需要指定包含文件后綴在內的完整路徑,例如abc/efg/123.jpg。String?localFile?=?"C:\\Users\\Administrator\\Pictures\\coding_java.png";String?fileKeyName?=?"coding_java.png";//?創建OSSClient實例。OSS?ossClient?=?new?OSSClientBuilder().build(endpoint,?accessKeyId,?accessKeySecret);InputStream?inputStream?=?new?FileInputStream(localFile);ossClient.putObject(bucketName,?fileKeyName,?inputStream);//?關閉OSSClient。ossClient.shutdown(); }3.3 整合Spring Cloud Alicloud OSS
3.3.1 ?passjava-common項目引入spring-cloud-starter-alicloud-oss依賴
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alicloud-oss</artifactId> </dependency>3.3.2 ?配置alicloud oss
spring:cloud:alicloud:access-key:?xxxxsecret-key:?xxxxoss:endpoint:?oss-cn-beijing.aliyuncs.com3.3.3 ?測試上傳
@Autowired OSSClient?ossClient;@Test void?testUploadByAlicloudOss()?throws?FileNotFoundException?{String?bucketName?=?"passjava";String?localFile?=?"C:\\Users\\Administrator\\Pictures\\coding_java.png";String?fileKeyName?=?"coding_java.png";InputStream?inputStream?=?new?FileInputStream(localFile);ossClient.putObject(bucketName,?fileKeyName,?inputStream);ossClient.shutdown(); } 上傳成功3.4 獲取服務端簽名
3.4.1 準備工作:
-
創建一個第三方服務passjava-thirdparty
-
引入passjava-common模塊,并且排除mybatis-plus依賴
-
配置服務發現和端口
-
配置配置中心
-
配置Nacos命名空間和oss.yml
-
開啟服務發現@EnableDiscoveryClient
3.4.2 獲取簽名類
@RestController @RequestMapping("/thirdparty/v1/admin/oss") public?class?OssController?{@AutowiredOSS?ossClient;@Value("${spring.cloud.alicloud.access-key}")private?String?accessId;@Value("${spring.cloud.alicloud.secret-key}")private?String?accessKey;@Value("${spring.cloud.alicloud.oss.endpoint}")private?String?endpoint;@Value("${spring.cloud.alicloud.oss.bucket}")private?String?bucket;@RequestMapping("/getPolicy")public?Map<String,?String>?getPolicy()?{String?host?=?"https://"?+?bucket?+?"."?+?endpoint;?//?host的格式為?bucketname.endpoint// callbackUrl為?上傳回調服務器的URL,請將下面的IP和Port配置為您自己的真實信息。//?String?callbackUrl?=?"http://88.88.88.88:8888";String?formatDate?=?new?SimpleDateFormat("yyyy-MM-dd").format(new?Date());String?dir?=?formatDate?+?"/";?//?用戶上傳文件時指定的前綴。Map<String,?String>?respMap?=?new?LinkedHashMap<String,?String>();try?{long?expireTime?=?30;long?expireEndTime?=?System.currentTimeMillis()?+?expireTime?*?1000;Date?expiration?=?new?Date(expireEndTime);PolicyConditions?policyConds?=?new?PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE,?0,?1048576000);policyConds.addConditionItem(MatchMode.StartWith,?PolicyConditions.COND_KEY,?dir);String?postPolicy?=?ossClient.generatePostPolicy(expiration,?policyConds);byte[]?binaryData?=?postPolicy.getBytes("utf-8");String?encodedPolicy?=?BinaryUtil.toBase64String(binaryData);String?postSignature?=?ossClient.calculatePostSignature(postPolicy);respMap.put("accessid",?accessId);respMap.put("policy",?encodedPolicy);respMap.put("signature",?postSignature);respMap.put("dir",?dir);respMap.put("host",?host);respMap.put("expire",?String.valueOf(expireEndTime?/?1000));}?catch?(Exception?e)?{//?Assert.fail(e.getMessage());System.out.println(e.getMessage());}?finally?{ossClient.shutdown();}return?respMap;} }測試接口
http://localhost:14000/api/thirdparty/v1/admin/oss/getPolicy? {"accessid":?"LTAI4G3KxBJ26EUbWsenmqhP","policy":?"eyJleHBpcmF0aW9uIjoiMjAyMC0wNC0yOFQwMjozMzowNy42NzNaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDIwLTA0LTI4LyJdXX0=","signature":?"pfn4cggFTMMNqTs+qUnDN5c+k5M=","dir":?"2020-04-28/","host":?"https://passjava.oss-cn-beijing.aliyuncs.com","expire":?"1588041187" }3.4.3 配置網關路由
因為前端頁面配置的統一訪問路徑是http://localhost:8060/api/,所以需要將訪問thirdparty的服務通過網關路由到thirdparty服務
將請求 http://localhost:8060/api/thirdparty/v1/admin/oss/getPolicy 轉發到 http://localhost:14000/api/thirdparty/v1/admin/oss/getPolicy?配置網關:
spring:cloud:gateway:routes:-?id:?route_thirdparty?#?題目微服務路由規則uri:?lb://passjava-thirdparty?#?負載均衡,將請求轉發到注冊中心注冊的assjava-thirdparty服務predicates:?#?斷言-?Path=/api/thirdparty/**?#?如果前端請求路徑包含?api/thirdparty,則應用這條路由規則filters:?#過濾器-?RewritePath=/api/(?<segment>.*),/$\{segment}?#?將跳轉路徑中包含的api替換成空測試可以上傳成功
3.4.4 配置跨域訪問
配置跨域訪問,所有post請求都可以跨域訪問
配置跨域訪問3.4.5 Web端上傳組件
-
單文件上傳組件
-
獲取簽名的JS文件
-
使用單文件上傳組件
上傳文件成功
6.7 整合統一異常處理
1.緣起
“我們在寫代碼的時候,通常會在方法里面添加各種try catch來捕獲異常,會發現有很多重復的代碼,所以我們可以整合統一異常處理來優化代碼結構。
”攔截異常并統一處理我們可以用到@RestControllerAdvice注解
2.自定義異常處理類
-
添加統一異常處理類注解@RestControllerAdvice
-
添加日志注解@Slf4j
-
添加異常處理方法注解@ExceptionHandler
3.推薦的系統錯誤碼
3.1 錯誤碼和錯誤信息定義類
-
1.錯誤碼長度:5個數字
-
2.前兩位:業務場景
-
3.后三位:錯誤碼
3.2 錯誤碼枚舉類
com.jackson0714.common.exception.BizCodeEnum
定義了兩種異常枚舉:系統未知異常、參數格式校驗失敗
package?com.jackson0714.common.exception;public?enum?BizCodeEnum?{UNKNOWN_EXCEPTION(10000,?"系統未知異常"),VALID_EXCEPTION(10001,?"參數格式校驗失敗");private?int?code;private?String?msg;BizCodeEnum(int?code,?String?msg)?{this.code?=?code;this.msg?=?msg;}public?int?getCode()?{return?code;}public?String?getMsg()?{return?msg;} }4.測試代碼
“測試場景1:校驗參數displayOrder必須為正整數,如果displayOrder不為正整數,則會拋出異常
”-
1.實體類上添加校驗注解@Positive
-
2.controller類里面添加save方法,并添加校驗參數注解@Valid
測試:
用Postman工具調用save方法
請求地址:
http://192.168.10.160:8060/api/question/v1/admin/question/save請求參數:
{"displayOrder":?0.2 }返回結果:
{"msg":?"參數格式校驗失敗","code":?10001,"data":?{"displayOrder":?"必須是正數"} } “測試場景2:對于代碼里面直接拋出的異常,也可以handle
”1.controller類里面添加查詢題目的方法,并拋出Exception異常
/** *?信息 */ @RequestMapping("/info/{id}") //@RequiresPermissions("question:question:info") public?R?info(@PathVariable("id")?Long?id)?throws?Exception?{QuestionEntity?question?=?questionService.getById(id);throw?new?Exception("test");//return?R.ok().put("question",?question); }測試:
用Postman工具調用save方法
請求地址:
http://192.168.10.160:8060/api/question/v1/admin/question/save返回結果:
{"msg":?"系統未知異常","code":?10000 }證明統一處理方法被調用了:
@ExceptionHandler(value=Throwable.class) public?R?handleException(Throwable?throwable)?{return?R.error(BizCodeEnum.UNKNOWN_EXCEPTION.getCode(),?BizCodeEnum.UNKNOWN_EXCEPTION.getMsg()); } 推薦文章-
硬剛一周,3W字總結,一年的經驗告訴你如何準備校招!
-
今年的校招,Java 好拿 offer 嗎?
-
10月了,該聊聊今年秋招了!
-
聊聊在騰訊實習快一個月的感受
總結
以上是生活随笔為你收集整理的5w 字 | 172 图 | 超级赛亚级 Spring Cloud 实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Minimum Number of Re
- 下一篇: gradle idea java ssm