first commit

This commit is contained in:
2023-09-07 00:56:03 +08:00
commit c0ca154d31
718 changed files with 56107 additions and 0 deletions

View File

@@ -0,0 +1 @@
/target

View File

@@ -0,0 +1,104 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.app</groupId>
<artifactId>app-service</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- rabbitmq -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-amqp</artifactId>-->
<!-- </dependency>-->
<!-- redis -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!-- </dependency>-->
<!-- spring boot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--MySQL JDBC驱动 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.6</version>
</dependency>
<!-- commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<!-- redisson -->
</dependencies>
</project>

View File

@@ -0,0 +1,15 @@
package org.app;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("org.app.dao")
public class AppServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AppServiceApplication.class, args);
}
}

View File

@@ -0,0 +1,34 @@
package org.app.common;
import org.app.exception.ApplicationExceptionEnum;
/**
* @author: Chackylee
* @description:
**/
public enum BaseErrorCode implements ApplicationExceptionEnum {
SUCCESS(200,"success"),
SYSTEM_ERROR(90000,"服务器内部错误,请联系管理员"),
PARAMETER_ERROR(90001,"参数校验错误"),
;
private int code;
private String error;
BaseErrorCode(int code, String error){
this.code = code;
this.error = error;
}
public int getCode() {
return this.code;
}
public String getError() {
return this.error;
}
}

View File

@@ -0,0 +1,69 @@
package org.app.common;
import org.app.exception.ApplicationExceptionEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: Chackylee
* @description:
**/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ResponseVO<T> {
private int code;
private String msg;
private T data;
public static ResponseVO successResponse(Object data) {
return new ResponseVO(200, "success", data);
}
public static ResponseVO successResponse() {
return new ResponseVO(200, "success");
}
public static ResponseVO errorResponse() {
return new ResponseVO(500, "系统内部异常");
}
public static ResponseVO errorResponse(int code, String msg) {
return new ResponseVO(code, msg);
}
public static ResponseVO errorResponse(ApplicationExceptionEnum enums) {
return new ResponseVO(enums.getCode(), enums.getError());
}
public boolean isOk(){
return this.code == 200;
}
public ResponseVO(int code, String msg) {
this.code = code;
this.msg = msg;
// this.data = null;
}
public ResponseVO success(){
this.code = 200;
this.msg = "success";
return this;
}
public ResponseVO success(T data){
this.code = 200;
this.msg = "success";
this.data = data;
return this;
}
}

View File

@@ -0,0 +1,30 @@
package org.app.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: Chackylee
* @description:
**/
@Data
@Component
@ConfigurationProperties(prefix = "appconfig")
public class AppConfig {
private String imUrl;
private String imVersion;
private Integer appId;
private String adminId;
private String privateKey;
private String jwtKey;
private Integer jwtExpireTime;
}

View File

@@ -0,0 +1,150 @@
package org.app.config;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "httpclient")
public class GlobalHttpClientConfig {
private Integer maxTotal; // 最大连接数
private Integer defaultMaxPerRoute; // 最大并发链接数
private Integer connectTimeout; // 创建链接的最大时间
private Integer connectionRequestTimeout; // 链接获取超时时间
private Integer socketTimeout; // 数据传输最长时间
private boolean staleConnectionCheckEnabled; // 提交时检查链接是否可用
PoolingHttpClientConnectionManager manager = null;
HttpClientBuilder httpClientBuilder = null;
// 定义httpClient链接池
@Bean(name = "httpClientConnectionManager")
public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
return getManager();
}
private PoolingHttpClientConnectionManager getManager() {
if (manager != null) {
return manager;
}
manager = new PoolingHttpClientConnectionManager();
manager.setMaxTotal(maxTotal); // 设定最大链接数
manager.setDefaultMaxPerRoute(defaultMaxPerRoute); // 设定并发链接数
return manager;
}
/**
* 实例化连接池,设置连接池管理器。 这里需要以参数形式注入上面实例化的连接池管理器
*
* @Qualifier 指定bean标签进行注入
*/
@Bean(name = "httpClientBuilder")
public HttpClientBuilder getHttpClientBuilder(
@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
// HttpClientBuilder中的构造方法被protected修饰所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionManager(httpClientConnectionManager);
return httpClientBuilder;
}
/**
* 注入连接池用于获取httpClient
*
* @param httpClientBuilder
* @return
*/
@Bean
public CloseableHttpClient getCloseableHttpClient(
@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {
return httpClientBuilder.build();
}
public CloseableHttpClient getCloseableHttpClient() {
if (httpClientBuilder != null) {
return httpClientBuilder.build();
}
httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionManager(getManager());
return httpClientBuilder.build();
}
/**
* Builder是RequestConfig的一个内部类 通过RequestConfig的custom方法来获取到一个Builder对象
* 设置builder的连接信息
*
* @return
*/
@Bean(name = "builder")
public RequestConfig.Builder getBuilder() {
RequestConfig.Builder builder = RequestConfig.custom();
return builder.setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout).setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
}
/**
* 使用builder构建一个RequestConfig对象
*
* @param builder
* @return
*/
@Bean
public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
return builder.build();
}
public Integer getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(Integer maxTotal) {
this.maxTotal = maxTotal;
}
public Integer getDefaultMaxPerRoute() {
return defaultMaxPerRoute;
}
public void setDefaultMaxPerRoute(Integer defaultMaxPerRoute) {
this.defaultMaxPerRoute = defaultMaxPerRoute;
}
public Integer getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(Integer connectTimeout) {
this.connectTimeout = connectTimeout;
}
public Integer getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
public void setConnectionRequestTimeout(Integer connectionRequestTimeout) {
this.connectionRequestTimeout = connectionRequestTimeout;
}
public Integer getSocketTimeout() {
return socketTimeout;
}
public void setSocketTimeout(Integer socketTimeout) {
this.socketTimeout = socketTimeout;
}
public boolean isStaleConnectionCheckEnabled() {
return staleConnectionCheckEnabled;
}
public void setStaleConnectionCheckEnabled(boolean staleConnectionCheckEnabled) {
this.staleConnectionCheckEnabled = staleConnectionCheckEnabled;
}
}

