当前位置: 首页 > news >正文

六、SpringBoot项目搭建

日志

Java 主流日志工具库

统一接口

什么是 REST?

Representational State Transfer——“表现层状态转化”。可以总结为一句话:REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征,对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST 要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。

什么是 RESTful API?

符合 REST 设计标准的 API,即 RESTful APIREST 架构设计,遵循的各项标准和准则,就是 HTTP 协议的表现,换句话说,HTTP 协议就是属于 REST 架构的设计模式。比如,无状态,请求-响应。

Restful相关文档

统一接口的目的

前后分离的模式进行开发,统一返回方便前端进行开发和封装,以及出现时给出响应编码和信息

状态码

@Getter
@AllArgsConstructor
public enum ResponseStatus {SUCCESS("200", "success"),FAIL("500", "failed"),HTTP_STATUS_200("200", "ok"),HTTP_STATUS_400("400", "request error"),HTTP_STATUS_401("401", "no authentication"),HTTP_STATUS_403("403", "no authorities"),HTTP_STATUS_500("500", "server error");public static final List<ResponseStatus> HTTP_STATUS_ALL = Collections.unmodifiableList(Arrays.asList(HTTP_STATUS_200, HTTP_STATUS_400, HTTP_STATUS_401, HTTP_STATUS_403, HTTP_STATUS_500));/*** response code*/private final String responseCode;/*** description.*/private final String description;}

结果封装

  • timestamp 接口返回时间
  • status 状态,
  • message 消息
  • data 数据
  • 考虑到数据的序列化(比如在网络上传输),这里data有时候还会extends Serializable
import lombok.Builder;
import lombok.Data;import java.io.Serializable;@Data
@Builder
public class R<T> {/*** response timestamp.*/private long timestamp;/*** response code, 200 -> OK.*/private String status;/*** response message.*/private String message;/*** response data.*/private T data;/*** response success result wrapper.** @param <T> type of data class* @return response result*/public static <T> R<T> success() {return success(null);}/*** response success result wrapper.** @param data response data* @param <T>  type of data class* @return response result*/public static <T> R<T> success(T data) {return R.<T>builder().data(data).message(ResponseStatus.SUCCESS.getDescription()).status(ResponseStatus.SUCCESS.getResponseCode()).timestamp(System.currentTimeMillis()).build();}/*** response error result wrapper.** @param message error message* @param <T>     type of data class* @return response result*/public static <T extends Serializable> R<T> fail(String message) {return fail(null, message);}/*** response error result wrapper.** @param data    response data* @param message error message* @param <T>     type of data class* @return response result*/public static <T> R<T> fail(T data, String message) {return R.<T>builder().data(data).message(message).status(ResponseStatus.FAIL.getResponseCode()).timestamp(System.currentTimeMillis()).build();}}

返回结果

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;@RestController
@RequestMapping("/test")
public class TestController {@PostMapping("list/{id}")public R<HashMap> list(@PathVariable("id") Long id) {//  service.list(id)HashMap<Object, Object> map = new HashMap<>();map.put("id", id);return R.success(map);}
}

参数校验

采用 spring validation 对参数绑定进行校验

参数类

import lombok.Builder;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;import javax.validation.constraints.*;
import java.io.Serializable;@Data
@Builder
public class TestParam implements Serializable {private static final long serialVersionUID = 1L;@NotEmpty(message = "could not be empty")private String userId;@NotEmpty(message = "could not be empty")@Email(message = "invalid email")private String email;@NotEmpty(message = "could not be empty")@Pattern(regexp = "^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$", message = "invalid ID")private String cardNo;@NotEmpty(message = "could not be empty")@Length(min = 1, max = 10, message = "nick name should be 1-10")private String nickName;@NotNull(message = "could not be empty")@Range(min = 0, max = 1, message = "sex should be 0-1")private int sex;@Max(value = 100, message = "Please input valid age")private int age;}

控制器

    @PostMapping("add")public ResponseEntity<String> add(@Valid @RequestBody TestParam testParam, BindingResult bindingResult) {if (bindingResult.hasErrors()) {List<ObjectError> errors = bindingResult.getAllErrors();errors.forEach(p -> {FieldError fieldError = (FieldError) p;log.error("Invalid Parameter : object - {},field - {},errorMessage - {}", fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());});return ResponseEntity.badRequest().body("invalid parameter");}return ResponseEntity.ok("success");}

测试
![**加粗样式**](https://img-blog.csdnimg.cn/deb7efda517244189de25a84e41551c4.png

2023-02-27 23:32:20.978 [http-nio-8080-exec-5] ERROR c.daihao.springbootdemo.controller.TestController - Invalid Parameter : object - testParam,field - cardNo,errorMessage - invalid ID

分组校验

有参数在添加时可以为空,在修改是不能为空,这时则可以使用分组校验

分组接口

public interface AddValidationGroup {
}
public interface EditValidationGroup {
}

参数字段添加分组

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.validation.constraints.NotEmpty;
import java.io.Serializable;@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TestValidationGroupParam implements Serializable {private static final long serialVersionUID = 1L;@NotEmpty(message = "{test.msg.userId.notEmpty}", groups = {EditValidationGroup.class}) private String userId;
}

@Validated注解分组校验

  @PostMapping("testValidationGroup/add")public ResponseEntity<TestValidationGroupParam> add(@Validated(AddValidationGroup.class) @RequestBody TestValidationGroupParam param) {return ResponseEntity.ok(param);}@PostMapping("testValidationGroup/edit")public ResponseEntity<TestValidationGroupParam> edit(@Validated(EditValidationGroup.class) @RequestBody TestValidationGroupParam param) {return ResponseEntity.ok(param);}

测试
在这里插入图片描述

@Validated和@Valid什么区别?

在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同

分组

  • @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

  • @Valid:作为标准JSR-303规范,还没有吸收分组的功能。

注解地方

@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上嵌套类型

常用注解

JSR303/JSR-349: JSR303是一项标准,只提供规范不提供实现,规定一些校验规范即校验注解,如@Null@NotNull@Pattern,位于javax.validation.constraints包下。JSR-349是其的升级版本,添加了一些新特性。

@AssertFalse            被注释的元素只能为false
@AssertTrue             被注释的元素只能为true
@DecimalMax             被注释的元素必须小于或等于{value}
@DecimalMin             被注释的元素必须大于或等于{value}
@Digits                 被注释的元素数字的值超出了允许范围(只允许在{integer}位整数和{fraction}位小数范围内)
@Email                  被注释的元素不是一个合法的电子邮件地址
@Future                 被注释的元素需要是一个将来的时间
@FutureOrPresent        被注释的元素需要是一个将来或现在的时间
@Max                    被注释的元素最大不能超过{value}
@Min                    被注释的元素最小不能小于{value}
@Negative               被注释的元素必须是负数
@NegativeOrZero         被注释的元素必须是负数或零
@NotBlank               被注释的元素不能为空
@NotEmpty               被注释的元素不能为空
@NotNull                被注释的元素不能为null
@Null                   被注释的元素必须为null
@Past                   被注释的元素需要是一个过去的时间
@PastOrPresent          被注释的元素需要是一个过去或现在的时间
@Pattern                被注释的元素需要匹配正则表达式"{regexp}"
@Positive               被注释的元素必须是正数
@PositiveOrZero         被注释的元素必须是正数或零
@Size                   被注释的元素个数必须在{min}{max}之间

自定义注解

自定义校验器

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;public class TelephoneNumberValidator implements ConstraintValidator<TelephoneNumber, String> {private static final String REGEX_TEL = "0\\d{2,3}[-]?\\d{7,8}|0\\d{2,3}\\s?\\d{7,8}|13[0-9]\\d{8}|15[1089]\\d{8}";@Overridepublic boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {try {return Pattern.matches(REGEX_TEL, s);} catch (Exception e) {return false;}}
}

自定义注解

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {TelephoneNumberValidator.class}) // 指定校验器
public @interface TelephoneNumber {String message() default "Invalid telephone number";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };
}

参数指定

