开发规范

发布于 2023-03-06  1424 次阅读


开发规范

rest 风格

缩写:REST (不是"rest"这个单词)
外文名:Representational State Transfer,简称REST。
中文名:表现层状态转移。1

URL中只使用名词来定位资源,用HTTP协议里的动词(GET、POST、PUT、DELETE)来实现资源的增删改查操作。

image-20220803143532593

image-20220803144833210

Service CRUD 接口

说明:

  • 通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用前缀命名方式区分Mapper层避免混淆,

get 查询单行 select
remove 删除 delte
querypage 分页 selectpage

  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
  • 对象 Wrapper 为 条件构造器

Mapper CRUD 接口

说明:

  • 通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器

  • 泛型 T 为任意实体对象

  • 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键

  • 对象 Wrapper 为 条件构造器

springboottest

image-20230306202400872

maven与yml 多环境配置

yml 写法

5.2.1约定

  • k: v 表示键值对关系,冒号后面必须有一个空格

  • 使用空格的缩进表示层级关系,空格数目不重要,只要是左对齐的一列数据,都是同一个层级的

  • 大小写敏感

  • 缩进时不允许使用Tab键,只允许使用空格

  • java中对于驼峰命名法,可用原名或使用-代替驼峰,如java中的lastName属性,在yml中使用lastName或 last-name都可正确映射。

  • yml中注释前面要加#

5.2.2键值关系

普通值(字面量)

k: v:字面量直接写;

字符串默认不用加上单引号或者双绰号;

"": 双引号;转意字符能够起作用

​ name: "sangeng \n caotang":输出;sangeng 换行 caotang

'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

name1: sangeng 
name2: 'sangeng  \n caotang'
name3: "sangeng  \n caotang"
age: 15
flag: true
日期
date: 2019/01/01
对象(属性和值)、Map(键值对)

多行写法:

在下一行来写对象的属性和值的关系,注意缩进

student:
  name: zhangsan
  age: 20

行内写法:

student: {name: zhangsan,age: 20}
数组、list、set

用- 值表示数组中的一个元素

多行写法:

pets:
  - dog
  - pig
  - cat

行内写法:

pets: [dog,pig,cat]
对象数组、对象list、对象set
students:
 - name: zhangsan
   age: 22
 - name: lisi
   age: 20
 - {name: wangwu,age: 18}

5.2.3 占位符赋值

可以使用 ${key:defaultValue} 的方式来赋值,若key不存在,则会使用defaultValue来赋值。

例如

server:
  port: ${myPort:88}

myPort: 80   

5.2.4 @@

SpringBoot中读取maven设置值

spring:
    profiles:
        active: @profile.active@

​ 上面的@属性名@就是读取maven中配置的属性值的语法格式。

配置文件书写技巧

​ 作为程序员在搞配置的时候往往处于一种分久必合合久必分的局面。开始先写一起,后来为了方便维护就拆分。对于多环境开发也是如此,下面给大家说一下如何基于多环境开发做配置独立管理,务必掌握。

准备工作

​ 将所有的配置根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

  • application-devDB.yml
  • application-devRedis.yml
  • application-devMVC.yml

使用

​ 使用include属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔

spring:
    profiles:
        active: dev
        include: devDB,devRedis,devMVC

​ 比较一下,现在相当于加载dev配置时,再加载对应的3组配置,从结构上就很清晰,用了什么,对应的名称是什么

注意

​ 当主环境dev与其他环境有相同属性时,主环境属性生效;其他环境中有相同属性时,最后加载的环境属性生效

image-20220805105430397

改良

​ 但是上面的设置也有一个问题,比如我要切换dev环境为pro时,include也要修改。因为include属性只能使用一次,这就比较麻烦了。SpringBoot从2.4版开始使用group属性替代include属性,降低了配置书写量。简单说就是我先写好,你爱用哪个用哪个。

spring:
    profiles:
        active: dev
        group:
            "dev": devDB,devRedis,devMVC
            "pro": proDB,proRedis,proMVC
            "test": testDB,testRedis,testMVC

​ 现在再来看,如果切换dev到pro,只需要改一下是不是就结束了?完美!

总结

  1. 多环境开发使用group属性设置配置文件分组,便于线上维护管理

多环境开发控制

​ 多环境开发到这里基本上说完了,最后说一个冲突问题。就是maven和SpringBoot同时设置多环境的话怎么搞。

​ 要想处理这个冲突问题,你要先理清一个关系,究竟谁在多环境开发中其主导地位。也就是说如果现在都设置了多环境,谁的应该是保留下来的,另一个应该遵从相同的设置。

​ maven是做什么的?项目构建管理的,最终生成代码包的,SpringBoot是干什么的?简化开发的。简化,又不是其主导作用。最终还是要靠maven来管理整个工程,所以SpringBoot应该听maven的。整个确认后下面就好做了。大体思想如下:

  • 先在maven环境中设置用什么具体的环境
  • 在SpringBoot中读取maven设置的环境即可

maven中设置多环境(使用属性方式区分环境)