View File

@@ -0,0 +1,24 @@
package org.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: Chackylee
* @description:
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}

View File

@@ -0,0 +1,28 @@
package org.app.controller;
import org.app.common.ResponseVO;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@RestController
public class CallbackController {
private static Logger logger
= LoggerFactory.getLogger(CallbackController.class);
@RequestMapping("/callback")
public ResponseVO callback(@RequestBody Object req, String command, Integer appId) {
logger.info("{}收到{}回调数据:{}",
appId,command, JSONObject.toJSONString(req));
return ResponseVO.successResponse();
}
}

View File

@@ -0,0 +1,35 @@
package org.app.controller;
import org.app.common.ResponseVO;
import org.app.model.req.LoginReq;
import org.app.model.req.RegisterReq;
import org.app.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: Chackylee
* @description:
**/
@RestController
@RequestMapping("v1")
public class LoginController {
@Autowired
LoginService loginService;
@RequestMapping("/login")
public ResponseVO login(@RequestBody @Validated LoginReq req) {
return loginService.login(req);
}
@RequestMapping("/register")
public ResponseVO register(@RequestBody @Validated RegisterReq req) {
return loginService.register(req);
}
}

View File

@@ -0,0 +1,28 @@
package org.app.dao;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author: Chackylee
* @description:
**/
@Data
@TableName("app_user")
public class User {
@TableId
private String userId;
//用户名
private String userName;
//密码
private String password;
//手机号
private String mobile;
//创建时间
private Long createTime;
//更新时间
private Long updateTime;
}

View File

@@ -0,0 +1,26 @@
package org.app.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.app.dao.User;
import org.app.model.req.SearchUserReq;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper extends BaseMapper<User> {
@Select("<script>" +
" select user_id from app_user " +
"<if test = 'searchType == 1'> " +
" where mobile = #{keyWord} " +
" </if>" +
" <if test = 'searchType == 2'> " +
" where user_name = #{keyWord} " +
" </if> " +
" </script> ")
public List<String> searchUser(SearchUserReq req);
}

View File

@@ -0,0 +1,43 @@
package org.app.enums;
import org.app.exception.ApplicationExceptionEnum;
/**
* @author: Chackylee
* @description:
**/
public enum ErrorCode implements ApplicationExceptionEnum {
USER_NOT_EXIST(10000,"用户不存在"),
USERNAME_OR_PASSWORD_ERROR(10001,"用户名或密码错误"),
MOBILE_IS_REGISTER(10002,"该手机号已注册了用户"),
REGISTER_ERROR(10003,"注册失败"),
REPORT_TAG_IS_NOT_EXIST(10004,"举报标签不存在"),
REDPACKET_IS_NOT_EXIST(10005,"红包不存在"),
USER_REDPACKET_IS_OPEN(10006,"用户已抢过该红包"),
REDPACKET_IS_EXPIRE(10007,"红包已过期"),
REDPACKET_IS_FINISH(10008,"红包已抢完"),
REDPACKET_IS_HOT(10009,"红包火爆请稍后再试"),
TRYLOCREDPACKET_INTERRUPTED(10010,"抢红包时被中断了"),
;
private int code;
private String error;
ErrorCode(int code, String error){
this.code = code;
this.error = error;
}
public int getCode() {
return this.code;
}
public String getError() {
return this.error;
}
}

View File

@@ -0,0 +1,24 @@
package org.app.enums;
public enum LoginTypeEnum {
/**
* 1 username2 验证码 3手机号+验证码
*/
USERNAME_PASSWORD(1),
SMS_CODE(2),
SMS_PASSWORD(3)
;
private int code;
LoginTypeEnum(int code){
this.code=code;
}
public int getCode() {
return code;
}
}

View File

@@ -0,0 +1,22 @@
package org.app.enums;
public enum RegisterTypeEnum {
/**
* 1 username2 MOBILE。
*/
USERNAME(1),
MOBILE(2),
;
private int code;
RegisterTypeEnum(int code){
this.code=code;
}
public int getCode() {
return code;
}
}

