开发前期准备工作

news2024/12/22 19:32:13

开发前期准备工作

文章目录

  • 开发前期准备工作
    • 0 代码规范
      • 0.1 强制
      • 0.2 推荐
      • 0.3 参考
        • `dao`:跟数据库打交道
        • `service`:业务层,人类思维解决
        • `controller`:抽象化
      • 0.4 注释规范
      • 0.5 日志规范
      • 0.6 专有名词
      • 0.7 控制层
        • 统一异常
        • 统一结构体
        • 控制层
        • 提示信息
      • 0.8 控制语句
    • 1 `idea`配置
    • 2 `swagger`配置,`knife4j`
    • 3 `jrebel`配置
    • 4 常用账号汇总
    • 5 集成单元测试
    • 6 新建个人项目
    • 7 断言

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
 */

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

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

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

// TODO pingmingbo 20221112 20221211

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方式,有一定的性能损耗,使用占位符只是替换动作,可以有效提升性能

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

7 打印日志的时机

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

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

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

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);
        }
    }

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);
    }
}
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());
    }
}

统一结构体

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;
    }
}

控制层

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();
    }
}
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;

}

提示信息

{
“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;
}

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

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

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

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


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

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

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

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

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

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

1 idea配置

博客地址

2 swagger配置,knife4j

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>2.0.7</version>
</dependency>
<!--接口平台-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

配置类

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();
    }
}

控制层

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();
    }
}

3 jrebel配置

4 常用账号汇总

git账号
系统用户账号
开发环境 MySQL

5 集成单元测试

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

与事务相关的测试类

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);
    }

   
}

与事务无关的测试类

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());
        }

   }


}

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");

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/973114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年8月CSDN客服月报|解决个3重大问题和8个次要问题,处理个用户需求及建议

听用户心声&#xff0c;解用户之需。hello&#xff0c;大家好&#xff0c;这里是《CSDN客诉报告》第23期&#xff0c;接下来就请大家一同回顾我们8月份解决的bug&#xff5e; 一、重大问题 1、【主站】博客访问异常 反馈量&#xff1a;102 持续时间&#xff1a;7月31日15:4…

Xcode,swift:Error Domain=kCLErrorDomain Code=1 (null)问题解决

问题描述: iOS开发时,当使用用户的位置权限时,获取用户经纬度报错:Error DomainkCLErrorDomain Code1 "(null)",错误域kCLError域代码1“(null)” 解决方法: 打开模拟机的设置-通用-语言与地区 将地区设置为中国(如果你的开发位置在中国的话) 点击左上方Features,选择…

leetCode动态规划“不同路径II”

迷宫问题是比较经典的算法问题&#xff0c;一般可以用动态规划、回溯等方法进行解题&#xff0c;这道题目是我昨晚不同路径这道题趁热打铁继续做的&#xff0c;思路与原题差不多&#xff0c;只是有需要注意细节的地方&#xff0c;那么话不多说&#xff0c;直接上coding和解析&a…

[Linux]编写一个极简版的shell(版本1)

[Linux]编写一个极简版的shell-version1 文章目录 [Linux]编写一个极简版的shell-version1命令行提示符打印接收命令行参数将命令行参数进行解释执行用户命令完整代码 本文能够帮助Linux系统学习者通过代码的角度更好地理解命令行解释器的实现原理。 命令行提示符打印 Linux操…

将两个文件夹中重复的图象删除

将两个文件夹中重复的图象删除 需求分析解决方案 需求分析 文件夹one和two存在图象的重复&#xff0c;将two文件中中重复的文件夹删除 解决方案 # coding: utf-8 from PIL import Image, ImageDraw, ImageFont import os import shutil import cv2 as cv import numpy as np …

二分搜索树节点的插入(Java 实例代码)

目录 二分搜索树节点的插入 Java 实例代码 src/runoob/binary/BinarySearchTreeInsert.java 文件代码&#xff1a; 二分搜索树节点的插入 首先定义一个二分搜索树&#xff0c;Java 代码表示如下: public class BST<Key extends Comparable<Key>, Value> { …

第 3 章 栈和队列(链栈)

1. 背景说明 链栈是指用单链表实现的栈&#xff0c;其存储结构为链式存储&#xff0c;实现类似于队列的链式实现&#xff0c;不过在插入元素时链栈在头部插入&#xff0c;而 链式队列在尾部插入&#xff0c;本示例中实现为带头结点的链栈&#xff0c;即栈顶元素为栈指针的下一…

Qcon2023: 大模型时代的技术人成长(简)

我目前致力于操作系统相关的研发&#xff0c; 公司的目标是打造物联网时代的智能原生操作系统。如何实现操作系统的AI Native 呢&#xff1f;带着这样的疑问我参加了Qcon2023 北京站的大会。 与Qcon 2022 北京站不同的是&#xff0c; 身份变了&#xff0c; 上次是分享者&#x…

【校招VIP】前端JavaScript语言之跨域

考点介绍&#xff1a; 什么是跨域&#xff1f;浏览器从一个域名的网页去请求另一个域名的资源时&#xff0c;域名、端口、协议任一不同&#xff0c;都是跨域。跨域是前端校招的一个重要考点&#xff0c;在面试过程中经常遇到&#xff0c;需要着重掌握。本期分享的前端算法考点之…

电商API对接流程,简单讲解!

电商API接口对接流程一般包括以下几个步骤&#xff1a; 1. 确定需求&#xff1a;首先确定您的电商平台需要与哪些其他系统或服务进行对接&#xff0c;以及需要传递哪些数据。 2. 寻找合适的API&#xff1a;根据您的需求&#xff0c;在开放平台或者第三方API市场中选择适合的API…

文件上传漏洞学习小结

目录 一、漏洞简介 二、上传的原理或本质 2.1 文件上传的本质 2.2 文件上传的过程及代码演示 三、文件上传常见触发点 四、文件上传常见检测方式 4.1 前端js检测 4.2 content-type &#xff08;MIME&#xff09;检测 4.3 黑名单检测 4.4 文件头检测 4.5 .htaccess文件…

软件评测师之数的表示

目录 一、数的进制(1)十进制&#xff1a;D(2)二进制&#xff1a;B(3)十六进制&#xff1a;H(4)八进制&#xff1a;O/Q 二、其他进制转十进制(1)二进制转十进制(2)十六进制转十进制(3)八进制转十进制 三、二进制与十六进制/八进制进行转换四、考法 一、数的进制 (1)十进制&…

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证 用HFSS设计了一微波元件&#xff0c;仿真出了其散射参量S、阻抗参量Z及导纳参量Y&#xff0c;用MATLAB验证他们之间的关系 HFSS设计螺旋线圈 用HFSS设计了一个螺旋线圈&#xff0c;如上图所示。 进行仿真&…

无涯教程-JavaScript - DAYS360函数

描述 DAYS360函数返回基于360天的年份(十二个月为30天)的两个日期之间的天数,该天数用于会计计算。 语法 DAYS360 (start_date,end_date,[method])争论 Argument描述Required/OptionalStart_dateThe two dates between which you want to know the number of days.Required…

ElasticSearch第三讲:ES详解 - Elastic Stack生态和场景方案

ElasticSearch第三讲&#xff1a;ES详解 - Elastic Stack生态和场景方案 本文是ElasticSearch第三讲&#xff0c;在了解ElaticSearch之后&#xff0c;我们还要了解Elastic背后的生态 即我们常说的ELK&#xff1b;与此同时&#xff0c;还会给你展示ElasticSearch的案例场景&…

Django框架中使用drf框架开发

一、drf框架特点&#xff1a; 全称 Django REST framework 两大部分&#xff1a;序列化/反序列化 和 增删改查序列化&#xff1a;把数据库数据提取出来变成python常用格式的过程反序列化&#xff1a;把数据写入到数据库的过程增加 &#xff1a; 校验请求数据 -> 执行反…

OpenWrt编译自己的应用程序

编译OpenWrt的应用程序可以参考OpenWrt内部其他应用程序的例程&#xff0c;来编写成自己的应用程序 一、OpenWrt源代码获取与编译 1.1、搭建环境 下载OpenWrt的官方源码&#xff1a; git clone https://github.com/openwrt/openwrt.git1.2、安装编译依赖项 sudo apt update…

2023年Tik Tok在印尼的市场分析,怎么开通海外娱乐公会?

2023年 印尼的TIKTOK用户 字节跳动广告资源发布的数据显示&#xff0c;到2023年初&#xff0c;TikTok在印度尼西亚有1.099亿18岁及以上的用户。 字节跳动的数据显示&#xff0c;2023年初&#xff0c;抖音广告在印尼18岁及以上的成年人中占56.8%。 与此同时&#xff0c;今年年…

2022年09月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;道路 N个以 1 … N 标号的城市通过单向的道路相连:。每条道路包含两个参数&#xff1a;道路的长度和需要为该路付的通行费&#xff08;以金币的数目来表示&#xff09; Bob and Alice 过去住在城市 1.…

msvcr120.dll找不到是什么原因

今天&#xff0c;我将为大家分享关于电脑msvcr120.dll丢失的6种不同解决方法。希望这些方法能够帮助到正在面临这个问题的朋友们。 首先&#xff0c;让我们来了解一下msvcr120.dll是什么文件。msvcr120.dll是Microsoft Visual C 2012 Redistributable Package的一个组件&#x…