import lombok.Builder;
import lombok.Data;import javax.validation.constraints.NotEmpty;
import java.io.Serializable;@Data
@Builder
public class TelephoneNumberParam implements Serializable {private static final long serialVersionUID = 1L;@NotEmpty(message = "{test.msg.userId.notEmpty}", groups = {EditValidationGroup.class})private String userId;@TelephoneNumber(message = "invalid telephone number")private String telephone;
}

统一异常

错误码枚举

/**** 错误码和错误信息定义类* 1. 错误码定义规则为5为数字* 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常* 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式* 错误码列表:*  10: 通用*      001:参数格式校验*/
public enum BizCodeEnum {UNKNOW_EXCEPTION("10000", "系统未知异常"), VAILD_EXCEPTION("10001", "参数格式校验失败");private String code;private String msg;BizCodeEnum(String code, String msg) {this.code = code;this.msg = msg;}public String getCode() {return code;}public String getMsg() {return msg;}
}

全局异常处理

/*** 集中处理所有异常*/
@Slf4j
@RestControllerAdvice(basePackages = "com.daihao.springbootdemo.controller")
public class ExceptionControllerAdvice {@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handleVaildException(MethodArgumentNotValidException e) {log.error("数据校验出现问题{},异常类型:{}", e.getMessage(), e.getClass());BindingResult bindingResult = e.getBindingResult();Map<String, String> errorMap = new HashMap<>();bindingResult.getFieldErrors().forEach((fieldError) -> {errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());});return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(), BizCodeEnum.VAILD_EXCEPTION.getMsg());}@ExceptionHandler(value = Throwable.class)public R handleException(Throwable throwable) {log.error("错误:", throwable);return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(), BizCodeEnum.UNKNOW_EXCEPTION.getMsg());}}

测试
在这里插入图片描述

相关文章:

六、SpringBoot项目搭建

日志 Java 主流日志工具库 统一接口 什么是 REST&#xff1f; Representational State Transfer——“表现层状态转化”。可以总结为一句话&#xff1a;REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征&#xff0c;对于同一个资源的一组不…...

【LeetCode】2363. 合并相似的物品

2363. 合并相似的物品 题目描述 给你两个二维整数数组 items1 和 items2 &#xff0c;表示两个物品集合。每个数组 items 有以下特质&#xff1a; items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 &#xff0c;weighti 表示第 i 件物品的 重量 。items 中每…...

华为OD机试题,用 Java 解【出租车计费】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果

论文题目&#xff1a;《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址&#xff1a;https://arxiv.org/pdf/2002.03662v3.pdf 代码地址&#xff1a;https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…...

如何管理好仓库/库房?

仓库管理是企业管理中不可缺少的一部分&#xff0c;事关企业能否正常运行的关键之一&#xff0c;古人有云&#xff1a;“三军未动粮草先行”&#xff0c;一个企业仓库管理做不好&#xff0c;他的生产管理肯定也是做不好的&#xff0c;不是说生产管理人员的管理能力不具备&#…...

Unity Lighting -- Unity的光源简介

在主菜单栏中&#xff0c;点击Window -> Rendering -> Light Explorer打开光源管理器&#xff0c;这个标签页可以看到场景中所有的光源&#xff0c;包括每个光源的类型&#xff0c;形状&#xff0c;模式&#xff0c;颜色&#xff0c;强度&#xff0c;阴影等信息。 在主菜…...

Android仿网易云音乐歌单详情页

效果图实现思路&#xff1a;1、Activity设置自定义Shared Element切换动画2、透明状态栏&#xff08;透明Toolbar,使背景图上移&#xff09;3、Toolbar底部增加和背景一样的高斯模糊图&#xff0c;并上移图片&#xff08;为了使背景图的底部作为Toolbar的背景&#xff09;4、上…...

linux基本功系列之free命令实战

文章目录前言一. free命令介绍二. 语法格式及常用选项三. 参考案例3.1 查看free相关的信息3.2 以MB的形式显示内存的使用情况3.3 以总和的形式显示内存的使用情况3.4 周期性的查询内存的使用情况3.5 以更人性化的形式来查看内存的结果输出总结前言 大家好&#xff0c;又见面了…...

