如何建设一个自己+的网站首页,网站关键字怎么分割,关键词排名代发,学校网页设计说明开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao#xff1a;跟数据库打交道service#xff1a;业务层#xff0c;人类思维解决controller#xff1a;抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示…开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao跟数据库打交道service业务层人类思维解决controller抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示信息 0.8 控制语句 1 idea配置2 swagger配置knife4j3 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 202212110.5 日志规范
1【强制】在日志输出时字符串变量之间的拼接使用占位符的方式。
说明因为 String 字符串的拼接会使用 StringBuilder 的 append()方式有一定的性能损耗。使用占位符仅是替换动作可以有效提升性能。
正例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.outSystem.err
10 谨慎使用e.printStackTrace(),否则出现锁死服务挂掉问题 短时间大量请求访问该接口代码异常进入catch打印e.printStackTrace()异常信息到控制台 这些错误堆栈字符串存储字符串缓存池内存空间该内存空间一下子撑爆了其他线程进行相互等待 堆积一定程度整个应用就挂掉了。 11 异常日志打印规范
logger.error(异常信息 ,e); /*** 处理异常几种方式*/Testpublic void testHandleCatch() {int num 0;try {num 3 / 0;logger.info(num : [{}], num);} catch (Exception e) {logger.error(异常信息 ,e);}}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();ListObjectError 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();SetConstraintViolation? 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();ListObjectError 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 HashMapString, 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 数据对象*/Overridepublic 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:// 业务代码breakdefault: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
dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-spring-boot-starter/artifactIdversion2.0.7/version
/dependency
!--接口平台--
dependencygroupIdio.springfox/groupIdartifactIdspringfox-boot-starter/artifactIdversion3.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,2437690868qq.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获取beanEasySqlInjector bean SpringUtil.getBean(EasySqlInjector.class);// 根据name获取beanEasySqlInjector easySqlInjector (EasySqlInjector)SpringUtil.getBean(easySqlInjector);// 根据name和class获取beanEasySqlInjector 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账号
系统用户账号
开发环境 MySQL5 集成单元测试
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions
/dependency
dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/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){newPortport;}Autowiredprivate DataSourceProperties dataSourceProperties;Autowiredprivate Environment environment;Resourceprivate UserService userService;Resourceprivate UserDao userDao;Testvoid 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问题*/Testpublic void testSetMapKey() {log.info(需求k1变为k2,value不变);MapString, Object map new HashMap();map.put(k1, v1);log.info(修改前);for (Map.EntryString, 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.EntryString, 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(12, 条件表达式为false);