后端常用实现

数据库的逻辑删除

  • MybatisPlus

    • 数据表添加字段is_deleted

      1
      2
      -- 0: 代表该数据未被删除
      alter table [table_name] add column is_deleted tinyint default 0;
    • 实体类

      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
      package com.example.zhxy.entity.pojo;


      import com.baomidou.mybatisplus.annotation.TableField;
      import com.baomidou.mybatisplus.annotation.TableLogic;
      import com.fasterxml.jackson.annotation.JsonIgnore;
      import io.swagger.annotations.ApiModel;
      import io.swagger.annotations.ApiModelProperty;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;

      import java.util.ArrayList;
      import java.util.List;

      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class User {
      // 添加逻辑删除字段
      @TableLogic
      // 数据库字段映射
      @TableField(value = "is_deleted")
      private Integer deleted;
      }
    • 可以进行自定义值为删除的配置

      1
      2
      3
      4
      5
      6
      7
      # 一下内容已经为默认配置,可忽略
      mybatis-plus:
      global-config:
      db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
    • 底层sql 的执行语句

      1
      2
      -- 删除:
      update user set deleted=1 where id = 1 and deleted=0

日期自动填充

  • 数据库中日期字段的选择【只适用与MySQL

    1
    2
    3
    4
    -- datetime: 以'YYYY-MM-DD HH:MM:SS'的格式存储日期和时间
    alter table [table_name] add column create_time datetime default current_timestamp;
    -- current_timestamp: 这是设置新列的默认值为当前时间戳
    alter table [table_name] add column update_time datetime default current_timestamp;
    可以勾选更新字段使用自动获取时间戳
  • 实体类时期字段的数据类型选择【通用数据库实现】

    1. 使用@Tabfield 的填充

      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
      // java 层面的实现
      package com.example.zhxy.entity.pojo;


      import com.baomidou.mybatisplus.annotation.FieldFill;
      import com.baomidou.mybatisplus.annotation.TableField;
      import com.baomidou.mybatisplus.annotation.TableLogic;
      import com.fasterxml.jackson.annotation.JsonIgnore;
      import io.swagger.annotations.ApiModel;
      import io.swagger.annotations.ApiModelProperty;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;

      import java.time.LocalDateTime;
      import java.util.ArrayList;
      import java.util.List;

      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public class User {
      @TableField(fill = FieldFill.INSERT)
      private LocalDateTime createTime;
      @TableField(fill = FieldFill.INSERT_UPDATE)
      private LocalDateTime updateTime;

      }
    2. 实现元对象处理器接口MetaObjectHandler

      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
      // 此处需要灵活配置,只是存在优化的点

      package com.example.zhxy.mybatis.meta;

      import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
      import lombok.extern.slf4j.Slf4j;
      import org.apache.ibatis.reflection.MetaObject;
      import org.springframework.stereotype.Component;

      import java.time.LocalDateTime;

      @Slf4j
      @Component
      public class MyMetaObjectHandler implements MetaObjectHandler {
      @Override
      public void insertFill(MetaObject metaObject) {
      log.info("start insert fill ....");
      // 或者
      this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
      Object age = this.getFieldValByName("age", metaObject);
      // TODO: 优化
      // 1. 可以通过 metaObject.hasXxx 判断进行优化选择自动填充字段【如果是某一个表中的字段时,因为自动填充只要执行 Insert 语句就会执行,所以对字段筛选,如果某个实体类中没有该字段,则不执行自动填充】
      boolean hasAgeSetter = metaObject.hasSetter("age");
      if (hasAgeSetter) {
      // 有这个字段则执行自动填充
      this.strictInsertFill(metaObject, "age", Integer.class, 3); // 起始版本 3.3.3(推荐)
      }
      // 2.说明业务层未实现数据填充,则进行自动填充
      if (age == null) {
      this.strictInsertFill(metaObject, "age", Integer.class, 3); // 起始版本 3.3.3(推荐)
      }
      }

      @Override
      public void updateFill(MetaObject metaObject) {
      log.info("start update fill ....");
      // 或者
      this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
      }
      }

