天天看點

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

P27-項目優化-前後端分離

  • 1.為什麼進行前後端分離
  • 2.前後端分離開發
    • 2.1介紹
    • 2.2開發流程
    • 2.3前端技術棧
      • 2.3.1開發工具
      • 2.3.2技術架構
  • 3.Yapi-用來定義接口
    • 3.1介紹
    • 3.2使用
      • 3.2.1添加項目
      • 3.2.2添加分類
      • 3.2.3添加接口
      • 3.2.4編輯接口
      • 3.2.5檢視接口
      • 3.2.6導出定義的接口
      • 3.2.7導入接口
  • 4.Swagger
    • 4.1介紹
    • 4.2使用方式
      • 4.2.1導入knife4j的maven坐标
      • 4.2.2導入knife4j相關配置類-WebMvcConfig
      • 4.2.3設定靜态資源,否則接口文檔頁面無法通路-WebMvcConfig
      • 4.2.4在LoginCheckFilter中設定不需要處理的請求路徑
    • 4.3常用注解
  • 5.項目部署
    • 5.1部署架構
    • 5.2部署環境
      • 5.2.1伺服器A- 192.168.138.100 [192.168.112.100(Linux)自己虛拟機端口]
      • 5.2.1伺服器B-192.168.138.101 [127.0.0.1(Windows) 自己ipv4位址]
      • 5.2.1伺服器C-172.17.2.94 [(Linux)]
    • 5.3部署前端項目
      • 5.3.1第一步:在伺服器A中安裝Nginx,将dist目錄上傳到Nginx的html目錄下
      • 5.3.2修改Nginx配置檔案nginx.conf
    • 5.4部署後端項目
      • 5.4.1第一步:在伺服器B中安裝jdk、git、 maven、MySQL,使用git clone指令将git遠端倉庫的代碼克隆下來
      • 5.4.2運作 springboot項目

1.為什麼進行前後端分離

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
  • 開發人員同時負責前端和後端代碼開發,分工不明确
  • 開發效率低
  • 前後端代碼混合在一個工程中,不便于管理
  • 對開發人員要求高,人員招聘困難

2.前後端分離開發

2.1介紹

前後端分離開發,就是在項目開發過程中,對于前端代碼的開發由專門的前端開發人員負責,後端代碼則由後端開發人員負責,這樣可以做到分工明确、各司其職,提高開發效率,前後端代碼并行開發,可以加快項目開發進度。目前,前後端分離開發方式已經被越來越多的公司所采用,成為目前項目開發的主流開發方式。

前後端分離開發後,從工程結構上也會發生變化,即前後端代碼不再混合在同一個maven工程中,而是分為前端工程和後端工程。

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

2.2開發流程

前後端分離開發後,面臨一一個問題,就是前端開發人員和後端開發人員如何進行配合來共同開發一一個項目?

可以按照如下流程進行:

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

接口(API接口)一個http的請求,主要就是去定義:

  • 請求路徑
  • 請求方式
  • 請求參數
  • 響應資料

等内容。

接口例子

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

2.3前端技術棧

2.3.1開發工具

  • Visual Studio Code
  • hbuilder .

2.3.2技術架構

  • nodejs
  • VUE
  • ElementUI
  • mock
  • webpack 前端打包工具

3.Yapi-用來定義接口

3.1介紹

YApi是高效、易用、功能強大的api管理平台,旨在為開發、産品、測試人員提供更優雅的接口管理服務。可以幫助.開發者輕松建立、釋出、維護API, YApi 還為使用者提供了優秀的互動體驗,開發人員隻需利用平台提供的接口資料寫入工具以及簡單的點選操作就可以實作接口的管理。

YApi讓接口開發更簡單高效,讓接口的管理更具可讀性、可維護性,讓團隊協作更合理。

要使用YApi,需要自己進行部署。

3.2使用

3.2.1添加項目

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.2添加分類

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.3添加接口

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.4編輯接口

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

請求參數設定

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

傳回參數設定

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.5檢視接口

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