View File

@@ -0,0 +1,44 @@
package org.app.exception;
/**
* @author: Chackylee
* @description:
**/
public class ApplicationException extends RuntimeException {
private int code;
private String error;
public ApplicationException(int code, String message) {
super(message);
this.code = code;
this.error = message;
}
public ApplicationException(ApplicationExceptionEnum exceptionEnum) {
super(exceptionEnum.getError());
this.code = exceptionEnum.getCode();
this.error = exceptionEnum.getError();
}
public int getCode() {
return code;
}
public String getError() {
return error;
}
/**
* avoid the expensive and useless stack trace for api exceptions
* @see Throwable#fillInStackTrace()
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}

View File

@@ -0,0 +1,8 @@
package org.app.exception;
public interface ApplicationExceptionEnum {
int getCode();
String getError();
}

View File

@@ -0,0 +1,113 @@
package org.app.exception;
import org.app.common.BaseErrorCode;
import org.app.common.ResponseVO;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
/**
* @author: Chackylee
* @description:
**/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value=Exception.class)
@ResponseBody
public ResponseVO unknowException(Exception e){
e.printStackTrace();
ResponseVO resultBean =new ResponseVO();
resultBean.setCode(BaseErrorCode.SYSTEM_ERROR.getCode());
resultBean.setMsg(BaseErrorCode.SYSTEM_ERROR.getError());
/**
* 未知异常的话,这里写逻辑,发邮件,发短信都可以、、
*/
return resultBean;
}
/**
* Validator 参数校验异常处理
*
* @param ex
* @return
*/
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseBody
public Object handleMethodArgumentNotValidException(ConstraintViolationException ex) {
Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
ResponseVO resultBean =new ResponseVO();
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
for (ConstraintViolation<?> constraintViolation : constraintViolations) {
PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath();
// 读取参数字段constraintViolation.getMessage() 读取验证注解中的message值
String paramName = pathImpl.getLeafNode().getName();
String message = "参数{".concat(paramName).concat("}").concat(constraintViolation.getMessage());
resultBean.setMsg(message);
return resultBean;
}
resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + ex.getMessage());
return resultBean;
}
@ExceptionHandler(ApplicationException.class)
@ResponseBody
public Object applicationExceptionHandler(ApplicationException e) {
// 使用公共的结果类封装返回结果, 这里我指定状态码为
ResponseVO resultBean =new ResponseVO();
resultBean.setCode(e.getCode());
resultBean.setMsg(e.getError());
return resultBean;
}
/**
* Validator 参数校验异常处理
*
* @param ex
* @return
*/
@ExceptionHandler(value = BindException.class)
@ResponseBody
public Object handleException2(BindException ex) {
FieldError err = ex.getFieldError();
String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage());
ResponseVO resultBean =new ResponseVO();
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
resultBean.setMsg(message);
return resultBean;
}
//json格式
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Object handleException1(MethodArgumentNotValidException ex) {
StringBuilder errorMsg = new StringBuilder();
BindingResult re = ex.getBindingResult();
for (ObjectError error : re.getAllErrors()) {
errorMsg.append(error.getDefaultMessage()).append(",");
}
errorMsg.delete(errorMsg.length() - 1, errorMsg.length());
ResponseVO resultBean =new ResponseVO();
resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode());
resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + " : " + errorMsg.toString());
return resultBean;
}
}

View File

@@ -0,0 +1,49 @@
package org.app.model.dto;
import lombok.Data;
/**
* @description:
* @author: lld
* @version: 1.0
*/
@Data
public class ImUserDataDto {
// 用户id
private String userId;
// 用户名称
private String nickName;
private String password;
// 头像
private String photo;
// 性别
private Integer userSex;
// 个性签名
private String selfSignature;
// 加好友验证类型Friend_AllowType 1需要验证
private Integer friendAllowType;
// 管理员禁止用户添加加好友0 未禁用 1 已禁用
private Integer disableAddFriend;
// 禁用标识(0 未禁用 1 已禁用)
private Integer forbiddenFlag;
// 禁言标识
private Integer silentFlag;
/**
* 用户类型 1普通用户 2客服 3机器人 100后台管理员
*/
private Integer userType;
private Integer appId;
private Integer delFlag;
}

View File

@@ -0,0 +1,20 @@
package org.app.model.proto;
import lombok.Data;
import java.util.List;
/**
* @author: Chackylee
* @description:
**/
@Data
public class GetUserInfoProto {
private List<String> userIds;
private List<String> standardField;
private List<String> customField;
}

View File

@@ -0,0 +1,51 @@
package org.app.model.proto;
import lombok.Data;
import java.util.List;
/**
* @author: Chackylee
* @description:
**/
@Data
public class ImportUserProto {
private List<UserData> userData;
@Data
public static class UserData{
// 用户id
private String userId;
// 用户名称
private String nickName;
private String password;
// 头像
private String photo;
// 性别
private Integer userSex;
// 个性签名
private String selfSignature;
// 加好友验证类型Friend_AllowType 1需要验证
private Integer friendAllowType;
// 管理员禁止用户添加加好友0 未禁用 1 已禁用
private Integer disableAddFriend;
// 禁用标识(0 未禁用 1 已禁用)
private Integer forbiddenFlag;
// 禁言标识
private Integer silentFlag;
/**
* 用户类型 1普通用户 2客服 3机器人
*/
private Integer userType;
}
}

