Commit ddb7c473 by Shadow

im-common项目迁移

parent 1a3c22be
......@@ -28,16 +28,16 @@ spring:
# Redis配置
redis:
# database: 0
# host: 127.0.0.1
# password:
# port: 6379
database: 0
host: 127.0.0.1
password:
host: 121.37.22.224
password: temple123456
port: 6379
# database: 0
# host: 121.37.22.224
# password: temple123456
# port: 6379
dubbo:
protocol:
port: 20882
......@@ -57,7 +57,7 @@ load-blance:
# NameServer地址 用;作为地址的分隔符
rocketmq:
namesrvAddr: 127.0.0.1:9876
namesrvAddr: 121.37.22.224:9876
# 生产者的组名
producerId: im-server
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.wecloud</groupId>
<artifactId>im-common-core</artifactId>
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<description>im server 核心模块</description>
<dependencies>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- spring-boot start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring-boot end -->
<!-- mybatis-plus begin -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- mybatis-plus end -->
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- swagger start -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!-- swagger end -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!-- Shiro+JWT start -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<!-- Shiro+JWT end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<!-- RocketMq start -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
</dependency>
<!-- RocketMq start -->
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.wecloud</groupId>
<artifactId>im-common-bom</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
package com.wecloud.im.core.bean;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* Filter请求详情信息
*
* @author geekidea
* @date 2020/3/26
**/
@Data
@Accessors(chain = true)
public class RequestDetail implements Serializable {
private static final long serialVersionUID = 2543641512850125440L;
/**
* 请求ip地址
*/
private String ip;
/**
* 请求路径
*/
private String path;
}
package com.wecloud.im.core.common.api;
/**
* <p>
* REST API 响应码
* </p>
*
* @author geekidea
* @since 2018-11-08
*/
public enum ApiCode {
/**
* 操作成功
**/
SUCCESS(200, "api.response.code.SUCCESS"),
/**
* 非法访问
**/
UNAUTHORIZED(401, "api.response.code.UNAUTHORIZED"),
/**
* 没有权限
**/
NOT_PERMISSION(403, "api.response.code.NOT_PERMISSION"),
/**
* 你请求的资源不存在
**/
NOT_FOUND(404, "api.response.code.NOT_FOUND"),
/**
* 操作失败
**/
FAIL(500, "api.response.code.FAIL"),
/**
* 登录失败
**/
LOGIN_EXCEPTION(4000, "api.response.code.LOGIN_EXCEPTION"),
/**
* 系统异常
**/
SYSTEM_EXCEPTION(5000, "api.response.code.SYSTEM_EXCEPTION"),
/**
* 请求参数校验异常
**/
PARAMETER_EXCEPTION(5001, "api.response.code.PARAMETER_EXCEPTION"),
/**
* 请求参数解析异常
**/
PARAMETER_PARSE_EXCEPTION(5002, "api.response.code.PARAMETER_PARSE_EXCEPTION"),
/**
* HTTP内容类型异常
**/
HTTP_MEDIA_TYPE_EXCEPTION(5003, "api.response.code.HTTP_MEDIA_TYPE_EXCEPTION"),
/**
* 系统处理异常
**/
SPRING_BOOT_PLUS_EXCEPTION(5100, "api.response.code.SPRING_BOOT_PLUS_EXCEPTION"),
/**
* 业务处理异常
**/
BUSINESS_EXCEPTION(5101, "api.response.code.BUSINESS_EXCEPTION"),
/**
* 数据库处理异常
**/
DAO_EXCEPTION(5102, "api.response.code.DAO_EXCEPTION"),
/**
* 验证码校验异常
**/
VERIFICATION_CODE_EXCEPTION(5103, "api.response.code.VERIFICATION_CODE_EXCEPTION"),
/**
* 登录授权异常
**/
AUTHENTICATION_EXCEPTION(5104, "api.response.code.AUTHENTICATION_EXCEPTION"),
/**
* 没有访问权限
**/
UNAUTHENTICATED_EXCEPTION(5105, "api.response.code.UNAUTHENTICATED_EXCEPTION"),
/**
* 没有访问权限
**/
UNAUTHORIZED_EXCEPTION(5106, "api.response.code.UNAUTHORIZED_EXCEPTION"),
/**
* JWT Token解析异常
**/
JWTDECODE_EXCEPTION(5107, "api.response.code.JWTDECODE_EXCEPTION"),
/**
* 默认的异常处理
*/
HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION(5108, "api.response.code.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION"),
/**
* 已有会话,不能重复创建会话
*/
REPETITION_CONVERSATION(6010, "api.response.code.REPETITION_CONVERSATION"),
/**
* 成员不存在,不能创建会话
*/
CLIENT_NOT_FOUNT(6011, "api.response.code.CLIENT_NOT_FOUNT"),
/**
* 被对方拉黑
*/
IS_BE_BLACK(6012, "api.response.code.IS_BE_BLACK"),
/**
* 你把对方拉黑
*/
IS_TO_BLACK(6013, "api.response.code.IS_TO_BLACK"),
/**
* 已被踢出会话
*/
IS_BE_KICK_OUT(6014, "api.response.code.IS_BE_KICK_OUT"),
/**
* 已被禁言
*/
IS_BE_MUTED(6015, "api.response.code.IS_BE_MUTED"),
/**
* 群聊已解散
*/
IS_BE_DISBAND(6016, "api.response.code.IS_BE_DISBAND"),
/**
* 群已禁止发链接
*/
IS_BE_FORBID_SEND_LINK(6017, "api.response.code.IS_BE_FORBID_SEND_LINK"),
/**
* 群已禁止发图片
*/
IS_BE_FORBID_SEND_PIC(6018, "api.response.code.IS_BE_FORBID_SEND_PIC"),
/**
* 消息超出数量限制
*/
MSG_EXCEED_QUANTITY_LIMIT(6019, "api.response.code.IS_BE_FORBID_SEND_PIC"),
/**
* 消息超出VIP数量限制
*/
EXCEED_VIP_QUANTITY_LIMIT(6020, "api.response.code.IS_BE_FORBID_SEND_PIC"),
;
private final int code;
private final String message;
ApiCode(final int code, final String message) {
this.code = code;
this.message = message;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
package com.wecloud.im.core.common.api;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.wecloud.im.core.config.il8n.I18nMessageUtil;
import com.wecloud.im.core.config.il8n.LanguageEnum;
/**
* <p>
* REST API 返回结果
* 国际化message封装
* </p>
*
* @author geekidea
* @since 2018-11-08
*/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 8004487252556526569L;
/**
* 响应码
*/
private int code;
/**
* 响应消息
*/
private String message;
/**
* 响应数据
*/
private T data;
public ApiResult() {
}
public static ApiResult<Boolean> result(boolean flag) {
if (flag) {
return ok();
}
return fail();
}
public static ApiResult<Boolean> result(ApiCode apiCode) {
return result(apiCode, null);
}
public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
return result(apiCode, null, data);
}
public static <T> ApiResult<T> result(ApiCode apiCode, T data, String language) {
return result(apiCode, null, data);
}
public static <T> ApiResult<T> result(ApiCode apiCode, String message, T data) {
// boolean success = false;
// if (apiCode.getCode() == ApiCode.SUCCESS.getCode()) {
// success = true;
// }
// 多语言国际化,根据http上下文, 取得heard中的language语言属性,实现不用在业务代码中传递语言字段
// HttpServletRequest request = HttpServletRequestUtil.getRequest();
// String language = request.getHeader("language");
String success = "SUCCESS";
try {
message = I18nMessageUtil.getMessage(LanguageEnum.getLanguageType(null), apiCode.getMessage(), success);
} catch (IOException e) {
message = success;
}
return (ApiResult<T>) ApiResult.builder()
.code(apiCode.getCode())
.message(message)
.data(data)
// .success(success)
// .time(new Date())
.build();
}
public static ApiResult<Boolean> ok() {
return ok(true);
}
public static <T> ApiResult<T> ok(T data) {
return result(ApiCode.SUCCESS, data);
}
// public static <T> ApiResult<T> ok(T data, String message) {
// return result(ApiCode.SUCCESS, message, data);
// }
// public static ApiResult<Map<String, Object>> okMap(String key, Object value) {
// Map<String, Object> map = new HashMap<>(1);
// map.put(key, value);
// return ok(map);
// }
public static ApiResult<Boolean> fail(ApiCode apiCode) {
return result(apiCode, null);
}
public static <T> ApiResult<T> fail(ApiCode apiCode, String language) {
return result(apiCode, null);
}
public static <T> ApiResult<T> fail(ApiCode apiCode, T data) {
if (ApiCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return result(apiCode, data);
}
public static ApiResult<String> fail(Integer errorCode, String message) {
return new ApiResult<String>()
// .setSuccess(false)
.setCode(errorCode)
.setMessage(message);
}
public static ApiResult<Map<String, Object>> fail(String key, Object value) {
Map<String, Object> map = new HashMap<>(1);
map.put(key, value);
return result(ApiCode.FAIL, map);
}
public static ApiResult<Boolean> fail() {
return fail(ApiCode.FAIL);
}
public static ApiResult<Boolean> fail(String language) {
return fail(ApiCode.FAIL, language);
}
}
package com.wecloud.im.core.common.bean;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 用户客户端信息对象
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
@Data
public class ClientInfo implements Serializable {
private static final long serialVersionUID = -5549531244606897514L;
/**
* ip
*/
private String ip;
/**
* ip对应的地址
*/
private String addree;
/**
* 浏览器名称
*/
private String browserName;
/**
* 浏览器版本
*/
private String browserversion;
/**
* 浏览器引擎名称
*/
private String engineName;
/**
* 浏览器引擎版本
*/
private String engineVersion;
/**
* 系统名称
*/
private String osName;
/**
* 平台名称
*/
private String platformName;
/**
* 是否是手机
*/
private boolean mobile;
/**
* 移动端设备型号
*/
private String deviceName;
/**
* 移动端设备型号
*/
private String deviceModel;
}
package com.wecloud.im.core.common.bean;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 设备信息
* </p>
*
* @author geekidea
* @date 2019-05-24
**/
@Data
public class DeviceInfo implements Serializable {
private static final long serialVersionUID = -5912785220335057555L;
/**
* 设备名称
*/
private String name;
/**
* 设备型号
*/
private String model;
}
package com.wecloud.im.core.common.controller;
import lombok.extern.slf4j.Slf4j;
/**
* Controller父类
*
* @author geekidea
* @date 2018-11-08
*/
@Slf4j
public abstract class BaseController {
}
package com.wecloud.im.core.common.controller;
import springfox.documentation.annotations.ApiIgnore;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.wecloud.im.core.log.annotation.OperationLogIgnore;
import com.wecloud.im.core.util.UUIDUtil;
/**
* CSRF 供swagger调用
*
* @author geekidea
* @date 2019/12/10
**/
@ApiIgnore
@OperationLogIgnore
@RestController
public class CsrfController {
@RequestMapping(value = "/csrf", method = {RequestMethod.GET, RequestMethod.POST})
public String csrf() {
return UUIDUtil.getUuid();
}
}
package com.wecloud.im.core.common.controller;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import org.apache.commons.collections4.CollectionUtils;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wecloud.im.core.common.api.ApiResult;
import com.wecloud.im.core.common.enums.BaseEnum;
import com.wecloud.im.core.common.vo.EnumVo;
import com.wecloud.im.core.log.annotation.OperationLogIgnore;
import com.wecloud.im.core.util.BaseEnumUtil;
/**
* <p>
* 展示实现BaseEnum接口的所有枚举值
* </p>
*
* @author geekidea
* @date 2018/11/02
*/
@RestController
@Slf4j
@OperationLogIgnore
@Api(value = "枚举字典", tags = {"枚举字典"})
public class EnumController {
private static final List<String> FRAMEWORK_ENUM_PACKAGES = Arrays.asList(
"io.geekidea.springbootplus.framework.common.enums",
"io.geekidea.springbootplus.system.enums");
/**
* 枚举包路径
*/
@Value("${spring-boot-plus.enum-packages}")
private List<String> enumPackages;
@GetMapping("/enum")
public ApiResult<Map<String, Map<Integer, EnumVo<? extends BaseEnum>>>> enumList() {
log.info("enumList...");
return ApiResult.ok(BaseEnumUtil.getEnumMap());
}
@PostConstruct
public void init() {
try {
if (enumPackages == null) {
enumPackages = new ArrayList<>();
}
enumPackages.addAll(FRAMEWORK_ENUM_PACKAGES);
// 获取BaseEnum接口的所有实现
log.info("enumPackages:" + enumPackages);
Reflections reflections = new Reflections(enumPackages);
Set<Class<? extends BaseEnum>> set = reflections.getSubTypesOf(BaseEnum.class);
if (CollectionUtils.isEmpty(set)) {
return;
}
// 循环获取BaseEnum枚举
for (Class<? extends BaseEnum> clazz : set) {
BaseEnum[] enumConstants = clazz.getEnumConstants();
Map<Integer, EnumVo<? extends BaseEnum>> enumVoMap = new ConcurrentHashMap<>(enumConstants.length);
for (BaseEnum baseEnum : enumConstants) {
Integer code = baseEnum.getCode();
String desc = baseEnum.getDesc();
EnumVo<BaseEnum> enumVo = new EnumVo<BaseEnum>()
.setCode(code)
.setDesc(desc)
.setBaseEnum(baseEnum);
enumVoMap.put(code, enumVo);
}
// 设置map
BaseEnumUtil.getEnumMap().put(clazz.getName(), enumVoMap);
}
log.info("enumMap:{}", BaseEnumUtil.getEnumMap());
} catch (Exception e) {
log.error("获取BaseEnum枚举map异常", e);
}
}
}
package com.wecloud.im.core.common.controller;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import com.wecloud.im.core.log.annotation.OperationLogIgnore;
/**
* <p>
* 项目根路径提示信息
* </p>
*
* @author geekidea
* @date 2018/11/12
*/
@Slf4j
@Controller
@OperationLogIgnore
@Api(value = "Index API", tags = {"Index"})
public class IndexController {
@GetMapping("/")
public String home() {
return "redirect:/index.html";
}
/**
* SwaggerUI
*/
@GetMapping("/docs")
public String docs() {
return "redirect:/swagger-ui.html";
}
// /**
// * SwaggerUI
// */
// @GetMapping("/websocketDocs")
// public String websocket() {
// return "redirect:/Wecloud-IM-Websocket-Docs.html";
// }
}
package com.wecloud.im.core.common.entity;
import io.swagger.annotations.ApiModel;
import java.io.Serializable;
/**
* 实体父类
*
* @author geekidea
* @date 2018-11-08
*/
@ApiModel("BaseEntity")
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = -7176390653391227433L;
}
package com.wecloud.im.core.common.enums;
/**
* 枚举类型父接口
*
* @author geekidea
* @date 2018-11-08
*/
public interface BaseEnum {
/**
* 通过枚举类型和code值获取对应的枚举类型
*
* @param enumType
* @param code
* @param <T>
* @return
*/
static <T extends BaseEnum> T valueOf(Class<? extends BaseEnum> enumType, Integer code) {
if (enumType == null || code == null) {
return null;
}
T[] enumConstants = (T[]) enumType.getEnumConstants();
if (enumConstants == null) {
return null;
}
for (T enumConstant : enumConstants) {
int enumCode = enumConstant.getCode();
if (code.equals(enumCode)) {
return enumConstant;
}
}
return null;
}
/**
* 获取枚举标识
*
* @return
*/
Integer getCode();
/**
* 获取枚举描述
*
* @return
*/
String getDesc();
}
package com.wecloud.im.core.common.exception;
import com.wecloud.im.core.common.api.ApiCode;
/**
* 业务异常
*
* @author geekidea
* @date 2018-11-08
*/
public class BusinessException extends SpringBootPlusException {
private static final long serialVersionUID = -2303357122330162359L;
public BusinessException(String message) {
super(message);
}
public BusinessException(Integer errorCode, String message) {
super(errorCode, message);
}
public BusinessException(ApiCode apiCode) {
super(apiCode);
}
}
package com.wecloud.im.core.common.exception;
import com.wecloud.im.core.common.api.ApiCode;
/**
* DAO异常
*
* @author geekidea
* @date 2018-11-08
*/
public class DaoException extends SpringBootPlusException {
private static final long serialVersionUID = -6912618737345878854L;
public DaoException(String message) {
super(message);
}
public DaoException(Integer errorCode, String message) {
super(errorCode, message);
}
public DaoException(ApiCode apiCode) {
super(apiCode);
}
}
package com.wecloud.im.core.common.exception;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.wecloud.im.core.common.api.ApiCode;
import com.wecloud.im.core.common.api.ApiResult;
/**
* 全局Error/404处理
*
* @author geekidea
* @date 2018-11-08
*/
@ApiIgnore
@RestController
@Slf4j
public class GlobalErrorController implements ErrorController {
private static final String ERROR_PATH = "/error";
@RequestMapping(ERROR_PATH)
public ApiResult<?> handleError(HttpServletRequest request, HttpServletResponse response) {
int status = response.getStatus();
switch (status) {
case HttpServletResponse.SC_UNAUTHORIZED:
return ApiResult.fail(ApiCode.UNAUTHORIZED);
case HttpServletResponse.SC_FORBIDDEN:
return ApiResult.fail(ApiCode.NOT_PERMISSION);
case HttpServletResponse.SC_NOT_FOUND:
return ApiResult.fail(ApiCode.NOT_FOUND);
default:
break;
}
return ApiResult.fail(ApiCode.FAIL);
}
@Override
public String getErrorPath() {
log.error("errorPath....");
return ERROR_PATH;
}
}
package com.wecloud.im.core.common.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.wecloud.im.core.common.api.ApiCode;
/**
* spring-boot-plus配置异常
*
* @author geekidea
* @date 2020/3/21
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SpringBootPlusConfigException extends SpringBootPlusException {
private static final long serialVersionUID = 8952028631871769425L;
private Integer errorCode;
private String message;
public SpringBootPlusConfigException() {
super();
}
public SpringBootPlusConfigException(String message) {
super(message);
this.message = message;
}
public SpringBootPlusConfigException(Integer errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.message = message;
}
public SpringBootPlusConfigException(ApiCode apiCode) {
super(apiCode.getMessage());
this.errorCode = apiCode.getCode();
this.message = apiCode.getMessage();
}
public SpringBootPlusConfigException(String message, Throwable cause) {
super(message, cause);
}
public SpringBootPlusConfigException(Throwable cause) {
super(cause);
}
}
package com.wecloud.im.core.common.exception;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.wecloud.im.core.common.api.ApiCode;
/**
* 自定义异常
*
* @author geekidea
* @date 2018-11-08
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SpringBootPlusException extends RuntimeException {
private static final long serialVersionUID = -2470461654663264392L;
private Integer errorCode;
private String message;
public SpringBootPlusException() {
super();
}
public SpringBootPlusException(String message) {
super(message);
this.message = message;
}
public SpringBootPlusException(Integer errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.message = message;
}
public SpringBootPlusException(ApiCode apiCode) {
super(apiCode.getMessage());
this.errorCode = apiCode.getCode();
this.message = apiCode.getMessage();
}
public SpringBootPlusException(String message, Throwable cause) {
super(message, cause);
}
public SpringBootPlusException(Throwable cause) {
super(cause);
}
}
package com.wecloud.im.core.common.param;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
/**
* ID参数
*
* @author geekidea
* @date 2018-11-08
*/
@Data
@ApiModel("ID参数")
public class IdParam implements Serializable {
private static final long serialVersionUID = -5353973980674510450L;
@NotNull(message = "ID不能为空")
private Long id;
}
package com.wecloud.im.core.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 公共Service接口
*
* @author geekidea
* @date 2018-11-08
*/
public interface BaseService<T> extends IService<T> {
}
package com.wecloud.im.core.common.service.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wecloud.im.core.common.service.BaseService;
import com.wecloud.im.core.util.LambdaColumn;
/**
* 公共Service父类
*
* @author geekidea
* @date 2018-11-08
*/
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements BaseService<T> {
/**
* 实体类型
*/
private Class<?> entityClass;
{
Class<?> clazz = this.getClass();
Type type = clazz.getGenericSuperclass();
if (type instanceof ParameterizedType) {
Type[] p = ((ParameterizedType) type).getActualTypeArguments();
this.entityClass = (Class<T>) p[1];
}
}
/**
* 获取对应字段的数据表列名称
*
* @param func
* @return
*/
public String getLambdaColumn(SFunction<T, ?> func) {
return new LambdaColumn<T>().get(func);
}
}
package com.wecloud.im.core.common.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 枚举类型VO
*
* @author geekidea
* @date 2019-11-02
**/
@Data
@Accessors(chain = true)
public class EnumVo<T> {
/**
* 枚举code
*/
private Integer code;
/**
* 枚举描述
*/
private String desc;
/**
* 枚举类型
*/
private T baseEnum;
}
package com.wecloud.im.core.config.converter;
import java.util.Date;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
/**
* 转换器配置
*
* @author geekidea
* @date 2018-11-08
*/
@Configuration
public class ConverterConfig {
@Bean
public Converter<String, Date> stringToDateConverter() {
return new StringToDateConverter();
}
@Bean
public Converter<String, Integer> stringToIntegerConverter() {
return new StringToIntegerConverter();
}
@Bean
public Converter<String, Double> stringToDoubleConverter() {
return new StringToDoubleConverter();
}
}
package com.wecloud.im.core.config.converter;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
/**
* <code>
* 日期转换器,将请求参数的日期字符串转换成java.util.Date类型
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
return StringToDateUtil.convert(source);
}
}
package com.wecloud.im.core.config.converter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
/**
* <code>
* <pre>
* 日期转换器,将请求参数的日期字符串转换成java.util.Date类型
* 日期格式顺序:
* 1.yyyy-MM-dd HH:mm:ss:S
* 2.yyyy-MM-dd HH:mm:ss
* 3.yyyy-MM-dd HH:mm
* 4.yyyy-MM-dd HH
* 5.yyyy-MM-dd
* </pre>
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToDateUtil {
/**
* 时间戳字符长度,不包含毫秒
*/
private static final Integer TIMESTAMP_LENGTH = 10;
/**
* 日期格式化数组
*/
private static DateFormat[] dateFormats = {
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:S"),
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
new SimpleDateFormat("yyyy-MM-dd HH:mm"),
new SimpleDateFormat("yyyy-MM-dd HH"),
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyy-MM")
};
/**
* <code>
* <pre>
* 1.如果日期字符串为空,则直接返回空
* 2.使用格式化组进行格式化,如果解析成功,则直接返回
* 4.否则,抛出非法参数异常
* @param source 请求的日期参数
* @return 解析后的日期类型:java.util.Date
* @exception IllegalArgumentException 非法参数异常
* </pre>
* </code>
*/
public static Date convert(String source) {
if (StringUtils.isBlank(source)) {
return null;
}
source = source.trim();
try {
int timeLength = source.length();
Long time = Long.parseLong(source);
if (timeLength == TIMESTAMP_LENGTH) {
time = time * 1000;
}
Date date = new Date(time);
return date;
} catch (Exception e) {
}
Date date = null;
boolean flag = false;
for (DateFormat dateFormat : dateFormats) {
try {
date = dateFormat.parse(source);
flag = true;
break;
} catch (ParseException e) {
}
}
if (flag) {
return date;
} else {
throw new IllegalArgumentException("不能解析日期:" + source);
}
}
}
package com.wecloud.im.core.config.converter;
import org.springframework.core.convert.converter.Converter;
/**
* <code>
*
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToDoubleConverter implements Converter<String, Double> {
@Override
public Double convert(String source) {
return StringToDoubleUtil.convert(source);
}
}
package com.wecloud.im.core.config.converter;
import org.apache.commons.lang3.StringUtils;
/**
* <code>
* <pre>
* 空字符串("")转换成Double的null
*
* </pre>
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToDoubleUtil {
public static Double convert(String source) {
if (StringUtils.isBlank(source)) {
return null;
}
Double d = Double.parseDouble(source);
return d;
}
}
package com.wecloud.im.core.config.converter;
import org.springframework.core.convert.converter.Converter;
/**
* <code>
*
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToIntegerConverter implements Converter<String, Integer> {
@Override
public Integer convert(String source) {
return StringToIntegerUtil.convert(source);
}
}
package com.wecloud.im.core.config.converter;
import org.apache.commons.lang3.StringUtils;
/**
* <code>
* <pre>
* 空字符串("")转换成Integer的null
*
* </pre>
* </code>
*
* @author geekidea
* @date 2018-11-08
*/
public class StringToIntegerUtil {
public static Integer convert(String source) {
if (StringUtils.isBlank(source)) {
return null;
}
Integer i = Integer.parseInt(source);
return i;
}
}
package com.wecloud.im.core.config.il8n;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;
/**
* 多语言国际化消息工具类
*/
public class I18nMessageUtil {
// 根目录
private static final String PATH_PARENT = "classpath:static/i18n/messages_";
// 后缀
private static final String SUFFIX = ".properties";
// 分解器
private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();
// 存取器
private static MessageSourceAccessor accessor;
private I18nMessageUtil() {
}
/**
* 初始化资源文件的存储器
* 加载指定语言配置文件
*
* @param language 语言类型(文件名即为语言类型,eg: en_us 表明使用 美式英文 语言配置)
*/
private static void initMessageSourceAccessor(String language) throws IOException {
/*
* 获取配置文件名
*/
Resource resource = RESOURCE_PATTERN_RESOLVER.getResource(PATH_PARENT + language + SUFFIX);
String fileName = resource.getURL().toString();
int lastIndex = fileName.lastIndexOf(".");
String baseName = fileName.substring(0, lastIndex);
/*
* 读取配置文件
*/
ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
reloadableResourceBundleMessageSource.setBasename(baseName);
reloadableResourceBundleMessageSource.setCacheSeconds(5);
reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
accessor = new MessageSourceAccessor(reloadableResourceBundleMessageSource);
}
/**
* 获取一条语言配置信息
*
* @param language 语言类型,zh_CN: 简体中文, en_US: 英文
* @param message 配置信息属性名,eg: api.response.code.user.signUp
* @param defaultMessage 默认信息,当无法从配置文件中读取到对应的配置信息时返回该信息
* @return
* @throws IOException
*/
public static String getMessage(String language, String message, String defaultMessage) throws IOException {
initMessageSourceAccessor(language);
return accessor.getMessage(message, defaultMessage, LocaleContextHolder.getLocale());
}
}
package com.wecloud.im.core.config.il8n;
import lombok.Getter;
import lombok.ToString;
import org.springframework.util.StringUtils;
/**
* 语言枚举类
*/
@Getter
@ToString
public enum LanguageEnum {
/**
* 美式英文
*/
LANGUAGE_EN_US("en_US"),
// /**
// * 柬埔寨 高棉语
// */
// LANGUAGE_KH("kh"),
/**
* 简体中文
*/
LANGUAGE_ZH_CN("zh_CN");
private final String language;
LanguageEnum(String language) {
this.language = language;
}
/**
* 获取指定语言类型(如果没有对应的语言类型,则返回中文)
*
* @param language 语言类型
* @return
*/
public static String getLanguageType(String language) {
// 设置默认为中文
if (StringUtils.isEmpty(language)) {
return LANGUAGE_ZH_CN.language;
}
for (LanguageEnum languageEnum : LanguageEnum.values()) {
if (languageEnum.language.equalsIgnoreCase(language)) {
return languageEnum.language;
}
}
return LANGUAGE_ZH_CN.language;
}
}
package com.wecloud.im.core.config.jackson.deserializer;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wecloud.im.core.config.converter.StringToDateUtil;
/**
* <p>
* Jackson Date序列化器
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public class JacksonDateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
String date = jp.getText();
return StringToDateUtil.convert(date);
}
}
package com.wecloud.im.core.config.jackson.deserializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wecloud.im.core.config.converter.StringToDoubleUtil;
/**
* @author geekidea
* @date 2018-11-08
*/
public class JacksonDoubleDeserializer extends JsonDeserializer<Double> {
@Override
public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String string = jsonParser.getText();
return StringToDoubleUtil.convert(string);
}
}
package com.wecloud.im.core.config.jackson.deserializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wecloud.im.core.config.converter.StringToIntegerUtil;
/**
* @author geekidea
* @date 2018-11-08
*/
public class JacksonIntegerDeserializer extends JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String string = jsonParser.getText();
return StringToIntegerUtil.convert(string);
}
}
package com.wecloud.im.core.config.jackson.deserializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wecloud.im.core.constant.DatePattern;
/**
* <p>
* Jackson LocaDateTime反序列化器
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public class JacksonLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
String string = jp.getText();
if (StringUtils.isBlank(string)) {
return null;
}
return LocalDateTime.parse(string, DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS));
}
}
package com.wecloud.im.core.config.jackson.deserializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.wecloud.im.core.config.converter.StringToDoubleUtil;
/**
* @author geekidea
* @date 2018-11-08
*/
public class JacksonLongDeserializer extends JsonDeserializer<Double> {
@Override
public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String string = jsonParser.getText();
return StringToDoubleUtil.convert(string);
}
}
package com.wecloud.im.core.config.jackson.serializer;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.wecloud.im.core.util.DateUtil;
/**
* <p>
* Jackson Date反序列化器
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public class JacksonDateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String string = null;
if (date != null) {
string = DateUtil.getDateTimeString(date);
}
jsonGenerator.writeString(string);
}
}
package com.wecloud.im.core.config.jackson.serializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.wecloud.im.core.constant.DatePattern;
/**
* <p>
* Jackson LocalDateTime 自定义序列化器
* </p>
*
* @author geekidea
* @date 2018/11/8
*/
public class JacksonLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String string = null;
if (localDateTime != null) {
string = localDateTime.format(DateTimeFormatter.ofPattern(DatePattern.YYYY_MM_DD_HH_MM_SS));
}
jsonGenerator.writeString(string);
}
}
package com.wecloud.im.core.config.jackson.serializer;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
/**
* <p>
* Jackson Long反序列化器
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public class JacksonLongSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String string = null;
if (aLong != null) {
string = aLong.toString();
}
jsonGenerator.writeString(string);
}
}
package com.wecloud.im.core.constant;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public interface ClientLoginRedisKey {
/**
* 登录用户信息key
* login:user:client
*/
String LOGIN_USER = "login:user:%s";
/**
* 登录用户username token
* login:user:token:client:token
*/
String LOGIN_USER_TOKEN = "login:user:token:%s:%s";
/**
* 登录用户下的所有token, 查询使用
* login:user:token:client:*
*/
String LOGIN_USER_ALL_TOKEN = "login:user:token:%s:*";
}
package com.wecloud.im.core.constant;
/**
* 公共常量
*
* @author geekidea
* @date 2018-11-08
*/
public interface CommonConstant {
/**
* 默认页码为1
*/
Long DEFAULT_PAGE_INDEX = 1L;
/**
* 默认页大小为10
*/
Long DEFAULT_PAGE_SIZE = 10L;
/**
* 数量最大为100
*/
Long MAX_PAGE_SIZE = 1000L;
/**
* 分页总行数名称
*/
String PAGE_TOTAL_NAME = "total";
/**
* 分页数据列表名称
*/
String PAGE_RECORDS_NAME = "records";
/**
* 分页当前页码名称
*/
String PAGE_INDEX_NAME = "pageIndex";
/**
* 分页当前页大小名称
*/
String PAGE_SIZE_NAME = "pageSize";
/**
* 登录token
*/
String JWT_DEFAULT_TOKEN_NAME = "token";
/**
* JWT-id
*/
String CLIENT_ID = "clientId";
String APP_KEY = "appKey";
String PLATFORM = "platform";
/**
* JWT刷新新token响应状态码
*/
int JWT_REFRESH_TOKEN_CODE = 460;
/**
* JWT刷新新token响应状态码,
* Redis中不存在,但jwt未过期,不生成新的token,返回361状态码
*/
int JWT_INVALID_TOKEN_CODE = 461;
/**
* JWT Token默认密钥
*/
String JWT_DEFAULT_SECRET = "666666";
/**
* JWT 默认过期时间,5184000L = 60天,单位秒
*/
Long JWT_DEFAULT_EXPIRE_SECOND = 5184000L;
/**
* ..
*/
String SPOT_SPOT = "..";
/**
* ../
*/
String SPOT_SPOT_BACKSLASH = "../";
/**
* 用户浏览器代理
*/
String USER_AGENT = "User-Agent";
/**
* 本机地址IP
*/
String LOCALHOST_IP = "127.0.0.1";
/**
* 本机地址名称
*/
String LOCALHOST_IP_NAME = "本机地址";
/**
* 局域网IP
*/
String LAN_IP = "192.168";
/**
* 局域网名称
*/
String LAN_IP_NAME = "局域网";
}
package com.wecloud.im.core.constant;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public interface CommonRedisKey {
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String LOGIN_TOKEN = "login:token:%s";
/**
* 登录用户盐值信息key
* login:salt:clientId
*/
String LOGIN_SALT = "login:salt:%s";
}
package com.wecloud.im.core.constant;
/**
* <p>
* 日期格式常量
* </p>
*
* @author geekidea
* @date 2018-11-08
*/
public interface DatePattern {
/**
* 年-月-日
*/
String YYYY_MM_DD = "yyyy-MM-dd";
/**
* 年-月-日 时:分
*/
String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
/**
* 年-月-日 时:分:秒
*/
String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 年-月-日 时:分:秒:毫秒
*/
String YYYY_MM_DD_HH_MM_SS_S = "yyyy-MM-dd HH:mm:ss.S";
/**
* 时:分
*/
String HH_MM = "HH:mm";
/**
* 时:分:秒
*/
String HH_MM_SS = "HH:mm:ss";
/**
* 时:分:秒:毫秒
*/
String HH_MM_SS_S = "HH:mm:ss:S";
}
package com.wecloud.im.core.exception;
import com.wecloud.im.core.common.api.ApiCode;
import com.wecloud.im.core.common.exception.SpringBootPlusException;
/**
* 系统登录异常
*
* @author geekidea
* @date 2019-08-04
*/
public class SysLoginException extends SpringBootPlusException {
private static final long serialVersionUID = -3157438982569715170L;
public SysLoginException(String message) {
super(message);
}
public SysLoginException(Integer errorCode, String message) {
super(errorCode, message);
}
public SysLoginException(ApiCode apiCode) {
super(apiCode);
}
}
package com.wecloud.im.core.exception;
import com.wecloud.im.core.common.api.ApiCode;
import com.wecloud.im.core.common.exception.SpringBootPlusException;
/**
* 验证码校验异常
*
* @author geekidea
* @date 2018-11-08
*/
public class VerificationCodeException extends SpringBootPlusException {
private static final long serialVersionUID = -2640690119865434398L;
public VerificationCodeException(String message) {
super(message);
}
public VerificationCodeException(Integer errorCode, String message) {
super(errorCode, message);
}
public VerificationCodeException(ApiCode apiCode) {
super(apiCode);
}
}
package com.wecloud.im.core.ip.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.wecloud.im.core.common.entity.BaseEntity;
/**
* IP地址
*
* @author geekidea
* @since 2020-03-25
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "IpAddress对象")
public class IpAddress extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String ipStart;
private String ipEnd;
@ApiModelProperty("区域")
private String area;
@ApiModelProperty("运营商")
private String operator;
private Long ipStartNum;
private Long ipEndNum;
}
package com.wecloud.im.core.ip.mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wecloud.im.core.ip.entity.IpAddress;
/**
* IP地址 Mapper 接口
*
* @author geekidea
* @since 2020-03-25
*/
@Repository
public interface IpAddressMapper extends BaseMapper<IpAddress> {
/**
* 通过ip地址获取IP对象
*
* @param ip
* @return
*/
IpAddress getByIp(@Param("ip") String ip);
}
package com.wecloud.im.core.ip.service;
import com.wecloud.im.core.common.service.BaseService;
import com.wecloud.im.core.ip.entity.IpAddress;
/**
* IP地址 服务类
*
* @author geekidea
* @since 2020-03-25
*/
public interface IpAddressService extends BaseService<IpAddress> {
/**
* 通过ip地址获取IP对象
*
* @param ip
* @return
*/
IpAddress getByIp(String ip);
/**
* 通过ip地址获取区域
*
* @param ip
* @return
*/
String getAreaByIp(String ip);
/**
* 通过ip地址获取运营商
*
* @param ip
* @return
*/
String getOperatorByIp(String ip);
}
package com.wecloud.im.core.ip.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wecloud.im.core.common.service.impl.BaseServiceImpl;
import com.wecloud.im.core.constant.CommonConstant;
import com.wecloud.im.core.ip.entity.IpAddress;
import com.wecloud.im.core.ip.mapper.IpAddressMapper;
import com.wecloud.im.core.ip.service.IpAddressService;
/**
* IP地址 服务实现类
*
* @author geekidea
* @since 2020-03-25
*/
@Slf4j
@Service
public class IpAddressServiceImpl extends BaseServiceImpl<IpAddressMapper, IpAddress> implements IpAddressService {
@Autowired
private IpAddressMapper ipAddressMapper;
@Override
public IpAddress getByIp(String ip) {
if (StringUtils.isBlank(ip)) {
return null;
}
if (CommonConstant.LOCALHOST_IP.equals(ip)) {
return new IpAddress().setArea(CommonConstant.LOCALHOST_IP_NAME);
}
if (CommonConstant.LAN_IP.equals(ip)) {
return new IpAddress().setArea(CommonConstant.LAN_IP_NAME);
}
return ipAddressMapper.getByIp(ip);
}
@Override
public String getAreaByIp(String ip) {
IpAddress ipAddress = getByIp(ip);
if (ipAddress != null) {
return ipAddress.getArea();
}
return null;
}
@Override
public String getOperatorByIp(String ip) {
IpAddress ipAddress = getByIp(ip);
if (ipAddress != null) {
return ipAddress.getOperator();
}
return null;
}
}
package com.wecloud.im.core.log.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* 模块名称注解
*
* @author geekidea
* @date 2020/3/19
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Module {
/**
* 模块名称
*
* @return
*/
String name() default "";
/**
* 模块名称
*
* @return
*/
@AliasFor("name")
String value() default "";
}
package com.wecloud.im.core.log.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import com.wecloud.im.core.log.enums.OperationLogType;
/**
* 操作日志注解
* 记录:日志名称,日志类型,日志备注
*
* @author geekidea
* @date 2020/3/19
**/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
/**
* 日志名称
*
* @return
*/
String name() default "";
/**
* 日志名称
*
* @return
*/
@AliasFor("name")
String value() default "";
/**
* 日志类型
*
* @return
*/
OperationLogType type() default OperationLogType.OTHER;
/**
* 日志备注
*
* @return
*/
String remark() default "";
}
package com.wecloud.im.core.log.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略操作日志记录注解
* 在controller上标注该方法后,将不会记录操作日志
* 可以标注在类和方法上,如果标记在类上,则会忽略controller中的所有方法
*
* @author geekidea
* @date 2020/3/19
**/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLogIgnore {
}
package com.wecloud.im.core.log.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import com.wecloud.im.core.common.enums.BaseEnum;
/**
* 操作日志类型枚举
*
* @author geekidea
* @date 2020/3/19
**/
@Getter
@AllArgsConstructor
public enum OperationLogType implements BaseEnum {
/**
* 其它
**/
OTHER(0, "其它"),
/**
* 添加
**/
ADD(1, "添加"),
/**
* 修改
**/
UPDATE(2, "修改"),
/**
* 删除
**/
DELETE(3, "删除"),
/**
* 查询
**/
query(4, "详情查询"),
/**
* 详情查询
**/
INFO(5, "详情查询"),
/**
* 列表查询
**/
LIST(6, "列表查询"),
/**
* 分页列表
**/
PAGE(7, "分页列表"),
/**
* 其它查询
**/
OTHER_QUERY(8, "其它查询"),
/**
* 文件上传
**/
UPLOAD(9, "文件上传"),
/**
* 文件下载
**/
download(10, "文件下载"),
/**
* Excel导入
**/
excel_import(11, "Excel导入"),
/**
* Excel导出
**/
EXCEL_EXPORT(12, "Excel导出");
private Integer code;
private String desc;
}
package com.wecloud.im.core.pagination;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
/**
* 可排序查询参数对象
*
* @author geekidea
* @since 2019-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("可排序查询参数对象")
public abstract class BasePageOrderParam extends BasePageParam {
private static final long serialVersionUID = 57714391204790143L;
@ApiModelProperty("排序")
private List<OrderItem> pageSorts;
public void defaultPageSort(OrderItem orderItem) {
this.defaultPageSorts(Arrays.asList(orderItem));
}
public void defaultPageSorts(List<OrderItem> pageSorts) {
if (CollectionUtils.isEmpty(pageSorts)) {
return;
}
this.pageSorts = pageSorts;
}
}
package com.wecloud.im.core.pagination;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import com.wecloud.im.core.constant.CommonConstant;
/**
* 查询参数
*
* @author geekidea
* @since 2018-11-08
*/
@Data
@ApiModel("查询参数对象")
public abstract class BasePageParam implements Serializable {
private static final long serialVersionUID = -3263921252635611410L;
@ApiModelProperty(value = "页码,默认为1", example = "1")
private Long pageIndex = CommonConstant.DEFAULT_PAGE_INDEX;
@ApiModelProperty(value = "页大小,默认为10", example = "10")
private Long pageSize = CommonConstant.DEFAULT_PAGE_SIZE;
@ApiModelProperty(value = "搜索字符串", example = "")
private String keyword;
public void setPageIndex(Long pageIndex) {
if (pageIndex == null || pageIndex <= 0) {
this.pageIndex = CommonConstant.DEFAULT_PAGE_INDEX;
} else {
this.pageIndex = pageIndex;
}
}
public void setPageSize(Long pageSize) {
if (pageSize == null || pageSize <= 0) {
this.pageSize = CommonConstant.DEFAULT_PAGE_SIZE;
} else if (pageSize > CommonConstant.MAX_PAGE_SIZE) {
// 每页不能超过100
this.pageSize = CommonConstant.MAX_PAGE_SIZE;
} else {
this.pageSize = pageSize;
}
}
}
package com.wecloud.im.core.pagination;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.google.common.base.CaseFormat;
import com.wecloud.im.core.util.PropertyColumnUtil;
/**
* 排序列映射
*
* @author geekidea
* @date 2020/3/14
**/
@Data
@Accessors(chain = true)
public class OrderMapping {
private boolean underLineMode;
private Map<String, String> map = new ConcurrentHashMap<>();
public OrderMapping() {
}
public OrderMapping(boolean underLineMode) {
this.underLineMode = underLineMode;
}
public OrderMapping mapping(String property, String column) {
map.put(property, column);
return this;
}
public OrderMapping mapping(String property, String tablePrefix, String column) {
if (StringUtils.isNotBlank(tablePrefix)) {
column = tablePrefix + "." + column;
}
map.put(property, column);
return this;
}
public OrderMapping mapping(String property, Class<?> clazz) {
String column = PropertyColumnUtil.getColumn(clazz, property);
map.put(property, column);
return this;
}
public OrderMapping mapping(String property, String tablePrefix, Class<?> clazz) {
String column = PropertyColumnUtil.getColumn(clazz, property);
mapping(property, tablePrefix, column);
return this;
}
public String getMappingColumn(String property) {
if (StringUtils.isBlank(property)) {
return null;
}
return map.get(property);
}
public void filterOrderItems(List<OrderItem> orderItems) {
if (CollectionUtils.isEmpty(orderItems)) {
return;
}
// 如果集合不为空,则按照PropertyColumnUtil映射
if (MapUtils.isNotEmpty(map)) {
orderItems.forEach(item -> {
item.setColumn(this.getMappingColumn(item.getColumn()));
});
} else if (underLineMode) {
// 如果开启下划线模式,自动转换成下划线
orderItems.forEach(item -> {
String column = item.getColumn();
if (StringUtils.isNotBlank(column)) {
// 驼峰转换成下划线
item.setColumn(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column));
}
});
}
}
}
package com.wecloud.im.core.pagination;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* 自定义分页参数
*
* @author geekidea
* @date 2020/3/27
**/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class PageInfo<T> extends Page<T> {
private static final long serialVersionUID = -2211095086394170578L;
/**
* 分页参数
*/
private BasePageParam pageParam;
/**
* 默认排序字段信息
*/
private OrderItem defaultOrderItem;
/**
* 排序字段映射
*/
private OrderMapping orderMapping;
public PageInfo() {
}
/**
* 传入分页参数
*
* @param pageParam
*/
public PageInfo(BasePageParam pageParam) {
this(pageParam, null, null);
}
/**
* 传入分页参数,默认排序
*
* @param basePageParam 分页相关参数
* @param defaultOrderItem 默认排序字段
*/
public PageInfo(BasePageParam basePageParam, OrderItem defaultOrderItem) {
this(basePageParam, defaultOrderItem, null);
}
/**
* 传入分页参数,排序字段映射
*
* @param pageParam
* @param orderMapping
*/
public PageInfo(BasePageParam pageParam, OrderMapping orderMapping) {
this(pageParam, null, orderMapping);
}
/**
* 传入分页参数,默认排序,排序字段映射
*
* @param pageParam
* @param defaultOrderItem
* @param orderMapping
*/
public PageInfo(BasePageParam pageParam, OrderItem defaultOrderItem, OrderMapping orderMapping) {
this.pageParam = pageParam;
this.defaultOrderItem = defaultOrderItem;
this.orderMapping = orderMapping;
this.handle();
}
/**
* 分页构造函数
*
* @param current 当前页
* @param size 每页显示条数
*/
public PageInfo(long current, long size) {
super(current, size, 0);
}
public PageInfo(long current, long size, long total) {
super(current, size, total, true);
}
public PageInfo(long current, long size, boolean isSearchCount) {
super(current, size, isSearchCount);
}
public PageInfo(long current, long size, long total, boolean isSearchCount) {
super(current, size, total, isSearchCount);
}
/**
* 如果是pageParam是OrderPageParam,并且不为空,则使用前端排序
* 否则使用默认排序
*/
private void handle() {
if (pageParam == null) {
return;
}
// 设置pageIndex/pageSize
super.setCurrent(pageParam.getPageIndex());
super.setSize(pageParam.getPageSize());
// 排序字段处理
BasePageOrderParam basePageOrderParam = (BasePageOrderParam) pageParam;
List<OrderItem> orderItems = basePageOrderParam.getPageSorts();
if (CollectionUtils.isEmpty(orderItems)) {
setDefaultOrder(defaultOrderItem);
return;
}
if (orderMapping == null) {
orderMapping = new OrderMapping(true);
}
orderMapping.filterOrderItems(orderItems);
super.setOrders(orderItems);
}
/**
* 设置默认排序
*
* @param defaultOrderItem
* @return
*/
public PageInfo<T> setDefaultOrder(OrderItem defaultOrderItem) {
if (defaultOrderItem != null) {
this.defaultOrderItem = defaultOrderItem;
super.setOrders(Arrays.asList(defaultOrderItem));
}
return this;
}
}
package com.wecloud.im.core.pagination;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.wecloud.im.core.constant.CommonConstant;
/**
* 分页结果对象
*
* @author geekidea
* @date 2018-11-08
*/
@Slf4j
@Data
@ApiModel("分页结果对象")
public class Paging<T> implements Serializable {
private static final long serialVersionUID = 4784961132604516495L;
@ApiModelProperty("总行数")
@JSONField(name = CommonConstant.PAGE_TOTAL_NAME)
@JsonProperty(CommonConstant.PAGE_TOTAL_NAME)
private long total = 0;
@ApiModelProperty("数据列表")
@JSONField(name = CommonConstant.PAGE_RECORDS_NAME)
@JsonProperty(CommonConstant.PAGE_RECORDS_NAME)
private List<T> records = Collections.emptyList();
@ApiModelProperty(value = "页码")
@JSONField(name = CommonConstant.PAGE_INDEX_NAME)
@JsonProperty(CommonConstant.PAGE_INDEX_NAME)
private Long pageIndex;
@ApiModelProperty(value = "页大小")
@JSONField(name = CommonConstant.PAGE_SIZE_NAME)
@JsonProperty(CommonConstant.PAGE_SIZE_NAME)
private Long pageSize;
public Paging() {
}
public Paging(IPage<T> page) {
this.total = page.getTotal();
this.records = page.getRecords();
this.pageIndex = page.getCurrent();
this.pageSize = page.getSize();
}
}
package com.wecloud.im.core.util;
import com.wecloud.im.core.common.exception.BusinessException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* @Author wenzhida
* @Date 2022/2/21 22:26
* @Description 加解密工具类
*/
public class AesUtil {
private static final String S_KEY = "weeKeejjLL123.VB";
/**
* 加密
* @param sSrc
* @return
*/
public static String encrypt(String sSrc) {
try {
byte[] raw = S_KEY.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
// "算法/模式/补码方式"
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(encrypted);
} catch (Exception e) {
throw new BusinessException("系统异常,稍后重试");
}
}
/**
* 解密
* @param sSrc
* @return
* @throws Exception
*/
public static String decrypt(String sSrc) {
try {
byte[] raw = S_KEY.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
Base64.Decoder decoder = Base64.getDecoder();
byte[] encrypted1 = decoder.decode(sSrc);//先用base64解密
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "utf-8");
return originalString;
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
} catch (Exception ex) {
System.out.println(ex.toString());
return null;
}
}
public static void main(String[] args) throws Exception {
// 需要加密的字串
String cSrc = "123";
System.out.println(cSrc);
// 加密
String enString = AesUtil.encrypt(cSrc);
System.out.println("加密后的字串是:" + enString);
// 解密
String DeString = AesUtil.decrypt(enString);
System.out.println("解密后的字串是:" + DeString);
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import org.fusesource.jansi.Ansi;
import org.springframework.core.env.Environment;
/**
* @author geekidea
* @date 2018-11-08
*/
@Slf4j
public class AnsiUtil {
private static final boolean ENABLE_ANSI;
static {
Boolean value = false;
try {
Environment environment = SpringContextUtil.getBean(Environment.class);
value = environment.getProperty("spring-boot-plus.enable-ansi", boolean.class);
value = value == null ? false : value;
} catch (Exception e) {
e.printStackTrace();
}
ENABLE_ANSI = value;
}
public static String getAnsi(Ansi.Color color, String text) {
if (ENABLE_ANSI) {
return Ansi.ansi().eraseScreen().fg(color).a(text).reset().toString();
}
return text;
}
public static String getAnsi(Ansi.Color color, String text, boolean flag) {
if (flag) {
return Ansi.ansi().eraseScreen().fg(color).a(text).reset().toString();
}
return text;
}
}
package com.wecloud.im.core.util;
import java.util.Base64;
/**
* @Author wenzhida
* @Date 2022/2/21 22:37
* @Description BASE64加密/解密
*/
public class Base64Util {
/***
* BASE64解密
* @param key
* @return
* @throws Exception
*/
public static byte[] decryBASE64(String key) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(key);
}
/***
* BASE64加密
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(key);
}
}
package com.wecloud.im.core.util;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.MapUtils;
import com.wecloud.im.core.common.enums.BaseEnum;
import com.wecloud.im.core.common.vo.EnumVo;
/**
* BaseEnum枚举工具类
*
* @author geekidea
* @date 2018-11-08
*/
public class BaseEnumUtil {
private static final Map<String, Map<Integer, EnumVo<? extends BaseEnum>>> ENUM_MAP = new LinkedHashMap<>();
/**
* 通过code获取描述
*
* @param baseEnumType
* @param code
* @return
*/
public static BaseEnum getEnum(Class<? extends BaseEnum> baseEnumType, Integer code) {
EnumVo<? extends BaseEnum> enumVo = getEnumVo(baseEnumType, code);
if (enumVo == null) {
return null;
}
return enumVo.getBaseEnum();
}
/**
* 通过code获取描述
*
* @param baseEnumType
* @param code
* @return
*/
public static EnumVo<? extends BaseEnum> getEnumVo(Class<? extends BaseEnum> baseEnumType, Integer code) {
Map<Integer, EnumVo<? extends BaseEnum>> map = getMap(baseEnumType);
if (MapUtils.isEmpty(map)) {
return null;
}
return map.get(code);
}
/**
* 判断code在枚举中是否存在
*
* @param baseEnumType
* @param code
* @return
*/
public static boolean exists(Class<? extends BaseEnum> baseEnumType, Integer code) {
EnumVo<? extends BaseEnum> enumVo = getEnumVo(baseEnumType, code);
if (enumVo == null) {
return false;
}
return true;
}
/**
* 判断code在枚举中是否不存在
*
* @param baseEnumType
* @param code
* @return
*/
public static boolean notExists(Class<? extends BaseEnum> baseEnumType, Integer code) {
return !exists(baseEnumType, code);
}
/**
* 通过code获取描述
*
* @param baseEnumType
* @param code
* @return
*/
public static String getDesc(Class<? extends BaseEnum> baseEnumType, Integer code) {
EnumVo<? extends BaseEnum> enumVo = getEnumVo(baseEnumType, code);
if (enumVo == null) {
return null;
}
return enumVo.getDesc();
}
/**
* 通过类型获取枚举Map
*
* @param baseEnumType
* @return
*/
public static Map<Integer, EnumVo<? extends BaseEnum>> getMap(Class<? extends BaseEnum> baseEnumType) {
return ENUM_MAP.get(baseEnumType.getName());
}
/**
* 通过类型获取枚举code集合
*
* @param baseEnumType
* @return
*/
public static Set<Integer> getCodeSet(Class<? extends BaseEnum> baseEnumType) {
Map<Integer, EnumVo<? extends BaseEnum>> map = getMap(baseEnumType);
if (MapUtils.isEmpty(map)) {
return null;
}
return map.keySet();
}
/**
* 通过类型获取枚举desc集合
*
* @param baseEnumType
* @return
*/
public static Collection<EnumVo<? extends BaseEnum>> getDescList(Class<? extends BaseEnum> baseEnumType) {
Map<Integer, EnumVo<? extends BaseEnum>> map = getMap(baseEnumType);
if (MapUtils.isEmpty(map)) {
return null;
}
return map.values();
}
public static Map<String, Map<Integer, EnumVo<? extends BaseEnum>>> getEnumMap() {
return ENUM_MAP;
}
}
package com.wecloud.im.core.util;
import javax.servlet.http.HttpServletRequest;
/**
* <code>
* 浏览器工具类<br/>
* 1.获取当前浏览器名称
* 2.判断当前用户的浏览器
* </code>
*
* @author geekidea
* @since 2018-11-08
*/
public final class BrowserUtil {
public static final String IE = "msie";
public static final String FIREFOX = "firefox";
public static final String CHROME = "chrome";
private BrowserUtil() {
throw new AssertionError();
}
/**
* 获取当前浏览器名称
*
* @param request
* @return 返回浏览器名称
*/
public static String getCurrent(HttpServletRequest request) {
String userAgent = request.getHeader("USER-AGENT").toLowerCase();
if (userAgent != null && !("".equals(userAgent.trim()))) {
if (userAgent.indexOf(CHROME) >= 0) {
return CHROME;
} else if (userAgent.indexOf(FIREFOX) >= 0) {
return FIREFOX;
} else if (userAgent.indexOf(IE) >= 0) {
return IE;
}
}
return null;
}
/**
* 是否是IE浏览器
*
* @param request
* @return
*/
public static boolean isIe(HttpServletRequest request) {
return IE.equals(getCurrent(request));
}
/**
* 是否是Firefox浏览器
*
* @param request
* @return
*/
public static boolean isFirefox(HttpServletRequest request) {
return FIREFOX.equals(getCurrent(request));
}
/**
* 是否是Chrome浏览器
*
* @param request
* @return
*/
public static boolean isChrome(HttpServletRequest request) {
return CHROME.equals(getCurrent(request));
}
}
package com.wecloud.im.core.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.wecloud.im.core.common.bean.ClientInfo;
import com.wecloud.im.core.common.bean.DeviceInfo;
import com.wecloud.im.core.constant.CommonConstant;
/**
* <p>
* 用户客户端信息工具类
* </p>
*
* @author geekidea
* @date 2019-05-24
**/
public class ClientInfoUtil {
private static final Pattern DEVICE_INFO_PATTERN = Pattern.compile(";\\s?(\\S*?\\s?\\S*?)\\s?Build/(\\S*?)[;)]");
private static final Pattern DEVICE_INFO_PATTERN_1 = Pattern.compile(";\\s?(\\S*?\\s?\\S*?)\\s?\\)");
/**
* 获取用户客户端信息
*
* @param request
* @return
*/
public static ClientInfo get(HttpServletRequest request) {
String userAgent = request.getHeader(CommonConstant.USER_AGENT);
return get(userAgent);
}
/**
* 获取用户客户端信息
*
* @param userAgentString
* @return
*/
public static ClientInfo get(String userAgentString) {
ClientInfo clientInfo = new ClientInfo();
UserAgent userAgent = UserAgentUtil.parse(userAgentString);
// 浏览器名称
clientInfo.setBrowserName(userAgent.getBrowser().getName());
// 浏览器版本
clientInfo.setBrowserversion(userAgent.getVersion());
// 浏览器引擎名称
clientInfo.setEngineName(userAgent.getEngine().getName());
// 浏览器引擎版本
clientInfo.setEngineVersion(userAgent.getEngineVersion());
// 用户操作系统名称
clientInfo.setOsName(userAgent.getOs().getName());
// 用户操作平台名称
clientInfo.setPlatformName(userAgent.getPlatform().getName());
// 是否是手机
clientInfo.setMobile(userAgent.isMobile());
// 获取移动设备名称和机型
DeviceInfo deviceInfo = getDeviceInfo(userAgentString);
// 设置移动设备名称和机型
clientInfo.setDeviceName(deviceInfo.getName());
clientInfo.setDeviceModel(deviceInfo.getModel());
// ip
clientInfo.setIp(IpUtil.getRequestIp());
return clientInfo;
}
/**
* 获取移动端用户设备的名称和机型
*
* @param userAgentString
* @return
*/
public static DeviceInfo getDeviceInfo(String userAgentString) {
DeviceInfo deviceInfo = new DeviceInfo();
try {
Matcher matcher = DEVICE_INFO_PATTERN.matcher(userAgentString);
String model = null;
String name = null;
if (matcher.find()) {
model = matcher.group(1);
name = matcher.group(2);
}
if (model == null && name == null) {
matcher = DEVICE_INFO_PATTERN_1.matcher(userAgentString);
if (matcher.find()) {
model = matcher.group(1);
}
}
deviceInfo.setName(name);
deviceInfo.setModel(model);
} catch (Exception e) {
e.printStackTrace();
}
return deviceInfo;
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
/**
* 获取文件的内容类型
* mime-type参考:https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?revision=1752884&view=co
*
* @author geekidea
* @date 2019/08/20
* @since
*/
@Slf4j
public final class ContentTypeUtil {
private static final String MIME_TYPE_CONFIG_FILE = "config/mime-type.properties";
private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
private static Properties properties;
static {
try {
properties = PropertiesLoaderUtils.loadProperties(new ClassPathResource(MIME_TYPE_CONFIG_FILE));
} catch (IOException e) {
log.error("读取配置文件" + MIME_TYPE_CONFIG_FILE + "异常", e);
}
log.info(MIME_TYPE_CONFIG_FILE + " = " + properties);
}
/**
* 获取文件内容类型
*
* @param file
* @return
*/
public static String getContentType(File file) {
if (file == null) {
return null;
}
Path path = Paths.get(file.toURI());
if (path == null) {
return null;
}
String contentType = null;
try {
contentType = Files.probeContentType(path);
} catch (IOException e) {
log.error("获取文件ContentType异常", e);
}
if (contentType == null) {
// 读取拓展的自定义配置
contentType = getContentTypeByExtension(file);
}
// 设置默认的内容类型
if (contentType == null) {
contentType = DEFAULT_MIME_TYPE;
}
return contentType;
}
/**
* 根据文件后缀获取自定义配置的文件mime-type
*
* @param file
* @return
*/
private static String getContentTypeByExtension(File file) {
if (properties == null) {
return null;
}
String extension = FilenameUtils.getExtension(file.getName());
if (StringUtils.isBlank(extension)) {
return null;
}
String contentType = properties.getProperty(extension);
return contentType;
}
}
package com.wecloud.im.core.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.wecloud.im.core.constant.DatePattern;
/**
* @author geekidea
* @date 2018-11-08
*/
public class DateUtil {
public static String getDateString(Date date) {
if (date == null) {
return null;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.YYYY_MM_DD);
String dateString = simpleDateFormat.format(date);
return dateString;
}
public static String getDateTimeString(Date date) {
if (date == null) {
return null;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.YYYY_MM_DD_HH_MM_SS);
String dateString = simpleDateFormat.format(date);
return dateString;
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Base64Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;
import com.wecloud.im.core.constant.CommonConstant;
/**
* 文件下载工具类
*
* @author geekidea
* @date 2019/8/21
* @since 1.2.1-RELEASE
*/
@Slf4j
public final class DownloadUtil {
/**
* 下载文件,使用默认下载处理器
*
* @param downloadDir
* @param downloadFileName
* @param allowFileExtensions
* @param response
* @throws Exception
*/
public static void download(String downloadDir, String downloadFileName, List<String> allowFileExtensions, HttpServletResponse response) throws Exception {
download(downloadDir, downloadFileName, allowFileExtensions, response, new DefaultDownloadHandler());
}
/**
* 下载文件,使用自定义下载处理器
*
* @param downloadDir 文件目录
* @param downloadFileName 文件名称
* @throws Exception
*/
public static void download(String downloadDir, String downloadFileName, List<String> allowFileExtensions, HttpServletResponse response, DownloadHandler downloadHandler) throws Exception {
log.info("downloadDir:{}", downloadDir);
log.info("downloadFileName:{}", downloadFileName);
if (StringUtils.isBlank(downloadDir)) {
throw new IOException("文件目录不能为空");
}
if (StringUtils.isBlank(downloadFileName)) {
throw new IOException("文件名称不能为空");
}
// 安全判断,防止../情况,防止出现类似非法文件名称:../../hello/123.txt
if (downloadFileName.contains(CommonConstant.SPOT_SPOT) || downloadFileName.contains(CommonConstant.SPOT_SPOT_BACKSLASH)) {
throw new IOException("非法的文件名称");
}
// 允许下载的文件后缀判断
if (CollectionUtils.isEmpty(allowFileExtensions)) {
throw new IllegalArgumentException("请设置允许下载的文件后缀");
}
// 获取文件名称
String fileExtension = FilenameUtils.getExtension(downloadFileName);
// 从服务器读取文件,然后输出
File downloadFile = new File(downloadDir, downloadFileName);
if (!downloadFile.exists()) {
throw new IOException("文件不存在");
}
// 判断文件类型,输出对应ContentType,如果没有对应的内容类型,可在config/mime-type.properties配置
String contentType = ContentTypeUtil.getContentType(downloadFile);
log.info("contentType:{}", contentType);
// 文件大小
long length = downloadFile.length();
log.info("length:{}", length);
// 下载回调处理
if (downloadHandler == null) {
// 使用默认下载处理器
downloadHandler = new DefaultDownloadHandler();
}
boolean flag = downloadHandler.handle(downloadDir, downloadFileName, downloadFile, fileExtension, contentType, length);
if (!flag) {
log.info("下载自定义校验失败,取消下载");
return;
}
// 下载文件名称编码,Firefox中文乱码处理
String encodeDownFileName;
HttpServletRequest request = HttpServletRequestUtil.getRequest();
String browser = BrowserUtil.getCurrent(request);
if (BrowserUtil.FIREFOX.equals(browser)) {
encodeDownFileName = "=?UTF-8?B?" + (Base64Utils.encodeToString(downloadFileName.getBytes(StandardCharsets.UTF_8))) + "?=";
} else {
encodeDownFileName = URLEncoder.encode(downloadFileName, "utf-8").replaceAll("\\+", "%20");
}
log.info("encodeDownFileName:{}", encodeDownFileName);
log.info("下载文件:" + downloadFile.getAbsolutePath());
response.reset();
// 设置Content-Disposition响应头
response.setHeader("Content-Disposition", "attachment;fileName=\"" + encodeDownFileName + "\"");
// 设置响应Content-Type
response.setContentType(contentType);
// 设置响应文件大小
response.setContentLengthLong(length);
// 文件下载
InputStream in = new BufferedInputStream(new FileInputStream(downloadFile));
FileCopyUtils.copy(in, response.getOutputStream());
}
public interface DownloadHandler {
/**
* 下载自定义处理
*
* @param dir
* @param fileName
* @param file
* @param fileExtension
* @param contentType
* @param length
* @return
* @throws Exception
*/
boolean handle(String dir, String fileName, File file, String fileExtension, String contentType, long length) throws Exception;
}
public static class DefaultDownloadHandler implements DownloadHandler {
@Override
public boolean handle(String dir, String fileName, File file, String fileExtension, String contentType, long length) throws Exception {
return false;
}
}
}
package com.wecloud.im.core.util;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
/**
* 获取公网ip
*/
@Component
@Slf4j
public class GetIpUtils {
private static final String LOCAL = "local";
private static final String AWS = "aws";
private static final String HUAWEI_CLOUD = "huawei";
/**
* 内网ip
*/
private static String lAN_IP = null;
/**
* 公网ip
*/
private static String PUBLIC_IP = null;
/**
* 服务器运营商local,aws,huawei
*/
@Value("${load-blance.server-type}")
private String serverType;
/**
* 排除无效的mac地址
*/
private final static byte[][] INVALID_MACS = {
{0x00, 0x05, 0x69}, // VMWare
{0x00, 0x1C, 0x14}, // VMWare
{0x00, 0x0C, 0x29}, // VMWare
{0x00, 0x50, 0x56}, // VMWare
{0x08, 0x00, 0x27}, // Virtualbox
{0x0A, 0x00, 0x27}, // Virtualbox
{0x00, 0x03, (byte) 0xFF}, // Virtual-PC
{0x00, 0x15, 0x5D} // Hyper-V
};
/**
* 判断是否为虚拟mac地址
*
* @param mac
* @return
*/
private static boolean isVmMac(byte[] mac) {
if (null == mac) {
return false;
}
for (byte[] invalid : INVALID_MACS) {
if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) {
return true;
}
}
return false;
}
/**
* 获取本机地址
*/
private static String getLocalIpAddress() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ni = networkInterfaces.nextElement();
/*
排除docker虚拟网卡
*/
String docker0 = "docker0";
if (ni.getName().equals(docker0)) {
continue;
}
if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) {
continue;
}
if (isVmMac(ni.getHardwareAddress())) {
continue;
}
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress.isLinkLocalAddress()) {
continue;
}
return inetAddress.getHostAddress();
}
}
} catch (SocketException e) {
log.info("获取本机IP地址失败。" + e);
}
return StringUtils.EMPTY;
}
/**
* 内网ip
*
* @return
*/
public static String getlanIp() {
if (lAN_IP == null) {
synchronized (GetIpUtils.class) {
if(lAN_IP == null) {
lAN_IP = getLocalIpAddress();
}
}
}
return lAN_IP;
}
/**
* 公网ip
*/
public String getPublicIp() {
if (PUBLIC_IP == null) {
switch (serverType) {
case LOCAL:
PUBLIC_IP = getlanIp();
break;
case AWS:
PUBLIC_IP = HttpUtil.get("http://instance-data/latest/meta-data/public-ipv4", 30);
break;
case HUAWEI_CLOUD:
PUBLIC_IP = HttpUtil.get("http://169.254.169.254/latest/meta-data/public-ipv4", 30);
break;
default:
}
}
return PUBLIC_IP;
}
}
package com.wecloud.im.core.util;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 获取当前请求的HttpServletRequest对象
* http上下文对象
*
* @author geekidea
* @date 2018-11-08
*/
public class HttpServletRequestUtil {
public static HttpServletRequest getRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
package com.wecloud.im.core.util;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
/**
* @author geekidea
* @date 2018-11-08
*/
public final class HttpServletResponseUtil {
private static final String UTF8 = "UTF-8";
private static final String CONTENT_TYPE = "application/json";
private HttpServletResponseUtil() {
throw new AssertionError();
}
public static void printJson(HttpServletResponse response, Object object) throws Exception {
response.setCharacterEncoding(UTF8);
response.setContentType(CONTENT_TYPE);
PrintWriter printWriter = response.getWriter();
printWriter.write(JSON.toJSONString(object));
printWriter.flush();
printWriter.close();
}
}
package com.wecloud.im.core.util;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import org.ini4j.Config;
import org.ini4j.Ini;
import org.ini4j.Profile;
/**
* @author geekidea
* @date 2019-09-29
* @since 1.3.0.RELEASE
**/
public class IniUtil {
public static Map<String, String> parseIni(String string) {
Config config = new Config();
config.setGlobalSection(true);
config.setGlobalSectionName("");
Ini ini = new Ini();
ini.setConfig(config);
try {
ini.load(new StringReader(string));
Profile.Section section = ini.get("");
return section;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static Map<String, String> parseIni(String sectionName, String string) {
Ini ini = new Ini();
try {
ini.load(new StringReader(string));
Profile.Section section = ini.get(sectionName);
return section;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
package com.wecloud.im.core.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 获取IP地址工具类
*
* @author geekidea
* @date 2018-11-08
*/
public final class IpUtil {
private static final String UNKNOWN = "unknown";
private static final String IPV6_LOCAL = "0:0:0:0:0:0:0:1";
private IpUtil() {
throw new AssertionError();
}
/**
* 获取请求用户的IP地址
*
* @return
*/
public static String getRequestIp() {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
return getRequestIp(request);
}
/**
* 获取请求用户的IP地址
*
* @param request
* @return
*/
public static String getRequestIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (IPV6_LOCAL.equals(ip)) {
ip = getLocalhostIp();
}
return ip;
}
public static String getLocalhostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
return null;
}
}
package com.wecloud.im.core.util;
import java.util.TimeZone;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* Jackson序列化工具类
*
* @author geekidea
* @date 2019-11-01
**/
public class Jackson {
/**
* 时区
*/
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone("GMT");
/**
* 键按自然顺序输出
*
* @param object
* @return
*/
public static String toJsonString(Object object) {
return toJsonString(object, false);
}
/**
* 键按自然顺序格式化输出
*
* @param object
* @param prettyFormat
* @return
*/
public static String toJsonString(Object object, boolean prettyFormat) {
if (object == null) {
return null;
}
ObjectMapper objectMapper = new ObjectMapper();
try {
// 格式化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, prettyFormat);
// 键按自然顺序输出
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
// 设置时区
objectMapper.setTimeZone(TIME_ZONE);
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 键按自然顺序格式化输出
*
* @param object
* @return
*/
public static String toJsonStringNonNull(Object object) {
return toJsonStringNonNull(object, false);
}
/**
* 键按自然顺序格式化输出
*
* @param object
* @param prettyFormat
* @return
*/
public static String toJsonStringNonNull(Object object, boolean prettyFormat) {
if (object == null) {
return null;
}
ObjectMapper objectMapper = new ObjectMapper();
try {
// 格式化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, prettyFormat);
// 键按自然顺序输出
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
// 为空的序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 设置时区
objectMapper.setTimeZone(TIME_ZONE);
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
package com.wecloud.im.core.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.beans.BeanMap;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* fasterxml 的json工具类
*
* @author lixiaozhong
*/
@Slf4j
public class JsonUtils {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* Json格式的字符串向JavaBean转换,传入空串将返回null
*
* @param strJsonBody Json格式的字符串
* @param c 目标JavaBean类型
* @return JavaBean对象, 如果解析失败返回 null
*/
public static <T> T decodeJson(String strJsonBody, Class<T> c) {
if (StringUtils.isEmpty(strJsonBody)) {
return null;
}
try {
return OBJECT_MAPPER.readValue(strJsonBody, c);
} catch (IOException e) {
log.warn("解析json字符串失败,原字符串: {} class {}", strJsonBody, c, e);
return null;
}
}
/**
* Json格式的字符串向JavaBean转换,传入空串将返回null (显式抛出异常)
*
* @param strJsonBody Json格式的字符串
* @param c 目标JavaBean类型
* @return JavaBean对象
* @throws IOException
*/
public static <T> T json2Object(String strJsonBody, Class<T> c) throws IOException {
if (StringUtils.isEmpty(strJsonBody)) {
return null;
}
return OBJECT_MAPPER.readValue(strJsonBody, c);
}
/**
* Json格式的字符串向HashMap转换,传入空串将返回空map (显式抛出异常)
*
* @param strJsonBody Json格式的字符串
* @return HashMap对象
* @throws IOException
*/
public static HashMap<String, Object> json2Map(String strJsonBody) throws IOException {
if (StringUtils.isEmpty(strJsonBody)) {
return new HashMap<String, Object>();
}
return OBJECT_MAPPER.readValue(strJsonBody, HashMap.class);
}
/**
* Json格式的字符串向HashMap转换,传入空串将返回空map
*
* @param strJsonBody Json格式的字符串
* @return HashMap对象
* @throws IOException
*/
public static HashMap<String, Object> decodeJson2Map(String strJsonBody) {
if (StringUtils.isEmpty(strJsonBody)) {
return new HashMap<String, Object>();
}
try {
return OBJECT_MAPPER.readValue(strJsonBody, HashMap.class);
} catch (IOException e) {
log.warn("解析json字符串失败,原字符串: {}", strJsonBody);
return null;
}
}
/**
*将json转换成Object对象
* @param strJsonBody
* @return
* @throws IOException
*/
public static Object json2Object(String strJsonBody) throws IOException {
if (StringUtils.isEmpty(strJsonBody)) {
return null;
}
// 每个属性的实际类型是string
return OBJECT_MAPPER.readValue(strJsonBody, Object.class);
}
/**
* Json格式的字符串向JavaBean List集合转换,传入空串将返回空list (显式抛出异常)
*
* @param strJsonBody
* @param c
* @return
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static <T> List<T> json2List(String strJsonBody, Class<T> c) throws IOException {
if (StringUtils.isEmpty(strJsonBody)) {
return Collections.emptyList();
}
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(ArrayList.class, c);
return OBJECT_MAPPER.readValue(strJsonBody, javaType);
}
/**
* Json格式的字符串向JavaBean List集合转换,传入空串将返回空list
*
* @param strJsonBody
* @param c
* @return 对象列表,解析失败返回 null
*/
@SuppressWarnings("unchecked")
public static <T> List<T> decodeJsonToList(String strJsonBody, Class<T> c) {
if (StringUtils.isEmpty(strJsonBody)) {
return Collections.emptyList();
}
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(ArrayList.class, c);
try {
return OBJECT_MAPPER.readValue(strJsonBody, javaType);
} catch (IOException e) {
log.warn("解析json字符串失败,原字符串: {}", strJsonBody);
return null;
}
}
/**
* Json格式的字符串向List<String>集合转换,传入空串将返回null
*
* @param strJsonBody
* @return
* @throws IOException
*/
public static List<String> json2List(String strJsonBody) throws IOException {
return json2List(strJsonBody, String.class);
}
/**
* Object转为Json格式字符串的方法(显式抛出异常)
*
* @param o
* @return
* @throws JsonProcessingException
*/
public static String object2Json(Object o) throws JsonProcessingException {
return OBJECT_MAPPER.writeValueAsString(o);
}
/**
* Object转为Json格式字符串的方法
*
* @param o
* @return 对象的json字符串,如果处理过程中出错,返回null
*/
public static String encodeJson(Object o) {
try {
return OBJECT_MAPPER.writeValueAsString(o);
} catch (JsonProcessingException e) {
log.warn("对象转换成json失败");
return null;
}
}
/**
* 判断字符也许是JSON
*
* @param string
* @return
*/
public static boolean maybeJson(String string) {
return maybeJsonArray(string) || maybeJsonObject(string);
}
/**
* 判断字符也许是JSONArray
*
* @param string
* @return
*/
public static boolean maybeJsonArray(String string) {
string = (null == string) ? string : string.trim();
return string != null && ("null".equals(string) || (string.startsWith("[") && string.endsWith("]")));
}
/**
* 判断字符也许是JSONObject
*
* @param string
* @return
*/
public static boolean maybeJsonObject(String string) {
string = (null == string) ? string : string.trim();
return string != null && ("null".equals(string) || (string.startsWith("{") && string.endsWith("}")));
}
/**
* 将map装换为javabean对象,不支持深度转换,支持深度请看 mapToBeanDeep 方法
*
* @param map
* @param clazz
* @return
*/
public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
T obj = null;
try {
obj = clazz.newInstance();
} catch (Exception e) {
log.error("mapToBean转换,创建实例对象失败", e);
return null;
}
BeanMap beanMap = BeanMap.create(obj);
beanMap.putAll(map);
return obj;
}
/**
* 将一个 Map/javaBean 对象转化为一个 javaBean 深度
* @param srcObject 要转化的对象,可以是map,bean
* @param destClass 要转化的类型
* @return 转化出来的 JavaBean 对象
*/
public static <T>T beanCopyDeep(Object srcObject, Class<T> destClass) {
String s = encodeJson(srcObject);
return decodeJson(s, destClass);
}
private static boolean isFinalType(Class clazz) {
if (clazz == String.class ) {
return true;
}
if (clazz == Boolean.class) {
return true;
}
if (clazz == Long.class) {
return true;
}
if (clazz == Integer.class) {
return true;
}
if (clazz == Double.class) {
return true;
}
if (clazz == Float.class) {
return true;
}
if (clazz == Short.class) {
return true;
}
if (clazz == BigDecimal.class) {
return true;
}
if (clazz == Byte.class) {
return true;
}
if (clazz == int.class) {
return true;
}
if (clazz == long.class) {
return true;
}
if (clazz == float.class) {
return true;
}
if (clazz == double.class) {
return true;
}
if (clazz == byte.class) {
return true;
}
if (clazz == char.class) {
return true;
}
if (clazz == short.class) {
return true;
}
if (clazz == boolean.class) {
return true;
}
return false;
}
/**
* 将javabean对象转换为map
*/
public static <T> Map<String, Object> beanToMap(T bean) {
Map<String, Object> map = new HashMap();
if (bean != null) {
BeanMap beanMap = BeanMap.create(bean);
for (Object key : beanMap.keySet()) {
Object value = beanMap.get(key);
map.put(key + "", value);
}
}
return map;
}
}
package com.wecloud.im.core.util;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
/**
* 根据lambda表达式获取数据库列名
*
* @author geekidea
* @date 2019/12/22
**/
public class LambdaColumn<T> {
private static Map<String, Map<String, String>> ENTITY_COLUMN_MAP = new ConcurrentHashMap<>();
public static <T> LambdaColumn<T> lambda() {
return new LambdaColumn<>();
}
public String get(SFunction<T, ?> func) {
SerializedLambda lambda = LambdaUtils.resolve(func);
String methodName = lambda.getImplMethodName();
String methodPropertyName = null;
if (methodName.startsWith("get")) {
methodPropertyName = methodName.substring(3);
methodPropertyName = methodPropertyName.substring(0, 1).toLowerCase() + methodPropertyName.substring(1);
}
Class<?> cls = lambda.getImplClass();
String className = lambda.getImplClassName();
if (ENTITY_COLUMN_MAP.containsKey(className)) {
return ENTITY_COLUMN_MAP.get(className).get(methodPropertyName);
}
Map<String, String> map = getPropertyColumnMap(cls);
if (MapUtils.isNotEmpty(map)) {
ENTITY_COLUMN_MAP.put(className, map);
}
return ENTITY_COLUMN_MAP.get(className).get(methodPropertyName);
}
/**
* 从mybatisplus的TableInfo类中获取列名map信息
*
* @param cls
* @return
*/
private Map<String, String> getPropertyColumnMap(Class<?> cls) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
List<TableFieldInfo> tableFieldInfos = tableInfo.getFieldList();
if (CollectionUtils.isEmpty(tableFieldInfos)) {
return null;
}
Map<String, String> map = new ConcurrentHashMap<>();
String keyProperty = tableInfo.getKeyProperty();
String keyColumn = tableInfo.getKeyColumn();
map.put(keyProperty, keyColumn);
for (TableFieldInfo tableFieldInfo : tableFieldInfos) {
String column = tableFieldInfo.getColumn();
String property = tableFieldInfo.getProperty();
map.put(property, column);
}
return map;
}
}
package com.wecloud.im.core.util;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* Map构建工具类
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public class MapUtil {
private final Map<String, Object> map;
private MapUtil() {
map = new HashMap<>();
}
public static MapUtil builder() {
return new MapUtil();
}
public MapUtil put(String key, Object value) {
this.map.put(key, value);
return this;
}
public Map<String, Object> build() {
return this.map;
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
/**
* 密码加密工具类
*
* @author geekidea
* @date 2018-11-08
*/
@Slf4j
public class PasswordUtil {
/**
* 密码加盐,再加密
*
* @param pwd
* @param salt
* @return
*/
public static String encrypt(String pwd, String salt) {
if (StringUtils.isBlank(pwd)) {
throw new IllegalArgumentException("密码不能为空");
}
if (StringUtils.isBlank(salt)) {
throw new IllegalArgumentException("盐值不能为空");
}
return DigestUtils.sha256Hex(pwd + salt);
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
/**
* 手机号码工具类
*
* @author geekidea
* @date 2020/2/26
**/
@Slf4j
public class PhoneUtil {
/**
* 手机号码长度
*/
private static final int PHONE_LENGTH = 11;
/**
* 脱敏*号
*/
private static final String ASTERISK = "****";
/**
* 手机号码脱敏
* 截取手机号码前三位,后4为,中间4位使用*号代替
* 18812345678
* 188****5678
*
* @param phone
* @return
*/
public static String desensitize(String phone) {
// 校验手机号码
if (StringUtils.isBlank(phone)) {
return null;
}
if (phone.length() != PHONE_LENGTH) {
log.error("手机号码不合法:" + phone);
return phone;
}
String before = phone.substring(0, 3);
String after = phone.substring(7, 11);
String desensitizePhone = before + "****" + after;
return desensitizePhone;
}
public static void main(String[] args) {
String phone = desensitize("1881234567");
System.out.println("phone = " + phone);
}
}
package com.wecloud.im.core.util;
import lombok.extern.slf4j.Slf4j;
import org.fusesource.jansi.Ansi;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
/**
* <p>
* 打印项目信息
* </p>
*
* @author geekidea
* @date 2019-05-08
**/
@Slf4j
public class PrintApplicationInfo {
/**
* 执行之前,打印前置条件提示
*/
public static void printTip(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
// 项目profile
String profileActive = environment.getProperty("spring.profiles.active");
StringBuffer tip = new StringBuffer();
tip.append("===========================================================================================\n");
tip.append(" \n");
tip.append(" !!!准备工作!!! \n");
// tip.append(" 1.导入SQL初始化脚本:docs/db,根据不同数据库导入对应SQL脚本并修改链接等信息配置\n");
// tip.append(" 2.启动Redis服务,必要条件\n");
// tip.append(" 3.启动SpringBootAdmin Server,可选操作,admin模块中,启动SpringBootPlusAdminApplication\n");
// tip.append(" 4.根据项目需要,修改项目配置,请先查看官网配置文档:https://springboot.plus/config/\n");
// tip.append(" 5.项目模块说明:\n");
// tip.append(" admin: SpringBootAdmin Server启动模块\n");
tip.append(" bootstrap: 项目启动模块\n");
tip.append(" config: 项目配置模块\n");
// tip.append(" distribution:项目打包模块,打包时,请先选中Maven Profiles中的release和对应环境\n");
// tip.append(" example: 业务自定义模块,自己的业务代码可在example下进行,也可以再创建模块\n");
tip.append(" framework: 项目核心框架模块\n");
tip.append(" generator: 代码生成模块,启动类:SpringBootPlusGenerator,请根据实际情况进行配置\n");
// tip.append(" scheduled: 任务调度模块\n");
// tip.append(" system: 系统管理模块\n");
// tip.append(" 6.FAQ:https://springboot.plus/faq\n");
// tip.append(" 7.如开发中遇到bug及问题,欢迎提交ISSUES:https://github.com/geekidea/spring-boot-plus/issues\n");
// tip.append(" 8.QQ:625301326,进群答案:springboot.plus\n");
tip.append(" \n");
tip.append("===========================================================================================\n");
if ("dev".equals(profileActive)) {
log.info("\n{}", Ansi.ansi().eraseScreen().fg(Ansi.Color.YELLOW).a(tip.toString()).reset().toString());
}
}
/**
* 启动成功之后,打印项目信息
*/
public static void print(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
// 项目名称
String projectFinalName = environment.getProperty("info.project-finalName");
// 项目版本
String projectVersion = environment.getProperty("info.project-version");
// 项目profile
String profileActive = environment.getProperty("spring.profiles.active");
// 项目路径
String contextPath = environment.getProperty("server.servlet.context-path");
// 项目IP或域名地址
String serverIp = environment.getProperty("spring-boot-plus.server-ip");
// 项目端口
String port = environment.getProperty("server.port");
// Spring Boot Admin Server地址,请先在admin模块中启动 SpringBootPlusAdminApplication
String springBootAdminServerUrl = environment.getProperty("spring.boot.admin.client.url");
log.info("projectFinalName : {}", projectFinalName);
log.info("projectVersion : {}", projectVersion);
log.info("profileActive : {}", profileActive);
log.info("contextPath : {}", contextPath);
log.info("serverIp : {}", serverIp);
log.info("port : {}", port);
String startSuccess = " ____ __ __ ____ \n" +
"/\\ _`\\ /\\ \\__ /\\ \\__ /\\ _`\\ \n" +
"\\ \\,\\L\\_\\ \\ ,_\\ __ _ __\\ \\ ,_\\ \\ \\,\\L\\_\\ __ __ ___ ___ __ ____ ____ \n" +
" \\/_\\__ \\\\ \\ \\/ /'__`\\ /\\`'__\\ \\ \\/ \\/_\\__ \\ /\\ \\/\\ \\ /'___\\ /'___\\ /'__`\\ /',__\\ /',__\\ \n" +
" /\\ \\L\\ \\ \\ \\_/\\ \\L\\.\\_\\ \\ \\/ \\ \\ \\_ /\\ \\L\\ \\ \\ \\_\\ \\/\\ \\__//\\ \\__//\\ __//\\__, `\\/\\__, `\\\n" +
" \\ `\\____\\ \\__\\ \\__/.\\_\\\\ \\_\\ \\ \\__\\ \\ `\\____\\ \\____/\\ \\____\\ \\____\\ \\____\\/\\____/\\/\\____/\n" +
" \\/_____/\\/__/\\/__/\\/_/ \\/_/ \\/__/ \\/_____/\\/___/ \\/____/\\/____/\\/____/\\/___/ \\/___/ \n" +
" \n" +
" ";
String homeUrl = "http://" + serverIp + ":" + port + contextPath;
String swaggerUrl = "http://" + serverIp + ":" + port + contextPath + "/swagger-ui.html";
String knife4jUrl = "http://" + serverIp + ":" + port + contextPath + "/doc.html";
// log.info("Admin: {}", springBootAdminServerUrl);
log.info("Home: {}", homeUrl);
log.info("Knife4j: {}", knife4jUrl);
// log.info("Swagger: {}", swaggerUrl);
log.info("spring-boot-plus project start success...........");
// if ("dev".equals(profileActive)) {
// log.info("\n{}", AnsiUtil.getAnsi(Ansi.Color.BLUE, startSuccess));
// } else {
// log.info("\n{}", startSuccess);
// }
}
}
package com.wecloud.im.core.util;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
/**
* @author geekidea
* @date 2020/3/2
**/
public class PropertyColumnUtil {
private static Map<Class<?>, Map<String, String>> cacheMap = new ConcurrentHashMap<>();
public static Map<Class<?>, Map<String, String>> getMap() {
return cacheMap;
}
/**
* 根据实体class,从mybatisplus中获取对应Table的属性列名Map
*
* @param clazz
* @return
*/
private static Map<String, String> getTableFieldMap(Class<?> clazz) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
if (tableInfo == null) {
return null;
}
List<TableFieldInfo> tableFieldInfos = tableInfo.getFieldList();
if (CollectionUtils.isEmpty(tableFieldInfos)) {
return null;
}
Map<String, String> cacheMap = tableFieldInfos.stream().collect(Collectors.toMap(TableFieldInfo::getProperty, TableFieldInfo::getColumn));
return cacheMap;
}
/**
* 从本地缓存中获取属性列名map
*
* @param clazz
* @return
*/
public static Map<String, String> getPropertyColumnMap(Class<?> clazz) {
Map<String, String> propertyColumnMap = cacheMap.get(clazz);
if (MapUtils.isEmpty(propertyColumnMap)) {
// 从TableInfo中获取,并缓存到内存map中
Map<String, String> fieldMap = getTableFieldMap(clazz);
if (MapUtils.isEmpty(fieldMap)) {
return null;
} else {
cacheMap.put(clazz, fieldMap);
return fieldMap;
}
} else {
return propertyColumnMap;
}
}
/**
* 通过实体class类型和属性名称,从缓存中获取对应的列名
*
* @param clazz
* @param property
* @return
*/
public static String getColumn(Class<?> clazz, String property) {
Map<String, String> propertyColumnMap = getPropertyColumnMap(clazz);
if (MapUtils.isEmpty(propertyColumnMap)) {
throw new IllegalArgumentException("没有找到对应的实体映射对象");
}
String column = propertyColumnMap.get(property);
if (StringUtils.isEmpty(column)) {
throw new IllegalArgumentException("没有找到对应的列");
}
return column;
}
}
package com.wecloud.im.core.util;
/**
* @Author wenzhida
* @Date 2022/2/23 14:57
* @Description 随机工具类
*/
public class RandomUtil {
/**
* 生成短信验证码
* @return
*/
public static String generateVerifyCode() {
Integer verifyCode = (int) ((Math.random() * 9 + 1) * 100000);
return verifyCode.toString();
}
/**
* 生成随机字符串
* @param length 字符串长度
* @return
*/
public static String generateRandomStr(int length) {
String src = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char[] m = src.toCharArray();
StringBuilder strSb = new StringBuilder();
for (int j = 0; j < length; j++) {
char c = m[(int) (Math.random() * 36)];
strSb.append(c);
}
return strSb.toString();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment