common 包,基础组件

pull/2/head
YunaiV 2021-01-03 23:27:19 +08:00
parent fc8eac548a
commit 0a6078610b
14 changed files with 641 additions and 0 deletions

View File

@ -0,0 +1,31 @@
package cn.iocoder.dashboard.common.exception;
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
import lombok.Data;
/**
*
*
* [0, 999] {@link GlobalException}
* [1 000 000 000, +) {@link ServiceErrorCodeRange}
*
* TODO i18
*/
@Data
public class ErrorCode {
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
public ErrorCode(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.dashboard.common.exception;
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Exception
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class GlobalException extends RuntimeException {
/**
*
*
* @see GlobalErrorCodeConstants
*/
private Integer code;
/**
*
*/
private String message;
/**
*
*/
public GlobalException() {
}
public GlobalException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public GlobalException(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,59 @@
package cn.iocoder.dashboard.common.exception;
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Exception
*/
@Data
@EqualsAndHashCode(callSuper = true)
public final class ServiceException extends RuntimeException {
/**
*
*
* @see ServiceErrorCodeRange
*/
private Integer code;
/**
*
*/
private String message;
/**
*
*/
public ServiceException() {
}
public ServiceException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public ServiceException(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public ServiceException setCode(Integer code) {
this.code = code;
return this;
}
public String getMessage() {
return message;
}
public ServiceException setMessage(String message) {
this.message = message;
return this;
}
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.dashboard.common.exception.enums;
import cn.iocoder.dashboard.common.exception.ErrorCode;
/**
*
* 0-999
*
* 使 HTTP https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
* HTTP 使使
* 使 0 使 200
*
* @author
*/
public interface GlobalErrorCodeConstants {
ErrorCode SUCCESS = new ErrorCode(0, "成功");
// ========== 客户端错误段 ==========
ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录");
ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限");
ErrorCode NOT_FOUND = new ErrorCode(404, "请求未找到");
ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确");
// ========== 服务端错误段 ==========
ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
static boolean isMatch(Integer code) {
return code != null
&& code >= SUCCESS.getCode() && code <= UNKNOWN.getCode();
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.dashboard.common.exception.enums;
/**
* 使
*
* 10
*
* 1
* 1 -
* x -
* 3
* 001 -
* 002 -
* 003 -
* 004 -
* 005 -
* ... - ...
* 3
*
*
* 001 - OAuth2
* 002 - User
* 003 - MobileCode
* 3
*
*
*
* @author
*/
public class ServiceErrorCodeRange {
// 模块 system 错误码区间 [1-000-001-000 ~ 1-000-002-000]
}

View File

@ -0,0 +1,122 @@
package cn.iocoder.dashboard.common.exception.util;
import cn.iocoder.dashboard.common.exception.ErrorCode;
import cn.iocoder.dashboard.common.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* {@link ServiceException}
*
*
* String.format 使 {} 使 {@link #doFormat(int, String, Object...)}
*
* {@link #MESSAGES} 使
*
* 1. cn.iocoder.oceans.user.api.constants.ErrorCodeEnum + ServiceExceptionConfiguration
* 2. .properties
* 3. Apollo
* 4. db
*/
public class ServiceExceptionUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceExceptionUtil.class);
/**
*
*/
private static final ConcurrentMap<Integer, String> MESSAGES = new ConcurrentHashMap<>();
public static void putAll(Map<Integer, String> messages) {
ServiceExceptionUtil.MESSAGES.putAll(messages);
}
public static void put(Integer code, String message) {
ServiceExceptionUtil.MESSAGES.put(code, message);
}
public static void delete(Integer code, String message) {
ServiceExceptionUtil.MESSAGES.remove(code, message);
}
// ========== 和 ServiceException 的集成 ==========
public static ServiceException exception(ErrorCode errorCode) {
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
return exception0(errorCode.getCode(), messagePattern);
}
public static ServiceException exception(ErrorCode errorCode, Object... params) {
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
return exception0(errorCode.getCode(), messagePattern, params);
}
/**
* ServiceException
*
* @param code
* @return
*/
public static ServiceException exception(Integer code) {
return exception0(code, MESSAGES.get(code));
}
/**
* ServiceException
*
* @param code
* @param params
* @return
*/
public static ServiceException exception(Integer code, Object... params) {
return exception0(code, MESSAGES.get(code), params);
}
public static ServiceException exception0(Integer code, String messagePattern, Object... params) {
String message = doFormat(code, messagePattern, params);
return new ServiceException(code, message);
}
// ========== 格式化方法 ==========
/**
* 使 params
*
* @param code
* @param messagePattern
* @param params
* @return
*/
private static String doFormat(int code, String messagePattern, Object... params) {
StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
int i = 0;
int j;
int l;
for (l = 0; l < params.length; l++) {
j = messagePattern.indexOf("{}", i);
if (j == -1) {
LOGGER.error("[doFormat][参数过多:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
if (i == 0) {
return messagePattern;
} else {
sbuf.append(messagePattern.substring(i, messagePattern.length()));
return sbuf.toString();
}
} else {
sbuf.append(messagePattern.substring(i, j));
sbuf.append(params[l]);
i = j + 2;
}
}
if (messagePattern.indexOf("{}", i) != -1) {
LOGGER.error("[doFormat][参数过少:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
}
sbuf.append(messagePattern.substring(i, messagePattern.length()));
return sbuf.toString();
}
}

View File

@ -0,0 +1,6 @@
/**
*
*
* CommonResult
*/
package cn.iocoder.dashboard.common;

View File

@ -0,0 +1,106 @@
package cn.iocoder.dashboard.common.pojo;
import cn.iocoder.dashboard.common.exception.ErrorCode;
import cn.iocoder.dashboard.common.exception.GlobalException;
import cn.iocoder.dashboard.common.exception.ServiceException;
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import org.springframework.util.Assert;
import java.io.Serializable;
/**
*
*
* @param <T>
*/
@Data
public final class CommonResult<T> implements Serializable {
/**
*
*
* @see ErrorCode#getCode()
*/
private Integer code;
/**
*
*/
private T data;
/**
*
*
* @see ErrorCode#getMessage() ()
*/
private String msg;
/**
* result
*
* A CommonResult B
*
* @param result result
* @param <T>
* @return CommonResult
*/
public static <T> CommonResult<T> error(CommonResult<?> result) {
return error(result.getCode(), result.getMsg());
}
public static <T> CommonResult<T> error(Integer code, String message) {
Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code), "code 必须是错误的!");
CommonResult<T> result = new CommonResult<>();
result.code = code;
result.msg = message;
return result;
}
public static <T> CommonResult<T> error(ErrorCode errorCode) {
return error(errorCode.getCode(), errorCode.getMessage());
}
public static <T> CommonResult<T> success(T data) {
CommonResult<T> result = new CommonResult<>();
result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
result.data = data;
result.msg = "";
return result;
}
@JSONField(serialize = false) // 避免序列化
public boolean isSuccess() {
return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code);
}
@JSONField(serialize = false) // 避免序列化
public boolean isError() {
return !isSuccess();
}
// ========= 和 Exception 异常体系集成 =========
/**
* {@link GlobalException} {@link ServiceException}
*/
public void checkError() throws GlobalException, ServiceException {
if (isSuccess()) {
return;
}
// 全局异常
if (GlobalErrorCodeConstants.isMatch(code)) {
throw new GlobalException(code, msg);
}
// 业务异常
throw new ServiceException(code, msg);
}
public static <T> CommonResult<T> error(ServiceException serviceException) {
return error(serviceException.getCode(), serviceException.getMessage());
}
public static <T> CommonResult<T> error(GlobalException globalException) {
return error(globalException.getCode(), globalException.getMessage());
}
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.dashboard.common.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@ApiModel("分页参数")
@Data
public class PageParam implements Serializable {
@ApiModelProperty(value = "页码,从 1 开始", required = true,example = "1")
@NotNull(message = "页码不能为空")
@Min(value = 1, message = "页码最小值为 1")
private Integer pageNo;
@ApiModelProperty(value = "每页条数,最大值为 100", required = true, example = "10")
@NotNull(message = "每页条数不能为空")
@Range(min = 1, max = 100, message = "条数范围为 [1, 100]")
private Integer pageSize;
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.dashboard.common.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@ApiModel("分页结果")
@Data
public final class PageResult<T> implements Serializable {
@ApiModelProperty(value = "数据", required = true)
private List<T> list;
@ApiModelProperty(value = "总量", required = true)
private Long total;
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.dashboard.common.pojo;
import java.io.Serializable;
/**
* DTO
*
* ing ES SortField
*/
public class SortingField implements Serializable {
/**
* -
*/
public static final String ORDER_ASC = "asc";
/**
* -
*/
public static final String ORDER_DESC = "desc";
/**
*
*/
private String field;
/**
*
*/
private String order;
// 空构造方法,解决反序列化
public SortingField() {
}
public SortingField(String field, String order) {
this.field = field;
this.order = order;
}
public String getField() {
return field;
}
public SortingField setField(String field) {
this.field = field;
return this;
}
public String getOrder() {
return order;
}
public SortingField setOrder(String order) {
this.order = order;
return this;
}
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.dashboard.util.collection;
import cn.hutool.core.collection.CollectionUtil;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Collection
*
* @author
*/
public class CollectionUtils {
public static <T> Set<T> asSet(T... objs) {
return new HashSet<>(Arrays.asList(objs));
}
public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) {
return from.stream().map(func).collect(Collectors.toList());
}
public static <T, U> Set<U> convertSet(List<T> from, Function<T, U> func) {
return from.stream().map(func).collect(Collectors.toSet());
}
public static <T, K> Map<K, T> convertMap(List<T> from, Function<T, K> keyFunc) {
return from.stream().collect(Collectors.toMap(keyFunc, item -> item));
}
public static <T, K, V> Map<K, V> convertMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
return from.stream().collect(Collectors.toMap(keyFunc, valueFunc));
}
public static <T, K> Map<K, List<T>> convertMultiMap(List<T> from, Function<T, K> keyFunc) {
return from.stream().collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(t -> t, Collectors.toList())));
}
public static <T, K, V> Map<K, List<V>> convertMultiMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
return from.stream().collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(valueFunc, Collectors.toList())));
}
// 暂时没想好名字,先以 2 结尾噶
public static <T, K, V> Map<K, Set<V>> convertMultiMap2(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet())));
}
public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
return org.springframework.util.CollectionUtils.containsAny(source, candidates);
}
public static <T> T getFirst(List<T> from) {
return !CollectionUtil.isEmpty(from) ? from.get(0) : null;
}
public static <T> void addIfNotNull(Collection<T> coll, T item) {
if (item == null) {
return;
}
coll.add(item);
}
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.dashboard.util.collection;
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Map
*
* @author
*/
public class MapUtils {
public static <K, V> List<V> getList(Multimap<K, V> multimap, Collection<K> keys) {
List<V> result = new ArrayList<>();
keys.forEach(k -> {
Collection<V> values = multimap.get(k);
if (CollectionUtil.isEmpty(values)) {
return;
}
result.addAll(values);
});
return result;
}
}

View File

@ -0,0 +1,7 @@
/**
* Hutool
* Utils
*
* ps Hutool Hutool
*/
package cn.iocoder.dashboard.util;