View File

@@ -0,0 +1,25 @@
package org.app.model.req;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author: Chackylee
* @description:
**/
@Data
public class LoginReq {
@NotBlank(message = "用户名不能为空")
private String userName;
@NotBlank(message = "密码不能为空")
private String password;
@NotNull(message = "请选择登录方式")
//登录方式 1用户名+密码 2手机号+验证码
private Integer loginType;
}

View File

@@ -0,0 +1,26 @@
package org.app.model.req;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author: Chackylee
* @description:
**/
@Data
public class RegisterReq {
private String userName;
@NotBlank(message = "密码不能为空")
private String password;
@NotNull(message = "请选择注册方式")
//注册方式 1手机号注册 2用户名
private Integer registerType;
private String proto;
}

View File

@@ -0,0 +1,21 @@
package org.app.model.req;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author: Chackylee
* @description:
**/
@Data
public class SearchUserReq {
@NotBlank(message = "关键字不能为空")
private String keyWord;
@NotNull(message = "搜索方式不能为空")
private Integer searchType;
}

View File

@@ -0,0 +1,16 @@
package org.app.model.resp;
import lombok.Data;
import java.util.Set;
/**
* @author: Chackylee
* @description:
**/
@Data
public class ImportUserResp {
private Set<String> successId;
private Set<String> errorId;
}

View File

@@ -0,0 +1,22 @@
package org.app.model.resp;
import lombok.Data;
/**
* @author: Chackylee
* @description:
**/
@Data
public class LoginResp {
//im的token
private String imUserSign;
//自己的token
private String userSign;
private String userId;
private Integer appId;
}

View File

@@ -0,0 +1,104 @@
package org.app.service;
import com.alibaba.fastjson.JSONObject;
import org.app.common.ResponseVO;
import org.app.config.AppConfig;
import org.app.dao.User;
import org.app.model.dto.ImUserDataDto;
import org.app.model.proto.GetUserInfoProto;
import org.app.model.proto.ImportUserProto;
import org.app.model.resp.ImportUserResp;
import org.app.utils.HttpRequestUtils;
import org.app.utils.SigAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author: Chackylee
* @description:
**/
@Service
public class ImService implements CommandLineRunner {
@Autowired
HttpRequestUtils httpRequestUtils;
@Autowired
AppConfig appConfig;
private SigAPI sigAPI;
public volatile static Map<String, Object> parameter;
public volatile static Object lock = new Object();
private String getUrl(String uri) {
return appConfig.getImUrl() + "/" + appConfig.getImVersion() + uri;
}
private Map<String, Object> getParamter() {
if (parameter == null) {
synchronized (lock) {
if(parameter == null){
parameter = new ConcurrentHashMap<>();
parameter.put("appId",appConfig.getAppId());
parameter.put("userSign",sigAPI.genUserSig(appConfig.getAdminId(),500000));
parameter.put("identifier",appConfig.getAdminId());
}
}
}
return parameter;
}
public ResponseVO<ImportUserResp> importUser(List<User> users) {
ImportUserProto proto = new ImportUserProto();
List<ImportUserProto.UserData> userData = new ArrayList<>();
users.forEach(e -> {
ImportUserProto.UserData u = new ImportUserProto.UserData();
u.setUserId(e.getUserId().toString());
u.setUserType(1);
userData.add(u);
});
String uri = "/user/importUser";
try {
proto.setUserData(userData);
ResponseVO responseVO = httpRequestUtils.doPost(getUrl(uri), ResponseVO.class, getParamter(), null, JSONObject.toJSONString(proto), "");
return responseVO;
}catch (Exception e){
e.printStackTrace();
}
return ResponseVO.errorResponse();
}
public ResponseVO<ImUserDataDto> getUserInfo(List<String> users) {
GetUserInfoProto proto = new GetUserInfoProto();
proto.setUserIds(users);
String uri = "/user/data/getUserInfo";
try {
// proto.setUserData(userData);
ResponseVO responseVO = httpRequestUtils.doPost(getUrl(uri), ResponseVO.class, getParamter(), null, JSONObject.toJSONString(proto), "");
return responseVO;
}catch (Exception e){
e.printStackTrace();
}
return ResponseVO.errorResponse();
}
@Override
public void run(String... args) throws Exception {
sigAPI = new SigAPI(appConfig.getAppId(),appConfig.getPrivateKey());
}
}

View File

@@ -0,0 +1,17 @@
package org.app.service;
import org.app.common.ResponseVO;
import org.app.model.req.LoginReq;
import org.app.model.req.RegisterReq;
/**
* @author: Chackylee
* @description:
**/
public interface LoginService {
public ResponseVO login(LoginReq req);
public ResponseVO register(RegisterReq req);
}