<profiles>
    <profile>
        <id>env_dev</id>
        <properties>
            <profile.active>dev</profile.active>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>     <!--默认启动环境-->
        </activation>
    </profile>
    <profile>
        <id>env_pro</id>
        <properties>
            <profile.active>pro</profile.active>
        </properties>
    </profile>
</profiles>

SpringBoot中读取maven设置值

spring:
    profiles:
        active: @profile.active@

​ 上面的@属性名@就是读取maven中配置的属性值的语法格式。

总结

  1. 当Maven与SpringBoot同时对多环境进行控制时,以Mavn为主,SpringBoot使用@..@占位符读取Maven对应的配置属性值
  2. 基于SpringBoot读取Maven配置属性的前提下,如果在Idea下测试工程时pom.xml每次更新需要手动compile方可生效

202208051104444.png

202208051105848.png

async

   @Override
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void getZip(List<CertificateVo> certificateVos, Long collegeId, String grade, Integer type, String fileUUID) throws Exception {
        List<String> filePaths = new ArrayList<>();
        for (CertificateVo certificateVo : certificateVos) {
            String certificateType = certificateVo.getCertificateType() == 1 ? "积分版" : "记录版";
            String pdfTitle = certificateVo.getUserName() + certificateVo.getNickName() + "(" + certificateType + ")" + ".pdf";
            String pdfPath = fileUploadPath + certificateVo.getCollegeName() + "/" + certificateVo.getGrade() + "/" + certificateType + "/" + certificateVo.getClassName() + "/" + certificateVo.getUserName() + "-" + certificateVo.getNickName() + "/" + pdfTitle;
            filePaths.add(pdfPath);
        }

transactional

image-20220803095031844

image-20220803095751517

hutool

UUID

httpstatus

qrcode

mybatisplus 使用 与 datascope

QueryWrapper

QueryWrapper<Certificate> qw = Wrappers.query();
qw.eq(bo.getCollegeId() != null, "scc.college_id", bo.getCollegeId());
qw.eq(bo.getCertificateType() != null, "scc.certificate_type", bo.getCertificateType());
qw.eq(bo.getGrade() != null, "scc.grade", bo.getGrade());
Map<String, Object> params = bo.getParams();
Object dataScope = params.get("dataScope");
qw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
   dataScope != null ? dataScope.toString() : null);

实现数据权限控制 以及分页条件查询

@Override
@DataScope(deptAlias = "sccj")
public TableDataInfo<CertificateJobVo> queryPageJobList(CertificateJobQueryBo bo) {
        QueryWrapper<CertificateJob> qw = Wrappers.query();
        qw.eq(bo.getCollegeId() != null, "sccj.college_id", bo.getCollegeId());
        qw.eq(bo.getZipType() != null, "sccj.certificate_type", bo.getZipType());
        qw.eq(bo.getGrade() != null, "sccj.grade", bo.getGrade());
        qw.eq(bo.getCreatorNickName() != null, "sccj.grade", bo.getCreatorNickName());
        Map<String, Object> params = bo.getParams();
        Object dataScope = params.get("dataScope");
        qw.apply(dataScope != null && StrUtil.isNotBlank(dataScope.toString()),
            dataScope != null ? dataScope.toString() : null);
        Page<CertificateJobVo> page = PageUtils.buildPage();
        List<CertificateJobVo> certificateJobVos =  certificateMapper.queryCertificateJobList(page, qw);
        page.setRecords(certificateJobVos);
        return PageUtils.buildDataInfo(page);
    }
List<CertificateJobVo> queryCertificateJobList(
    Page<CertificateJobVo> page, 
    @Param(Constants.WRAPPER) QueryWrapper<CertificateJob> qw);
<select id="queryCertificateJobList" resultType="com.ruoyi.secondClass.vo.CertificateJobVo">
    SELECT *
    FROM
    sc_certificate_job as sccj
    left join sys_dept as d on d.dept_id = sccj.dept_id
    <where>
        ${ew.sqlSegment}
    </where>
</select>

LambdaQueryWrapper

LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
User user = new User();
user.setName("Jone");
user.setAge(20);
//条件 函数式接口 值
queryWrapper.eq(StringUtils.isNotBlank(user.getName()),User::getName,user.getName());
queryWrapper.ge(user.getAge()!=null,User::getAge,user.getAge());

userMapper.selectList(queryWrapper).forEach(System.out::println);

git

image-20220802152704517

image-20220802160725021

git branch

git checkout

git remote -add 添加远程分支

git push -f master

git checkout -b 分支名
git push origin 分支名:分支名
git branch -a查看所有分支

image-20220802175026090

  • feat:提交新功能
  • fix:修复了bug
  • docs:只修改了文档
  • style:调整代码格式,未修改代码逻辑(比如修改空格、格式化、缺少分号等)
  • refactor:代码重构,既没修复bug也没有添加新功能
  • perf:性能优化,提高性能的代码更改
  • test:添加或修改代码测试
  • chore:对构建流程或辅助工具和依赖库(如文档生成等)的更改

image-20220802200810672

git rebase(变基) vs git merge(合并)

日志

debug info warn error

image-20220805113400848

image-20220805113454192

快捷键

快捷键 Shift+F6 重新命名 Ctrl+w 选中单词