润滑油东莞网站建设技术支持,国际外贸网站推广,江苏网站建设市场,论坛网站策划日志
Java 主流日志工具库
统一接口
什么是 REST#xff1f;
Representational State Transfer——“表现层状态转化”。可以总结为一句话#xff1a;REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征#xff0c;对于同一个资源的一组不…日志
Java 主流日志工具库
统一接口
什么是 REST
Representational State Transfer——“表现层状态转化”。可以总结为一句话REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念资源是以名词为核心来组织的首先关注的是名词。REST 要求必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。
什么是 RESTful API
符合 REST 设计标准的 API即 RESTful API。REST 架构设计遵循的各项标准和准则就是 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 ListResponseStatus 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 RT {/*** 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 RT success() {return success(null);}/*** response success result wrapper.** param data response data* param T type of data class* return response result*/public static T RT success(T data) {return R.Tbuilder().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 RT 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 RT fail(T data, String message) {return R.Tbuilder().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 RHashMap list(PathVariable(id) Long id) {// service.list(id)HashMapObject, 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 ResponseEntityString add(Valid RequestBody TestParam testParam, BindingResult bindingResult) {if (bindingResult.hasErrors()) {ListObjectError 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);}测试
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 ResponseEntityTestValidationGroupParam add(Validated(AddValidationGroup.class) RequestBody TestValidationGroupParam param) {return ResponseEntity.ok(param);}PostMapping(testValidationGroup/edit)public ResponseEntityTestValidationGroupParam 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是一项标准,只提供规范不提供实现规定一些校验规范即校验注解如NullNotNullPattern位于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 ConstraintValidatorTelephoneNumber, 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();MapString, 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());}}测试