View File

@@ -0,0 +1,23 @@
package org.app.service;
import org.app.common.ResponseVO;
import org.app.dao.User;
import org.app.model.req.RegisterReq;
import org.app.model.req.SearchUserReq;
public interface UserService {
public ResponseVO<User> getUserByUserNameAndPassword(String userName, String password);
public ResponseVO<User> getUserByMobile(String mobile);
public ResponseVO<User> getUserByUserName(String userName);
public ResponseVO<User> getUserById(Integer userId);
public ResponseVO<User> registerUser(RegisterReq req);
public ResponseVO searchUser(SearchUserReq req);
}

View File

@@ -0,0 +1,88 @@
package org.app.service.impl;
import org.app.common.ResponseVO;
import org.app.config.AppConfig;
import org.app.dao.User;
import org.app.enums.ErrorCode;
import org.app.enums.LoginTypeEnum;
import org.app.enums.RegisterTypeEnum;
import org.app.model.req.LoginReq;
import org.app.model.req.RegisterReq;
import org.app.model.resp.LoginResp;
import org.app.service.LoginService;
import org.app.service.UserService;
import org.app.utils.SigAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author: Chackylee
* @description:
**/
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
UserService userService;
@Autowired
AppConfig appConfig;
/**
* @param [req]
* @return com.lld.app.common.ResponseVO
* @description 登录服务需返回im userSign和app的userSign
* @author chackylee
*/
@Override
public ResponseVO login(LoginReq req) {
LoginResp loginResp = new LoginResp();
if (LoginTypeEnum.USERNAME_PASSWORD.getCode() == req.getLoginType()) {
ResponseVO<User> userResp = userService.getUserByUserNameAndPassword(req.getUserName(), req.getPassword());
if (userResp.isOk()) {
User user = userResp.getData();
SigAPI SigAPI = new SigAPI(appConfig.getAppId(),
appConfig.getPrivateKey());
String s = SigAPI.genUserSig(user.getUserId(),
500000);
loginResp.setImUserSign(s);
loginResp.setUserSign("asdasdsd");
loginResp.setUserId(user.getUserId());
} else if (userResp.getCode() == ErrorCode.USER_NOT_EXIST.getCode()) {
return ResponseVO.errorResponse(ErrorCode.USERNAME_OR_PASSWORD_ERROR);
} else {
return userResp;
}
} else if (LoginTypeEnum.SMS_CODE.getCode() == req.getLoginType()) {
String key = "lld";
}
loginResp.setAppId(appConfig.getAppId());
return ResponseVO.successResponse(loginResp);
}
/**
* @description 注册我们的服务并向im导入用户
* @author chackylee
* @param [req]
*/
@Override
@Transactional
public ResponseVO register(RegisterReq req) {
if(RegisterTypeEnum.USERNAME.getCode() == req.getRegisterType()){
ResponseVO<User> userByUserName = userService.getUserByUserName(req.getUserName());
if(userByUserName.isOk()){
return ResponseVO.errorResponse(ErrorCode.REGISTER_ERROR);
}
ResponseVO<User> userResponseVO = userService.registerUser(req);
return userResponseVO;
}
return ResponseVO.successResponse();
}
}

View File

@@ -0,0 +1,152 @@
package org.app.service.impl;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.app.common.ResponseVO;
import org.app.dao.User;
import org.app.dao.mapper.UserMapper;
import org.app.enums.ErrorCode;
import org.app.exception.ApplicationException;
import org.app.model.dto.ImUserDataDto;
import org.app.model.req.RegisterReq;
import org.app.model.req.SearchUserReq;
import org.app.model.resp.ImportUserResp;
import org.app.service.ImService;
import org.app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author: Chackylee
* @description:
**/
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Autowired
ImService imService;
/**
* @param [userName, password]
* @return com.lld.app.common.ResponseVO
* @description 根据用户名和密码获取用户
* @author chackylee
*/
@Override
public ResponseVO getUserByUserNameAndPassword(String userName, String password) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("user_name", userName);
wrapper.eq("password", password);
User user = userMapper.selectOne(wrapper);
if (user == null) {
return ResponseVO.errorResponse(ErrorCode.USER_NOT_EXIST);
}
return ResponseVO.successResponse(user);
}
/**
* @param [mobile]
* @return com.lld.app.common.ResponseVO
* @description 根据手机号获取用户
* @author chackylee
*/
@Override
public ResponseVO getUserByMobile(String mobile) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("mobile", mobile);
User user = userMapper.selectOne(wrapper);
if (user == null) {
return ResponseVO.errorResponse(ErrorCode.USER_NOT_EXIST);
}
return ResponseVO.successResponse(user);
}
@Override
public ResponseVO<User> getUserByUserName(String userName) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("user_name", userName);
User user = userMapper.selectOne(wrapper);
if (user == null) {
return ResponseVO.errorResponse(ErrorCode.USER_NOT_EXIST);
}
return ResponseVO.successResponse(user);
}
/**
* @param [userId]
* @return com.lld.app.common.ResponseVO
* @description 根据用户id获取用户
* @author chackylee
*/
@Override
public ResponseVO getUserById(Integer userId) {
User user = userMapper.selectById(userId);
if (user == null) {
return ResponseVO.errorResponse(ErrorCode.USER_NOT_EXIST);
}
return ResponseVO.successResponse(user);
}
@Override
@Transactional
public ResponseVO<User> registerUser(RegisterReq req) {
User user = new User();
user.setCreateTime(System.currentTimeMillis());
// user.setMobile(req.getUserName());
user.setPassword(req.getPassword());
user.setUserName(req.getUserName());
user.setUserId(req.getUserName());
userMapper.insert(user);
ArrayList<User> users = new ArrayList<>();
users.add(user);
ResponseVO responseVO = imService.importUser(users);
if(responseVO.isOk()){
Object data = responseVO.getData();
ObjectMapper objectMapper = new ObjectMapper();
ImportUserResp importUserResp = objectMapper.convertValue(data, ImportUserResp.class);
Set<String> successId = importUserResp.getSuccessId();
if(successId.contains(user.getUserId().toString())){
return ResponseVO.successResponse(user);
}else {
throw new ApplicationException(ErrorCode.REGISTER_ERROR);
}
}else{
throw new ApplicationException(responseVO.getCode(),responseVO.getMsg());
}
}
@Override
public ResponseVO searchUser(SearchUserReq req) {
List<String> userIds = userMapper.searchUser(req);
//手机号搜索
// if(req.getSearchType() == 1){
// userIds = userMapper.searchUser(req);
// }else if(){
//
// }
ResponseVO<ImUserDataDto> userInfo = imService.getUserInfo(userIds);
return userInfo;
}
}

