<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      伙伴匹配系統(移動端 H5 網站(APP 風格)基于Spring Boot 后端 + Vue3 - 02

      伙伴匹配系統(移動端 H5 網站(APP 風格)基于Spring Boot 后端 + Vue3 - 02

      項目地址:

      @


      后端整合 Swagger + Knife4j 接口文檔

      什么是接口文檔,寫接口信息的文檔。

      每個接口的信息包括:

      • 請求參數
      • 響應參數:
        • 錯誤碼
      • 接口地址
      • 接口名稱
      • 請求類型
      • 請求格式
      • 備注

      誰用接口文檔?

      答:一般是后端或者負責人來提供,后端和前端都要使用

      為什么需要接口文檔?

      • 有一個書面內容(背書或者歸檔),便于大家參考和查閱,便于沉淀和維護,拒絕口口相傳。
      • 接口文檔便于前端和后端開發對接,前后端聯調的介質,后端 => 接口文檔 <= 前端。
      • 好的接口文檔支持在線調試,在線測試,可以作為工具提高我們的開發測試效率。

      怎么做接口文檔?

      • 手寫:比如騰訊文檔、Markdown筆記
      • 自動化接口文檔生成:自動根據項目代碼生成完整的文檔或在線調試的網頁。Swagger、Postman(側重接口管理)(國外);apifox、apipost、eolink(國產)

      使用 Swagger

      1. 引l入依賴(Swagger或Knife4j:https://doc.xiaominfo.com/knife4j/documentation/get_start.html))
      2. 自定義Swagger配置類
      3. 定義需要生成接口文檔的代碼位置(Controller)
      4. 千萬注意:線上環境不要把接口暴露出去!!!可以通過在SwaggerConfig配置文件開頭加上@Profile({"dev","test"})限定配置僅在部分環境開啟
      5. 啟動即可
      6. 可以通過在controller方法上添加[@Api、@ApilmplicitParam(name]VApi、@ApilmplicitParam(name)="name",value="姓名",required=true)[@ApiOperation(value]/ApiOperation(value)=“向客人問好")等注解來自定義生成的接口描述信息

      使用 swagger 日志

      swagger 官網地址:https://swagger.io/

      導入相關的依賴

      
              <!-- swagger -->
              <dependency>
                  <groupId>io.springfox</groupId>
                  <artifactId>springfox-swagger2</artifactId>
                  <version>3.0.0</version>
              </dependency>
              <dependency>
                  <groupId>io.springfox</groupId>
                  <artifactId>springfox-swagger-ui</artifactId>
                  <version>3.0.0</version>
              </dependency>
      

      在配置文件config目錄下,添加swagger 的配置文件 SwaggerConfig.java

      package com.yupi.yupao.config;
      
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Profile;
      import springfox.documentation.builders.ApiInfoBuilder;
      import springfox.documentation.builders.PathSelectors;
      import springfox.documentation.builders.RequestHandlerSelectors;
      import springfox.documentation.service.ApiInfo;
      import springfox.documentation.service.Contact;
      import springfox.documentation.spi.DocumentationType;
      import springfox.documentation.spring.web.plugins.Docket;
      import springfox.documentation.swagger2.annotations.EnableSwagger2;
      import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
      
      /**
       * 自定義 Swagger 接口文檔的配置
       *
       * @author <a >Raibnowsea</a>
       */
      @Configuration
      //@EnableSwagger2WebMvc
      @EnableSwagger2
      @Profile({"dev", "test"})  // 表示該項目在什么樣的開發環境下,對外開發接口文檔
      public class SwaggerConfig {
      
          @Bean(value = "defaultApi2")  //
          public Docket defaultApi2() {
              return new Docket(DocumentationType.SWAGGER_2)
                      .apiInfo(apiInfo())
                      .select()
                      // 這里一定要標注你控制器的位置
                      .apis(RequestHandlerSelectors.basePackage("com.rainbowsea.yupao.controller"))
                      .paths(PathSelectors.any())
                      .build();
          }
      
      
          /**
           * api 信息
           *
           * @return
           */
          private ApiInfo apiInfo() {
              return new ApiInfoBuilder()
                      .title("魚皮用戶中心")
                      .description("魚皮用戶中心接口文檔")
                      .termsOfServiceUrl("https://github.com/rainbowsea")
                      .contact(new Contact("yupi", "https://github.com/rainbowsea", "xxx@qq.com"))
                      .version("1.0")
                      .build();
          }
      }
      
      

      apis(RequestHandler)
      

      如果 Spring Boot Verision >= 2.6 ,需要添加如下配置

      spring:
        mvc:
        	pathmatch:
            matching-strategy: ANT_PATH_MATCHER
      

      訪問路徑:你的項目名映射路徑+/doc.html ;比如: localhost:8080/api/doc.html

      網頁內容抓取-存量用戶信息導入及同步

      看上了網頁信息,怎么抓到的

      1. 分析原網站是怎么獲取這些數據的?哪個接口? F12,刷新——>觸發請求

      2. 用程序去調用接口

      3. 處理(清洗)一下數據,之后就可以寫到數據庫里。

      流程:

      1. 從 Excel 中導入全量用戶數據,判重
      2. 抓取寫了自我介紹的同學信息,提取出用戶昵稱,用戶唯一 id,自我介紹信息。
      3. 從自我介紹中提取信息,

      Easy Excel 讀取 Excel 當中的信息

      Easy Excel 官網地址:https://alibaba-easyexcel.github.io/index.html

      Easy Excel 官方文檔:https://easyexcel.opensource.alibaba.com/docs/current/

      兩種讀 Excel 的方式:

      1. 確定表頭:建立對象;和表頭形成映射
      2. 不確定表頭:每一行數據映射為 Map<String.Object>

      兩種讀取模式:

      1. 監聽器:先創建監聽器,再讀取文件時綁定監聽器。單獨抽離處理邏輯,代碼清晰易于維護;一條一條處理,適用于數據量大的場景。
      2. 同步讀:無需創建監聽器,一次性獲取完整數據。方便簡單,但是數據量大時會有等待時常,也可能內存溢出。

      導入 Easy Excel 依賴

      <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>easyexcel</artifactId>
          <version>3.1.1</version>
      </dependency>
      

      這里我們創建一個:最簡單的讀的對象。用于存放我們讀取到的 Excel 信息將其映射為一個對象。

      1. 確定表頭:建立對象;和表頭形成映射
      2. 不確定表頭:每一行數據映射為 Map<String.Object>
      package com.rainbowsea.yupao.one;
      
      
      import com.alibaba.excel.annotation.ExcelProperty;
      import lombok.Data;
      
      @Data
      public class DemoExcelData {
      
          //@ExcelProperty(index = 1) 可以用列表匹配
      
          /**
           * id 
           * 強制讀取第幾個,這里不建議用 index 和 name 同時使用,
           * 要么一個對象只用 index ,要么一個對象只用 name 去匹配
           */
          @ExcelProperty("成員編號")
          private String planeCode;
      
          /**
           * 用戶昵稱
           */
          @ExcelProperty("成員昵稱")
          private String username;
      
      }
      
      

      讀取方式一:監聽器:先創建監聽器,再讀取文件時綁定監聽器。單獨抽離處理邏輯,代碼清晰易于維護;一條一條處理,適用于數據量大的場景。

      package com.rainbowsea.yupao.one;
      
      
      import com.alibaba.excel.context.AnalysisContext;
      import com.alibaba.excel.read.listener.ReadListener;
      import lombok.extern.slf4j.Slf4j;
      
      /**
       * Excel 讀取監聽
       *
       */
      @Slf4j
      public class TableListener implements ReadListener<DemoExcelData> {
      
          /**
           * 這個每一條數據解析都會來調用
           *
           * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
           * @param context
           */
          @Override
          public void invoke(DemoExcelData data, AnalysisContext context) {
              System.out.println(data);
          }
      
          /**
           * 所有數據解析完成了 都會來調用
           *
           * @param context
           */
          @Override
          public void doAfterAllAnalysed(AnalysisContext context) {
              System.out.println("已解析完成");
          }
      }
      

      package com.rainbowsea.yupao.one;
      
      
      import com.alibaba.excel.EasyExcel;
      
      import java.util.List;
      
      /**
       * 導入 Excel
       *
       */
      public class ImportExcel {
      
          /**
           * 讀取數據
           */
          public static void main(String[] args) {
              // todo 記得改為自己的測試文件
              String fileName = "E:\\Java\\project\\魚皮星球項目\\伙伴匹配系統\\yupao\\yupao-backend\\src\\main\\resources\\testExcel.xlsx";
              readByListener(fileName);
          }
      
          /**
           * 監聽器讀取
           * @param fileName
           */
          public static void readByListener(String fileName) {
              EasyExcel.read(fileName, DemoExcelData.class, new TableListener()).sheet().doRead();
          }
      
      
      }
      
      

      讀取方式二:同步讀:無需創建監聽器,一次性獲取完整數據。方便簡單,但是數據量大時會有等待時常,也可能內存溢出。

      package com.rainbowsea.yupao.one;
      
      
      import com.alibaba.excel.EasyExcel;
      
      import java.util.List;
      
      /**
       * 導入 Excel
       *
       */
      public class ImportExcel {
      
          /**
           * 讀取數據
           */
          public static void main(String[] args) {
              // todo 記得改為自己的測試文件
              String fileName = "E:\\Java\\project\\魚皮星球項目\\伙伴匹配系統\\yupao\\yupao-backend\\src\\main\\resources\\testExcel.xlsx";
              
              synchronousRead(fileName);
          }
      
      
      
          /**
           * 同步讀
           *
           * @param fileName
           */
          public static void synchronousRead(String fileName) {
              // 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet 同步讀取會自動finish
              List<DemoExcelData> totalDataList =
                      EasyExcel.read(fileName).head(DemoExcelData.class).sheet().doReadSync();
              for (DemoExcelData xingQiuTableUserInfo : totalDataList) {
                  System.out.println(xingQiuTableUserInfo);
              }
          }
      
        
      
      
      }
      
      

      技巧:讀取 Excel 當前的數據,進行一個過濾,提交操作

      package com.yupi.yupao.once.importuser;
      
      import com.alibaba.excel.EasyExcel;
      import org.apache.commons.lang3.StringUtils;
      
      import java.util.List;
      import java.util.Map;
      import java.util.stream.Collectors;
      
      /**
       * 導入星球用戶到數據庫
       *
       * @author <a >程序員魚皮</a>
       * @from <a >編程導航知識星球</a>
       */
      public class ImportXingQiuUser {
      
          public static void main(String[] args) {
              // todo 記得改為自己的測試文件
              String fileName = "E:\\星球項目\\yupao-backend\\src\\main\\resources\\prodExcel.xlsx";
              // 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet 同步讀取會自動finish
              List<XingQiuTableUserInfo> userInfoList =
                      EasyExcel.read(fileName).head(XingQiuTableUserInfo.class).sheet().doReadSync();
              System.out.println("總數 = " + userInfoList.size());
              Map<String, List<XingQiuTableUserInfo>> listMap =
                      userInfoList.stream()
                              .filter(userInfo -> StringUtils.isNotEmpty(userInfo.getUsername()))
                              .collect(Collectors.groupingBy(XingQiuTableUserInfo::getUsername));
              for (Map.Entry<String, List<XingQiuTableUserInfo>> stringListEntry : listMap.entrySet()) {
                  if (stringListEntry.getValue().size() > 1) {
                      System.out.println("username = " + stringListEntry.getKey());
                      System.out.println("1");
                  }
              }
              System.out.println("不重復昵稱數 = " + listMap.keySet().size());
          }
      }
      
      

      關于 Easy Excel 的寫入到 Excel 的操作,大家可以參考官方文檔:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write

      前端頁面跳轉傳值

      1. query => url serachParams ,url 后附加參數,傳遞的值長度有限。
      2. vuex(全局狀態管理),eg:搜索頁將關鍵詞塞到狀態中,搜索結果頁從狀態取值。

      banner.txt 廣告位

      只需要在 resource根目錄下創建一個: banner.txt 文件即可

      文件當中輸入/填寫你所想要讓你的項目啟動的時候的一些提示信息即可。

      這樣其他人沿用了你的項目,啟動該項目的時候,則會看到你的這個廣告信息。

      用戶中心——> RainbowSea CSDN 博客地址: rainbowsea.blog.csdn.net
      

      后端接受前端值時出現的問題:

      問題:我們需要將前端的傳值的格式修改一下,修改為一個可以被后端識別為一個字符串的值。

      **這里使用 **axios-js**的一個前端庫,進行解決 **

      axios-js 官網地址:https://www.axios-http.cn/docs/intro

      yarn add axios
      

      @CrossOrigin 后端跨域,允許任何請求都同意

      一般都是后端處理跨域問題的,更加靈活。后端統一防守。只能防前端,不能防止后端

      @CrossOrigin(origins="localhost:8080")
      

      改造用戶中心,把單機登錄改為分布式 Session 登錄

      還有一種方式就是:使用 Tociket 。但是 Tociket 過期時間不是那么容易簡單控制的(需要額外配置,但是更加靈活)

      Session 共享

      種 Session 的時候注意范圍:cookie.domain

      比如兩個域名:

      • aaa.yupi.com
      • bbb.yupi.com

      如果要共享 cookie,可以種一個更高層的公共域名,比如:yupi.com 。

      為什么服務器 A 登錄后,請求發送到服務器 B,不認識該用戶?

      思考:為什么服務器 A 登錄后,請求發到服務器 B,不認識該用戶?

      原因如下:

      1. 用戶在 A 登錄,所以 Session(用戶登錄信息)存在了 A 上
      2. 結果請求 B 時,B 沒有用戶信息,所以不認識

      如圖:

      解決方案:共享存儲,而不是把數據放到單臺服務器的內存中。

      Redis 基于內存的 K/V 數據庫 ,此處選擇 Redis,因為用戶信息讀取?(是否登錄的判斷極其頻繁),Redis 基于內存,讀寫性能很高,簡單的數據單機 qps 5w-10w

      通過將打包的項目,使用java -jar .\yupao-backend-0.0.1-SNAPSHOT.jar --server.port=8081定義 8081 作為該項目的新的端口,從而啟動一個新的項目上的作為一個新的服務器啟動一個項目——》到達分布式服務器的一種方式。

      E:\Java\project\魚皮星球項目\伙伴匹配系統\yupao\yupao-backend\target>java -jar .\yupao-backend-0.0.1-SNAPSHOT.jar --server.port=8081
      

      Redis Windows 安裝

      1. 安裝 Windows 版本的 Redis

      在 application.yaml 文件配置 Redis 的相關配置:

      spring:
        # Redis 配置
        redis:
          port: 6379
          host: localhost
          database: 0
      

      1. 引入 redis. 能夠操作 redis:盡量和你的 Spring Boot 的版本一一對應上。
      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
          <version>2.6.4</version>
      </dependency>
      
      

      1. 引入 spring-session 和 Redis 的整合,使得自動將 session 存儲到 Redis 當中。同樣:盡量和你的 Spring Boot 的版本一一對應上。
      <!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
      <dependency>
          <groupId>org.springframework.session</groupId>
          <artifactId>spring-session-data-redis</artifactId>
          <version>2.6.4</version>
      </dependency>
      

      1. 修改 spring-session 存儲配置,默認是在 spring.session.store-type默認是 none ,表示存儲在單臺服務器。
      • store-type:redis 表示從 redis 讀寫兩個都從 Redis 來 session 。

      spring:
        session:
          timeout: 86400
          store-type: redis
      

      server:
        port: 8080
        servlet:
          context-path: /api
      spring:
        profiles:
          active: dev
        application:
          name: yupao-backend
        mvc:
          pathmatch:
            matching-strategy: ant_path_matcher
        # DataSource Config
        datasource:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/usercenter
          username: root
          password: MySQL123
          # session 失效時間
        session:
          timeout: 86400
          store-type: redis
        # Redis 配置
        redis:
          port: 6379
          host: localhost
          database: 0
      mybatis-plus:
        global-config:
          db-config:
            logic-delete-field: isDelete # 全局邏輯刪除字段名,所以項目表當中所有邏輯刪除,都用這個字段名,保證全局性
            logic-delete-value: 1 # 邏輯已刪除值(默認值為 1)
            logic-not-delete-value: 0 # 邏輯未刪除值(默認值為 0)
        configuration:
          # 取消數據庫駝峰映射
          map-underscore-to-camel-case: false
          log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      
      
      

      重新啟動兩個項目,模擬分布式,測試

      最后:

      “在這個最后的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回復是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮斗。感謝你們,我們總會在某個時刻再次相遇。”

      在這里插入圖片描述

      posted @ 2025-07-30 11:52  Rainbow-Sea  閱讀(74)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲欧美电影在线一区二区| 国产天美传媒性色av高清| 日韩精品一区二区在线视| 国产成人午夜福利高清在线观看| 东光县| 久久精品无码一区二区三区| 久热伊人精品国产中文| 国产精品国产高清国产av| 亚洲国产一区二区三区亚瑟| 在线观看成人av天堂不卡| 国产av国片精品一区二区| 久久久综合香蕉尹人综合网| 狠狠躁夜夜躁人人爽蜜桃| 亚洲老妇女亚洲老熟女久| 国内精品人妻一区二区三区| 国产精品户外野外| 久久天堂无码av网站| 国99久9在线 | 免费| 久久精品夜夜夜夜夜久久| 精品久久亚洲中文无码| 亚洲最大日韩精品一区| 少妇无码一区二区三区免费| 欧美精品一区二区三区中文字幕| 亚洲成av人片在线观看www| 亚洲成年av天堂动漫网站| 久久亚洲精品情侣| 少妇av一区二区三区无码| 亚洲成av人片无码迅雷下载| 亚洲av成人一区二区三区| 国产一区精品在线免费看| 人人做人人爽人人爱| 久久96热人妻偷产精品| 亚洲欧美日韩成人一区| 中文字幕在线国产精品| 国产亚洲精品第一综合麻豆| 最新av中文字幕无码专区| 色综合久久天天综线观看| 一区二区三区AV波多野结衣| 亚洲熟女乱色综合一区| 精品一卡2卡三卡4卡乱码精品视频| 综合区一区二区三区狠狠|