目錄
nginx:
nginx反向代理和負載均衡概念
nginx反向代理和負載均衡如何配置?
后端環境:maven管理
sky-common
sky-pojo
sky-server:
后端環境搭建--Git進行版本控制
后端數據庫--Mysql
前后端聯調
前后端運行:
前后端聯調如何完成--斷點調試跟蹤代碼
斷點調試小tips:
.yml文件簡介:
YAML 的常見應用場景
令牌生成
完善登錄功能
TODO使用小tips
導入接口文檔
Swagger技術
介紹
使用方式
在線接口測試:
Swagger常用注解
nginx:
nginx學習,看這一篇就夠了:下載、安裝。使用:正向代理、反向代理、負載均衡。常用命令和配置文件,很全-CSDN博客
前端分為web端、小程序端
web端在nginx下面的html文件夾下面,nginx必須放在沒有中文目錄的環境運行
運行方法:雙擊nginx.exe,用瀏覽器打開訪問localhost,訪問端口號默認80
nginx反向代理和負載均衡概念
驗證方法:在前端頁面點擊登錄(打開F12開發者模式)可以看到前端請求地址
nginx反向代理:將前端發送的動態請求轉發到后端服務器
nginx反向代理好處:
- 緩存提高訪問速度,
- 進行負載均衡(把大量請求按照指定方式均衡的分配給集群中的每臺服務器),
- 保證后端服務安全
nginx反向代理和負載均衡如何配置?
反向代理主要依靠proxy_pass來配置
負載均衡的底層也是基于反向代理實現的,多配置了一些服務器server,轉發可能需要給多個后臺服務器
在這個項目中,負載均衡的配置文件在
后端環境:maven管理
sky-common
- constant:常量類
- context:上下文相關
- enumaration:枚舉類
- exception:自定義異常類
- json:處理json轉換
- properties:Springboot中的配置屬性類,把配置文件中的一些配置對象封裝
- result:后端返回結果
- utils:工具類
sky-pojo
前三項都屬于POJO(Plain Old Java Object?,簡單老式java對象),一種遵循簡單設計原則的普通 Java 類,主要用于封裝數據。
POJO 的核心特點:
- 無繼承要求:不需要繼承特定的類(如?
Serializable
?等,不過實際中為了序列化可能會實現) - 無接口強制:不需要實現特定的接口
- 字段私有化:成員變量通常用?
private
?修飾 - 提供訪問方法:通過?
public
?的?getter
?和?setter
?方法操作字段 - 無業務邏輯:主要用于數據存儲,不包含復雜的業務處理方法
- 可包含構造方法:通常會有默認構造方法和帶參數的構造方法
sky-server:
配置文件、配置類、攔截器、controller、service、mapper、啟動類等
后端環境搭建--Git進行版本控制
在IDEA中VCS(version control system版本控制系統)新建git倉庫,上方就會出現Git相關操作按鈕。
先對號commit到本地倉庫,再箭頭push到遠程倉庫
后端數據庫--Mysql
前段時間做數據庫作業好像破壞了什么Mysql配置,啟動方式:
管理員身份運行cmd,net start mysql,再使用Navicat
前后端聯調
前后端運行:
前端雙擊nginx
后端代碼編譯:點擊compile(父工程sky-take-out整體編譯)
sky-server中運行application,運行項目
嘗試在登錄頁面前端登錄,報錯,原因沒有修改數據庫連接賬號密碼
修改之后成功登錄:
前后端聯調如何完成--斷點調試跟蹤代碼
右上角綠框可以快速運行查看啟動類,旁邊的小蟲子是debug斷點調試,
在EmployeeController類里面有login方法,打一個斷點
重新登陸
@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("員工登錄:{}", employeeLoginDTO);
員工登錄DTO中封裝前端試圖登錄的賬號密碼
斷點調試可以方便看到前端提供過來的數據
- Mapper中的sql語句,如果是簡單的查詢可以寫注解,復雜/mybatis中動態標簽通過xml配置
- 后面的異常處理,由全局捕獲業務異常的GlobalExceptionHandeler捕獲,類型是BaseException(父類),其他類型的異常繼承它
斷點調試小tips:
stepover單步調試(F8),resume program左側--運行至下一個斷點
ctrl + alt + b可以跳轉到光標的函數位置
.yml文件簡介:
.yml
?是一種文件格式的擴展名,對應的文件類型是?YAML 文件(YAML 全稱是 "YAML Ain't Markup Language",即 “YAML 不是標記語言”)。它是一種數據序列化格式,主要用于存儲和傳輸結構化數據,語法簡潔、易讀
簡潔直觀:
采用縮進(通常是空格,而非 Tab)來表示數據的層級關系,避免了 XML 或 JSON 中的大量標簽(如?<tag>
)或括號(如?{}
?[]
),可讀性極強。
例如,一個簡單的用戶信息 YAML 配置:
user:name: Aliceage: 25hobbies:- reading- hikingcontact:email: alice@example.comphone: 123456789
YAML 的常見應用場景
- 配置文件:很多框架(如 Spring Boot、Docker、Kubernetes、Ansible 等)默認使用 YAML 作為配置文件格式,例如 Spring Boot 的?
application.yml
?用于配置數據庫連接、端口號等。 - 數據存儲:可用于存儲簡單的結構化數據(如測試數據、配置參數)。
- API 交互:部分 API 會使用 YAML 格式傳輸數據(雖然 JSON 更常見)。
格式 | 特點 | 適用場景 |
---|---|---|
YAML | 縮進表示層級,簡潔易讀,支持注釋 | 配置文件(如 Spring Boot 配置)、人工編輯的結構化數據 |
JSON | 用括號表示層級,語法嚴格(無注釋),機器友好 | API 數據傳輸、前端與后端交互 |
XML | 標簽嵌套,語法繁瑣,支持復雜結構和命名空間 | 傳統配置文件(如早期 Java 框架)、文檔標記 |
如圖上中的兩個是springboot的配置文件
令牌生成
JwtProperties是一個配置屬性類,在common-properties中,如下所示
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
// 封裝了SpringBoot里面的一些配置項
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {/*** 管理端員工生成jwt令牌相關配置*/private String adminSecretKey;private long adminTtl;private String adminTokenName;/*** 用戶端微信用戶生成jwt令牌相關配置*/private String userSecretKey;private long userTtl;private String userTokenName;}
其中
@ConfigurationProperties(prefix = "sky.jwt")
是 Spring Boot 中的一個注解,用于將配置文件(如?application.yml
?或?application.properties
)中指定前綴的配置項,自動綁定到當前類的屬性上。
-
@ConfigurationProperties
:
這是 Spring Boot 提供的核心注解,作用是 “配置屬性綁定”。它會自動讀取配置文件中的內容,并將符合規則的配置值賦值給類中的成員變量。 -
prefix = "sky.jwt"
:
prefix
?表示 “配置前綴”,指定了要讀取的配置項的共同前綴。
這意味著:Spring 會去配置文件中尋找所有以?sky.jwt
?開頭的配置項,然后與當前類的屬性進行匹配綁定。
所以在aplication.yml中找到下面這一段,會被綁定到JwtProperties類的屬性上
sky:jwt:# 設置jwt簽名加密時使用的秘鑰admin-secret-key: itcast# 設置jwt過期時間admin-ttl: 7200000# 設置前端傳遞過來的令牌名稱admin-token-name: token
可以看到和上面一一對應
生成jwt令牌在EmployeeController
package com.sky.controller.admin;import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.entity.Employee;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.utils.JwtUtil;
import com.sky.vo.EmployeeLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;/*** 員工管理*/
@RestController
@RequestMapping("/admin/employee")
@Slf4j
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@Autowiredprivate JwtProperties jwtProperties;/*** 登錄** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("員工登錄:{}", employeeLoginDTO);Employee employee = employeeService.login(employeeLoginDTO);//登錄成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, employee.getId());// jwt令牌String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);// 需要傳遞給前端的信息,用VO進行封裝EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);}/*** 退出** @return*/@PostMapping("/logout")public Result<String> logout() {return Result.success();}}
其中EmployeeLoginVO如下所示
package com.sky.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "員工登錄返回的數據格式")
public class EmployeeLoginVO implements Serializable {@ApiModelProperty("主鍵值")private Long id;@ApiModelProperty("用戶名")private String userName;@ApiModelProperty("姓名")private String name;@ApiModelProperty("jwt令牌")private String token;}
完善登錄功能
問題:密碼在數據庫明文存儲,安全性低?
TODO使用小tips
導入接口文檔
教程使用Yapi,這個網站現在無法使用
嘗試使用ApiPost失敗,于是嘗試apifox,導入類型選擇Yapi,可以成功導入
Swagger技術
介紹
可以幫助后端生成接口文檔,并進行在線調試
?
使用方式
Bean注解:使用Spring框架創建并管理對象
在server的config類下面
package com.sky.config;import com.sky.interceptor.JwtTokenAdminInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;/*** 配置類,注冊web層相關組件*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@Autowiredprivate JwtTokenAdminInterceptor jwtTokenAdminInterceptor;/*** 注冊自定義攔截器** @param registry*/protected void addInterceptors(InterceptorRegistry registry) {log.info("開始注冊自定義攔截器...");registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin/employee/login");}/*** 通過knife4j生成接口文檔* @return*/@Beanpublic Docket docket() {log.info("準備生成接口文檔...");ApiInfo apiInfo = new ApiInfoBuilder().title("蒼穹外賣項目接口文檔").version("2.0").description("蒼穹外賣項目接口文檔").build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select()// 指定生成接口需要掃描的包.apis(RequestHandlerSelectors.basePackage("com.sky.controller")).paths(PathSelectors.any()).build();return docket;}/*** 設置靜態資源映射* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("開始設置靜態資源映射...");registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}
由于上面配置的靜態資源映射,將后端接口文檔映射到localhost:8080/doc.html
- 如果不設置靜態資源映射,SpringMVC會以為在請求某一個controller,是動態請求
- 如果掃描包的名字寫錯了,就無法正確掃描生成動態接口文檔
訪問即可查看該接口文檔
knife4j為此動態生成接口文檔
目前已經有的兩個接口是解析下面的類生成的
/*** 員工管理*/
@RestController
@RequestMapping("/admin/employee")
@Slf4j
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@Autowiredprivate JwtProperties jwtProperties;/*** 登錄** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("員工登錄:{}", employeeLoginDTO);Employee employee = employeeService.login(employeeLoginDTO);//登錄成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, employee.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);}/*** 退出** @return*/@PostMapping("/logout")public Result<String> logout() {return Result.success();}}
在線接口測試:
Swagger常用注解
在EmployeeController里面加入相關注解之后