View File

@@ -0,0 +1,90 @@
package org.app.utils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* @description:
* @author: lld
* @version: 1.0
*/
public class Base64URL {
public static byte[] base64EncodeUrl(byte[] input) {
byte[] base64 = new BASE64Encoder().encode(input).getBytes();
for (int i = 0; i < base64.length; ++i)
switch (base64[i]) {
case '+':
base64[i] = '*';
break;
case '/':
base64[i] = '-';
break;
case '=':
base64[i] = '_';
break;
default:
break;
}
return base64;
}
public static byte[] base64EncodeUrlNotReplace(byte[] input) {
byte[] base64 = new BASE64Encoder().encode(input).getBytes(Charset.forName("UTF-8"));
for (int i = 0; i < base64.length; ++i)
switch (base64[i]) {
case '+':
base64[i] = '*';
break;
case '/':
base64[i] = '-';
break;
case '=':
base64[i] = '_';
break;
default:
break;
}
return base64;
}
public static byte[] base64DecodeUrlNotReplace(byte[] input) throws IOException {
for (int i = 0; i < input.length; ++i)
switch (input[i]) {
case '*':
input[i] = '+';
break;
case '-':
input[i] = '/';
break;
case '_':
input[i] = '=';
break;
default:
break;
}
return new BASE64Decoder().decodeBuffer(new String(input,"UTF-8"));
}
public static byte[] base64DecodeUrl(byte[] input) throws IOException {
byte[] base64 = input.clone();
for (int i = 0; i < base64.length; ++i)
switch (base64[i]) {
case '*':
base64[i] = '+';
break;
case '-':
base64[i] = '/';
break;
case '_':
base64[i] = '=';
break;
default:
break;
}
return new BASE64Decoder().decodeBuffer(base64.toString());
}
}

View File

