1、前后端分离开发

【1】介绍

前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责,这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。

前后端分离开发后,从工程结构上也会发生变化,即前后端代码不再混合在同一个maven工程中,而是分为前端工程后端工程

image-20230312210023485.png


【2】开发流程

前后端分离开发后,面临一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一个项目?

可以按照如下流程进行:

image-20230312211633336.png

接口(API接口)就是一个http的请求地址,主要就是去定义:请求路径、请求方式、请求参数、响应数据等内容。


【3】前端技术栈

开发工具

  • Visual Studio Code
  • hbuilder

技术框架

  • nodejs
  • VUE
  • ElementUI
  • mock
  • webpack

2、Yapi

【1】介绍

YApi是高效、易用、功能强大的api管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护API,YApi还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。

YApi让接口开发更简单高效,让接口的管理更具可读性、可维护性、让团队协作更合理。

源码地址:https://github.com/YMFE/yapi

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


【2】使用

省略。。。目前使用apifox


3、Swagger

【1】介绍

使用Swagger你只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。

官网:https://swagger.io/

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。

1
2
3
4
5
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>

【2】使用方式

操作步骤:

  1. 导入knife4j的maven坐标

    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.2</version>
    </dependency>
  2. 导入knife4j相关配置类(WebMvcConfig)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    package com.itheima.reggie.config;

    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
    import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
    import com.itheima.reggie.common.JacksonObjectMapper;
    import com.itheima.reggie.entity.Employee;
    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.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.math.BigInteger;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import java.util.List;

    import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

    @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/");
    }

    /**
    * 扩展mvc框架的消息转换器
    * @param converters
    */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    log.info("扩展消息转换器...");
    //创建消息转换器对象
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    //设置对象转换器,底层使用Jackson将Java对象转为json
    messageConverter.setObjectMapper(new JacksonObjectMapper());
    //将上面的消息转换器对象追加到mvc框架的转换器集合中
    converters.add(0, messageConverter);
    }

    @Bean
    public Docket createRestApi() {
    // 文档类型
    return new Docket(DocumentationType.SWAGGER_2)
    .apiInfo(apiInfo())
    .select() .apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller"))
    .paths(PathSelectors.any())
    .build();
    }

    private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    .title("瑞吉外卖")
    .version("1.0")
    .description("瑞吉外卖接口文档")
    .build();
    }
    }
  3. 设置静态资源,否则接口文档页面无法访问

    1
    2
    registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
  4. 在LoginCheckFilter中设置不需要处理的请求路径

    1
    2
    3
    4
    5
    6
    7
    String[] urls = new String[]{
    ...
    "/doc.html",
    "/webjars/**",
    "/swagger-resources",
    "/v2/api-docs"
    };

【3】常用注解
注解 说明
@Api 用在请求的类上,例如Controller,表示对类的说明
@ApiModel 用在类上,通常是实体类,表示一个返回响应数据的信息
@ApiModelProperty 用在属性上,描述响应类的属性
@ApiOperation 用在请求的方法上,说明方法的用途、作用
@ApiImplicitParams 用在请求的方法上,表示一组参数说明
@ApiImplicitParam 用在@ApiImplicitParams注解中,指定一个请求参数的各个方面

4、项目部署

【1】部署架构

image-20230313092443822.png


【2】部署环境说明
  • 192.168.138.100(服务器A)

    Nginx:部署前端项目、配置反向代理

    Mysql:主从复制结构中的主库

  • 192.168.138.101(服务器B)

    jdk:运行Java项目

    git:版本控制工具

    maven:项目构建工具

    jar:Spring Boot项目打包成jar包基于内置Tomcat运行

    Mysql:主从复制结构中的从库

  • 172.17.2.94(服务器C)

    Redis:缓存中间件

【3】部署前端项目

第一步:在服务器A中安装Nginx,将课程资料中的dist目录上传到Nginx的html目录下

image-20230313093439593.png


第二步:修改Nginx配置文件nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name localhost;

location / {
root html/dist;
index index.html;
}

location ^~ /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://192.168.138.101:8080;
}
}

【4】部署后端项目

第一步:在服务器B中安装jdk、git、maven、MySQL,使用git clone命令将git远程仓库的代码克隆下来。

image-20230313095336400.png