华为OD机试模拟题 用 C++ 实现 - 连续子串(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明连续子串题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD …...

【软考——系统架构师】UML 建模与架构文档化

&#x1f50e;这里是【软考——系统架构师】&#xff0c;关注我考试轻松过线 &#x1f44d;如果对你有帮助&#xff0c;给博主一个免费的点赞以示鼓励 欢迎各位&#x1f50e;点赞&#x1f44d;评论收藏⭐️ 文章目录UML 基础UML 软件开发过程系统架构文档化送书福利UML 基础 U…...

Spring中常用注解

声明 bean 的注解 Component&#xff1a;泛指各种组件 Controller、Service、Repository 都可以称为Component Controller&#xff1a;控制层 Service&#xff1a;业务层 Repository&#xff1a;数据访问层Bean 的生命周期属性 Scope 设置类型包括&#xff1a;设置 Spring 容器…...

基于SpringCloud的可靠消息最终一致性06:轮询事务消息

上一节把可靠消息最终一致性的正常逻辑代码顺序执行了一次,并且对于同一个事务消息,在正常情况下它要被发送至少两次。 这是因为在发送消息之前,TransactionMessageService就已经把消息保存到了数据库中。而在首次消费完消息后,TransactionMessageListener并没有从数据库中…...

Python Flask + Echarts 轻松制作动态酷炫大屏( 附代码)

目录一、确定需求方案二、整体架构设计三、编码实现 &#xff08;关键代码&#xff09;四、完整代码五、运行效果1.动态实时更新数据效果图 说明: 其中 今日抓拍&#xff0c;抓拍总数&#xff0c;预警信息统计&#xff0c;监控点位统计图表 做了动态实时更新处理。 ​ 2.静态…...

Wepack(1):SourceMap讲解以及使用

今天我们来讲讲定位源码的工具 Sourcemap &#xff0c; 我们先讲最简单的配置&#xff0c;之后才补充 sourcemap 的其他属性 Sourcemap 作用 可以在打包的代码直接对应相应源码 例如 vue2 , vue3可以把对应的错误上传到相关服务器 使用 webpack.config.js const config …...

华为OD机试题,用 Java 解【最多等和不相交连续子序列】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

Kubernetes06:Controller

Kubernetes06:Controller 1、什么是controller 管理和运行容器的对象&#xff0c;是一个物理概念 在集群上管理和运行容器的对象 2、Pod和Controller之间的关系 Pod是通过controller来实现应用的运维 比如伸缩、滚动升级等等操作Pod和Controller之间通过 label 标签建立关系…...

采购文件中 RFI、RFQ、RFP、IFB的区别

【PMBOK的描述】   采购文件用于征求潜在卖方的建议书。如果主要依据价格来选择卖方&#xff08;如购买商业或标准产品时&#xff09;&#xff0c;通常就使用标书、投标或报价等术语。如果主要依据其他考虑&#xff08;如技术能力或技术方法&#xff09;来选择卖方&#xff0…...

linux升级gcc版本详细教程

0.前言一般linux操作系统默认的gcc版本都比较低&#xff0c;例如centos7系统默认的gcc版本为4.8.5。gcc是从4.7版本开始支持C11的&#xff0c;4.8版本对C11新特性的编译支持还不够完善&#xff0c;因此如果需要更好的体验C11以及以上版本的新特性&#xff0c;需要升级gcc到一个…...

NBA Top Shot 跌落神坛

近日&#xff0c;美国职业篮球联盟&#xff08;NBA&#xff09;授权的NFT 项目“NBA Top Shot Moments”被纽约法院初步裁定为“可能符合证券的定义”&#xff0c;虽然这不是对2021年用户指控该项目违法的最终判决&#xff0c;但这个裁定引发了市场担忧&#xff0c;部分NFT的地…...

状态管理Pinia使用详解(带你入门)

状态管理Pinia使用详解(带你从入门到入神) 序&#xff1a; ​ 如果你之前使用过 vuex 进行状态管理的话&#xff0c;那么 pinia 就是一个类似的插件。它是最新一代的轻量级状态管理插件。你可以通过defineStore来简单创建一个存储管理。 ​ 与 vuex 相比&#xff0c;pinia 提…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...