久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

Spring Boot + Vue 3全棧項(xiàng)目實(shí)戰(zhàn):前后端分離開發(fā)與部署指南

Spring Boot + Vue 3全棧項(xiàng)目實(shí)戰(zhàn):前后端分離開發(fā)與部署指南 1. 項(xiàng)目概述1.1 核心需求解析做全棧開發(fā)這幾年我見過(guò)太多半路出家的開發(fā)者在 Spring Boot 和 Vue 的邊界線上反復(fù)橫跳——后端能寫接口但前端拿著 JSON 不知道往哪兒塞前端能把頁(yè)面畫出來(lái)但遇到跨域、鑒權(quán)、打包部署就抓瞎。這個(gè)實(shí)戰(zhàn)指南解決的就是這個(gè)問(wèn)題把一條完整的前后端分離開發(fā)鏈路串起來(lái)從零開始搭建一個(gè)可直接運(yùn)行的全棧項(xiàng)目。注意這里的關(guān)鍵詞是“全?!辈皇恰扒昂蠖烁鲗懸话搿薄m?xiàng)目會(huì)包含一個(gè)完整的業(yè)務(wù)閉環(huán)前端 Vue 負(fù)責(zé)頁(yè)面交互和數(shù)據(jù)展示后端 Spring Boot 負(fù)責(zé)接口服務(wù)和數(shù)據(jù)持久化中間通過(guò) RESTful API 通信最終打包部署到同一臺(tái)服務(wù)器上跑通整個(gè)流程。這個(gè)過(guò)程中涉及的技術(shù)點(diǎn)非常密集——Vue 的生命周期、Axios 的請(qǐng)求攔截、Spring Boot 的分層架構(gòu)、MyBatis 的數(shù)據(jù)映射、JWT 的登錄態(tài)管理、Nginx 的反向代理——任何一個(gè)環(huán)節(jié)掉鏈子整個(gè)項(xiàng)目就跑不起來(lái)。這個(gè)項(xiàng)目的受眾其實(shí)很廣。剛?cè)胄械某跫?jí)開發(fā)者可以通過(guò)它建立全棧思維知道前端發(fā)起的請(qǐng)求在后端到底經(jīng)歷了什么寫了好幾年接口的后端開發(fā)可以補(bǔ)上前端技能獨(dú)立負(fù)責(zé)完整模塊做畢設(shè)或小團(tuán)隊(duì)項(xiàng)目的同學(xué)可以直接拿這套骨架改業(yè)務(wù)邏輯就能上線。我的建議是無(wú)論你偏向前端還是后端都完整地把項(xiàng)目過(guò)一遍收獲最大的恰恰是你知識(shí)短板那部分的內(nèi)容。1.2 技術(shù)棧全景與選型理由Spring Boot 3.x 搭配 Vue 3.x 是當(dāng)前主流選擇我用的版本組合是 Spring Boot 3.2.5 Vue 3.4.21 Vite 5.2.0。這套組合的好處是生態(tài)成熟遇到問(wèn)題搜一下基本都是現(xiàn)成的答案。Spring Boot 3.x 相比 2.x 最大的變化是底層基于 Spring Framework 6支持 Jakarta EE 規(guī)范默認(rèn)使用 Java 17 及以上版本開發(fā)體驗(yàn)和性能都有明顯提升。Vue 3 的組合式 API 寫起來(lái)比 Options API 更符合直覺配合 Vite 的開發(fā)服務(wù)器熱更新速度能縮短到一兩秒。數(shù)據(jù)庫(kù)我用 MySQL 8.0持久層框架選了 MyBatis Plus 而不是純 MyBatis原因很簡(jiǎn)單——單表操作完全不需要手寫 SQL自帶的方法夠用復(fù)雜查詢?cè)倏辞闆r寫 XML。鑒權(quán)方案采用 JWT Spring Security但做了簡(jiǎn)化處理只用了 Spring Security 的加密工具類沒有引入完整的安全過(guò)濾鏈。很多全棧項(xiàng)目的通病是過(guò)度設(shè)計(jì)明明是個(gè)小項(xiàng)目卻把微服務(wù)、分布式那套全上了結(jié)果光搭建環(huán)境就花了大半時(shí)間。這次的實(shí)戰(zhàn)特意保持克制讓你能專注于理解核心鏈路。提示如果你的環(huán)境是 JDK 8暫時(shí)不想升級(jí)建議使用 Spring Boot 2.7.x 配合 Vue 2但同樣建議盡早升級(jí)。JDK 17 的垃圾回收性能和容器支持都比 8 好很多IntelliJ IDEA 2023 版本對(duì) JDK 17 的支持也更順手。2. 整體設(shè)計(jì)與架構(gòu)拆解2.1 前后端分離架構(gòu)的邊界劃分全棧項(xiàng)目最容易犯的錯(cuò)誤是職責(zé)混亂。前端代碼里塞后端邏輯后端代碼里混頁(yè)面模板時(shí)間一長(zhǎng)代碼就成漿糊了。這次項(xiàng)目采用嚴(yán)格的前后端分離模式前端是純靜態(tài)資源通過(guò) Axios 異步調(diào)用后端接口后端只負(fù)責(zé)提供 JSON 數(shù)據(jù)不做頁(yè)面渲染。簡(jiǎn)單來(lái)說(shuō)你可以把整套系統(tǒng)想象成一家餐廳前端是服務(wù)員負(fù)責(zé)記錄顧客需求、展示菜品渲染數(shù)據(jù)后端是后廚負(fù)責(zé)準(zhǔn)備菜品處理業(yè)務(wù)數(shù)據(jù)庫(kù)就是儲(chǔ)藏室。服務(wù)員不需要知道菜怎么做后廚也不需要直接和顧客溝通兩者之間的點(diǎn)菜單就是 API 接口。拿一個(gè)具體的業(yè)務(wù)場(chǎng)景來(lái)說(shuō)用戶在前端頁(yè)面上登錄填完表單點(diǎn)擊提交按鈕Vue 組件把表單數(shù)據(jù)通過(guò) POST 請(qǐng)求發(fā)送到后端的/api/login接口后端 Controller 接收請(qǐng)求調(diào) Service 層校驗(yàn)用戶名密碼再調(diào) Mapper 層查數(shù)據(jù)庫(kù)校驗(yàn)通過(guò)后生成一個(gè) JWT token 返回給前端。前端收到 token 后存在 localStorage 里之后每次請(qǐng)求都在請(qǐng)求頭帶上這個(gè) token后端用攔截器驗(yàn)證 token 是否有效。整個(gè)鏈路中前端和后端各自獨(dú)立開發(fā)、獨(dú)立測(cè)試、獨(dú)立部署契約就是接口文檔。2.2 后端分層設(shè)計(jì)的職責(zé)劃分后端項(xiàng)目的包結(jié)構(gòu)按照經(jīng)典的三層架構(gòu)來(lái)組織Controller 層負(fù)責(zé)接收請(qǐng)求和參數(shù)校驗(yàn)Service 層負(fù)責(zé)業(yè)務(wù)邏輯Mapper 層負(fù)責(zé)數(shù)據(jù)庫(kù)操作。在這個(gè)之上再加一個(gè) Entity 包放實(shí)體類一個(gè) DTO 包放數(shù)據(jù)傳輸對(duì)象一個(gè) Config 包放配置類一個(gè) Common 包放統(tǒng)一返回結(jié)果和異常處理。每個(gè)層之間通過(guò)接口和類來(lái)協(xié)作。Controller 不直接操作數(shù)據(jù)庫(kù)Service 不寫 SQLMapper 只做數(shù)據(jù)映射。剛?cè)腴T的開發(fā)者容易把業(yè)務(wù)代碼全堆在 Controller 里一個(gè)方法寫上百行看起來(lái)很“高效”實(shí)際上后面需求一變更就得重寫。我曾經(jīng)接手過(guò)一個(gè)項(xiàng)目登錄接口里直接拼 SQL 查數(shù)據(jù)庫(kù)后來(lái)要加驗(yàn)證碼功能那叫一個(gè)費(fèi)勁。打個(gè)比方三層架構(gòu)就像公司的三級(jí)審批——Controller 是前臺(tái)接待負(fù)責(zé)接需求和判斷訴求是否合理Service 是部門主管負(fù)責(zé)制定處理方案并協(xié)調(diào)資源Mapper 是具體執(zhí)行人負(fù)責(zé)落實(shí)細(xì)節(jié)。每一層只做自己該做的事出問(wèn)題時(shí)能快速定位是哪個(gè)環(huán)節(jié)的鍋。2.3 前端組件化設(shè)計(jì)的模塊劃分前端項(xiàng)目按功能模塊劃分目錄結(jié)構(gòu)api目錄放接口請(qǐng)求封裝router目錄放路由配置stores目錄放 Pinia 狀態(tài)管理views目錄放頁(yè)面組件components目錄放公共組件。組件化設(shè)計(jì)的關(guān)鍵是找到合適的拆分粒度。舉個(gè)具體的例子后臺(tái)管理系統(tǒng)里常見的“用戶管理”頁(yè)面可以拆成搜索欄、表格、彈窗表單三個(gè)部分。搜索欄接收用戶輸入的查詢條件通過(guò)事件把條件拋給父組件父組件拿到條件后更新列表數(shù)據(jù)表格展示數(shù)據(jù)并監(jiān)聽行點(diǎn)擊彈窗表單負(fù)責(zé)新增和編輯。組件拆分有個(gè)度阿里推出的前端規(guī)范里提到一個(gè)原則如果一個(gè)組件太長(zhǎng)超過(guò)合理范圍還沒法拆分出可復(fù)用的子組件可能就是職能不單一。反過(guò)來(lái)把組件拆得太碎也有問(wèn)題——有一次我把一個(gè)簡(jiǎn)單的列表頁(yè)拆成了十多個(gè)組件每個(gè)組件只有幾十行代碼結(jié)果傳參傳得頭暈調(diào)試一個(gè) bug 得在文件間跳來(lái)跳去。一般的原則是只在組件被兩個(gè)以上地方復(fù)用或者單個(gè)組件的復(fù)雜度已經(jīng)明顯影響可讀性時(shí)才需要拆分。3. 環(huán)境準(zhǔn)備與項(xiàng)目初始化3.1 開發(fā)環(huán)境的版本選型與安裝清單先過(guò)一遍環(huán)境清單。后端需要 JDK 17、Maven 3.9、MySQL 8.0前端需要 Node.js 18我用的 20.12.0、npm或 pnpm/yarn這里用 npm、Vite 作為構(gòu)建工具。IDE 方面我推薦后端用 IntelliJ IDEA前端用 VS Code兩個(gè)都裝也沒問(wèn)題。幾個(gè)需要注意的坑先提前說(shuō)JDK 版本必須和環(huán)境變量匹配。裝了多個(gè) JDK 的機(jī)器上IDEA 里配置的 Project SDK 和系統(tǒng)環(huán)境變量最好統(tǒng)一否則 Maven 編譯時(shí)可能用錯(cuò)版本。Node.js 盡量用偶數(shù)版本。Node 官方對(duì)奇數(shù)次版本的支持時(shí)間較短有些依賴可能不兼容。當(dāng)年 Node 15 時(shí)代裝 Vite 就是各種問(wèn)題后來(lái)學(xué)聰明了直接固定用最新 LTS 版本。MySQL 8.0 的認(rèn)證插件。默認(rèn)的caching_sha2_password在舊版連接驅(qū)動(dòng)下會(huì)報(bào)錯(cuò)Spring Boot 3.x 自帶的 MySQL Connector/J 8.x 沒問(wèn)題但如果你的其他老項(xiàng)目還在用 5.x 驅(qū)動(dòng)連接 MySQL 8 會(huì)失敗。安裝順序沒有硬性要求但建議先裝后端環(huán)境再裝前端環(huán)境。因?yàn)楹蠖伺芷饋?lái)之后你可以先用 Postman 測(cè)試接口確認(rèn)沒問(wèn)題再寫前端頁(yè)面這樣排查問(wèn)題時(shí)范圍更清晰。3.2 后端項(xiàng)目初始化三步走先用 IntelliJ IDEA 創(chuàng)建 Spring Boot 項(xiàng)目。如果你用的是 IDEA 2023 版本可以直接在 New Project 里選 Spring InitializrGroup 填com.exampleArtifact 填fullstackJava 版本選 17依賴勾選 Spring Web、Spring Security可選也可以后面手動(dòng)加、MySQL Driver、Lombok、Validation。需要補(bǔ)充說(shuō)明的是Spring Initializr 生成的項(xiàng)目默認(rèn)帶一個(gè)mvnwMaven Wrapper它允許你在沒有全局安裝 Maven 的機(jī)器上直接執(zhí)行./mvnw命令來(lái)構(gòu)建項(xiàng)目這對(duì)保證構(gòu)建環(huán)境一致性很有幫助。如果你的機(jī)器沒有 Maven可以用它來(lái)代替mvn命令。項(xiàng)目生成后先別急著寫代碼把目錄補(bǔ)齊。基礎(chǔ)結(jié)構(gòu)大概是src/main/java/com/example/fullstack ├── controller ├── service │ ├── impl ├── mapper ├── entity ├── dto ├── config └── common然后在pom.xml里加入 MyBatis Plus 的依賴。有個(gè)地方容易踩坑MyBatis Plus 在 Spring Boot 3.x 下需要引入mybatis-plus-spring-boot3-starter而不是mybatis-plus-boot-starter那是給 Spring Boot 2.x 用的。如果你用錯(cuò)版本啟動(dòng)時(shí)大概率會(huì)報(bào)Invalid value type for attribute factoryBeanObjectType之類的錯(cuò)誤。配置文件application.yml按以下內(nèi)容配置server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/fullstack_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: your_password jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto這里有個(gè)細(xì)節(jié)Jackson 的日期格式設(shè)置很重要。如果前端傳來(lái)的日期字符串是2024-05-20 10:30:00格式后端 LocalDateTime 字段不加JsonFormat注解或全局配置默認(rèn)是 ISO 格式反序列化時(shí)就會(huì)報(bào)錯(cuò)。全局配好省得每個(gè)字段都寫注解。3.3 前端項(xiàng)目初始化與依賴配置前端我用 Vite 創(chuàng)建項(xiàng)目命令如下npm create vitelatest frontend -- --template vue cd frontend npm install然后安裝項(xiàng)目需要的依賴npm install vue-router4 pinia axios element-plus選 Element Plus 做 UI 組件庫(kù)是國(guó)內(nèi)全棧項(xiàng)目的常見選擇它對(duì)中文場(chǎng)景支持好表格、表單、分頁(yè)這些后臺(tái)管理常用的組件都有現(xiàn)成的。同時(shí)安裝它的圖標(biāo)庫(kù)element-plus/icons-vue可以在全局注冊(cè)方便在菜單和按鈕里直接用圖標(biāo)。依賴裝完之后先配置 Vite 的代理和構(gòu)建選項(xiàng)。開發(fā)階段前端和后端分離運(yùn)行需要把請(qǐng)求代理到后端服務(wù)生產(chǎn)階段前端構(gòu)建后的靜態(tài)文件由 Nginx 托管也需要配置轉(zhuǎn)發(fā)規(guī)則。在開發(fā)環(huán)境vite.config.js里加代理import { defineConfig } from vite import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], server: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })這樣前端代碼里請(qǐng)求/api/login時(shí)Vite 會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到http://localhost:8080/api/login繞過(guò)了開發(fā)環(huán)境下的跨域限制。生產(chǎn)環(huán)境則交給 Nginx 配置 location 塊做反向代理。提示配置代理解決的是開發(fā)階段的跨域問(wèn)題。如果你的前后端部署在同一臺(tái)服務(wù)器、同一個(gè)域名下生產(chǎn)環(huán)境一般不需要跨域處理但如果部署在不同域名或端口下則要在后端加 CORS 配置。這個(gè)細(xì)節(jié)等到部署章節(jié)詳細(xì)講。4. 核心功能開發(fā)實(shí)操4.1 用戶認(rèn)證模塊的完整實(shí)現(xiàn)方案用戶認(rèn)證是幾乎所有全棧系統(tǒng)的剛性需求。我用 JWT 實(shí)現(xiàn)了這套認(rèn)證流程核心思路是用戶登錄成功后后端簽發(fā)一個(gè)有效期為一定時(shí)間的 token前端存儲(chǔ)這個(gè) token在每次請(qǐng)求的 Authorization 請(qǐng)求頭里帶上來(lái)后端通過(guò)攔截器統(tǒng)一校驗(yàn)。先說(shuō)數(shù)據(jù)表結(jié)構(gòu)用戶表設(shè)計(jì)為CREATE TABLE sys_user ( id bigint(20) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用戶名, password varchar(100) NOT NULL COMMENT 加密后的密碼, nickname varchar(50) DEFAULT NULL COMMENT 昵稱, email varchar(100) DEFAULT NULL COMMENT 郵箱, status tinyint(4) DEFAULT 1 COMMENT 狀態(tài)1啟用 0禁用, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4;密碼存儲(chǔ)用的是 BCrypt 加密算法這是 Spring Security 里自帶的工具類不需要額外引依賴// 加密 String encodedPassword BCryptPasswordEncoder().encode(rawPassword); // 校驗(yàn) boolean matches encoder.matches(rawPassword, encodedPassword);這里有一個(gè)很容易被忽略的安全細(xì)節(jié)matches方法第一個(gè)參數(shù)是明文密碼第二個(gè)是數(shù)據(jù)庫(kù)里取出來(lái)的密文。我第一次寫的時(shí)候參數(shù)順序搞反了調(diào)試了半小時(shí)才發(fā)現(xiàn)是參數(shù)順序問(wèn)題。另外注意 BCrypt 的加密結(jié)果是隨機(jī)的同一個(gè)明文每次加密出來(lái)的密文都不一樣所以不能用常規(guī)字符串比較必須用matches方法校驗(yàn)。登錄接口的邏輯不復(fù)雜偽代碼是這樣的Controller 接收LoginRequest用戶名密碼Service 層根據(jù)用戶名查用戶如果用戶不存在直接拋異常提示“用戶名或密碼錯(cuò)誤”注意這里的提示不能太具體否則會(huì)暴露用戶是否存在存在則用 BCrypt 校驗(yàn)密碼失敗同樣提示“用戶名或密碼錯(cuò)誤”成功后用用戶 ID、用戶名和當(dāng)前時(shí)間戳生成 JWT返回 token 用戶信息。4.2 JWT 攔截器的實(shí)現(xiàn)與請(qǐng)求鏈路JWT 攔截器是一個(gè)關(guān)鍵的“橫切關(guān)注點(diǎn)”。我用 Spring 的HandlerInterceptor實(shí)現(xiàn)配合 WebMvcConfigurer 注冊(cè)讓所有/api/**下的接口都經(jīng)過(guò)校驗(yàn)登錄接口本身要放行。核心邏輯如下Component public class JwtInterceptor implements HandlerInterceptor { Autowired private JwtUtils jwtUtils; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行預(yù)檢請(qǐng)求 if (request.getMethod().equals(OPTIONS)) { return true; } // 前端約定 token 放在請(qǐng)求頭的 Authorization 字段中 String token request.getHeader(Authorization); if (token null || token.isEmpty()) { return this.unauthorized(response, 未登錄或登錄已過(guò)期); } // 校驗(yàn) token 合法性 try { String userId jwtUtils.getUserIdFromToken(token); request.setAttribute(userId, userId); return true; } catch (Exception e) { return this.unauthorized(response, token 無(wú)效或已過(guò)期); } } private boolean unauthorized(HttpServletResponse response, String msg) throws IOException { response.setStatus(401); response.setContentType(application/json;charsetutf-8); response.getWriter().write(JSON.toJSONString(Result.error(401, msg))); return false; } }注意一個(gè)細(xì)節(jié)預(yù)檢請(qǐng)求OPTIONS一定要放行。瀏覽器在跨域 POST 請(qǐng)求前會(huì)自動(dòng)發(fā)送一個(gè) OPTIONS 預(yù)檢請(qǐng)求如果你的攔截器把它攔下來(lái)了前端會(huì)報(bào) CORS 錯(cuò)誤而且這個(gè)錯(cuò)誤在瀏覽器控制臺(tái)看起來(lái)像是后端 CORS 配置有問(wèn)題實(shí)際上卻是攔截器沒放行 OPTIONS。攔截器只是一個(gè)粗粒度的路由守衛(wèi)對(duì)于不同接口的細(xì)粒度權(quán)限比如只有管理員能調(diào)用的接口可以在 Controller 方法上加自定義注解再在攔截器里讀取注解做二次判斷這個(gè)屬于權(quán)限系統(tǒng)的進(jìn)階內(nèi)容本次項(xiàng)目不做展開。4.3 用戶管理模塊的 CRUD 與分頁(yè)查詢用戶管理模塊雖然簡(jiǎn)單但把前后端交互的典型模式都覆蓋了查詢列表、新增、編輯、刪除。我用 MyBatis Plus 的IService和BaseMapper框架代碼量比傳統(tǒng) MyBatis 少很多。Controller 層代碼示例RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; GetMapping(/list) public ResultIPageUserVO list(RequestParam(defaultValue 1) Integer pageNum, RequestParam(defaultValue 10) Integer pageSize, String keyword) { PageUser page new Page(pageNum, pageSize); LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(keyword)) { wrapper.like(User::getUsername, keyword).or().like(User::getNickname, keyword); } wrapper.orderByDesc(User::getCreateTime); IPageUser userPage userService.page(page, wrapper); // 轉(zhuǎn) VO 返回不直接暴露實(shí)體 return Result.success(PageUtil.convert(userPage, UserVO.class)); } // 新增、編輯、刪除邏輯省略遵循同樣的模式 }細(xì)節(jié)問(wèn)題來(lái)了新增用戶密碼需要加密存儲(chǔ)編輯用戶如果密碼為空說(shuō)明不修改密碼。這些分情況討論的業(yè)務(wù)邏輯都放在 Service 層。Controller 里寫太多 if-else后面維護(hù)起來(lái)就想罵人。前端對(duì)應(yīng)這個(gè)接口的調(diào)用也是固定套路封裝在api/user.js模塊里import request from ../utils/request export function getUserList(data) { return request({ url: /user/list, method: get, params: data }) } export function addUser(data) { return request({ url: /user/add, method: post, data }) } // ...4.4 Axios 請(qǐng)求封裝的幾個(gè)關(guān)鍵決策點(diǎn)Axios 封裝的好壞直接決定整個(gè)前端項(xiàng)目請(qǐng)求代碼的整潔程度。我的做法是單獨(dú)建一個(gè)utils/request.js文件生成一個(gè)配置了基礎(chǔ) URL、超時(shí)時(shí)間和攔截器的 Axios 實(shí)例。核心代碼import axios from axios import { ElMessage } from element-plus import router from ../router const request axios.create({ baseURL: /api, timeout: 10000 }) // 請(qǐng)求攔截器自動(dòng)附加 token request.interceptors.request.use( config { const token localStorage.getItem(token) if (token) { config.headers.Authorization token } return config }, error Promise.reject(error) ) // 響應(yīng)攔截器統(tǒng)一處理錯(cuò)誤碼 request.interceptors.response.use( response { const res response.data // 如果后端返回了業(yè)務(wù)錯(cuò)誤碼 if (res.code ! 200) { ElMessage.error(res.message || 請(qǐng)求失敗) if (res.code 401) { // token 過(guò)期跳轉(zhuǎn)登錄頁(yè) localStorage.removeItem(token) router.push(/login) } return Promise.reject(new Error(res.message)) } return res.data }, error { ElMessage.error(error.message || 網(wǎng)絡(luò)錯(cuò)誤) return Promise.reject(error) } ) export default request幾個(gè)決策點(diǎn)說(shuō)一下。baseURL 設(shè)為/api配合 Vite 代理或 Nginx 反向代理前端代碼里就不用寫死后端地址環(huán)境切換時(shí)只需要改代理配置就行。響應(yīng)攔截器里把后端的code/message/data統(tǒng)一解開前端調(diào)用接口時(shí)直接拿到業(yè)務(wù)數(shù)據(jù)不需要每個(gè)調(diào)用處都寫.then(res res.data)。還有一個(gè)細(xì)節(jié)上的選擇token 存 localStorage 還是 sessionStorage。有人建議存 sessionStorage因?yàn)殛P(guān)閉瀏覽器就自動(dòng)清掉安全一些但用戶希望刷新頁(yè)面后保持登錄狀態(tài)所以我用 localStorage。另外邏輯上要區(qū)分業(yè)務(wù)錯(cuò)誤碼比如 500和 HTTP 狀態(tài)碼比如 404上述封裝里對(duì)這兩類錯(cuò)誤都做了處理。5. 前端關(guān)鍵頁(yè)面與交互實(shí)現(xiàn)5.1 登錄頁(yè)的實(shí)現(xiàn)與表單校驗(yàn)登錄頁(yè)是系統(tǒng)的“門面”雖然邏輯簡(jiǎn)單但涉及的交互細(xì)節(jié)并不少。我用 Element Plus 的el-form組件實(shí)現(xiàn)配合它的表單校驗(yàn)規(guī)則用戶名必填格式校驗(yàn)長(zhǎng)度 3-20 個(gè)字符。密碼必填長(zhǎng)度 6-32 個(gè)字符。點(diǎn)擊登錄時(shí)先校驗(yàn)表單通過(guò)后才發(fā)請(qǐng)求。登錄成功后跳轉(zhuǎn)到首頁(yè)并提示“歡迎回來(lái)xxx”。登錄頁(yè)有一個(gè)容易被忽視的用戶體驗(yàn)問(wèn)題請(qǐng)求失敗時(shí)表單要保留用戶輸入不能整個(gè)頁(yè)面刷新重置。Vue 的單頁(yè)應(yīng)用優(yōu)勢(shì)在這里體現(xiàn)得比較明顯。另外登錄按鈕在請(qǐng)求期間要處于 loading 狀態(tài)防止用戶重復(fù)提交。這些都是小細(xì)節(jié)但拿捏好才是專業(yè)的表現(xiàn)。關(guān)于“記住密碼”功能嚴(yán)謹(jǐn)?shù)拈_發(fā)不會(huì)把密碼存在前端通常只記住用戶名。這個(gè)項(xiàng)目我沒有做這個(gè)功能因?yàn)樯婕懊舾行畔⒉蛔霰茸龈踩?.2 布局與路由守衛(wèi)后臺(tái)管理系統(tǒng)的典型布局是左側(cè)菜單欄 右側(cè)內(nèi)容區(qū)。我用 Element Plus 的el-container組件實(shí)現(xiàn)菜單數(shù)據(jù)直接寫死在路由配置里通過(guò)v-for循環(huán)渲染。路由配置的要點(diǎn)是嵌套路由const routes [ { path: /login, component: Login }, { path: /, component: Layout, redirect: /dashboard, children: [ { path: dashboard, name: Dashboard, component: Dashboard, meta: { title: 首頁(yè), icon: HomeFilled } }, { path: user, name: User, component: UserManagement, meta: { title: 用戶管理, icon: User } } ] } ]路由守衛(wèi)是前端鑒權(quán)的另一道防線。在router.beforeEach里檢查是否登錄未登錄則重定向到登錄頁(yè)router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.path /login) { next() } else { if (!token) { next({ path: /login }) } else { next() } } })提醒一句前端路由守衛(wèi)只是提升用戶體驗(yàn)的手段不是安全措施。真正校驗(yàn) token 的有效性還得靠后端的攔截器因?yàn)橛脩艨梢灾苯痈那岸舜a繞過(guò)路由守衛(wèi)。一切前端校驗(yàn)都是“防君子不防小人”。5.3 表格、分頁(yè)與表單的聯(lián)動(dòng)模式用戶管理頁(yè)面的核心交互是搜索欄輸入條件 → 點(diǎn)擊查詢 → 表格展示數(shù)據(jù) → 點(diǎn)擊編輯彈出表單 → 保存后刷新列表。這是后臺(tái)管理系統(tǒng)最高頻的交互模式。頁(yè)面數(shù)據(jù)結(jié)構(gòu)大概是searchForm搜索條件的響應(yīng)式數(shù)據(jù)tableData當(dāng)前頁(yè)的數(shù)據(jù)列表pageInfo頁(yè)碼、每頁(yè)條數(shù)、總條數(shù)dialogVisible彈窗顯隱formModel表單數(shù)據(jù)formRules表單校驗(yàn)規(guī)則交互邏輯是點(diǎn)擊搜索時(shí)把頁(yè)碼重置為 1然后調(diào)用列表接口把返回的數(shù)據(jù)和總條數(shù)賦值給響應(yīng)式變量。前端代碼里分頁(yè)組件和表格的狀態(tài)同步是需要注意的地方el-pagination v-model:current-pagepageInfo.pageNum v-model:page-sizepageInfo.pageSize :totalpageInfo.total layouttotal, prev, pager, next, sizes changeloadData /需要注意el-pagination在 Element Plus 3.x 里事件名已經(jīng)改成了change舊版是current-change和size-change兩個(gè)事件分別處理。如果團(tuán)隊(duì)里有老手用新版時(shí)還寫舊事件表格點(diǎn)擊分頁(yè)沒反應(yīng)排查老半天最后發(fā)現(xiàn)是事件名不對(duì)。彈出表單的編輯功能有一個(gè)常見坑編輯用戶時(shí)打開彈窗要把當(dāng)前行的數(shù)據(jù)深拷貝到表單模型里避免直接修改表格數(shù)據(jù)源。如果不做深拷貝彈窗里改字段時(shí)表格數(shù)據(jù)也會(huì)跟著變因?yàn)橐玫氖峭粋€(gè)對(duì)象。用JSON.parse(JSON.stringify(...))做深拷貝最簡(jiǎn)單或者用展開運(yùn)算符新建對(duì)象。5.4 狀態(tài)管理與跨組件通信的方案選擇Vue 3 中狀態(tài)管理的選擇比 Vue 2 時(shí)代豐富多了。Pinia 是官方推薦方案用它替代 Vuex 寫起來(lái)舒服得多沒有 mutations、actions 那套冗余的流程store 里定義的 state 直接用actions 就是一個(gè)普通函數(shù)。這個(gè)項(xiàng)目用到 Pinia 的場(chǎng)景用戶登錄后存基本信息和 token。在登錄成功時(shí)調(diào)用userStore.setLoginInfo(...)然后在多個(gè)組件里通過(guò)userStore.username展示當(dāng)前登錄用戶。示例代碼import { defineStore } from pinia export const useUserStore defineStore(user, { state: () ({ token: localStorage.getItem(token) || , userId: null, username: , nickname: }), actions: { setLoginInfo(data) { this.token data.token this.userId data.userId this.username data.username this.nickname data.nickname localStorage.setItem(token, data.token) }, logout() { this.token this.userId null this.username this.nickname localStorage.removeItem(token) } } })在這個(gè)系統(tǒng)里用戶信息需要全局共享但很多業(yè)務(wù)組件之間的通信其實(shí)用 props 和 emit 就夠。過(guò)度引入全局狀態(tài)管理會(huì)讓代碼難追蹤——某個(gè)字段不知道被誰(shuí)修改了找起來(lái)很費(fèi)勁。我的原則是跨頁(yè)面、跨層級(jí)深組件才考慮 Pinia父子組件之間能用 props/emit 就用 props/emit。6. 前后端聯(lián)調(diào)與常見問(wèn)題排查6.1 聯(lián)調(diào)前的接口約定與準(zhǔn)備前后端分離開發(fā)模式下聯(lián)調(diào)階段往往是問(wèn)題集中爆發(fā)的時(shí)期。前端認(rèn)為接口該這么返回后端認(rèn)為前端該那么傳參經(jīng)常對(duì)不上。經(jīng)驗(yàn)是先定接口文檔再動(dòng)代碼哪怕是簡(jiǎn)單的表格約定、字段類型、命名風(fēng)格、錯(cuò)誤碼都提前對(duì)齊。接口文檔我用 YApi 或者 Apifox 維護(hù)簡(jiǎn)單項(xiàng)目也可以在項(xiàng)目根目錄放一個(gè) Markdown 格式的接口說(shuō)明文檔。文檔要約定如下內(nèi)容請(qǐng)求方式GET/POST/PUT/DELETE請(qǐng)求路徑和參數(shù)路徑參數(shù)、查詢參數(shù)、請(qǐng)求體參數(shù)參數(shù)類型string/number/boolean/object/array返回格式code/message/data 的結(jié)構(gòu)鑒權(quán)方式token 放在哪里怎么傳錯(cuò)誤碼語(yǔ)義200 成功、401 未授權(quán)、500 服務(wù)器錯(cuò)誤、業(yè)務(wù)錯(cuò)誤從 400 開始聯(lián)調(diào)前先用 Postman 把后端接口全部測(cè)一遍。實(shí)測(cè)下來(lái)后端寫接口時(shí)引入一個(gè)全局性的統(tǒng)一返回結(jié)構(gòu)ResultT聯(lián)調(diào)效率能提升不少。前端看到code/message/data就知道怎么處理省去了解析各種怪異結(jié)構(gòu)的時(shí)間。我在項(xiàng)目里定義了一個(gè)通用返回體Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(Integer code, String message) { ResultT result new Result(); result.setCode(code); result.setMessage(message); return result; } }任何接口都返回Result包裝后的對(duì)象異常處理用全局RestControllerAdvice捕獲并統(tǒng)一轉(zhuǎn)成這個(gè)格式前端就永遠(yuǎn)只需要處理一種結(jié)構(gòu)代碼邏輯非常簡(jiǎn)單。6.2 跨域問(wèn)題的三種表現(xiàn)與對(duì)應(yīng)解法跨域是全棧聯(lián)調(diào)最常遇到的問(wèn)題但它有不同層次的原因癥狀相同解法不同。第一種開發(fā)環(huán)境跨域。前端在http://localhost:3000后端在http://localhost:8080。瀏覽器攔截了跨域請(qǐng)求。通用的解法是后端加 CORS 配置讓后端允許前端來(lái)源訪問(wèn)。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(http://localhost:3000) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }但更推薦用 Vite 代理解決前端配置代理后前端請(qǐng)求的地址看起來(lái)是同源的。代理方式更好是因?yàn)樗芽缬騿?wèn)題的處理留在了構(gòu)建層后端不需要關(guān)心前端運(yùn)行在哪個(gè)端口而且開發(fā)環(huán)境和生產(chǎn)環(huán)境的代理配置方式保持一致生產(chǎn)環(huán)境用 Nginx。第二種后端接口報(bào) CORS 錯(cuò)誤但后端沒有 CORS 配置。這種情況多半是瀏覽器請(qǐng)求直接打到了后端地址而請(qǐng)求方式是非簡(jiǎn)單請(qǐng)求比如 PUT/DELETE或者帶了自定義請(qǐng)求頭比如 Authorization。這時(shí)候?yàn)g覽器會(huì)先發(fā) OPTIONS 預(yù)檢請(qǐng)求如果后端攔截器沒放行 OPTIONS就會(huì)報(bào) CORS 錯(cuò)。解決辦法是攔截器放行 OPTIONS。第三種生產(chǎn)環(huán)境跨域。前端和后端部署在不同域名。這種情況下最穩(wěn)妥的做法是用 Nginx 做反向代理讓前后端在同一個(gè)域名下前端請(qǐng)求/api路徑時(shí) Nginx 轉(zhuǎn)發(fā)給后端服務(wù)。6.3 開發(fā)過(guò)程中遇到的高頻報(bào)錯(cuò)速查表下面整理一份聯(lián)調(diào)階段的常見報(bào)錯(cuò)和解決建議都是實(shí)操中反復(fù)出現(xiàn)的問(wèn)題報(bào)錯(cuò)現(xiàn)象可能原因解決方法前端請(qǐng)求掛起很久后報(bào) timeout后端服務(wù)未啟動(dòng)或接口路徑不對(duì)檢查后端日志確認(rèn)服務(wù)啟動(dòng)檢查請(qǐng)求的路徑和 Controller 映射是否一致404 Not FoundURL 路徑寫錯(cuò)或 Controller 方法沒有映射核對(duì)前端 api 模塊中的 URL 和后端RequestMapping是否有出入401 Unauthorizedtoken 缺失或無(wú)效確認(rèn)登錄是否成功、token 是否在請(qǐng)求頭中被正確攜帶500 后端報(bào) NullPointerException后端代碼對(duì) null 值沒有處理看異常堆棧定位到具體行號(hào)檢查參數(shù)是否為空數(shù)據(jù)庫(kù)中文亂碼數(shù)據(jù)庫(kù)連接串沒有指定字符集或者表默認(rèn)字符集錯(cuò)誤在 JDBC URL 后加characterEncodingutf8建表時(shí)指定DEFAULT CHARSETutf8mb4MySQL 連接失敗 Public Key Retrieval is not allowed連接串缺少 allowPublicKeyRetrieval 參數(shù)JDBC URL 中加入allowPublicKeyRetrievaltrue打包前端后訪問(wèn)頁(yè)面空白路由模式或靜態(tài)資源路徑配置問(wèn)題如果使用 history 模式Nginx 要配置 try_files 重寫規(guī)則跨域報(bào) Access-Control-Allow-OriginCORS 配置不當(dāng)按照上文跨域問(wèn)題的三種表現(xiàn)依次排查6.4 前后端聯(lián)調(diào)中的時(shí)間同步與數(shù)據(jù)格式問(wèn)題還有一種不報(bào)錯(cuò)但結(jié)果不對(duì)的坑最典型的是時(shí)間字段。后端 LocalDateTime 序列化后得到的是2024-05-20T10:30:00而前端希望顯示的是2024-05-20 10:30:00。我見過(guò)不少項(xiàng)目因?yàn)闀r(shí)間格式對(duì)不上前端硬生生寫了個(gè)字符串替換函數(shù)來(lái)轉(zhuǎn)格式相當(dāng)丑陋。正確做法是在后端做好全局配置讓所有時(shí)間字段統(tǒng)一輸出為固定格式前端直接拿到標(biāo)準(zhǔn)字符串后展示或傳給后端。JSON 序列化這里再提一次在application.yml里加 Jackson 的時(shí)間格式配置代碼里不需要再給每個(gè)LocalDateTime字段加JsonFormat注解。不過(guò)要注意的是如果分頁(yè)返回的數(shù)據(jù)里包含時(shí)間排序序列化后的字符串格式影響不大只要保證比較的邏輯放在數(shù)據(jù)庫(kù)層面做就行。另一個(gè)常見問(wèn)題是前端傳日期字符串給后端時(shí)后端用DateTimeFormat注解或全局配置 Jackson 的LocalDateTime反序列化格式來(lái)接收。我遇到過(guò)前端傳2024-05-20 10:30:00后端接收后解析失敗報(bào) 400 錯(cuò)誤。這是因?yàn)?Fastjson 和 Jackson 對(duì) LocalDateTime 支持有差異解決方式是統(tǒng)一用 Jackson并在全局配置里聲明日期格式。7. 項(xiàng)目打包與生產(chǎn)環(huán)境部署7.1 前端構(gòu)建與單頁(yè)應(yīng)用路由配置生產(chǎn)部署的第一步是前端構(gòu)建。執(zhí)行npm run buildVite 會(huì)生成dist目錄里面是壓縮后的靜態(tài)資源文件。這里要特別關(guān)注兩個(gè)點(diǎn)。第一構(gòu)建產(chǎn)物的路徑問(wèn)題。如果你把前端部署在域名根路徑/下那baseURL保持/api沒問(wèn)題但如果部署在子路徑比如https://example.com/admin下Vite 構(gòu)建時(shí)要在vite.config.js里配置base: /admin/否則靜態(tài)資源的引用路徑全部 404。第二前端路由的 history 模式需要服務(wù)端配合。Vue Router 的 history 模式URL 中不帶#刷新在子路由頁(yè)面比如/user時(shí)如果不配置服務(wù)端重寫規(guī)則Nginx 只會(huì)看文件系統(tǒng)里有沒有對(duì)應(yīng)的user目錄結(jié)果就是 404。Nginx 配置如下location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; }try_files的$uri先看請(qǐng)求路徑對(duì)應(yīng)的文件是否存在如果不存在就回退到/index.html由前端路由接管。7.2 后端打包與啟動(dòng)腳本后端用 Maven 打包mvn clean package -DskipTests命令執(zhí)行完會(huì)在target目錄下生成fullstack-0.0.1-SNAPSHOT.jar。如果你用的是 Java 17 和 Spring Boot 3.x還有一個(gè)可執(zhí)行 jar 的特性Spring Boot 的 Maven 插件會(huì)自動(dòng)配置 Main-Class你不需要額外配置直接java -jar就能運(yùn)行。啟動(dòng)命令java -jar fullstack-0.0.1-SNAPSHOT.jar --spring.profiles.activeprod生產(chǎn)環(huán)境的配置建議單獨(dú)建一個(gè)application-prod.yml里面配置生產(chǎn)環(huán)境用的數(shù)據(jù)庫(kù)地址、端口、日志級(jí)別等和開發(fā)環(huán)境區(qū)分開。日志輸出也建議配置到文件中不要只輸出到控制臺(tái)服務(wù)重啟后日志就丟了。一個(gè)典型的日志配置logging: level: com.example.fullstack: info file: name: logs/fullstack.log線上環(huán)境有個(gè)小建議用nohup啟動(dòng)服務(wù)避免終端斷開時(shí)進(jìn)程被殺掉?;蛘吒?guī)范的寫法是注冊(cè)為 systemd 服務(wù)讓操作系統(tǒng)管理進(jìn)程生命周期開機(jī)自啟、崩潰重啟都能自動(dòng)處理。7.3 Nginx 反向代理與服務(wù)部署細(xì)節(jié)Nginx 在這套系統(tǒng)中的角色是托管前端靜態(tài)文件 反向代理后端 API。完整配置參考如下server { listen 80; server_name your-domain.com; # 前端靜態(tài)資源 location / { root /var/www/frontend/dist; index index.html; try_files $uri $uri/ /index.html; } # 后端 API 反向代理 location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }這里有個(gè)細(xì)節(jié)location /api/加尾斜杠proxy_pass http://127.0.0.1:8080;不帶尾斜杠那 請(qǐng)求/api/user/list會(huì)轉(zhuǎn)發(fā)到http://127.0.0.1:8080/api/user/list路徑和原來(lái)保持一致。如果把proxy_pass寫成http://127.0.0.1:8080/請(qǐng)求會(huì)被轉(zhuǎn)發(fā)到http://127.0.0.1:8080/user/list/api前綴會(huì)被吞掉。這個(gè)細(xì)節(jié)容易踩坑務(wù)必確認(rèn)后端 Controller 的映射上有/api前綴否則會(huì)報(bào) 404。HTTPS 配置線上環(huán)境一般用 Certbot 自動(dòng)申請(qǐng)證書并配置到 Nginx這里先不展開但強(qiáng)調(diào)一句生產(chǎn)環(huán)境不要裸奔 HTTP涉及登錄和 token 的接口不上 HTTPS 相當(dāng)于把門鎖掛在門外面。7.4 數(shù)據(jù)庫(kù)初始化與遷移策略生產(chǎn)環(huán)境數(shù)據(jù)庫(kù)初始化不能靠手動(dòng)一條條執(zhí)行 SQL。我用 Flyway 做數(shù)據(jù)庫(kù)版本管理每次 SQL 變更寫一個(gè)帶版本號(hào)的文件放到resources/db/migration目錄應(yīng)用啟動(dòng)時(shí)會(huì)自動(dòng)執(zhí)行未執(zhí)行過(guò)的腳本。打比方說(shuō)明一下Flyway 就像數(shù)據(jù)庫(kù)的 Git每次變更都是一個(gè) commit版本號(hào)遞增它會(huì)在數(shù)據(jù)庫(kù)中建一張flyway_schema_history表來(lái)記錄已經(jīng)執(zhí)行過(guò)的版本下次啟動(dòng)時(shí)自動(dòng)跳過(guò)已執(zhí)行的只執(zhí)行新增的遷移腳本。示例遷移文件-- V1__create_user_table.sql CREATE TABLE sys_user ( id bigint(20) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用戶名, password varchar(100) NOT NULL COMMENT 加密后的密碼, nickname varchar(50) DEFAULT NULL COMMENT 昵稱, email varchar(100) DEFAULT NULL COMMENT 郵箱, status tinyint(4) DEFAULT 1 COMMENT 狀態(tài)1啟用 0禁用, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4;使用 Flyway 有兩點(diǎn)要非常謹(jǐn)慎已經(jīng)提交給團(tuán)隊(duì)的遷移腳本不要修改哪怕里面 SQL 寫錯(cuò)了也要靠新的遷移腳本來(lái)修正否則團(tuán)隊(duì)的數(shù)據(jù)庫(kù)版本就對(duì)不上了。另外生產(chǎn)庫(kù)不要輕易執(zhí)行flyway clean它會(huì)重建整個(gè)數(shù)據(jù)庫(kù)操作前就算寫滿警告也不為過(guò)。8. 常用工具與效率提升清單8.1 接口調(diào)試工具的選擇聯(lián)調(diào)階段接口測(cè)試工具的作用很大。Postman 是最經(jīng)典的選擇優(yōu)勢(shì)是功能齊全、支持 Collection 管理、環(huán)境變量設(shè)置。Apifox 是國(guó)內(nèi)團(tuán)隊(duì)常用的方案優(yōu)勢(shì)是集成了接口文檔管理、Mock 數(shù)據(jù)、自動(dòng)化測(cè)試。如果項(xiàng)目中后端還沒有完全開發(fā)完Apifox 可以直接在接口文檔上生成 Mock 數(shù)據(jù)給前端先行開發(fā)這種前后端并行開發(fā)的模式能省不少時(shí)間。實(shí)際使用建議如果你是一個(gè)人做全棧直接用 IDEA 的 HTTP Client 就行不需要額外裝軟件。IDEA 里新建.http文件寫請(qǐng)求可以配合{{var}}使用環(huán)境變量還可以在后端代碼左側(cè)直接 Run 生成對(duì)應(yīng)的測(cè)試請(qǐng)求效率很高。8.2 數(shù)據(jù)庫(kù)連接與查詢工具數(shù)據(jù)庫(kù)客戶端方面Navicat 和 DataGrip 都常用。Navicat 功能全面、界面友好DataGrip 更適合寫復(fù)雜 SQL它提供的智能提示和格式化功能非常好用。個(gè)人項(xiàng)目簡(jiǎn)單查詢用 VS Code 的 MySQL 插件也可以湊合。我的建議是對(duì)于持久層查詢用 MyBatis Plus 的LambdaQueryWrapper寫條件查詢已經(jīng)非常直觀大多數(shù)場(chǎng)景不需要打開數(shù)據(jù)庫(kù)客戶端。只有在排查數(shù)據(jù)問(wèn)題時(shí)才需要連數(shù)據(jù)庫(kù)。遇到數(shù)據(jù)庫(kù)連接不上的情況先檢查服務(wù)是否啟動(dòng)、端口是否被占用、認(rèn)證插件版本是否匹配這三個(gè)點(diǎn)大多數(shù)問(wèn)題都能解決。8.3 聯(lián)調(diào)排查常用的瀏覽器開發(fā)者工具前端調(diào)試離不開瀏覽器開發(fā)者工具。Network 面板能看到每個(gè)請(qǐng)求的狀態(tài)碼、耗時(shí)、請(qǐng)求頭和響應(yīng)體Console 面板直接報(bào)錯(cuò)信息Vue 專門有 Vue DevTools 插件可以查看組件樹、Pinia 狀態(tài)和路由信息。排查問(wèn)題建議按照這個(gè)順序來(lái)看先在 Network 里確認(rèn)請(qǐng)求發(fā)出去了沒有、狀態(tài)碼是多少再看請(qǐng)求頭里的 Content-Type 和 Authorization 對(duì)不對(duì)然后看響應(yīng)體里的具體數(shù)據(jù)最后結(jié)合 Console 的報(bào)錯(cuò)信息定位問(wèn)題。有的開發(fā)者一上來(lái)就在代碼里打斷點(diǎn)其實(shí)大多數(shù)聯(lián)調(diào)問(wèn)題在網(wǎng)絡(luò)請(qǐng)求這一層就能定位。8.4 代碼生成器的合理使用到了項(xiàng)目后期增刪改查的代碼寫多了會(huì)產(chǎn)生明顯的機(jī)械重復(fù)感。手動(dòng)復(fù)制粘貼再改字段名容易出錯(cuò)我保留了一條規(guī)則多表關(guān)聯(lián)、復(fù)雜業(yè)務(wù)邏輯的代碼必須手寫但單表 CRUD 的代碼交給生成器生成生成完再人工審查和微調(diào)。MyBatis Plus 官方提供了一個(gè)代碼生成器mybatis-plus-generator可以根據(jù)數(shù)據(jù)庫(kù)表自動(dòng)生成 Entity、Mapper、Service、Controller 代碼。用它的時(shí)機(jī)設(shè)置在項(xiàng)目初始化階段把表結(jié)構(gòu)設(shè)計(jì)好一鍵生成基礎(chǔ)代碼后面再在 Service 中補(bǔ)充業(yè)務(wù)邏輯。這能省去大量重復(fù)勞動(dòng)但你一定要會(huì)改生成的代碼不然會(huì)陷入“低級(jí)錯(cuò)誤看不出來(lái)”的局面。9. 項(xiàng)目擴(kuò)展方向與進(jìn)階建議9.1 從單體應(yīng)用到模塊化演進(jìn)當(dāng)前項(xiàng)目的結(jié)構(gòu)是單體應(yīng)用這個(gè)結(jié)構(gòu)適合大多數(shù)中小型項(xiàng)目。隨著業(yè)務(wù)量增長(zhǎng)你可以按模塊拆分比如用戶模塊、訂單模塊、商品模塊每個(gè)模塊獨(dú)立成一個(gè) Maven 模塊甚至獨(dú)立成一個(gè) Spring Boot 服務(wù)。拆分的關(guān)鍵依據(jù)是團(tuán)隊(duì)規(guī)模和部署復(fù)雜度不要因?yàn)橼厔?shì)而盲目拆分。如果項(xiàng)目超過(guò) 10 個(gè)接口、3 個(gè)以上開發(fā)人員合理的模塊化拆分能明顯減少合并沖突和協(xié)作成本。反過(guò)來(lái)如果就是一個(gè)人的項(xiàng)目拆成微服務(wù)純屬自找麻煩。9.2 引入 Redis 緩存與接口性能優(yōu)化項(xiàng)目中如果有熱點(diǎn)數(shù)據(jù)比如用戶信息、系統(tǒng)配置可以引入 Redis 做緩存層。實(shí)現(xiàn)方式是在原有的 Service 邏輯包一層先查緩存緩存未命中再查數(shù)據(jù)庫(kù)同時(shí)把結(jié)果寫入緩存并設(shè)置過(guò)期時(shí)間。用 Redis 的StringRedisTemplate就夠不需要引入復(fù)雜的緩存框架。這個(gè)實(shí)踐我建議放到項(xiàng)目穩(wěn)定之后再做第二個(gè)版本迭代。先保證功能正確再考慮性能。接口響應(yīng)時(shí)間慢先看是不是數(shù)據(jù)庫(kù)查詢的問(wèn)題有沒有索引、有沒有 N1 查詢?cè)贈(zèng)Q定要不要加緩存。過(guò)早引入緩存會(huì)讓 bug 排查多一層維度代價(jià)不小。9.3 安全加固與權(quán)限模型的進(jìn)階方向做全棧項(xiàng)目時(shí)很多人忽略了權(quán)限設(shè)計(jì)。目前項(xiàng)目只有“登錄/未登錄”兩層。如果你的系統(tǒng)需要不同角色管理員、普通用戶、訪客可以引入 RBAC 權(quán)限模型用戶-角色-權(quán)限三層結(jié)構(gòu)。表設(shè)計(jì)上新建sys_role、sys_menu、sys_user_role、sys_role_menu四張表后端在攔截器或注解層面校驗(yàn)是否有指定權(quán)限。前端對(duì)應(yīng)地可以做動(dòng)態(tài)路由用戶登錄后根據(jù)后端返回的權(quán)限列表動(dòng)態(tài)生成可訪問(wèn)的路由配置。這個(gè)是很多全棧項(xiàng)目的進(jìn)階難點(diǎn)會(huì)接觸到更深的前后端正交互。建議把當(dāng)前項(xiàng)目跑通后再往這個(gè)方向升級(jí)每一步都是新的技術(shù)內(nèi)容。9.4 前端工程化的進(jìn)一步打磨前端部分可以繼續(xù)打磨的點(diǎn)很多代碼規(guī)范ESLint Prettier、提交規(guī)范Commitlint husky、單元測(cè)試Vitest、自動(dòng)化部署GitHub Actions。這些屬于前端工程化范疇。舉一個(gè)很實(shí)用的例子在項(xiàng)目里加 ESLint 和 Prettier 配置團(tuán)隊(duì)協(xié)作時(shí)代碼風(fēng)格統(tǒng)一少了無(wú)謂的爭(zhēng)吵。不建議一開始就上全量工程化配置先把項(xiàng)目跑通再逐步加上這些工具學(xué)習(xí)曲線更平滑。10. 完整的實(shí)操流程對(duì)照表下表整理了這個(gè)項(xiàng)目從零到上線的完整操作清單按順序執(zhí)行每完成一步打一個(gè)勾階段關(guān)鍵操作產(chǎn)出物耗時(shí)預(yù)估環(huán)境準(zhǔn)備JDK 17、Maven、Node.js 20、MySQL 8開發(fā)環(huán)境跑通0.5 天數(shù)據(jù)庫(kù)設(shè)計(jì)創(chuàng)建數(shù)據(jù)庫(kù)和表、初始化測(cè)試數(shù)據(jù)SQL 腳本0.5 天后端骨架創(chuàng)建 Spring Boot 項(xiàng)目、MyBatis Plus 配置可啟動(dòng)空項(xiàng)目0.5 天后端核心接口登錄、CRUD、攔截器、全局異常處理可測(cè)試的 REST API2-3 天前端骨架Vite 創(chuàng)建項(xiàng)目、配置路由、Pinia、Axios可運(yùn)行前端基礎(chǔ)工程1 天前端頁(yè)面開發(fā)登錄頁(yè)、布局頁(yè)、用戶管理頁(yè)可交互的完整頁(yè)面2-3 天前后端聯(lián)調(diào)測(cè)試登錄流程、CRUD 流程、異常流程完整的業(yè)務(wù)閉環(huán)1 天打包部署前端 build、后端 jar、Nginx 配置生產(chǎn)環(huán)境可訪問(wèn)系統(tǒng)1 天上線檢查安全、日志、備份、監(jiān)控穩(wěn)定運(yùn)行的系統(tǒng)0.5 天這是一個(gè)典型的個(gè)人全棧項(xiàng)目的工期預(yù)估。如果你是第一次做時(shí)間會(huì)翻倍正?,F(xiàn)象。如果遇到卡殼超過(guò)半天的問(wèn)題建議跳過(guò)去先把主流程跑通再回頭看卡住的部分。我個(gè)人的經(jīng)驗(yàn)是全棧開發(fā)能力的提升不是線性的而是靠一個(gè)個(gè)完整的項(xiàng)目串起來(lái)的。這個(gè)項(xiàng)目雖然從技術(shù)角度看每個(gè)環(huán)節(jié)都是“常用技術(shù)”但當(dāng)它們組合在一起形成完整閉環(huán)時(shí)你對(duì)前端和后端協(xié)作模式的理解會(huì)上一個(gè)臺(tái)階。當(dāng)你遇到任何業(yè)務(wù)需求時(shí)腦子里能浮現(xiàn)出完整的請(qǐng)求鏈路和數(shù)據(jù)流轉(zhuǎn)圖而不是只盯著自己熟悉的那一層這就算真正入門了。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
91色夜| 天天天天操| 粉嫩少妇自慰在线| 超碰在线人妻| 黑人狂躁日本妞一区二区三区| 欧美激情性爱视频网站| 九九九热精品| 欧美裸体美女日麻屄| A 天堂在线观看视频| 国产精品久久久亚洲第一牛牛_在线观看 | 色婷婷国产精品一区在线观看| www.四虎在线| 国产成人精品日本亚洲语言| 国产成人亚洲精品无码古代早漏男 | 色狠狠综合噜一二三区| 蜜乳av首页| 中文字幕黄片在线| 99热日| 青青五月天| 亚洲欧美日韩电影网站一区 | 高清无码学生妹高潮| 九九九久千久久激情蜜桃在线看 | 久久草视频污视频| 99抽插| 97天天爽| 玖色AV| 在线精品福利免费播放| 无码久久亚洲高清,| 亚洲高清91| 草b在线| 大香蕉宗合网在线| 黄色一级视| 超碰在线人妻中文字幕| 女人综合网| 粉嫩av一区二区三区四季| 婷婷国产精品九区| 天美av在线观看| 91小视频| 日本亚洲熟女视频| 久久性视频| 天天躁日日躁AAAAXXXX国产| 欧美日韩午夜精品一区二区三区| 久久六六| 黄色av一区二区在线| 久久天天摸| 青春草莓视频在线观看网址| 人人人人人人少妇| 两女互慰AV高潮喷水在线观看| 一区二区激情国产熟女| 97超碰精品成| 97超碰在线资源网站| 91美腿丝袜在线观看| www久久久| 久久久一区二区三区麻豆| 亚州中文字幕超碰97| 亚洲欧美经典一区二区| A片 AV一级在线播放观看免费 | 自拍偷拍亚洲熟女妇人精品| 性爱Av免费| 国模私拍一区二区三区神乳| 日本色色视频网站| 亚洲乱码国产乱码精网站| 亚洲色 国产 欧美 日韩| 精品中文字幕一区二区l - 百度| 婷婷五月天基地| 色色丁香| 久九干| 超碰在线974| 在线视频五十市| 伊人丝袜美腿高跟在线观看高清 | 麻豆蜜桃视频在线观看| 亚洲欧美日韩偷拍色图| a亚洲欧美色欲| 无码精品蜜桃一区二区三区ww| 九区国产| 久久久久久久久国产| 九九综合久久| 色香在线| 日夜伊人网| 91真人天天在线| 久久久久亚洲Av无码专区老牛影视| 超碰九区| 色99久草| 久久精品视| 婷婷91| 亚州伊人色综台| 久操 高清| 亚欧洲一区二区视频| 久久九九精品一区二区 | 国产精品69久久久久久久| 大茄子熟女AV导航| 看大黄色大片原件| 色av中文字| 亚洲人久久久网| 国产sv美女内射| 天天影视色香欲综合网小说| 女人高潮抽搐喷水视频网站| 伊人97色天使| 亚州黄站| 免费看日产一区二区三区| 97在线免费看| 日本在线伊人啪啪| 国产日韩在线播放| 免费看污网址| 国产亚洲精品一区二区三区| 欧美视频边做饭边橾| 亚洲欧美在线综合| 丰满翘臀美女影院视频| 一本色道久久综合亚洲二区三区| 天天影视色香欲综合网小说| 青青草在线成人视频| 午夜亚洲| 在线人人人人人人精品超| 亚洲不卡AV在线| 91色s| 欧美伊人久久综合网| 婷婷激情四射| 激情婷婷丁香网| www.色吧5.com| 新久久AV| 日日夜夜噜| 国产午夜精品在线观看| 欧美日韩黄色片一区二区三区四区人与兽做爱| 夂久色| 久久熟女久| 91爱| 天天综合色电影| 五十路人妻在线| 中文字幕日韩电影人妻| 日本999精品| w w w.久久精品| 水澄无码AV| 国产美女自拍视频| 性爱久久| 人妻少妇久久中文字幕一区二区 麻豆 | 香蕉一区二区三区在线视频| 国产日韩久久| 九九九久千久久激情蜜桃在线看 | 大香蕉中文网| 91大学精品激情戏| 亚洲欧美国产中文视频| 中文字幕78| 97超碰天天爱天天爱| av网站国产主播在线| 97色在线| 日韩啪啪视频| 日韩熟女精品无码专区一区二区| 久久久一区二区三区三州| 大香蕉啪啪啪啪在线| 秋霞一级A片黄色视频| 五月天伊人| 国产一区二区三三视频| 天天操天天7| 2024人人操人人摸| 午夜啪| 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 午夜精品久久久久久久第一页按摩| 秋霞欧美性爰视频| 日韩强奸av| 亚洲AO在线| 精品九九国产无码| 亚洲欧美变态| 日韩美一区| 精品无码久久久久久国产浪潮| 福利大香蕉| 爆操无码| 人人看人人插| 久9综合在线| 天天看少妇| 亚洲国产奇米影视久久| 破处bbq| 精品国产少妇高潮视频| 睡产熟女乱伦| www.av家庭乱伦| 综合性视频99| 国产大片精久久久久久| 超碰AV在线| 中文字幕一区二区视频在线观看| 久日综合网| www.狠狠干.coom | 男女91| 一,爱啪啪,在线免费视频| 9久久久久久| 亚洲免费97免费| 久久亚洲av成人无码国产| 一区在线精品中文字幕| 超碰97亚洲| 天天摸天天舔天天操| 黄色污污污污污污网站| 一级啊性爱在线视频| 国产精品成久久久久午夜午夜| 久艹99| 91精品人妻一区二区-全集完整版免费正片国语-B02AV | 欧美少妇一区二区三区| 久久99黄色卞西瓜| 偷看洗澡一二三区美女| 高清国产成人无码| 九九综合九九综合| 91综合色| 大香蕉欧美| avav青青草久久夜| 神马影院午夜福利久久久| 日韩亚洲美女一区久久| www.久久99| 国产福利小视频高清在线观看| 久久久久久久人妻丝袜| 人人操人人肉久久精品| 一本色道久久综合精品婷婷| 人妻激情视频| 玖玖久久久| 亚洲第一视频 欧美风情 日韩| 免费看污网址| 亚洲永久永久永久永久一级一级一级精品 | 99re国产中文字幕| 亚洲中文字幕三级在线| 色牛牛AV| 国产AV超爽| 欧美A片中文字幕| 久久久成人免费av电影| 色www精品视频在线观看| 人妻AV 中文字幕的| 玖玖资源综合在线视频| 亚洲高清无码免费观看视频| 婬女免费一二三区A片| 2018天天干在线视频| 国产51色综合久久免费| α√在线| 91强奸乱轮| 婷婷中文网| 爱我干综合| 久色网| 综合婷婷| 精品九九九九九九九九九| 91l欧美在线| 性老妇一区二区三区| 麻豆AV96熟妇人妻| 国产一区二区三区,在线观看观看| 精品久久九| 91n免费处女| 亚洲综人| 搡老女人老91二区| 91动漫操逼视频| 日韩免费看黄片| 婷婷伊人| 欧美日韩222| 国产欧美黑人丰满在线| 亚洲天堂电影网99999| 亚洲丝袜诱惑| 性爱乱伦视频免费| 中文字幕av乱伦| renqi久久久久久久久久久久| 99re视频在线观看这里只有精品| 熟女人妻久久中文字幕一二区| 精品少妇后入一区二区三区四区人妻巨乳 | 九九九九免费视频| 91狠狠综| 国产亚洲精品玖玖玖在线观看| 免费毛片在线播放| 亚洲欧美setu| 国产精品久久久久婷婷二区次| 亚洲在线网站| 亚洲欧美成人在线| 欧美少妇性乱| 草草电影院| 精品国产乱码| 久久婷婷热| 亚洲淫乱骚妇AV| 97亚洲自在精品在线观看| 精品国产AV一区天美传媒| 操逼逼一区视频| 亚洲国产尤物yw在线观看| 日韩女模中文造逼| 日日夜夜国产综合| 中欧人妻丝袜中文字幕| 國產尤物AV尤物在線觀看| 青青爽| 国内成人圈中文字幕无码视频| 啊啊啊啊啊啊啊啊在线观看| A 天堂在线观看视频| 澳门成人网站久国产日韩| 久久夜精品一区二区三区| 97干在线视频| 激情综合网五月婷婷五月天| 闷骚老熟女15P| 欧美狠狠狠| 日韩精品一区二区日韩| 91网18| 久草午夜| 一二三啪啪专区| 欧美色图综合网| 8050午夜少妇无码| 久久久久久久六六| 人干人人人操人人摸| 三级片大波波| 欧美亚洲| 99999无码| 易易A毛视频| 人人操人人大香蕉| 极品一区二区三区免费| www.99在线| 果冻传媒一区二区三区| 欧美视频一区二区在线| 久久精品72| 亚洲欧洲无码bt精品合集| 五月婷色| 加勒比综合| 大香樵伊人网| 中文字幕乱码在线| 免费A V在线| 国产日韩中文字幕欧美| 九九综合久久| 天天日夜干| 夜夜爽爽爽| 日本不卡二区| 区一二区日韩亚洲乱码av电影| 欧美色日本| 中文字幕日韩专区精品系列 | 久久久久免费少妇| 免费视频一二三区| 观看免费区二区三区二| 亚洲啪啪视频免费| 中文字幕在线2| 亚洲精品无码久久AV| 日韩欧美水蜜桃人妻| 亚洲97久久精品亚洲| 久久国产精品熟女人妻| 97 超碰 人人做 人人爱| 蜜乳AV免费观看| 激情欧美日韩女同久久| 午夜无码精品免费看性色| 色天堂在线观看| 1769精品一区二区三区| 人人操人人摸超碰| 日韩啪啪啪视频| 亚洲 自拍偷拍 欧美| 狠狠躁日日躁夜夜躁A| 91爆操视频| 肥臀熟女一区二区三区视频| 打av高清| 日韩少妇一区二区三区| 欧美一级A一级a爱片久久| 熟女丝袜视频| 中国东北熟女老太婆内谢| 欧美草草| 中文字幕视频2区| 亚洲 自拍偷拍 欧美| 欧美精品系列| 狠狠躁天天躁日日躁| 日韩性爱视频免费在线| 亚洲av国产av综合av卡| 人妻熟女一区二区三区视频| 97爱爱影院| 国产一区二区三区精品观看啪| 极品色综合| 国产乱码久久| 国产久久av| 欧美综合色,www| 日韩在线97| 国产精品麻豆成人AV艾秋| 国产亚洲99久久精品熟| 日韩一级片| 99亚洲国产精品色一区二区三区| 91在线观看,天天综合| 国精品一区二区三| 青草视频在线看看看看看看看看看| 精品人妻一区二区三区四区石在线| 午夜综合在线| 激情欧美日韩女同久久| 亚洲欧美精品一区天堂久久 | 激情文学欧美| 青青草天天亲夜夜操网| 国产黄色影片在线观看| 日韩欧美亚洲自拍偷拍| 久久99久久99精品天美传媒棢·纸:. | 国产美女销魂在线观看不卡| 精品亚洲天堂| 日韩AV噜噜噜一区二区三区四区| 欧美日韩另类字幕中文| 日本999精品视频| 蜜臀久久一区二区| 久久人妻视频| 国产67194| 国产精品自在线发布| 日本性爱视频一级| 中日韩免费看男女操逼大全| 青草成人免费视频一COm| 全国男人天堂网| 碰人碰碰人人开房人肉| 精品成人女人久久| 亚洲图片偷拍欧美| 1.igao73.com 加入收藏 免费专区 国产精品 中文字幕 日韩精品 欧美精品 精彩 | 亚洲人妻一区二区三区| 精品久热| 婷婷丁香五月天综合东京热| 日韩人成网站在线播放| 人人摸人人叼| 六十路日本| 激情五月天社区| 免费簧片在线观看| 日韩精品视频在线观看一卡二卡| 欧美日韩国内不卡| 婷婷久久大香蕉| 亚洲成?V人片在线观看福利| 婷婷丁香成人| 国产精品老熟女一区二区| 欧美日韩丝袜| AV天堂男人的天堂| 日韩欧美天天爽爽爽天天爽爽| 亚洲欧美日韩有码| 天天日天天操VV| 传媒免费一区二区三区| 91美女在线看| 91国精产品| 久久亚州大香蕉| 0755午夜福利视频| 亚洲精品久久久久毛片A片拉屎| 精品视频在线观看| 成全在线观看免费观看| 爽 好舒服 无码刺激久久| 亚洲av乱伦色图网站| 日本成人电影资源网| 强奸a片网| 一区二区三区在线资源| 欧美永久激情一区二区| 激情文学小说一区二区| 美女久久久| 久久av无码| 操逼网免费无码视频| 精品久久久亚洲AV成人网站| 成人午夜小视频手机在线看| 99欧美| 国产夫妻一区二区| 久久中久文96| 婷婷午夜清品久久久久久久性色视频观| 女性91网站| 国产精品女生av| 国产成人无码久久精品| 久久9久9久99久9久9| 后入式视频国产自| 日本乱人伦片中文三区| 精品一区二区人妖| 暖暖精品二区三区观看| 欧美色图人妻| 97综合久久| 福利伊人玖玖国产| 日本女厕偷拍| 色综合大香蕉| 人妻81p| 嗯嗯嗯不要不要免费视频| 97超碰这里只有精品| 舔足天天操天天射| 青青草丝袜在线视频| 日韩乱码Av| 亚洲AV色图一区| 日本爽爽爽爽爽爽免费视频| 婷婷中文字幕| 亚州五月| 一级性爱aaaa| 日韩精品系列| 日韩成人在线性爱视频| 在线观看十八禁| 国产午夜福利合集| a片在线播放| 大香交伊人网| 97超碰精品图片| 十八禁的黄污污免费网站| 九九99久久| 人妻少妇久久中文| 户外裸露刺激视频第一区| 人人色人人射人人妻| 一区二区三区高清 | 欲色啪| 人人贴人人摸| 宗合情欲网| 亚洲精品久久久久毛片A片拉屎 | 情趣丝袜无码操逼视频| 亚洲国产综合久久天堂| 超碰97丝袜| 99精彩视频| 五十路成人在线视频二区三区| 99国产精品视频尤物| 97久久精品亚洲中六字幕| 中文操逼字幕| 欧美性暴力猛交XXXX| 综合色区偷拍| www.久久| 日韩肏逼视频| 久久免费看高潮毛片韩国| 日韩天天综合| 五月丁香色婷婷| 日韩97超碰| 99热超碰在线| 啊啊啊啊啊啊在线观看| 四虎影视在线| 熟女精品日韩一区二区三区| 色五月婷婷在线| 成人区人妻精品一| www.婷婷五月天| 国产白丝AV| 人人爽天天爽| 亚洲成人性爱网站在线播放| 亚洲和欧美裸体美女双飞视频| 国产亚洲精品久久久久小| 欧美淫穴| 日本精品网站在线中文| 欧美 亚洲 综合 制服 另类| 一级久久性爱视频| 超碰九区| 欧美日韩婷婷中文| 在线性黄高清免费视频| 亚洲欧洲激情卡通另类文学四射小说网站 | 韩国一级做A片免费的| 欧洲综合色| 中文字幕在线24| 日本成人免费一区二区三区| 欧美变态激情网| 无遮挡h肉动漫在线观看| 美女性91| baiduhicn.com。| 妺妺跟我一起洗澡没忍住| 久 久无码人妻AV| 97精品综合| 精品国产Av无码久久久亚洲| 丝袜狠狠草尤物 91| 天天色综合天天操| 精品欧美老熟女一二区| 啊啊啊啊好疼视频| 欧美老熟另类| 日韩性爱免费视频在线网站| 嗯嗯啊好爽| 日噜夜夜夜夜夜夜夜夜夜夜爽爽爽爽爽爽爽爽爽爽爽爽 | 狠狠色伊人亚洲综合网站色| 国产人人干| 日韩在线视频1234| 巨爆乳一区二区爆乳区| 欧美日韩中文视频播放| 在线情色电影 91大| 久久午夜伦| 欧美日韩香蕉| 国产精品久久久吖| 青青操国产夫妻| 久久久网一区| 亚洲精品丝袜| 色色99| 3d成人精品一区二区| 欧美超碰97| 2019男人的天堂| 日韩钢筋无码高清啾啾啾| 五月丁香激情综合网| 中文字幕一区二区韩| 一级毛片电影免费看| 精品国产乱码久久久久久久| 色综合99999| 国产又大又粗又长视频在线| 久久国产精品一级二级三级| 999国产精品999| 成人小说视频在线精品欧美| 精品综合久久久久久五月天| 这里只有精品97| 好爽要喷了| 精品一国2| 日韩熟女精品无码专区一区二区| 成人婷婷丁香| 99在线免费视频| 国产久久久久久久久一区二区| 国产精品干干干| 99婷婷一区二区| 96精品久久久久久久久| 天天综合-91入口| 久久伊人影院| 校园激情狠狠四射| 青青草公开在线免费不卡视频| 91 国产丝袜在线播放-百度| 欧美在线中M| 亚洲激情色片 | 人人色人人射人人妻| 久热色情精品| 神马久久久久眼| 久久免费老司机精品| 色香色香欲天天天影视综合网| 婷婷99狠狠躁天天躁| 久久婷婷伊人| 天天摸,夜夜摸| 五月黑AⅤ| 欧美在线色图| 91天天爱| 尤物视频新赏网鲜网色诱网| JuliaAnn丝袜熟女系列| 国产强奸乱伦第1页| 情色图区| 亚洲综合电影| 亚洲国产欧美另类自拍| 亚洲色图欧美视频| 日逼国产| 麻豆国产尤物AV| 久久久久久久少妇| 97免费视频在线观看视频| 加勒比久久av| 亚洲日韩电影| 亚洲精品一二牛牛| 91社区拍啪人妻| 亚洲福利中文字幕在线| av天天在线观看| 艳尻美人妻| 91久久精品美女高潮喷水| 欧洲精品一级二级精品综合视频综合 | 97国产天堂岛| avav青青草久久夜| 成人精品久久久午夜福利| 美國A片| 欧美视频在线视频免费va| 人人操,人人液| 日韩国产不卡在线视频| 中文字幕精品资源在线| 人妻碰碰碰碰碰碰| 啊啊啊啊好疼视频| 乱伦熟女论坛| 成人黑料社久久| 国产夜夜艹| 一本色道久久综合亚洲二区三区| 91天美免费| 日韩黄片影院| 日日夜夜干| 98超碰日本| 在线视频97| 国产一区在线免费播放| 亚洲宗合电影| 久久久久久综合久久伊人蜜月| 一级片在线观看高清无码| 色色五月婷婷| 久操视频在线| 99婷婷一区二区| 91操操| 精品中文一区二区| 蜜臀AV秘一区翔田千里| 午夜精品久久久久久久男人的天堂 | 日韩成人私密一级精品av| 欧美做爰无码A片视频| 中文字幕日韩精品一区二区三区| 猛猛干| 人、人、摸,人、人、草| 美腿丝袜高跟网免费视频免费视频| 91N综合网| 国产成人精品必看| 一区=区三区视频| 欧美激情在线观看视频| 国产在线视视频有精品| 男女性扦B| 国产一进一出视频网站| 欧美狠狠弄| 三久久久四久久久久| 激情五月婷婷| 亚洲天堂资源在线| 久久婷婷五月综合| 情色五月天就去干| 婷婷激情五月天小说网| 超碰69| 亚洲成人av电影在线| 69人妻精品丰满熟女区| 74成人在线| 久久超碰97中文字幕| 国产精品白领在线观看| 视频在线观看一二三区| 丰满人妻一区二区三区色-百度| 99视频只有精品| 另类欧美色| 激情开心五月天| 天天情欲宗合网| 中日韩欧美精品无码AⅤ一区二区| 91在线美女| 无码高清操逼| 一道本东京热加勒比一区二区三区 | 精品高清一区二区三区三州| 最新精品久久蜜桃| 久久直播国产| 欧美爱国产综合、| 欧美综合自拍亚洲综合图| 柠檬AV导航| 农村少妇久久久久久久| 狠狠色色| 少妇色| 97欧美精品综合| 国产一级特黄大片处女| 欧美日韩国产电影| 日韩,欧美,中文在线| 91久久国产精品| 色性欧美| 天天色天天干天天爱| 午夜精品久久久久久久| 狠狠色丁香| 免费观看成人www精品视频| 97精品久久久久久久| 超碰在线欧美性爱激情| 色呦色呦色精品| 太久视频| 色与欲影视| 熟妇艹鸡八| 午夜偷拍久久熟女| 色爱亚洲| 东北女人操比视频| 久久99操天天日| 久久亚州精品成人Av无| 久久后入制服| 夜夜高潮夜夜爽| av午夜影院在线播放| 午夜一区| 老女人碰碰在线碰碰视频| 婷婷丁香六月| 亚洲人妻在线一区| 亚洲色图图片| 大香蕉日韩欧美| 91红杏| 激情AV| 国产精品网址| 色综合1991| 五月婷婷hd| 日本熟女中文| 熟女五十路一区二区三| 丝袜足交视频| 欧美少妇性乱| 久操B网| 99自拍视频| 日韩无码黄色片| 欧美高清91| 强奸熟女一区二区三区| 无码欧美有限公司| 337p大胆噜噜噜噜噜91Av| 久久久精品91八戒| 性一级黄色录像片网站导航| 欧美青青草视频| 婷婷成人久久久精品| 国产视频一区二区免费| 二男一女成人A片| 久久精品人妻一区| 日韩小电影| 欧美97网| 久久久久深夜无码| 在线情色电影 91大 | 欧美疯狂做爰xxxx| 无码最新| 99re免费| 狠狠干91| 人人操人人色网| 久久久蜜桃臀无码视频| 98超碰欧美| 欧美性五月| 久久一区二区加油站| 97国产色图 | 久草精品视频| 久久久久亚洲一区女同性恋中文字幕| 九九九久千久久激情蜜桃在线看 | 中韩中文字幕在线观看| 日韩欧美天堂| 伊人久久亚洲色欲综合网站 | 麻豆精品三区视频| 欧美91网站| 超碰97最新人妻| 青青草国产盗摄一二三区| 1234区中文字幕在线观看_青青草国产在线_日韩一区二区 | 久久九操在线观看| 日本三级韩国三级美三级91| 综合激情一一91| 97天天在线| 插B在线观看| 综合网少妇| 国产精品农村妇女精品| 国产免费内射视频| 日本黄色精品| 精品在线蜜臀| 久久久国产av美女私房| 国产对白刺激视频| 色香阁在线| 小草三级久久观看| 午夜视频好爽啊| 99热导航| 伊人久久婷婷| 99re6久热只有精品6在线直播| 久热69九色熟妇97| av麻豆啪啪| 无码九九九九| 亚洲久久天堂| 我要色综合网| 加勒比在线观看一区二区| 插穴性爱视频在线观看| 亚洲午夜av| 亚洲伊人久久精品狠狠在线| 9久精品视频在线观看| 熟女欧美日韩综合婷婷| 超碰欧美97资源| 九热中文字幕| 婷婷伊人五月| 无码免费精品高清| www黄片免费看com| 精品国产乱码久久久久久久久1| 另类图片五月| 风骚少妇视频中文字幕| 亚洲国产97| 亚洲中文日韩精品| 人人摸人人干| 久久国产精品m码| 午夜福利免费精品视频| 亚洲人在线成线成人| 国产精品对白自产拍| 97在线视频网站| 亚洲成人性爱在线观看| 一区二区三区四区姦女| 精品人妻15区| 丝袜人妻av一区二区| 操逼网站视频漫画国产| 97综合在线观看| 久久9精品网站| 亚洲春色一区二区三区| av婷婷色婷婷色六月| 亚洲91亚洲| 成人久久精品| 日本曲间由美性生活片| 亚洲性刺激| 亚洲欧综合另类无码一区| 九九英色视频| 狠狠操,使劲操| 99热免费| 搡老女人老91妇女老熟女| 91精品丝袜久久久久久| 久久精品综合| 乱伦系列一区二区| 青青草无码视频| 密乳AV免费观看| 啊啊啊97视频| 精品成人无码| 色九九九综合| 欧美天天干| 96国产污污污丝袜| 一牛影视成人片免费| 999综合色| 91人妻精华帖| 在线情色电影 91大 | 人人操人人93| 中美日韩毛片| 日本高清视频xxxx| 亚洲色图国产另类| 色色香蕉| 爱丝福利| 99热在线播放| 精品少妇999| 99re这里只有精品3| 免费A片三p视频| 国产成自自拍在线观看| 欧美天天干| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 国产麻豆一区二三区| 熟女人妇一区二区三区| 熟女久久| 人人爽天天爽| 午夜视频久久久久一区| 青草园大香蕉| 婷婷五月天色| A级在线视频| 亚洲精品蜜桃久久久久久久| 亚洲成熟国产精品美女| 嗯嗯不要 视频| 最新加勒比丝袜在线| 国产精品日韩在线一区| 色女免费在线观看视频网址| 欧美做爰无码A片视频| 亚洲日韩精品一区二区| AV一二区| 丝袜美腿制服人妻二区中文字幕| 97视频一区| 亚洲精品丝袜| 亚洲九月丁香| 麻豆天美传媒毛片| 中文字幕在线2| www.天天干| 天天激情综合站| 91蜜臀人妻中文字幕在线| 亚洲AV无码天美传媒一区| 免费?级毛片无码?∨蜜芽试看| 99日免费视频中文字幕| 亚洲夜色在线| 粉嫩粉嫩一区性色AV片| 久久久四区| 久污| 中文字幕一区二区三区人妻少妇在线| av绯色| 国产精品操| 色香欲天天天天综合色| 美女黄页| www.色综合| 手机在线中文字幕国产| 精品久| 亚洲校园激情| 欧美亚洲美少妇一区二区| 9久热| 日本操逼二区| 人妻性爱一区二区| 国产日韩怡红院| 我中文字幕6区| 少妇蜜汁| 亚洲综合五月天婷婷丁香| 女人被男人桶爽视频网站| 日日爱99| 97欧美资源| 伦理日韩国产久久| 久久综合女优| 99久久com免费视频′| 美女黄频a美女大全免费皮| 性videos欧美熟妇hdx| 美女91| 97人人夜| 亚洲国产福利视频| 97超碰中文| 求求你操操我| 亚洲男人的天堂V| 大香蕉免费中文| 蜜臀操逼黄色视频操的好爽| 特级特黄一级毛片免费| 一起草三级AV电影在线观看| 91性感在线| 怡红院成人视频| 国产精品午夜福利| 久久久91福利姬| 国产一区二区三区,在线观看观看| 欧美日韩国第一区| 欧美九九爱| 夜夜嗨一区二区| 狠狠狠狠狠| 涩涩五月天| 五月激情天| 人人操AV| 亚洲nv男人的天堂网| 五月婷婷基地| 26uuu国产| 色九九九九久| 欧美精品四区| 北京专精特新企业招聘信息| 97色冈| 欧美一区二区在线资源| 亚洲国产综合久久久性感熟妇| 一色网男人的天堂| 色综合中文字幕不卡| 男人的天堂在线有码| 95精品在线| 中文字幕丝袜人妻| 久久超碰大香蕉| 色综合超碰超| 国产三级中文字幕粉嫩| 校园春色 亚洲| 老熟女综合| 百度百度日本操逼| 国产强奸91| 九九探花视频在线观看| 综合一区中亚洲国产成人综合精品| 国产乱伦一二三区| 婷婷月色| 欧美内射少妇| 色偷偷男人的天堂麻豆| 在线洲亚线| 国产精品熟女一区二区三区| 久久伊人最新网址视频| 8x福利精品第一福利视频导航| 黄色电影观看久久9| 国产成人久久久精品免费AV| 日韩欧美视频青青| 亚91亚洲网| 男人的天堂日韩| AV天堂因数| 国产丝袜美女在线一区| 国产精品久久久无码AV网站| 久久99久久99久久99人受| 精品无码一区二区| 久湿久久| 亚洲高清自拍| 欧美大香蕉同搞| 六月激情网| 上床不卡网站| 蜜臀久久99精品久久久久电影| 亚洲欧美综合| 艹比视频国产精品| 亚州宗合另类| 久久骚| 欧美亚洲中文| 爱av免费| 国产人伦精品一区二区三区| 99re在线视频| 永久免费观看的毛片的网站| 91社操逼| 综合国产97| 男人的天堂kva| 国产丝袜欧美在线视频| 影音先锋国产精品| 午夜精品久久久久| 俞拍久久国应视频| 国产高清在线观看欧美| 人妻少妇蜜桃视频欧美一区| 久久精品国产精品| 激情综合网激情综合| 亚洲无线码一区国产欧美国| 日日干夜夜操视频h| 亚洲熟女诱惑| 91成人久久| 五月婷婷hd| 亚洲在线91| 亚洲AV无码国产精品久久久久 | 人妻三级在线中文字幕| 成人免费在线网站| 大香蕉99热| 日日骚中文字幕| 极品色www影院| 久久久久9999精品九九九| 欧洲性爱无码区| 激情小说五月天| 蜜臀中文无码午夜| 秋霞无码av鲁丝片一区| 97久久超碰国产网站| 91成人18| 丁香五月av| 日韩日韩日韩-国产乱码精品一区二区| 天天激情综合站| 蜜臀亚洲中文| 精品无码久久久久久久久果冻糖心| 国产福利第一视频| 日本不卡免费二区| 日韩成人精品视频自拍| 蜜臀久久99精品| 久久成人国产精品| 嗯嗯嗯,草死我| 国产偷拍网站| 天堂资源欧美| 日韩欧美福利视频看看| 97视频在线免费看| 欧美综合天天| 久操B网| 91久久青青草原精品| 精品精品精品| 96久久久久| 97九色人妻| 91狠狠综| 亚洲中文字幕乱码无码一区二区| 七月婷婷综合| 久久这里精品国产99丫e6| 百度百度日本操逼| 夜夜爽妓女| 人人操,人人插| 亚州综合AⅤ| 乱伦Av网| 九九九久| 97在线精品| 97在线视频免费| 少妇诱惑视频| 亚洲图片日本AⅤ欧美在线| 超碰地址97| 久久亚洲AV成人精品无码| 久久久久久99999国产精品| 婷婷综合网| 偷拍综合网| 青青操少妇| 久久成人午夜精品影院| AV色五月| 97色色网| 欧美区亚洲区偷拍区| 欧美成人综合| 国内精品久久久久影院亚洲| 人妻另类| 麻豆亚洲Av成人无码一区精品| 秋霞 色色| 999九九精品| 色色色欧美| 一区AV| 天天天操天天天爱| 亚洲国产第一页综合视频| 麻豆国产97在线| Aa东京男人的天堂| 日本一本一区二区三区四区五区欧美日韩中文字幕 | 温婉少妇玩3p| 欧美一级二级三级| 国产成自自拍在线观看| 黄色片大香蕉| 尤物网站91| 99在线啪| 青青11操操操操操操操操| 天天色,天天干,天天干| 99久久久| 青娱乐蜜桃臀AV色婷| 亚洲色欲天天人妻无码系列专区| 视频不卡中文字幕| 啊嗯嗯啊好大好爽| 久久最新免费视频23| 激情综合网五月婷婷五月天| 久久九色| 伊人在线大香蕉视频久久| 东北夫妻性偷拍| 欧美强奸乱| 波多野结衣AV无码一区| 97精品一区| 神马久久久久久久久久| 99欧美| 国产高清MV操逼视频| 超碰色综合| aV中文麻| 熟妇国产免费一区| 久久久9视频| 国产激情视频在线观看| 久久亚洲欧美中文字幕国语| 78超碰| 亚洲双插| 黄色片G G G| 亚洲天堂另类小说男人| 色播五月丁香| 欧日a| 日韩精品碰碰| 午夜视频黄| 好爽视频在线观看视频| 91精品婷婷国产综合久久| 免费网色网站| 日欧美色| 日本免费一区二| 东京热亚洲一区二区| 麻豆啪啪啪视频| 狠狠色狠狠色狠狠五月| 国产家庭乱伦性爱视频| 视频一区二区免费在线| 男人天堂2030| 91 偷| 九九九九九九综合| 中日992视频| 激情四射婷婷六月天| 超碰98综合网| 久热久操| 青青伊人久久| 使劲用力艹少妇视频一区二区| 97色欧州| 丝袜天堂| 九九拍拍精品视频在线播放 | 麻豆一区二区三区在线看 | 亚洲性爱免费电影| 国产无码高清操逼视频| 欧美一级AAAAAAA| CCYY草草影院地址入口| 三级日韩一区二区三区| 亚洲一区二区性爱电影| 大香蕉在线86| 亚洲综合在线高清| 少妇被玩视频二三区| 欧美久久婷| 日韩精品熟妇| 91高跟美女在线播放| 加勒比日本在线| 60秒免费小视频| 亚洲日韩熟女人妻高清在线| 九九九九九九九九九五码| 涩涩久久精品| 国产AV线| 91熟女丨老女人| 97视频在线| 92性色国产午夜福利在线661| 99精品国产户外露出| 久久午夜鲁丝片| 乱伦图av| 亚洲激情在线一区二区| 五月开心网|