接口設定好,在編輯裡面設定狀态為完成

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.6導出定義的接口

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

3.2.7導入接口

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

4.Swagger

4.1介紹

使用Swagger你隻需要按照它的規範去定義接口及接口相關的資訊,再通過Swagger衍生出來的一系列項目和工具,就可以做到生成各種格式的接口文檔,以及線上接口調試頁面等等。

knife4j是為Java MVC架構內建Swagger生成Api文檔的增強解決方案。

<dependency>
	<groupld>com.github.xiaoymin</ groupld>
	<artifactld>knife4j-spring-boot-starter</ artifactld>
	<version>3.0.2</version>
</dependency>
           

4.2使用方式

4.2.1導入knife4j的maven坐标

<dependency>
	<groupld>com.github.xiaoymin</ groupld>
	<artifactld>knife4j-spring-boot-starter</ artifactld>
	<version>3.0.2</version>
</dependency>
           

4.2.2導入knife4j相關配置類-WebMvcConfig

package com.jq.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.jq.commom.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

/**
 * 配置類,映射靜态資源
 */
@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    /**
     * 設定靜态資源映射
     * @param registry
     */
    @Override
    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/");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }

    /**
     * 擴充 Spring Mvc 的消息轉換器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("擴充消息轉換器...");
        //建立消息轉換器對象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //設定對象轉換器,底層使用Jackson将Java對象轉換為JSON
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息轉換器對象追加到spring MVC架構的轉換器集合中
        converters.add(0,messageConverter);
    }
    @Bean
    public Docket createRestApi() {
        // 文檔類型
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jq.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("瑞吉外賣")
                .version("1.0")
                .description("瑞吉外賣接口文檔")
                .build();
    }
}

           

4.2.3設定靜态資源,否則接口文檔頁面無法通路-WebMvcConfig

/**
     * 設定靜态資源映射
     * @param registry
     */
    @Override
    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/");
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }
           

4.2.4在LoginCheckFilter中設定不需要處理的請求路徑

package com.jq.filter;

import com.alibaba.fastjson.JSON;
import com.jq.commom.BaseContext;
import com.jq.commom.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定義過濾器
 * 檢查使用者是否已經完成登入
 */
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    //路徑比對器,支援通配符
    public static final AntPathMatcher PATH_MATCHER=new AntPathMatcher();
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request=(HttpServletRequest) servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;
        /**
         * 1、擷取本次請求的URI
         * 2、判斷本次請求是否需要處理
         * 3、如果不需要處理,則直接放行
         * 4、判斷登入狀态,如果已登入,則直接放行
         * 5、如果未登入則傳回未登入結果
         */
        //1、擷取本次請求的URI
        String requestURI =request.getRequestURI();// /backend/index.html
        log.info("攔截到請求:{}",requestURI);
        //定義不需要處理的請求路徑
        String []urls=new String[]{
                "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**",
                "/common/**",
                "/user/sendMsg",
                "/user/login",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources",
                "/v2/api-docs"
        };

        //2、判斷本次請求是否需要處理
        boolean check = check(urls, requestURI);
        //3、如果不需要處理,則直接放行
        if (check){
            log.info("本次請求{}不需要處理",requestURI);
            filterChain.doFilter(request,response);
            return;
        }
        //4-1、背景管理系統:判斷登入狀态,如果已登入,則直接放行
        if(request.getSession().getAttribute("employee")!=null){
            log.info("使用者已登入,使用者id為:{}",request.getSession().getAttribute("employee"));

            //擷取使用者id
            Long empId=(Long) request.getSession().getAttribute("employee");
            //調用BaseContext來設定目前使用者登入的id
            BaseContext.setCurrentId(empId);

            filterChain.doFilter(request,response);
            return;
        }
        //4-2、前端移動端使用者系統:判斷登入狀态,如果已登入,則直接放行
        if(request.getSession().getAttribute("user")!=null){
            log.info("使用者已登入,使用者id為:{}",request.getSession().getAttribute("user"));

            //擷取使用者id
            Long userId=(Long) request.getSession().getAttribute("user");
            //調用BaseContext來設定目前使用者登入的id
            BaseContext.setCurrentId(userId);

            filterChain.doFilter(request,response);
            return;
        }
        log.info("使用者未登入");
        //5、如果未登入則傳回未登入結果,通過輸出流的方式向用戶端頁面響應資料
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));

        return;


    }

    /**
     * 路徑比對,檢查本次請求是否需要放行
     * @param urls
     * @param requestURI
     * @return
     */
    public boolean check(String [] urls,String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match){
                return true;
            }
        }
        return false;
    }
}

           
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