@@ -0,0 +1,278 @@
package org.app.utils;
import org.app.config.GlobalHttpClientConfig;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
/**
* @author: Chackylee
* @description:
**/
@Component
public class HttpRequestUtils {
@Autowired
private CloseableHttpClient httpClient;
@Autowired
private RequestConfig requestConfig;
@Autowired
GlobalHttpClientConfig httpClientConfig;
public String doGet(String url, Map<String, Object> params, String charset) throws Exception {
return doGet(url,params,null,charset);
}
/**
* 通过给的url地址获取服务器数据
*
* @param url 服务器地址
* @param params 封装用户参数
* @param charset 设定字符编码
* @return
*/
public String doGet(String url, Map<String, Object> params, Map<String, Object> header, String charset) throws Exception {
if (StringUtils.isEmpty(charset)) {
charset = "utf-8";
}
URIBuilder uriBuilder = new URIBuilder(url);
// 判断是否有参数
if (params != null) {
// 遍历map,拼接请求参数
for (Map.Entry<String, Object> entry : params.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 声明 http get 请求
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.setConfig(requestConfig);
if (header != null) {
// 遍历map,拼接header参数
for (Map.Entry<String, Object> entry : header.entrySet()) {
httpGet.addHeader(entry.getKey(),entry.getValue().toString());
}
}
String result = "";
try {
// 发起请求
CloseableHttpResponse response = httpClient.execute(httpGet);
// 判断状态码是否为200
if (response.getStatusLine().getStatusCode() == 200) {
// 返回响应体的内容
result = EntityUtils.toString(response.getEntity(), charset);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return result;
}
/**
* GET请求 含URL 参数
*
* @param url
* @param params
* @return 如果状态码为200则返回body如果不为200则返回null
* @throws Exception
*/
public String doGet(String url, Map<String, Object> params) throws Exception {
return doGet(url, params, null);
}
/**
* GET 请求不含URL参数
*
* @param url
* @return
* @throws Exception
*/
public String doGet(String url) throws Exception {
return doGet(url, null, null);
}
public String doPost(String url, Map<String, Object> params, String jsonBody, String charset) throws Exception {
return doPost(url,params,null,jsonBody,charset);
}
/**
* 带参数的post请求
*
* @param url
* @return
* @throws Exception
*/
public String doPost(String url, Map<String, Object> params, Map<String, Object> header, String jsonBody, String charset) throws Exception {
if (StringUtils.isEmpty(charset)) {
charset = "utf-8";
}
URIBuilder uriBuilder = new URIBuilder(url);
// 判断是否有参数
if (params != null) {
// 遍历map,拼接请求参数
for (Map.Entry<String, Object> entry : params.entrySet()) {
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 声明httpPost请求
HttpPost httpPost = new HttpPost(uriBuilder.build());
// 加入配置信息
httpPost.setConfig(requestConfig);
// 判断map是否为空不为空则进行遍历封装from表单对象
if (StringUtils.isNotEmpty(jsonBody)) {
StringEntity s = new StringEntity(jsonBody, charset);
s.setContentEncoding(charset);
s.setContentType("application/json");
// 把json body放到post里
httpPost.setEntity(s);
}
if (header != null) {
// 遍历map,拼接header参数
for (Map.Entry<String, Object> entry : header.entrySet()) {
httpPost.addHeader(entry.getKey(),entry.getValue().toString());
}
}
String result = "";
// CloseableHttpClient httpClient = HttpClients.createDefault(); // 单个
CloseableHttpResponse response = null;
try {
// 发起请求
response = httpClient.execute(httpPost);
// 判断状态码是否为200
if (response.getStatusLine().getStatusCode() == 200) {
// 返回响应体的内容
result = EntityUtils.toString(response.getEntity(), charset);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return result;
}
/**
* 不带参数post请求
* @param url
* @return
* @throws Exception
*/
public String doPost(String url) throws Exception {
return doPost(url, null,null,null);
}
/**
* get 方法调用的通用方式
* @param url
* @param tClass
* @param map
* @param charSet
* @return
* @throws Exception
*/
public <T> T doGet(String url, Class<T> tClass, Map<String, Object> map, String charSet) throws Exception {
String result = doGet(url, map, charSet);
if (StringUtils.isNotEmpty(result))
return JSON.parseObject(result, tClass);
return null;
}
/**
* get 方法调用的通用方式
* @param url
* @param tClass
* @param map
* @param charSet
* @return
* @throws Exception
*/
public <T> T doGet(String url, Class<T> tClass, Map<String, Object> map, Map<String, Object> header, String charSet) throws Exception {
String result = doGet(url, map, header, charSet);
if (StringUtils.isNotEmpty(result))
return JSON.parseObject(result, tClass);
return null;
}
/**
* post 方法调用的通用方式
* @param url
* @param tClass
* @param map
* @param jsonBody
* @param charSet
* @return
* @throws Exception
*/
public <T> T doPost(String url, Class<T> tClass, Map<String, Object> map, String jsonBody, String charSet) throws Exception {
String result = doPost(url, map,jsonBody,charSet);
if (StringUtils.isNotEmpty(result))
return JSON.parseObject(result, tClass);
return null;
}
public <T> T doPost(String url, Class<T> tClass, Map<String, Object> map, Map<String, Object> header, String jsonBody, String charSet) throws Exception {
String result = doPost(url, map, header,jsonBody,charSet);
if (StringUtils.isNotEmpty(result))
return JSON.parseObject(result, tClass);
return null;
}
/**
* post 方法调用的通用方式
* @param url
* @param map
* @param jsonBody
* @param charSet
* @return
* @throws Exception
*/
public String doPostString(String url, Map<String, Object> map, String jsonBody, String charSet) throws Exception {
return doPost(url, map,jsonBody,charSet);
}
/**
* post 方法调用的通用方式
* @param url
* @param map
* @param jsonBody
* @param charSet
* @return
* @throws Exception
*/
public String doPostString(String url, Map<String, Object> map, Map<String, Object> header, String jsonBody, String charSet) throws Exception {
return doPost(url, map, header, jsonBody,charSet);
}
}

View File

@@ -0,0 +1,195 @@
package org.app.utils;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.app.utils.Base64URL;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
/**
* @description: app用户 后台管理员
*
* 10000 xxx 10001 bbbb
* @author: lld
* @version: 1.0
*/
public class SigAPI {
final private long appId;
final private String key;
public SigAPI(long appId, String key) {
this.appId = appId;
this.key = key;
}
public static void main(String[] args) throws InterruptedException {
SigAPI asd = new SigAPI(10000, "123456");
String sign = asd.genUserSig("lld", 100000000);
// Thread.sleep(2000L);
JSONObject jsonObject = decodeUserSig(sign);
System.out.println("sign:" + sign);
System.out.println("decoder:" + jsonObject.toString());
}
/**
* @description: 解密方法
* @param
* @return com.alibaba.fastjson.JSONObject
* @author lld
*/
public static JSONObject decodeUserSig(String userSig) {
JSONObject sigDoc = new JSONObject(true);
try {
byte[] decodeUrlByte = Base64URL.base64DecodeUrlNotReplace(userSig.getBytes());
byte[] decompressByte = decompress(decodeUrlByte);
String decodeText = new String(decompressByte, "UTF-8");
if (StringUtils.isNotBlank(decodeText)) {
sigDoc = JSONObject.parseObject(decodeText);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return sigDoc;
}
/**
* 解压缩
*
* @param data 待压缩的数据
* @return byte[] 解压缩后的数据
*/
public static byte[] decompress(byte[] data) {
byte[] output = new byte[0];
Inflater decompresser = new Inflater();
decompresser.reset();
decompresser.setInput(data);
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
try {
byte[] buf = new byte[1024];
while (!decompresser.finished()) {
int i = decompresser.inflate(buf);
o.write(buf, 0, i);
}
output = o.toByteArray();
} catch (Exception e) {
output = data;
e.printStackTrace();
} finally {
try {
o.close();
} catch (IOException e) {
e.printStackTrace();
}
}
decompresser.end();
return output;
}
/**
* 【功能说明】用于签发 IM 服务中必须要使用的 UserSig 鉴权票据
* <p>
* 【参数说明】
*/
public String genUserSig(String userid, long expire) {
return genUserSig(userid, expire, null);
}
private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
+ "TLS.appId:" + appId + "\n"
+ "TLS.expireTime:" + currTime + "\n"
+ "TLS.expire:" + expire + "\n";
if (null != base64Userbuf) {
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
}
try {
byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
hmac.init(keySpec);
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
return "";
}
}
private String genUserSig(String userid, long expire, byte[] userbuf) {
long currTime = System.currentTimeMillis() / 1000;
JSONObject sigDoc = new JSONObject();
sigDoc.put("TLS.identifier", userid);
sigDoc.put("TLS.appId", appId);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.expireTime", currTime);
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
sigDoc.put("TLS.userbuf", base64UserBuf);
}
String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
if (sig.length() == 0) {
return "";
}
sigDoc.put("TLS.sig", sig);
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
0, compressedBytesLength)))).replaceAll("\\s*", "");
}
public String genUserSig(String userid, long expire, long time,byte [] userbuf) {
JSONObject sigDoc = new JSONObject();
sigDoc.put("TLS.identifier", userid);
sigDoc.put("TLS.appId", appId);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.expireTime", time);
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
sigDoc.put("TLS.userbuf", base64UserBuf);
}
String sig = hmacsha256(userid, time, expire, base64UserBuf);
if (sig.length() == 0) {
return "";
}
sigDoc.put("TLS.sig", sig);
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
0, compressedBytesLength)))).replaceAll("\\s*", "");
}
}