Mybatis-Plus分页

  • 创建配置类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.example.zhxy.config;

    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    /**
    * mybatis-plus 分页配置
    */
    @Configuration
    public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); // 指定数据库类型
    interceptor.addInnerInterceptor(paginationInterceptor);
    return interceptor;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 新版本
    @Configuration
    @MapperScan("scan.your.mapper.package")
    public class MybatisPlusConfig {

    /**
    * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
    */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
    return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
    }

前端解构

  • 数组结构

    1
    2
    3
    4
    5
    6
    7
    8
    <script>
    const arr = [1, 2, 3, 4];
    let [num1, num2, num3] = arr;
    console.log(num1)
    console.log(num2)
    console.log(num3)
    console.log(num4)
    </script>
  • 对象结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <script>
    const userInfo = {
    userName: "zs",
    friend: {
    name: 'lisi',
    age: 18
    }
    };
    let {userName, friend} = userInfo;
    console.log(userName)
    console.log(friend)
    </script>
  • 结构数据重命名

    1
    2
    3
    4
    // 将 data 重新命名为 res
    const {data:res} = {}
    // 获取 data 属性
    console.log(res.data)

前端统一数据模型

  • 响应

    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
    package com.example.zhxy.common;


    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;

    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;

    public class ResponseUtil {

    public static void out(HttpServletResponse response, ResultModel resultModel) {
    ObjectMapper objectMapper = new ObjectMapper();
    // 封装 response 的状态码和内容格式
    response.setStatus(HttpStatus.OK.value());
    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    // 内容:resultModel json
    try {
    // 使用jackson,把json格式的resultModel写入到response的输出流中
    objectMapper.writeValue(response.getOutputStream(), resultModel);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }
  • 统一数据类型

    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
    package com.example.zhxy.common;


    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;

    import java.io.Serializable;

    @Data
    public class ResultModel<T> implements Serializable {

    private int code; // 1000表示成功 401表示认证失败

    private String message;
    private T data;

    private static ResultModel resultModel = new ResultModel();

    public static ResultModel success(String message) {
    resultModel.setCode(1000);
    resultModel.setMessage(message);
    resultModel.setData(null);
    return resultModel;
    }

    public static ResultModel success(Object data) {
    resultModel.setCode(200);
    resultModel.setMessage("success");
    resultModel.setData(data);
    return resultModel;
    }

    public static ResultModel success(String message, Object data) {
    resultModel.setCode(200);
    resultModel.setMessage(message);
    resultModel.setData(data);
    return resultModel;
    }

    public static ResultModel success(Integer code, String message) {
    resultModel.setCode(200);
    resultModel.setMessage(message);
    return resultModel;
    }

    public static ResultModel success(Integer code, String message, Object data) {
    resultModel.setCode(code);
    resultModel.setMessage(message);
    resultModel.setData(data);
    return resultModel;
    }

    public static ResultModel error() {
    resultModel.setCode(500);
    resultModel.setMessage("error");
    resultModel.setData(null);
    return resultModel;
    }

    public static ResultModel error(String message) {
    resultModel.setCode(500);
    resultModel.setMessage(message);
    resultModel.setData(null);
    return resultModel;
    }

    public static ResultModel error(Integer code, String message, Object data) {
    resultModel.setCode(code);
    resultModel.setMessage(message);
    resultModel.setData(data);
    return resultModel;
    }

    public static ResultModel error(int code, String message) {
    resultModel.setCode(code);
    resultModel.setMessage(message);
    resultModel.setData(null);
    return resultModel;
    }
    }

Vscode关于@ 提示插件

  • Path Autocomplete

  • 配置

    1
    2
    3
    4
    5
    "path-autocomplete.extensionOnImport": true,
    // 配置 @ 路径提示
    "path-autocomplete.pathMappings": {
    "@": "${folder}/src"
    }