4.3常用注解

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

加入注解後的swagger文檔

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

5.項目部署

5.1部署架構

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

5.2部署環境

伺服器:

5.2.1伺服器A- 192.168.138.100 [192.168.112.100(Linux)自己虛拟機端口]

  • Nginx:部署前端項目、配置反向代理
  • Mysql:主從複制結構中的主庫

5.2.1伺服器B-192.168.138.101 [127.0.0.1(Windows) 自己ipv4位址]

  • jdk:運作Java項目
  • git:版本控制工具
  • maven:項目建構工具
  • jar: Spring Boot項目打成jar包基于内置Tomcat運作
  • Mysql:主從複制結構中的從庫

5.2.1伺服器C-172.17.2.94 [(Linux)]

  • Redis:緩存中間件

5.3部署前端項目

5.3.1第一步:在伺服器A中安裝Nginx,将dist目錄上傳到Nginx的html目錄下

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

進入nginx目錄下的html目錄

cd /usr/local/nginx/html/

           

上傳dist目錄

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

5.3.2修改Nginx配置檔案nginx.conf

記得關閉防火牆,要不然外部浏覽器通路不到

#反向代理配置
location ^~ /api/ { 
	rewrite ^/api/(.*)$ /$1 break;  //url重寫
	proxy_pass http://192.168.138.101:8080;
	}

           

自己的配置檔案如下

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
  • 通路的 192.168.112.100
  • 反向代理的結果 :192.168.112.100/api/employee/login
  • 反向代理URL重寫 :/api/employee/login —》/employee/login
  • 後端正常通路是 192.168.137.1:8080/employee/login

5.4部署後端項目

5.4.1第一步:在伺服器B中安裝jdk、git、 maven、MySQL,使用git clone指令将git遠端倉庫的代碼克隆下來

瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署

5.4.2運作 springboot項目

  • Windows ,直接運作 springboot項目即可
  • Linux環境下,運作 springboot項目

    第二步:将reggiesStart.sh檔案.上傳到伺服器B,通過chmod指令設定執行權限.

    #!/bin/sh
    echo =================================
    echo  自動化部署腳本啟動
    echo =================================
    
    echo 停止原來運作中的工程
    APP_NAME=reggie_take_out
    
    tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
    if [ ${tpid} ]; then
        echo 'Stop Process...'
        kill -15 $tpid
    fi
    sleep 2
    tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
    if [ ${tpid} ]; then
        echo 'Kill Process!'
        kill -9 $tpid
    else
        echo 'Stop Success!'
    fi
    
    echo 準備從Git倉庫拉取最新代碼
    cd /usr/local/javaapp/reggie_take_out
    
    echo 開始從Git倉庫拉取最新代碼
    git pull
    echo 代碼拉取完成
    
    echo 開始打包
    output=`mvn clean package -Dmaven.test.skip=true`
    
    cd target
    
    echo 啟動項目
    nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &
    echo 項目啟動完成
    
    
               
    修改權限
    chmod 777 reggiesStart.sh
               
    瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
    Windows下運作springboot,修改圖檔的路徑
    瑞吉外賣項目學習筆記-P27-項目優化-前後端分離1.為什麼進行前後端分離2.前後端分離開發3.Yapi-用來定義接口4.Swagger5.項目部署
    如果是在Linux運作springboot,修改圖檔的路徑
    # 檔案上傳後儲存路徑
    rj:
      path: /usr/local/img/