[*] 统一消息模型

This commit is contained in:
acgist
2022-11-11 07:59:36 +08:00
parent ad76cf7fc4
commit e668670da8
57 changed files with 1542 additions and 764 deletions

View File

@@ -51,6 +51,8 @@ import com.acgist.taoyao.boot.controller.TaoyaoControllerAdvice;
import com.acgist.taoyao.boot.controller.TaoyaoErrorController;
import com.acgist.taoyao.boot.interceptor.SecurityInterceptor;
import com.acgist.taoyao.boot.model.MessageCode;
import com.acgist.taoyao.boot.service.IdService;
import com.acgist.taoyao.boot.service.impl.IdServiceImpl;
import com.acgist.taoyao.boot.utils.ErrorUtils;
import com.acgist.taoyao.boot.utils.FileUtils;
import com.acgist.taoyao.boot.utils.JSONUtils;
@@ -80,6 +82,12 @@ public class BootAutoConfiguration {
@Autowired
private ApplicationContext context;
@Bean
@ConditionalOnMissingBean
public IdService idService() {
return new IdServiceImpl();
}
@Bean
@Primary
@ConditionalOnMissingBean

View File

@@ -1,133 +0,0 @@
package com.acgist.taoyao.boot.config;
import java.time.format.DateTimeFormatter;
import lombok.Getter;
/**
* 格式
*
* @author acgist
*/
public interface FormatStyle {
/**
* 默认日期格式
*/
public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 日期时间
*
* @author acgist
*/
@Getter
public static enum DateTimeStyle {
// YYYY
YYYYMMDD_HH24_MM("yyyyMMdd HH:mm"),
YYYY_MM_DD_HH24_MM("yyyy-MM-dd HH:mm"),
YYYYMMDDHH24MMSS("yyyyMMddHHmmss"),
YYYYMMDDHH24MMSSSSS("yyyyMMddHHmmssSSS"),
YYYYMMDD_HH24_MM_SS("yyyyMMdd HH:mm:ss"),
YYYYMMDD_HH24_MM_SS_SSS("yyyyMMdd HH:mm:ss.SSS"),
YYYY_MM_DD_HH24_MM_SS("yyyy-MM-dd HH:mm:ss"),
YYYY_MM_DD_HH24_MM_SS_SSS("yyyy-MM-dd HH:mm:ss.SSS"),
// YY
YYMMDD_HH24_MM("yyMMdd HH:mm"),
YY_MM_DD_HH24_MM("yy-MM-dd HH:mm"),
YYMMDDHH24MMSS("yyMMddHHmmss"),
YYMMDDHH24MMSSSSS("yyMMddHHmmssSSS"),
YYMMDD_HH24_MM_SS("yyMMdd HH:mm:ss"),
YYMMDD_HH24_MM_SS_SSS("yyMMdd HH:mm:ss.SSS"),
YY_MM_DD_HH24_MM_SS("yy-MM-dd HH:mm:ss"),
YY_MM_DD_HH24_MM_SS_SSS("yy-MM-dd HH:mm:ss.SSS"),
// ISO
YY_MM_DD_HH24_MM_SS_ISO("yy-MM-dd'T'HH:mm:ss"),
YY_MM_DD_HH24_MM_SS_SSS_ISO("yy-MM-dd'T'HH:mm:ss.SSS"),
YYYY_MM_DD_HH24_MM_SS_ISO("yyyy-MM-dd'T'HH:mm:ss"),
YYYY_MM_DD_HH24_MM_SS_SSS_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS"),
// UTC
YY_MM_DD_HH24_MM_SS_UTC("yy-MM-dd'T'HH:mm:ss'Z'"),
YY_MM_DD_HH24_MM_SS_SSS_UTC("yy-MM-dd'T'HH:mm:ss.SSS'Z'"),
YYYY_MM_DD_HH24_MM_SS_UTC("yyyy-MM-dd'T'HH:mm:ss'Z'"),
YYYY_MM_DD_HH24_MM_SS_SSS_UTC("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private DateTimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
/**
* 时间
*
* @author acgist
*/
@Getter
public static enum TimeStyle {
HH24("HH"),
HH24MM("HHmm"),
HH24_MM("HH:mm"),
HH24MMSS("HHmmss"),
HH24_MM_SS("HH:mm:ss"),
HH24MMSSSSS("HHmmssSSS"),
HH24_MM_SS_SSS("HH:mm:ss.SSS");
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private TimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
/**
* 日期
*
* @author acgist
*/
@Getter
public static enum DateStyle {
YYMMDD("yyMMdd"),
YYYYMMDD("yyyyMMdd"),
YY_MM_DD("yy-MM-dd"),
YYYY_MM_DD("yyyy-MM-dd");
/**
* 格式
*/
private String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private DateStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
}

View File

@@ -18,14 +18,23 @@ import lombok.Setter;
public class WebrtcProperties {
/**
* 类型
* 架构类型
*
* @author acgist
*/
public enum Type {
/**
* SFU架构
*/
SFU,
/**
* MCU架构
*/
MCU,
/**
* MESH架构
*/
MESH;
}
@@ -33,7 +42,15 @@ public class WebrtcProperties {
/**
* 类型
*/
@Schema(name = "类型", description = "WebRTC媒体架构")
@Schema(name = "架构类型", description = "WebRTC架构类型")
private Type type;
/**
* stun服务器
*/
private String[] stun;
/**
* turn服务器
*/
private String[] turn;
}

View File

@@ -18,7 +18,7 @@ import com.acgist.taoyao.boot.utils.ErrorUtils;
public class TaoyaoControllerAdvice {
@ExceptionHandler(Exception.class)
public Message<String> exception(Exception e, HttpServletRequest request, HttpServletResponse response) {
public Message exception(Exception e, HttpServletRequest request, HttpServletResponse response) {
return ErrorUtils.message(e, request, response);
}

View File

@@ -24,7 +24,7 @@ public class TaoyaoErrorController implements ErrorController {
@Operation(summary = "统一错误地址", description = "全局统一错误地址")
@RequestMapping(value = ErrorUtils.ERROR_PATH)
public Message<String> index(HttpServletRequest request, HttpServletResponse response) {
public Message index(HttpServletRequest request, HttpServletResponse response) {
return ErrorUtils.message(request, response);
}

View File

@@ -46,7 +46,7 @@ public class SecurityInterceptor implements HandlerInterceptor {
/**
* @param request 请求
*
* @return 是否公共请求
* @return 是否许可请求
*/
private boolean permit(HttpServletRequest request) {
final String uri = request.getRequestURI();
@@ -54,8 +54,8 @@ public class SecurityInterceptor implements HandlerInterceptor {
return false;
}
for (String permit : this.securityProperties.getPermit()) {
if(uri.startsWith(permit)) {
log.debug("授权成功(公共请求):{}-{}", uri, permit);
if(StringUtils.startsWith(uri, permit)) {
log.debug("授权成功(许可请求):{}-{}", uri, permit);
return true;
}
}
@@ -73,11 +73,10 @@ public class SecurityInterceptor implements HandlerInterceptor {
if(StringUtils.isEmpty(authorization)) {
return false;
}
final int index = authorization.indexOf(' ');
if(index < 0 || !authorization.substring(0, index).equalsIgnoreCase(SecurityProperties.BASIC)) {
if(!StringUtils.startsWithIgnoreCase(authorization, SecurityProperties.BASIC)) {
return false;
}
authorization = authorization.substring(index).strip();
authorization = authorization.substring(SecurityProperties.BASIC.length()).strip();
authorization = new String(Base64.getDecoder().decode(authorization));
if(!authorization.equals(this.securityProperties.getAuthorization())) {
return false;

View File

@@ -0,0 +1,42 @@
package com.acgist.taoyao.boot.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 信令头部
*
* @author acgist
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Header implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 信令版本
*/
private String v;
/**
* 请求标识
*/
private Long id;
/**
* 终端标识
*/
private String sn;
/**
* 协议标识
*/
private Integer pid;
}

View File

@@ -7,61 +7,88 @@ import org.apache.commons.lang3.StringUtils;
import com.acgist.taoyao.boot.utils.JSONUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 响应消息
* 消息
*
* @author acgist
*
* @param <T> 消息类型
*/
@Getter
@Setter
@Schema(name = "响应消息", description = "HTTP响应消息")
public class Message<T> implements Serializable {
@Schema(name = "消息", description = "请求响应消息")
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 响应编码
*/
@Schema(name = "响应编码", description = "0000表示成功其他都是失败")
@Schema(name = "响应编码", description = "响应消息标识响应状态")
private String code;
/**
* 响应描述
*/
@Schema(name = "响应描述", description = "响应编码描述")
@Schema(name = "响应描述", description = "响应消息描述响应编码")
private String message;
/**
* 响应内容
* 请求响应头部
*/
@Schema(name = "响应内容", description = "响应内容")
private T body;
@Schema(name = "请求响应头部", description = "请求响应头部")
private Header header;
/**
* 请求响应主体
*/
@Schema(name = "请求响应主体", description = "请求响应主体")
private Object body;
/**
* @param code 状态编码
*
* @return this
*/
public Message setCode(MessageCode code) {
this.code = code.getCode();
this.message = code.getMessage();
return this;
}
/**
* @param code 状态编码
* @param message
*
* @return this
*/
public Message setCode(MessageCode code, String message) {
if(StringUtils.isEmpty(message)) {
message = code.getMessage();
}
this.code = code.getCode();
this.message = message;
return this;
}
/**
* 成功消息
*
* @param <T> 消息类型
*
* @return 成功消息
*/
public static final <T> Message<T> success() {
public static final Message success() {
return success(null);
}
/**
* 成功消息
*
* @param <T> 消息类型
*
* @param body 消息内容
* @param body 主体
*
* @return 成功消息
*/
public static final <T> Message<T> success(T body) {
final Message<T> message = new Message<>();
public static final Message success(Object body) {
final Message message = new Message();
message.code = MessageCode.CODE_0000.getCode();
message.message = MessageCode.CODE_0000.getMessage();
message.body = body;
@@ -69,94 +96,65 @@ public class Message<T> implements Serializable {
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @return 错误消息
*/
public static final <T> Message<T> fail() {
return fail(MessageCode.CODE_9999);
public static final Message fail() {
return fail(null, null, null);
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @param message 消息内容
* @param message 主体
*
* @return 错误消息
*/
public static final <T> Message<T> fail(String message) {
return fail(MessageCode.CODE_9999, message);
public static final Message fail(String message) {
return fail(null, message, null);
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @param code 错误编码
* @param code 响应编码
*
* @return 错误消息
*/
public static final <T> Message<T> fail(MessageCode code) {
return fail(code, null);
public static final Message fail(MessageCode code) {
return fail(code, null, null);
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @param code 错误编码
* @param message 错误描述
* @param code 响应编码
* @param message 响应描述
*
* @return 错误消息
*/
public static final <T> Message<T> fail(MessageCode code, String message) {
final Message<T> failMessage = new Message<>();
failMessage.code = code.getCode();
if (StringUtils.isEmpty(message)) {
failMessage.message = code.getMessage();
} else {
failMessage.message = message;
public static final Message fail(MessageCode code, String message) {
return fail(code, message, null);
}
/**
* @param code 响应编码
* @param body 主体
*
* @return 错误消息
*/
public static final Message fail(MessageCode code, Object body) {
return fail(code, null, body);
}
/**
* @param code 响应编码
* @param message 响应描述
* @param body 主体
*
* @return 错误消息
*/
public static final Message fail(MessageCode code, String message, Object body) {
if(code == null) {
code = MessageCode.CODE_9999;
}
return failMessage;
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @param code 错误编码
* @param body 消息内容
*
* @return 错误消息
*/
public static final <T> Message<T> fail(MessageCode code, T body) {
final Message<T> message = new Message<>();
message.code = code.getCode();
message.message = code.getMessage();
message.body = body;
return message;
}
/**
* 错误消息
*
* @param <T> 消息类型
*
* @param code 错误编码
* @param message 错误描述
* @param body 消息内容
*
* @return 错误消息
*/
public static final <T> Message<T> fail(MessageCode code, String message, T body) {
final Message<T> failMessage = new Message<>();
if (StringUtils.isEmpty(message)) {
message = code.getMessage();
}
final Message failMessage = new Message();
failMessage.code = code.getCode();
failMessage.message = message;
failMessage.body = body;

View File

@@ -1,17 +1,17 @@
package com.acgist.taoyao.boot.service;
/**
* ID生成
* ID
*
* @author acgist
*/
public interface IdService {
/**
* 生成十位的IDYYMMddHHmmss + sn + xxxx
* 生成十位的IDYYMMddHHmmss(12) + sn(1) + xxxxxx(6)
*
* @return ID
*/
Long id();
long id();
}

View File

@@ -1,5 +1,46 @@
package com.acgist.taoyao.boot.service.impl;
public class IdServiceImpl {
import java.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Value;
import com.acgist.taoyao.boot.service.IdService;
public class IdServiceImpl implements IdService {
/**
* 机器序号
*/
@Value("${taoyao.sn:0}")
private int sn = 9;
/**
* 当前索引
*/
private int index;
/**
* 最大索引
*/
private static final int MAX_INDEX = 999999;
@Override
public long id() {
synchronized (this) {
if (++this.index > MAX_INDEX) {
this.index = 0;
}
}
final LocalDateTime time = LocalDateTime.now();
return
100000000000000000L * (time.getYear() % 100) +
1000000000000000L * time.getMonthValue() +
10000000000000L * time.getDayOfMonth() +
100000000000L * time.getHour() +
1000000000L * time.getMinute() +
10000000L * time.getSecond() +
// 机器序号一位
1000000L * this.sn +
// 每秒并发数量
this.index;
}
}

View File

@@ -6,15 +6,13 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import com.acgist.taoyao.boot.config.FormatStyle.DateStyle;
import com.acgist.taoyao.boot.config.FormatStyle.DateTimeStyle;
import com.acgist.taoyao.boot.config.FormatStyle.TimeStyle;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
@@ -28,6 +26,125 @@ public final class DateUtils {
private DateUtils() {
}
/**
* 默认日期格式
*/
public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 日期时间
*
* @author acgist
*/
@Getter
public static enum DateTimeStyle {
// YYYY
YYYYMMDD_HH24_MM("yyyyMMdd HH:mm"),
YYYY_MM_DD_HH24_MM("yyyy-MM-dd HH:mm"),
YYYYMMDDHH24MMSS("yyyyMMddHHmmss"),
YYYYMMDDHH24MMSSSSS("yyyyMMddHHmmssSSS"),
YYYYMMDD_HH24_MM_SS("yyyyMMdd HH:mm:ss"),
YYYYMMDD_HH24_MM_SS_SSS("yyyyMMdd HH:mm:ss.SSS"),
YYYY_MM_DD_HH24_MM_SS("yyyy-MM-dd HH:mm:ss"),
YYYY_MM_DD_HH24_MM_SS_SSS("yyyy-MM-dd HH:mm:ss.SSS"),
// YY
YYMMDD_HH24_MM("yyMMdd HH:mm"),
YY_MM_DD_HH24_MM("yy-MM-dd HH:mm"),
YYMMDDHH24MMSS("yyMMddHHmmss"),
YYMMDDHH24MMSSSSS("yyMMddHHmmssSSS"),
YYMMDD_HH24_MM_SS("yyMMdd HH:mm:ss"),
YYMMDD_HH24_MM_SS_SSS("yyMMdd HH:mm:ss.SSS"),
YY_MM_DD_HH24_MM_SS("yy-MM-dd HH:mm:ss"),
YY_MM_DD_HH24_MM_SS_SSS("yy-MM-dd HH:mm:ss.SSS"),
// ISO
YY_MM_DD_HH24_MM_SS_ISO("yy-MM-dd'T'HH:mm:ss"),
YY_MM_DD_HH24_MM_SS_SSS_ISO("yy-MM-dd'T'HH:mm:ss.SSS"),
YYYY_MM_DD_HH24_MM_SS_ISO("yyyy-MM-dd'T'HH:mm:ss"),
YYYY_MM_DD_HH24_MM_SS_SSS_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS"),
// UTC
YY_MM_DD_HH24_MM_SS_UTC("yy-MM-dd'T'HH:mm:ss'Z'"),
YY_MM_DD_HH24_MM_SS_SSS_UTC("yy-MM-dd'T'HH:mm:ss.SSS'Z'"),
YYYY_MM_DD_HH24_MM_SS_UTC("yyyy-MM-dd'T'HH:mm:ss'Z'"),
YYYY_MM_DD_HH24_MM_SS_SSS_UTC("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private DateTimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
/**
* 时间
*
* @author acgist
*/
@Getter
public static enum TimeStyle {
HH24("HH"),
HH24MM("HHmm"),
HH24_MM("HH:mm"),
HH24MMSS("HHmmss"),
HH24_MM_SS("HH:mm:ss"),
HH24MMSSSSS("HHmmssSSS"),
HH24_MM_SS_SSS("HH:mm:ss.SSS");
/**
* 格式
*/
private final String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private TimeStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
/**
* 日期
*
* @author acgist
*/
@Getter
public static enum DateStyle {
YYMMDD("yyMMdd"),
YYYYMMDD("yyyyMMdd"),
YY_MM_DD("yy-MM-dd"),
YYYY_MM_DD("yyyy-MM-dd");
/**
* 格式
*/
private String format;
/**
* 格式工具
*/
private final DateTimeFormatter dateTimeFormatter;
private DateStyle(String format) {
this.format = format;
this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
}
}
/**
* 生成时间戳
*

View File

@@ -76,7 +76,7 @@ public final class ErrorUtils {
*
* @return 错误信息
*/
public static final Message<String> message(HttpServletRequest request, HttpServletResponse response) {
public static final Message message(HttpServletRequest request, HttpServletResponse response) {
return message(null, request, response);
}
@@ -87,11 +87,11 @@ public final class ErrorUtils {
*
* @return 错误信息
*/
public static final Message<String> message(Throwable t, HttpServletRequest request, HttpServletResponse response) {
final Message<String> message;
public static final Message message(Throwable t, HttpServletRequest request, HttpServletResponse response) {
final Message message;
int status = globalStatus(request, response);
final Object globalError = t == null ? globalError(request) : t;
final Object rootError = ExceptionUtils.root(globalError);
final Object rootError = rootException(globalError);
if(rootError instanceof MessageCodeException) {
// 自定义的异常
final MessageCodeException messageCodeException = (MessageCodeException) rootError;
@@ -220,4 +220,35 @@ public final class ErrorUtils {
return messageCode.getMessage();
}
/**
* @param t 异常
*
* @return 原始异常
*
* @see #rootException(Throwable)
*/
public static final Object rootException(Object t) {
if(t instanceof Throwable) {
return rootException((Throwable) t);
}
return t;
}
/**
* @param t 异常
*
* @return 原始异常
*/
public static final Throwable rootException(Throwable t) {
Throwable cause = t;
do {
// 直接返回状态编码异常
if(cause instanceof MessageCodeException) {
return cause;
}
} while(cause != null && (cause = cause.getCause()) != null);
// 返回原始异常
return t;
}
}

View File

@@ -1,43 +0,0 @@
package com.acgist.taoyao.boot.utils;
import com.acgist.taoyao.boot.model.MessageCodeException;
/**
* 异常工具
*
* @author acgist
*/
public class ExceptionUtils {
/**
* @param t 异常
*
* @return 原始异常
*
* @see #root(Throwable)
*/
public static final Object root(Object t) {
if(t instanceof Throwable) {
return ExceptionUtils.root((Throwable) t);
}
return t;
}
/**
* @param t 异常
*
* @return 原始异常
*/
public static final Throwable root(Throwable t) {
Throwable cause = t;
do {
// 直接返回状态编码异常
if(cause instanceof MessageCodeException) {
return cause;
}
} while(cause != null && (cause = cause.getCause()) != null);
// 返回原始异常
return t;
}
}

View File

@@ -10,10 +10,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import com.acgist.taoyao.boot.config.FormatStyle.DateStyle;
import com.acgist.taoyao.boot.config.FormatStyle.DateTimeStyle;
import com.acgist.taoyao.boot.config.FormatStyle.TimeStyle;
import com.acgist.taoyao.boot.model.MessageCodeException;
import com.acgist.taoyao.boot.utils.DateUtils.DateStyle;
import com.acgist.taoyao.boot.utils.DateUtils.DateTimeStyle;
import com.acgist.taoyao.boot.utils.DateUtils.TimeStyle;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;