• 开发前期准备工作


    开发前期准备工作

    0 代码规范

    0.1 强制

    避免在子父类的成员变量之间、或者不同代码块的局部变量之间采用完全相同的命名,使可理解性降低。

    0.2 推荐

    好的命名、代码结构是自解释的,注释力求精简准确、表达到位

    0.3 参考

    dao:跟数据库打交道

    [增加]

    insert:插入

    batchInsert批量插入

    insertSelective:条件插入

    insertUseGeneratedKeys

    [删除]

    delete:删除

    delete*ById:根据主键删除

    [修改]

    update:更新

    update*ById:根据主键更新

    [查询]

    service:业务层,人类思维解决

    add:添加

    find*ById:根据主键查询

    find*By**:根据条件查询

    find*ByList:多条件查询

    modify:修改

    modify*ById:根据主键修改

    remove:删除

    remove*ById:根据主键删除

    controller:抽象化

    insert:插入

    batchInsert:批量插入

    queryOne:查询单个

    queryById:根据主键查询

    queryByList:多条件查询

    count:计数

    update:更新

    update*ById:根据主键更新

    delete:删除

    delete*ById:根据主键删除

    0.4 注释规范

    1 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐

    2 所有的类都必须添加创建者和创建日期,而日期的设置统一为 yyyy/MM/dd 的格式

    /**
     * @author pingmingbo
     * @date 2022/11/11
     */
    
    • 1
    • 2
    • 3
    • 4

    3 代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改

    4 好的命名、代码结构是自解释的,注释力求精简准确、表达到位

    5 特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描,经常清理此类标记

    // TODO pingmingbo 20221112 20221211
    
    • 1

    0.5 日志规范

    1【强制】在日志输出时,字符串变量之间的拼接使用占位符的方式。

    说明:因为 String 字符串的拼接会使用 StringBuilderappend()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。

    正例:logger.debug("Processing trade with id: {} and symbol: {}", id, symbol);

    2 敏感信息不能记录在日志里面,比如用户名和密码

    3 日志打印禁止直接使用JSON工具将对象转换String

    4 使用warn级别日志记录用户输入参数错误情况,避免用户投诉时候,无所适从;注意日志输出级别,

    error级别只记录系统逻辑错误、异常等重要错误信息,如非必要,请不要在此场景打出error级别日志

    5 日志输出时候,字符串之间的拼接使用占位符方式

    logger.info("traceId:[{}],and symbol:[{}]",id,symbol);
    说明:因为String字符串的拼接会使用StringBuilder的append方式,有一定的性能损耗,使用占位符只是替换动作,可以有效提升性能
    
    • 1
    • 2

    6 如果循环体次数过多,避免打印不必要的日志

    7 打印日志的时机

    • 当遇到问题,只能通过debug定位
    • 碰到if else或者 Switch分支语句,需要在各自分支首行打印日志,确定进入哪个分支
    • 经常以功能为核心进行开发,提交代码之前,可以确定通过日志看到整个流程

    8 日志占位符基本格式,通过[]进行参数变量隔离

    logger.info("traceId:[{}],and symbol:[{}]",id,symbol);
    
    • 1

    9 线上禁止使用System.out,System.err

    10 谨慎使用e.printStackTrace(),否则出现锁死,服务挂掉问题

    短时间大量请求访问该接口,代码异常,进入catch,打印e.printStackTrace()异常信息到控制台,

    这些错误堆栈字符串存储字符串缓存池内存空间,该内存空间一下子撑爆了,其他线程进行相互等待,

    堆积一定程度,整个应用就挂掉了。

    11 异常日志打印规范

    logger.error("异常信息 ",e);

       /**
         * 处理异常几种方式
         */
        @Test
        public void testHandleCatch() {
            int num = 0;
            try {
                num = 3 / 0;
                logger.info("num : [{}]", num);
            } catch (Exception e) {
                logger.error("异常信息 ",e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    image-20221215230914727

    0.6 专有名词

    DO:数据库表对应的pojo实体类,字段一一对应,通过DAO向上传输

    DTO:数据传输对象,service或者manager向外传输

    BO:业务对象,service

    Query:数据查询对象,各层接收上层查询请求,注意超过两个参数进行封装,禁止使用map传递

    VO:通常是web层向模板引擎传输对象

    0.7 控制层

    统一异常
    package com.geekmice.springbootselfexercise.exception;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise.exception
     * @Author: pingmingbo
     * @CreateTime: 2023-08-10  23:07
     * @Description: 自定义异常
     * @Version: 1.0
     */
    public class BusinessException extends RuntimeException {
        private String message;
    
        public BusinessException(String message) {
            super(message);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package com.geekmice.springbootselfexercise.exception;
    
    import com.geekmice.springbootselfexercise.utils.AjaxResult;
    import org.apache.commons.collections4.CollectionUtils;
    import org.springframework.validation.BindException;
    import org.springframework.validation.ObjectError;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.ConstraintViolationException;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise
     * @Author: pingmingbo
     * @CreateTime: 2023-08-10  22:34
     * @Description: 统一异常处理
     * @Version: 1.0
     */
    @RestControllerAdvice(annotations = {Validated.class})
    public class CommonExceptionHandler {
        /**
         * 用于捕获@RequestBody类型参数触发校验规则抛出的异常
         *
         * @param e
         * @return
         */
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public AjaxResult handleValidException(MethodArgumentNotValidException e) {
            StringBuilder sb = new StringBuilder();
            List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
            if (!CollectionUtils.isEmpty(allErrors)) {
                for (ObjectError error : allErrors) {
                    sb.append(error.getDefaultMessage()).append(";");
                }
            }
            return AjaxResult.error(sb.toString());
        }
    
        /**
         * 用于捕获@RequestParam/@PathVariable参数触发校验规则抛出的异常
         *
         * @param e
         * @return
         */
        @ExceptionHandler(value = ConstraintViolationException.class)
        public AjaxResult handleConstraintViolationException(ConstraintViolationException e) {
            StringBuilder sb = new StringBuilder();
            Set<ConstraintViolation<?>> conSet = e.getConstraintViolations();
            for (ConstraintViolation<?> con : conSet) {
                String message = con.getMessage();
                sb.append(message).append(";");
            }
            return AjaxResult.error(sb.toString());
        }
    
        @ExceptionHandler(value = BindException.class)
        public AjaxResult handleConstraintViolationException(BindException e) {
            StringBuilder sb = new StringBuilder();
            List<ObjectError> allErrors = e.getAllErrors();
            for (ObjectError allError : allErrors) {
                String defaultMessage = allError.getDefaultMessage();
                sb.append(defaultMessage).append(";");
            }
            return AjaxResult.error(sb.toString());
        }
    
        @ExceptionHandler(value = Exception.class)
        public AjaxResult exception(Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    
        /**
         * 自定义业务异常
         *
         * @param e
         * @return
         */
        @ExceptionHandler(value = BusinessException.class)
        public AjaxResult exception(BusinessException e) {
            return AjaxResult.error(e.getMessage());
        }
    }
    
    • 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
    统一结构体
    package com.geekmice.springbootselfexercise.utils;
    
    /**
     * @BelongsProject: spring-boot-scaffold
     * @BelongsPackage: com.geekmice.sbparamsvalidated.util
     * @Author: pingmingbo
     * @CreateTime: 2023-04-19  11:34
     * @Description: 自定义统一返回结果
     * @Version: 1.0
     */
    
    
    import org.apache.commons.lang3.ObjectUtils;
    import org.springframework.http.HttpStatus;
    
    import java.util.HashMap;
    
    /**
     * 操作消息提醒
     *
     * @author ruoyi
     */
    public class AjaxResult extends HashMap<String, Object> {
        private static final long serialVersionUID = 1L;
    
        /**
         * 状态码
         */
        public static final String CODE_TAG = "code";
    
        /**
         * 返回内容
         */
        public static final String MSG_TAG = "msg";
    
        /**
         * 数据对象
         */
        public static final String DATA_TAG = "data";
    
        /**
         * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
         */
        public AjaxResult() {
        }
    
        /**
         * 初始化一个新创建的 AjaxResult 对象
         *
         * @param code 状态码
         * @param msg  返回内容
         */
        public AjaxResult(int code, String msg) {
            super.put(CODE_TAG, code);
            super.put(MSG_TAG, msg);
        }
    
        /**
         * 初始化一个新创建的 AjaxResult 对象
         *
         * @param code 状态码
         * @param msg  返回内容
         * @param data 数据对象
         */
        public AjaxResult(int code, String msg, Object data) {
            super.put(CODE_TAG, code);
            super.put(MSG_TAG, msg);
            if (ObjectUtils.isNotEmpty(data)) {
                super.put(DATA_TAG, data);
            }
        }
    
        /**
         * 返回成功消息
         *
         * @return 成功消息
         */
        public static AjaxResult success() {
            return AjaxResult.success("操作成功");
        }
    
        /**
         * 返回成功数据
         *
         * @return 成功消息
         */
        public static AjaxResult success(Object data) {
            return AjaxResult.success("操作成功", data);
        }
    
        /**
         * 返回成功消息
         *
         * @param msg 返回内容
         * @return 成功消息
         */
        public static AjaxResult success(String msg) {
            return AjaxResult.success(msg, null);
        }
    
        /**
         * 返回成功消息
         *
         * @param msg  返回内容
         * @param data 数据对象
         * @return 成功消息
         */
        public static AjaxResult success(String msg, Object data) {
            return new AjaxResult(HttpStatus.OK.value(), msg, data);
        }
    
        /**
         * 返回错误消息
         *
         * @return
         */
        public static AjaxResult error() {
            return AjaxResult.error("操作失败");
        }
    
        /**
         * 返回错误消息
         *
         * @param msg 返回内容
         * @return 警告消息
         */
        public static AjaxResult error(String msg) {
            return AjaxResult.error(msg, null);
        }
    
        /**
         * 返回错误消息
         *
         * @param msg  返回内容
         * @param data 数据对象
         * @return 警告消息
         */
        public static AjaxResult error(String msg, Object data) {
            return new AjaxResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data);
        }
    
        /**
         * 返回错误消息
         *
         * @param code 状态码
         * @param msg  返回内容
         * @return 警告消息
         */
        public static AjaxResult error(int code, String msg) {
            return new AjaxResult(code, msg, null);
        }
    
        /**
         * 方便链式调用
         *
         * @param key   键
         * @param value 值
         * @return 数据对象
         */
        @Override
        public AjaxResult put(String key, Object value) {
            super.put(key, value);
            return this;
        }
    }
    
    
    • 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
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    控制层
    package com.geekmice.springbootselfexercise.controller;
    
    import com.geekmice.springbootselfexercise.annotation.MethodExporter;
    import com.geekmice.springbootselfexercise.utils.AjaxResult;
    import com.geekmice.springbootselfexercise.vo.ParamVO;
    import com.geekmice.springbootselfexercise.vo.UserVO;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.Valid;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise.controller
     * @Author: pingmingbo
     * @CreateTime: 2023-08-10  22:29
     * @Description: TODO
     * @Version: 1.0
     */
    @RestController
    @RequestMapping(value = "param")
    @Slf4j
    @Validated
    public class ParamController {
    
        @GetMapping(value = "getMethod")
        public AjaxResult getMethod(@Valid ParamVO paramVO) {
            return AjaxResult.success();
        }
    
        @PostMapping(value = "postMethod")
        public AjaxResult postMethod(@Valid @RequestBody ParamVO paramVO) {
            return AjaxResult.success();
        }
    }
    
    • 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
    package com.geekmice.springbootselfexercise.vo;
    
    import lombok.Data;
    
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    import java.util.Date;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise.vo
     * @Author: pingmingbo
     * @CreateTime: 2023-08-10  22:28
     * @Description: 入参VO
     * @Version: 1.0
     */
    @Data
    public class ParamVO {
        /**
         * 用户名
         */
        @NotBlank(message = "用户名不能为空")
        private String userName;
        /**
         * 生日
         */
        @NotNull(message = "生日不为空")
        private Date birthday;
        /**
         * 性别
         */
        @NotBlank(message = "性别不为空")
        private String sex;
        /**
         * 地址
         */
        private String address;
    
        /**
         * 分数
         */
        private Integer score;
    
    }
    
    • 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
    提示信息

    {
    “msg”: “生日不为空;性别不为空;用户名不能为空;”,
    “code”: 500
    }

    0.8 控制语句

    1 在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default语句并且放在最后,即使它什么代码也没有。

    说明:注意 break 是退出 switch 语句块,而 return 是退出方法体。

    switch(str){
        case str1:
            // 业务代码
            break;
        case str2:
            // 业务代码
            break
        default:
            break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2 三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,可能抛出因自动拆箱导致的 NPE 异常

    说明:以下两种场景会触发类型对齐的拆箱操作:

    1) 表达式 1 或表达式 2 的值只要有一个是原始类型。

    2) 表达式 1 或表达式 2 的值的类型不一致,会强制拆箱升级成表示范围更大的那个类型

    
    
    • 1

    3 当某个方法的代码总行数超过 10 行时,return / throw 等中断逻辑的右大括号后均需要加一个空行。

    说明:这样做逻辑清晰,有利于代码阅读时重点关注。

    4 除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

    说明:很多 if 语句内的逻辑表达式相当复杂,与、或、取反混合运算,甚至各种方法纵深调用,理解成本非常高。如果赋值一个非常好理解的布尔变量名字,则是件令人爽心悦目的事情。

    5 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)

    6 避免采用取反逻辑运算符

    1 idea配置

    博客地址

    2 swagger配置,knife4j

    <dependency>
        <groupId>com.github.xiaoymingroupId>
        <artifactId>knife4j-spring-boot-starterartifactId>
        <version>2.0.7version>
    dependency>
    
    <dependency>
        <groupId>io.springfoxgroupId>
        <artifactId>springfox-boot-starterartifactId>
        <version>3.0.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    配置类

    package com.geekmice.springbootselfexercise.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    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;
    
    /**
     * @BelongsProject: spring-boot-scaffold
     * @BelongsPackage: com.geekmice.sbhelloworld.com.geekmice.sbpagehelper.config
     * @Author: pingmingbo
     * @CreateTime: 2023-07-30  15:45
     * @Description: TODO
     * @Version: 1.0
     */
    @Configuration
    public class Knife4jConfig {
        @Bean(value = "defaultApi2")
        public Docket customDocket() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.geekmice.springbootselfexercise.controller"))
                    .build();
        }
    
        /**
         * 构建 api文档的详细信息函数
         * @return
         */
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("现货交易")
                    .version("1.0.0")
                    .description("现货交易详情")
                    .contact(new Contact("geekmice","http://geekmice.cn","2437690868@qq.com"))
                    .build();
        }
    }
    
    • 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

    控制层

    package com.geekmice.springbootselfexercise.controller;
    
    import com.geekmice.springbootselfexercise.injector.EasySqlInjector;
    import com.geekmice.springbootselfexercise.utils.AjaxResult;
    import com.geekmice.springbootselfexercise.utils.SpringUtil;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise.controller
     * @Author: pingmingbo
     * @CreateTime: 2023-08-09  21:52
     * @Description: bean操作
     * @Version: 1.0
     */
    @RestController
    @RequestMapping(value = "bean")
    @Api(tags = "3.获取bean操作")
    @Slf4j
    public class BeanController {
    
        @GetMapping(value = "getBean")
        @ApiOperation(value = "获取bean")
        public AjaxResult getBean() {
            // 根据class获取bean
            EasySqlInjector bean = SpringUtil.getBean(EasySqlInjector.class);
    
            // 根据name获取bean
            EasySqlInjector easySqlInjector = (EasySqlInjector)SpringUtil.getBean("easySqlInjector");
    
            // 根据name和class获取bean
            EasySqlInjector easySqlInjectorSecond = SpringUtil.getBean("easySqlInjector", EasySqlInjector.class);
    
            log.info("easySqlInjectorSecond : [{}]" , easySqlInjectorSecond);
            log.info("easySqlInjector : [{}]", easySqlInjector);
            log.info("bean : [{}]", bean);
            return AjaxResult.success();
        }
    }
    
    • 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

    3 jrebel配置

    4 常用账号汇总

    git账号
    系统用户账号
    开发环境 MySQL
    
    • 1
    • 2
    • 3

    5 集成单元测试

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintagegroupId>
                <artifactId>junit-vintage-engineartifactId>
            exclusion>
        exclusions>
    dependency>
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
        <scope>testscope>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    与事务相关的测试类

    package com.geekmice.springbootselfexercise;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.geekmice.springbootselfexercise.config.DataSourceProperties;
    import com.geekmice.springbootselfexercise.dao.UserDao;
    import com.geekmice.springbootselfexercise.domain.UserDomain;
    import com.geekmice.springbootselfexercise.service.UserService;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections4.ListUtils;
    import org.apache.commons.lang3.RandomStringUtils;
    import org.apache.ibatis.session.ResultContext;
    import org.apache.ibatis.session.ResultHandler;
    import org.junit.jupiter.api.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.core.env.Environment;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import javax.annotation.Resource;
    import java.time.LocalDateTime;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    /**
     * @description 测试类,需要调用dao
     */
    @Slf4j
    @SpringBootTest(classes = SpringBootSelfExerciseApplication.class)
    @RunWith(SpringRunner.class)
    class DaoTest {
    
        private String port;
        private static String newPort;
    
        @Value("${server.port}")
        public void setPort(String port){
            newPort=port;
        }
    
        @Autowired
        private DataSourceProperties dataSourceProperties;
    
        @Autowired
        private Environment environment;
    
        @Resource
        private UserService userService;
    
        @Resource
        private UserDao userDao;
    
        @Test
        void contextLoads() {
            // log.info("端口号:【{}】",port);
            String username = dataSourceProperties.getUsername();
            String password = dataSourceProperties.getPassword();
            String url = dataSourceProperties.getUrl();
            String driverClassName = dataSourceProperties.getDriverClassName();
            log.info("用户名:【{}】",username);
            log.info("密码:【{}】",password);
            log.info("地址URL:【{}】",url);
            log.info("驱动类:【{}】",driverClassName);
        }
    
       
    }
    
    
    • 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

    与事务无关的测试类

    package com.geekmice.springbootselfexercise;
    
    import cn.hutool.extra.spring.SpringUtil;
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.geekmice.springbootselfexercise.domain.TempData;
    import com.geekmice.springbootselfexercise.domain.UserDomain;
    import com.geekmice.springbootselfexercise.utils.BigDecimalUtil;
    import com.geekmice.springbootselfexercise.utils.DateUtil;
    import com.geekmice.springbootselfexercise.utils.FileUtil;
    import com.google.common.collect.Lists;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections4.CollectionUtils;
    import org.apache.commons.collections4.ListUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.lang3.time.DateFormatUtils;
    import org.apache.commons.lang3.time.DateUtils;
    import org.junit.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.core.env.Environment;
    import org.springframework.util.Assert;
    
    import javax.annotation.PostConstruct;
    import java.math.BigDecimal;
    import java.sql.Timestamp;
    import java.text.ParseException;
    import java.time.LocalDateTime;
    import java.util.*;
    import java.util.stream.Collectors;
    
    /**
     * @BelongsProject: spring-boot-self-exercise
     * @BelongsPackage: com.geekmice.springbootselfexercise
     * @Author: pingmingbo
     * @CreateTime: 2023-08-06  09:27
     * @Description: 无事务
     * @Version: 1.0
     */
    @Slf4j
    @SpringBootTest
    public class NoDaoTest {
    
    
    
        /**
         * 解决map修改key问题
         */
        @Test
        public void testSetMapKey() {
            log.info("需求:k1变为k2,value不变");
            Map<String, Object> map = new HashMap<>();
            map.put("k1", "v1");
            log.info("修改前");
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                log.info("key:【{}】,value:【{}】", entry.getKey(), entry.getValue());
            }
            String pendingItem = map.get("k1").toString();
            map.remove("k1");
            map.put("k2", pendingItem);
            log.info("修改后");
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                log.info("key:【{}】,value:【{}】", entry.getKey(), entry.getValue());
            }
    
       }
    
    
    }
    
    • 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

    6 新建个人项目

    工具类,配置类,切面,过滤器,监听器,常量,统一异常,统一结构体,文件解析类,自定义注解,反射

    7 断言

    处理抛异常情况,简单场景可以使用

    逻辑复杂使用iflese,throw抛异常

    // 对象
    Assert.notNull(null, "对象不为空");
    Assert.isNull(new Object(), "对象为空");
    
    // 集合
    Assert.notEmpty((Map)null, "集合不为空");
    Assert.isTrue(CollectionUtils.isEmpty(testBuildData()), "集合必须空");
    
    // 字符串包含
    Assert.isTrue(StringUtils.contains("abc", "e"), "不能包含");
    Assert.isTrue(!StringUtils.contains("abc", "a"), "必须包含");
    
    // 表达式
    Assert.isTrue(1>2, "条件表达式为false");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    img

  • 相关阅读:
    深入理解右值引用与移动语义
    【阿里云】阿里云跨账号内网互通
    MySQL中对varchar类型的列进行统计分析
    思维模型 周期
    QT:debug日志—打不开头文件以及qDebug和Q_CLASSINFO的使用
    快速傅里叶变换及其实现
    如何进阶一名有竞争力的程序员?
    系统集成|第十一章(笔记)
    【算法】链表的基本操作和高频算法题
    算法 学习杂谈
  • 原文地址:https://blog.csdn.net/greek7777/article/details/132684156