View File

@@ -0,0 +1,49 @@
spring:
profiles:
active: dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
password: frfr46467979+
url: jdbc:mysql://127.0.0.1:3306/im-core?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8&allowPublicKeyRetrieval=true
username: root
hikari:
max-lifetime: 50000
application:
name: app.service
# logger 配置
logging:
config: classpath:logback-spring.xml
server:
port: 8989
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:mapper/*.xml
global-config:
db-config:
update-strategy: NOT_EMPTY
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
appConfig:
imUrl: http://127.0.0.1:8000
imVersion: v1
appId: 10000
adminId: admin
privateKey: 123456
httpclient:
maxTotal: 100
defaultMaxPerRoute: 50
connectTimeout: 2000
connectionRequestTimeout: 2000
socketTimeout: 5000
staleConnectionCheckEnabled: true

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds" >
<include resource="org/springframework/boot/logging/logback/defualts.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<springProperty scope="context" name="springAppEnv" source="spring.profiles.active"/>
<!-- <springProperty scope="context" name="logFile" source="logging.file"/> -->
<property name="logFile" value="logs/mylog.log"/>
<!--日志在工程中的输出位置-->
<property name="LOG_FILE" value="${logFile}"/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!--控制台的日志输出样式-->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--控制台 Appender-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!--隐藏服务发现后输出的日志-->
<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="WARN"/>
<logger name="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" level="WARN"/>
<springProfile name="test,dev">
<!--文件-->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${logFile}.%d{yyyy-MM-dd}.log
</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} -%msg%n
</Pattern>
</layout>
</appender>
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="fileAppender"/>
</root>
</springProfile>
<springProfile name="prod">
<!--文件-->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<Prudent>true</Prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${logFile}.%d{yyyy-MM-dd}.log
</FileNamePattern>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} -%msg%n
</Pattern>
</layout>
</appender>
<root level="WARN">
<appender-ref ref="console"/>
<appender-ref ref="fileAppender"/>
</root>
</springProfile>
</configuration>