Commit e6c090eb authored by chenyongfeng's avatar chenyongfeng

初始化

parent 1c96c19a
Pipeline #20392 failed with stages
in 59 seconds
This diff is collapsed.
package io.github.doocs.im; package io.github.doocs.im;
import org.springframework.context.annotation.Configuration;
import io.github.doocs.im.util.VersionInfoUtil; import io.github.doocs.im.util.VersionInfoUtil;
/** /**
* @author bingo * @author bingo
* @since 2021/11/2 14:17 * @since 2021/11/2 14:17
*/ */
@Configuration
public class ClientConfiguration { public class ClientConfiguration {
private static final String DEFAULT_USER_AGENT = VersionInfoUtil.getDefaultUserAgent(); private static final String DEFAULT_USER_AGENT = VersionInfoUtil.getDefaultUserAgent();
private static final int DEFAULT_MAX_RETRIES = 3; private static final int DEFAULT_MAX_RETRIES = 3;
...@@ -22,6 +25,12 @@ public class ClientConfiguration { ...@@ -22,6 +25,12 @@ public class ClientConfiguration {
*/ */
private static final long DEFAULT_EXPIRE_TIME = 24 * 60 * 60L; private static final long DEFAULT_EXPIRE_TIME = 24 * 60 * 60L;
//------------------------------------------------------------------------------
private int maxRetries = DEFAULT_MAX_RETRIES; private int maxRetries = DEFAULT_MAX_RETRIES;
private long connectTimeout = DEFAULT_CONNECT_TIMEOUT; private long connectTimeout = DEFAULT_CONNECT_TIMEOUT;
private long readTimeout = DEFAULT_READ_TIMEOUT; private long readTimeout = DEFAULT_READ_TIMEOUT;
......
package io.github.doocs.im; package io.github.doocs.im;
import io.github.doocs.im.core.*;
import io.github.doocs.im.util.SigUtil;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.github.doocs.im.core.Account;
import io.github.doocs.im.core.Group;
import io.github.doocs.im.core.Member;
import io.github.doocs.im.core.Message;
import io.github.doocs.im.core.Operation;
import io.github.doocs.im.core.Profile;
import io.github.doocs.im.core.RecentContact;
import io.github.doocs.im.core.Sns;
import io.github.doocs.im.util.SigUtil;
/** /**
* @author hyh * @author hyh
* @since 2021/07/29 16:11 * @since 2021/07/29 16:11
*/ */
@Component
public class ImClient { public class ImClient {
private final long sdkAppId;
private final String key; @Value("${sdkAppId}")
private final String userId; private Long sdkAppId;
private final ClientConfiguration config; @Value("${key}")
private String key;
@Value("${userId}")
private String userId;
@Autowired
private ClientConfiguration config;
private String userSig; private String userSig;
private long userSigExpireTs; private long userSigExpireTs;
private static final String VERSION = "v4"; private static final String VERSION = "v4";
private static final String FORMAT_URL = "https://console.tim.qq.com/%s/%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=json"; private static final String FORMAT_URL =
"https://console.tim.qq.com/%s/%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=json";
public final Account account;
public final Message message; public Account account;
public final Member member; public Message message;
public final Profile profile; public Member member;
public final Group group; public Profile profile;
public final Sns sns; public Group group;
public final Operation operation; public Sns sns;
public final RecentContact recentContact; public Operation operation;
public RecentContact recentContact;
private static final ClientConfiguration DEFAULT_CONFIG = new ClientConfiguration();
// public ImClient(long sdkAppId, String userId, String key) {
public static ImClient getInstance(long sdkAppId, String userId, String key) { //
return new ImClient(sdkAppId, userId, key); //
} // }
public static ImClient getInstance(long sdkAppId, String userId, String key, ClientConfiguration config) { // private static final ClientConfiguration DEFAULT_CONFIG = new ClientConfiguration();
return new ImClient(sdkAppId, userId, key, config);
public static ImClient getInstance(long sdkAppId, String userId, String key) {
// return new ImClient(sdkAppId, userId, key);
return null;
} }
//
// public static ImClient getInstance(long sdkAppId, String userId, String key, ClientConfiguration config) {
// return new ImClient(sdkAppId, userId, key, config);
// }
//
// public ImClient(long sdkAppId, String userId, String key) {
// this(sdkAppId, userId, key, DEFAULT_CONFIG);
// }
// public ImClient(long sdkAppId, String userId, String key, ClientConfiguration config) {
// this.sdkAppId = sdkAppId;
// this.userId = userId;
// this.key = key;
// this.config = config;
// this.userSig = SigUtil.genUserSig(sdkAppId, key, userId, config.getExpireTime());
// this.userSigExpireTs = System.currentTimeMillis() / 1000 + config.getExpireTime() - 100;
//
// account = new Account(this);
// message = new Message(this);
// member = new Member(this);
// profile = new Profile(this);
// group = new Group(this);
// operation = new Operation(this);
// sns = new Sns(this);
// recentContact = new RecentContact(this);
// }
@PostConstruct
public void initMethod() {
public ImClient(long sdkAppId, String userId, String key) {
this(sdkAppId, userId, key, DEFAULT_CONFIG);
}
public ImClient(long sdkAppId, String userId, String key, ClientConfiguration config) {
this.sdkAppId = sdkAppId;
this.userId = userId;
this.key = key;
this.config = config;
this.userSig = SigUtil.genUserSig(sdkAppId, key, userId, config.getExpireTime()); this.userSig = SigUtil.genUserSig(sdkAppId, key, userId, config.getExpireTime());
this.userSigExpireTs = System.currentTimeMillis() / 1000 + config.getExpireTime() - 100; this.userSigExpireTs = System.currentTimeMillis() / 1000 + config.getExpireTime() - 100;
...@@ -85,7 +126,38 @@ public class ImClient { ...@@ -85,7 +126,38 @@ public class ImClient {
public String getUrl(String serviceName, String command) { public String getUrl(String serviceName, String command) {
String sig = getUserSig(); String sig = getUserSig();
long random = ThreadLocalRandom.current().nextLong(0, 0x100000000L); long random = ThreadLocalRandom.current().nextLong(0, 0x100000000L);
return String.format(FORMAT_URL, VERSION, serviceName, command, return String.format(FORMAT_URL, VERSION, serviceName, command, sdkAppId, userId, sig, random);
sdkAppId, userId, sig, random); }
public Account getAccount() {
return account;
}
public Message getMessage() {
return message;
}
public Member getMember() {
return member;
}
public Profile getProfile() {
return profile;
}
public Group getGroup() {
return group;
}
public Sns getSns() {
return sns;
}
public Operation getOperation() {
return operation;
}
public RecentContact getRecentContact() {
return recentContact;
} }
} }
package io.github.doocs.im;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
DruidDataSourceAutoConfigure.class ,
HibernateJpaAutoConfiguration.class})
public class QcloudImApplication {
public static void main(String[] args) {
SpringApplication.run(QcloudImApplication.class,args);
}
}
package io.github.doocs.im.config;
import lombok.Data;
@Data
public class BusinessException extends RuntimeException {
private CommonError commonError;
public BusinessException(ErrorEnum errorEnum) {
super();
this.commonError = new CommonError(errorEnum);
}
public BusinessException(CommonError commonError) {
super();
this.commonError = commonError;
}
}
package io.github.doocs.im.config;
import lombok.Data;
@Data
public class CommonError {
private String code;
private String msg;
public CommonError(String code, String msg) {
this.code = code;
this.msg = msg;
}
public CommonError(ErrorEnum errorEnum) {
this.code = errorEnum.getCode();
this.msg = errorEnum.getMsg();
}
}
package io.github.doocs.im.config;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
@Data
public class CommonResult {
private String status;
private Object data;
public static CommonResult success() {
CommonResult commonResult = new CommonResult();
commonResult.setStatus("success");
commonResult.setData("操作成功!");
return commonResult;
}
public static CommonResult success(Object data) {
CommonResult success = success();
if (data == null) {
success.setData(new JSONObject());
return success;
}
success.setData(data);
return success;
}
public static CommonResult fail(ErrorEnum errorEnum) {
CommonResult commonResult = new CommonResult();
commonResult.setStatus("fail");
CommonError commonError = new CommonError(errorEnum);
commonResult.setData(commonError);
return commonResult;
}
public static CommonResult fail(CommonError commonError) {
CommonResult commonResult = new CommonResult();
commonResult.setStatus("fail");
commonResult.setData(commonError);
return commonResult;
}
}
package io.github.doocs.im.config;
public enum ErrorEnum {
UNKNOWN_ERROR("10001", "未知错误!"),
REQUEST_ERROR("10002", "请求qcloud失败!"),
ACCOUNT_KILLED("1000", "账号已被失效!"),
ACCOUNT_DELETE("1001", "账号已被删除!"),
E404_ERROR("10003", "请求不存在!"),
BIND_ERROR("10004", "请求参数不存在"),
PARAM_ERROR_4("10005", "请求参数错误"),
METHOD_ERROR("10006", "请求方式get/post错误!"),
SAVE_ERROR("10008", "保存失败!"),
DEL_ERROR("10007", "删除数量为0!"),
EXISTS_ERROR("20001", "名称已存在!"),
EXCEL_ERROR("30001", "excel文件内容不能为空!"),
EXCEL_PARSE_ERROR("30002", "excel文件内容解析失败!"),
EMAIL_ERROR("30003", "与预留邮箱不一致!"),
EMAIL_FAIL_ERROR("30004", "邮件发送失败!"),
CODE_ERROR("30005", "验证码不正确!"),
CODE_CREATE_ERROR("30006", "验证码生成失败!"),
CODE_EFFECT_ERROR("30007", "验证码已经失效!"),
USERNAME_ERROR("30008", "用户邮箱不能为空!"),
PASSWORD_ERROR("30009", "密码不能为空!"),
USERNOTEXISTS_ERROR("30010", "用户不存在!"),
PASSWORDFAIL_ERROR("30011", "密码不正确!"),
PARAMVALUE_ERROR("30012", "参数值错误!"),
PARAMLOSE_ERROR("30013", "参数缺失!"),
LOGIN_ERROR("30014", "请重新登陆!"),
PHONEVERIFY_ERROR("30015", "手机号未注册!"),
IDNULL_ERROR("30016", "id不能为空!"),
NO_AUTH_ERROR("10000","没有权限,请联系管理员授权"),
NOTALL_ERROR("30017","开始结束时间必须同时存在!") ,
VERIFY_CODE_ERROR("30018","手机验证码错误!") ,
BIND_CHILDREN_ERROR("30019","请绑定孩子!"),
RESERVE_COURSE_ERROR("30020","暂未约课!"),
REQUEST_FAILED("30021","request failed!"),
RESERVE_FULL("30022","课程已约满"),
RESERVE_ABOVE("30023","约课已超出剩余"),
RESERVE_DATE_ERROR("30024","约课日期有过去的时间请重新约课"),
USERCOUNT_ERROR("30025","账户已失效!"),
USERBLOCK_ERROR("30026","账户已冻结!"),
BINDTYPE_ERROR("30027","已绑定身份!"),
PAYMENT_ERROR("30028","订单已确认收款,不能重复提交!"),
RESERVE_ERROR("30029","您已在该时段预约,不能重复提交!"),
NULL_TIMEZONE_ERROR("30030","时区不可为空!!");
private String code;
private String msg;
ErrorEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package io.github.doocs.im.config;
/**
* @Auther chenyongfeng
* @Date 2021/5/28
*/
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class ExecutorConfig {
@Bean(name = "mypool")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(20);
// 配置最大线程数
executor.setMaxPoolSize(30);
// 配置队列大小
executor.setQueueCapacity(5);
// 配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("Thread-");
executor.setAwaitTerminationSeconds(10000);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 执行初始化
executor.initialize();
return executor;
}
}
package io.github.doocs.im.config;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;
import lombok.extern.slf4j.Slf4j;
@ControllerAdvice
@Slf4j
public class GlobalExceptionAdvice {
@ExceptionHandler(Exception.class)
@ResponseBody
public CommonResult exceptionHandler(Exception e) {
log.error(e.getMessage(), e);
return CommonResult.fail(new CommonError(ErrorEnum.UNKNOWN_ERROR));
}
/**
* 自定义异常
*
* @param e
* @return
*/
@ExceptionHandler(BusinessException.class)
@ResponseBody
public CommonResult exceptionHandler(BusinessException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(e.getCommonError());
}
/**
* 参数转换错误
*
* @param e
* @return
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public CommonResult handleConstraintViolationException(HttpMessageNotReadableException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(ErrorEnum.PARAM_ERROR_4);
}
/**
* 404
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public CommonResult handleConstraintViolationException(NoHandlerFoundException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(ErrorEnum.E404_ERROR);
}
/**
* 参数校验失败 在方法内的参数
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(ConstraintViolationException.class)
public CommonResult handleConstraintViolationException(ConstraintViolationException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(new CommonError("10009",
e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining())));
}
/**
* 参数绑定错误 id ids
*
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(ServletRequestBindingException.class)
public CommonResult handleConstraintViolationException(ServletRequestBindingException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(ErrorEnum.BIND_ERROR);
}
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
public CommonResult handleConstraintViolationException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(new CommonError("10009", e.getBindingResult().getFieldError().getDefaultMessage()));
}
@ResponseBody
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public CommonResult handleConstraintViolationException(HttpRequestMethodNotSupportedException e) {
log.error(e.getMessage(), e);
return CommonResult.fail(ErrorEnum.METHOD_ERROR);
}
// @ResponseBody
// @ExceptionHandler(AccessDeniedException.class)
// public CommonResult handleAuthorizationException(AccessDeniedException e) {
// log.error(e.getMessage(), e);
// return CommonResult.fail(ErrorEnum.NO_AUTH_ERROR);
// }
/**
* 文件上传异常处理
*
* @param e
* @return
*/
// @ResponseBody
// @ExceptionHandler(MultipartException.class)
// public CommonResult exception(MaxUploadSizeExceededException e) {
// if (e.getCause().getCause() instanceof FileUploadBase.FileSizeLimitExceededException) {
// log.error("message异常信息为=========》" + e.getMessage());
// log.error("cause异常信息为=========》" + e.getCause().getCause());
// String s = "单个上传文件大小不能超过20MB";
// return CommonResult.fail(new CommonError("40001","单个上传文件大小不能超过20MB"));
//
// } else if (e.getCause().getCause() instanceof FileUploadBase.SizeLimitExceededException) {
// log.error("message异常信息为=========》" + e.getMessage());
// log.error("cause异常信息为=========》" + e.getCause().getCause());
// return CommonResult.fail(new CommonError("40002","总上传文件大小不能超过100MB"));
//
// }
// return CjwommonResult.fail(new CommonError("40000","文件上传异常!"));
//
// }
}
package io.github.doocs.im.config;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
@Component
@ConfigurationProperties(prefix = "spring.http-client.pool")
@Data
public class HttpClientPoolConfig {
/**
* java配置的优先级低于yml配置;如果yml配置不存在,会采用java配置
*/
/**
* 连接池的最大连接数
*/
private int maxTotalConnect;
/**
* 同路由的并发数
*/
private int maxConnectPerRoute;
/**
* 客户端和服务器建立连接超时,默认2s
*/
private int connectTimeout = 2 * 1000;
/**
* 指客户端从服务器读取数据包的间隔超时时间,不是总读取时间,默认30s
*/
private int readTimeout = 30 * 1000;
private String charset = "UTF-8";
/**
* 重试次数,默认2次
*/
private int retryTimes = 2;
/**
* 从连接池获取连接的超时时间,不宜过长,单位ms
*/
private int connectionRequestTimout = 200;
/**
* 针对不同的地址,特别设置不同的长连接保持时间
*/
private Map<String, Integer> keepAliveTargetHost;
/**
* 针对不同的地址,特别设置不同的长连接保持时间,单位 s
*/
private int keepAliveTime = 60;
}
package io.github.doocs.im.config;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import lombok.Getter;
import lombok.Setter;
/**
* @Description mongo配置类
* @Author Mr.nobody
* @Date 2020/11/7
* @Version 1.0
*/
@Configuration
// 将带有@ConfigurationProperties注解的类注入为Spring容器的Bean,
// 任何被@ConfigurationProperties注解的beans将自动被Environment属性配置。
@EnableConfigurationProperties(MongoConfig.MongoClientOptionProperties.class)
public class MongoConfig {
/**
* 此Bean也是可以不显示定义的,如果我们没有显示定义生成MongoTemplate实例, SpringBoot利用我们配置好的MongoDbFactory在配置类中生成一个MongoTemplate,
* 之后我们就可以在项目代码中直接@Autowired了。因为用于生成MongoTemplate 的MongoDbFactory是我们自己在MongoConfig配置类中生成的,所以我们自定义的连接池参数也就生效了。
*
* @param mongoDbFactory
* mongo工厂
* @param converter
* 转换器
* @return MongoTemplate实例
*/
@Bean
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MappingMongoConverter converter) {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
// 设置读从库优先
mongoTemplate.setReadPreference(ReadPreference.secondaryPreferred());
return mongoTemplate;
}
/**
* 转换器 MappingMongoConverter可以自定义mongo转换器,主要自定义存取mongo数据时的一些操作,例如 mappingConverter.setTypeMapper(new
* DefaultMongoTypeMapper(null)) 方法会将mongo数据中的_class字段去掉。
*
* @param factory
* mongo工厂
* @param context
* 上下文
* @param conversions
* 自定义转换器
* @return 转换器对象
*/
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context,
MongoCustomConversions conversions) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
mappingConverter.setCustomConversions(conversions);
// remove _class field
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
/**
* 自定义mongo连接池
*
* @param properties
* 属性配置类
* @return MongoDbFactory对象
*/
@Bean
public MongoDbFactory mongoDbFactory(MongoClientOptionProperties properties) {
MongoClient mongoClient;
// 创建客户端参数
MongoClientOptions mongoClientOptions = mongoClientOptions(properties);
// 解析获取mongo服务地址
List<ServerAddress> serverAddressList = getServerAddress(properties.getAddress());
// 创建认证
MongoCredential mongoCredential = getCredential(properties);
// 创建客户端
if (null == mongoCredential) {
mongoClient = new MongoClient(serverAddressList, mongoClientOptions);
} else {
mongoClient = new MongoClient(serverAddressList, mongoCredential, mongoClientOptions);
}
return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
}
/**
* 创建认证
*
* @param properties
* 属性配置类
* @return 认证对象
*/
private MongoCredential getCredential(MongoClientOptionProperties properties) {
if (!StringUtils.isEmpty(properties.getUsername()) && !StringUtils.isEmpty(properties.getPassword())) {
// 没有专用认证数据库则取当前数据库
String database = StringUtils.isEmpty(properties.getAuthenticationDatabase()) ? properties.getDatabase()
: properties.getAuthenticationDatabase();
return MongoCredential.createCredential(properties.getUsername(), database,
properties.getPassword().toCharArray());
}
return null;
}
/**
* 获取数据库服务地址
*
* @param mongoAddress
* 地址字符串
* @return 服务地址数组
*/
private List<ServerAddress> getServerAddress(String mongoAddress) {
String[] mongoAddressArray = mongoAddress.trim().split(",");
List<ServerAddress> serverAddressList = new ArrayList<>(4);
for (String address : mongoAddressArray) {
String[] hostAndPort = address.split(":");
serverAddressList.add(new ServerAddress(hostAndPort[0], Integer.parseInt(hostAndPort[1])));
}
return serverAddressList;
}
/**
* mongo客户端参数配置
*
* @param properties
* 属性配置类
* @return mongo客户端参数配置对象
*/
private MongoClientOptions mongoClientOptions(MongoClientOptionProperties properties) {
return MongoClientOptions.builder().applicationName(properties.getClientName())
.connectTimeout(properties.getConnectionTimeoutMs())
.maxConnectionIdleTime(properties.getMaxConnectionIdleTimeMs())
.maxConnectionLifeTime(properties.getMaxConnectionLifeTimeMs()).socketTimeout(properties.getReadTimeoutMs())
.maxWaitTime(properties.getMaxWaitTimeMs()).heartbeatFrequency(properties.getHeartbeatFrequencyMs())
.minHeartbeatFrequency(properties.getMinHeartbeatFrequencyMs())
.heartbeatConnectTimeout(properties.getHeartbeatConnectionTimeoutMs())
.heartbeatSocketTimeout(properties.getHeartbeatReadTimeoutMs())
.connectionsPerHost(properties.getConnectionsPerHost())
.minConnectionsPerHost(properties.getMinConnectionsPerHost())
.threadsAllowedToBlockForConnectionMultiplier(properties.getThreadsAllowedToBlockForConnectionMultiplier())
// .readPreference(ReadPreference.secondaryPreferred()).sslEnabled(true).build();
.readPreference(ReadPreference.secondaryPreferred()).build();
}
@Getter
@Setter
@Validated
@ConfigurationProperties(prefix = "mongodb")
public static class MongoClientOptionProperties {
/**
* 基础连接参数
*/
private String database; // 要连接的数据库
private String username; // 用户名
private String password; // 密码
private String address; // IP和端口(host:port),例如127.0.0.1:27017。集群模式用,分隔开,例如host1:port1,host2:port2
private String authenticationDatabase; // 设置认证数据库,如果有的话
/**
* 客户端连接池参数
*/
private String clientName; // 客户端的标识,用于定位请求来源等,一般用程序名
@Min(value = 1)
private int connectionTimeoutMs; // TCP(socket)连接超时时间,毫秒
@Min(value = 1)
private int maxConnectionIdleTimeMs; // TCP(socket)连接闲置时间,毫秒
@Min(value = 1)
private int maxConnectionLifeTimeMs; // TCP(socket)连接最多可以使用多久,毫秒
@Min(value = 1)
private int readTimeoutMs; // TCP(socket)读取超时时间,毫秒
@Min(value = 1)
private int maxWaitTimeMs; // 当连接池无可用连接时客户端阻塞等待的最大时长,毫秒
@Min(value = 2000)
private int heartbeatFrequencyMs; // 心跳检测发送频率,毫秒
@Min(value = 300)
private int minHeartbeatFrequencyMs; // 最小的心跳检测发送频率,毫秒
@Min(value = 200)
private int heartbeatConnectionTimeoutMs; // 心跳检测连接超时时间,毫秒
@Min(value = 200)
private int heartbeatReadTimeoutMs; // 心跳检测读取超时时间,毫秒
@Min(value = 1)
private int connectionsPerHost; // 线程池允许的最大连接数
@Min(value = 1)
private int minConnectionsPerHost; // 线程池空闲时保持的最小连接数
@Min(value = 1)
// 计算允许多少个线程阻塞等待时的乘数,算法:threadsAllowedToBlockForConnectionMultiplier*maxConnectionsPerHost
private int threadsAllowedToBlockForConnectionMultiplier;
}
}
package io.github.doocs.im.config;
import java.util.Date;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
/**
* @Auther chenyongfeng
* @Date 2021/7/30
*/
@Configuration
public class MyBatisFillConfig implements MetaObjectHandler {
// 使用mp实现添加操作,这个方法会执行,metaObject元数据(表中的名字,表中的字段)
@Override
public void insertFill(MetaObject metaObject) {
// 根据名称设置属性值
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("applyTime",new Date(),metaObject);
}
// 使用mp实现修改操作,这个方法会执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
package io.github.doocs.im.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
/**
* mybatis-plus分页配置
*
* @author muxh
* @date 2021/10/18 16:46
*/
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
package io.github.doocs.im.config;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置校验快速失败
*/
@Configuration
public class ValidatorConfig {
@Bean
public Validator validator() {
ValidatorFactory validatorFactory =
Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory();
return validatorFactory.getValidator();
}
}
\ No newline at end of file
package io.github.doocs.im.config;
/**
* @Auther chenyongfeng
* @Date 2021/5/26
*/
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.hibernate.validator.HibernateValidator;
public class ValidatorUtil {
private static Validator validatorFast = Validation.byProvider(HibernateValidator.class).configure().failFast(true)
.buildValidatorFactory().getValidator();
private static Validator validatorAll = Validation.byProvider(HibernateValidator.class).configure().failFast(false)
.buildValidatorFactory().getValidator();
/**
* 校验遇到第一个不合法的字段直接返回不合法字段,后续字段不再校验
*
* @param <T>
* @param domain
* @throws Exception
* @Time 2020年6月22日 上午11:36:13
*/
public static <T> void validateFast(T domain) {
Set<ConstraintViolation<T>> validateResult = validatorFast.validate(domain);
if (validateResult.size() > 0) {
// System.out.println(validateResult.iterator().next().getPropertyPath() +":"+
// validateResult.iterator().next().getMessage());
throw new BusinessException(new CommonError("10009", validateResult.iterator().next().getPropertyPath()
+ ":" + validateResult.iterator().next().getMessage()));
}
}
/**
* 校验所有字段并返回不合法字段
*
* @param <T>
* @param domain
* @return
* @throws Exception
* @Time 2020年6月22日 上午11:36:55
*/
public static <T> Set<ConstraintViolation<T>> validateAll(T domain) throws Exception {
Set<ConstraintViolation<T>> validateResult = validatorAll.validate(domain);
if (validateResult.size() > 0) {
Iterator<ConstraintViolation<T>> it = validateResult.iterator();
while (it.hasNext()) {
ConstraintViolation<T> cv = it.next();
System.out.println(cv.getPropertyPath() + ":" + cv.getMessage());
}
}
return validateResult;
}
}
package io.github.doocs.im.config;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* WebJsonConverterConfig
*
* @author WebJsonConverterConfig
*/
// @Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
return jackson2HttpMessageConverter;
}
}
...@@ -17,6 +17,9 @@ public class ActionStatus { ...@@ -17,6 +17,9 @@ public class ActionStatus {
*/ */
public static final String FAIL = "FAIL"; public static final String FAIL = "FAIL";
public static final String SOMEERROR = "SomeError";
private ActionStatus() { private ActionStatus() {
} }
......
package io.github.doocs.im.constant;
public class MongoAccoutStatus {
public static final int EFFECTIVED = 1;
public static final int KILLED = 2;
public static final int DELETEED = 3;
}
package io.github.doocs.im.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.servie.AccountService;
import io.github.doocs.im.vo.AccountVO;
import io.github.doocs.im.vo.QueryOnlineStatusRequestVO;
@RestController
@RequestMapping("/account")
public class AccountController {
@Autowired
AccountService accountService;
/**
* 生成im账号 有会从当前服务返回,没有会请求腾讯im获取返回 也可用于户账号查询 生成的imid 规则为source_originalId
*
* @param accountVO
* @return
*/
@PostMapping("/accountImport")
public CommonResult accountImport(@Validated @RequestBody AccountVO accountVO) {
return accountService.accountImport(accountVO);
}
/**
* 查询账号在线状态
*
* @param
* @return
*/
@PostMapping("/queryOnlineStatus")
public CommonResult queryOnlineStatus(@Validated @RequestBody QueryOnlineStatusRequestVO queryOnlineStatusRequest) {
return accountService.queryOnlineStatus(queryOnlineStatusRequest);
}
}
package io.github.doocs.im.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.model.request.AddGroupMemberRequest;
import io.github.doocs.im.model.request.CreateGroupRequest;
import io.github.doocs.im.model.request.DeleteGroupMemberRequest;
import io.github.doocs.im.model.request.DestroyGroupRequest;
import io.github.doocs.im.model.request.GroupMsgRecallRequest;
import io.github.doocs.im.model.request.ModifyGroupBaseInfoRequest;
import io.github.doocs.im.model.request.SetUnreadMsgNumRequest;
import io.github.doocs.im.servie.GroupService;
@RestController
@RequestMapping("/group")
public class GroupController {
@Autowired
GroupService groupService;
/**
* 创建群组
*
* @param createGroupRequest
* @return
*/
@RequestMapping("/createGroup")
public CommonResult createGroup(@RequestBody CreateGroupRequest createGroupRequest) {
return groupService.createGroup(createGroupRequest);
}
/**
* 添加群成员
*
* @param addGroupMemberRequest
* @return
*/
@RequestMapping("/addGroupMember")
public CommonResult addGroupMember(@RequestBody AddGroupMemberRequest addGroupMemberRequest) {
return groupService.addGroupMember(addGroupMemberRequest);
}
/**
* 删除群成员
*
* @param addGroupMemberRequest
* @return
*/
@RequestMapping("/deleteGroupMember")
public CommonResult deleteGroupMember(@RequestBody DeleteGroupMemberRequest addGroupMemberRequest) {
return groupService.deleteGroupMember(addGroupMemberRequest);
}
/**
* 解散群组
*
* @param destroyGroupRequest
* @return
*/
@RequestMapping("/destroyGroup")
public CommonResult destroyGroup(@RequestBody DestroyGroupRequest destroyGroupRequest) {
return groupService.destroyGroup(destroyGroupRequest);
}
/**
* 修改群基础信息
*
* @param modifyGroupBaseInfoRequest
* @return
*/
@RequestMapping("/modifyGroupBaseInfo")
public CommonResult modifyGroupBaseInfo(@RequestBody ModifyGroupBaseInfoRequest modifyGroupBaseInfoRequest) {
return groupService.modifyGroupBaseInfo(modifyGroupBaseInfoRequest);
}
/**
* 设置群成员消息未读数
*
* @param setUnreadMsgNumRequest
* @return
*/
@RequestMapping("/setUnreadMsgNum")
public CommonResult setUnreadMsgNum(@RequestBody SetUnreadMsgNumRequest setUnreadMsgNumRequest) {
return groupService.setUnreadMsgNum(setUnreadMsgNumRequest);
}
/**
* 管理员撤回群消息
* @param groupMsgRecallRequest
* @return
*/
@RequestMapping("/groupMsgRecall")
public CommonResult groupMsgRecall(@RequestBody GroupMsgRecallRequest groupMsgRecallRequest) {
return groupService.groupMsgRecall(groupMsgRecallRequest);
}
}
package io.github.doocs.im.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.github.doocs.im.servie.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.vo.SimpleMessageVO;
@RestController
@RequestMapping("/message")
public class MessageController {
@Autowired
MessageService messageService;
@PostMapping("/sendMessage")
public CommonResult sendMessage(@RequestBody SimpleMessageVO simpleMessageVO) throws JsonProcessingException {
return messageService.sendMessage(simpleMessageVO);
}
// public static void main(String[] args) {
// String a = "https://img14.360buyimg.com/pop/jfs/t1/181251/30/8749/184198/60c32b0bEbe5d7052/dc859b8261fb7c8b.jpg";
// int length = a.length();
// System.out.println(length);
// }
}
...@@ -43,7 +43,7 @@ public class Account { ...@@ -43,7 +43,7 @@ public class Account {
* @return 结果 * @return 结果
* @throws IOException 异常 * @throws IOException 异常
*/ */
public AccountImportResult accountImport(AccountImportRequest accountImportRequest) throws IOException { public AccountImportResult accountImport(AccountImportRequest accountImportRequest) throws Exception {
String url = imClient.getUrl(SERVICE_NAME, ACCOUNT_IMPORT_COMMAND); String url = imClient.getUrl(SERVICE_NAME, ACCOUNT_IMPORT_COMMAND);
return HttpUtil.post(url, accountImportRequest, AccountImportResult.class, imClient.getConfig()); return HttpUtil.post(url, accountImportRequest, AccountImportResult.class, imClient.getConfig());
} }
......
...@@ -72,7 +72,7 @@ public class Group { ...@@ -72,7 +72,7 @@ public class Group {
* @return 结果 * @return 结果
* @throws IOException 异常 * @throws IOException 异常
*/ */
public CreateGroupResult createGroup(CreateGroupRequest createGroupRequest) throws IOException { public CreateGroupResult createGroup(CreateGroupRequest createGroupRequest) throws Exception {
String url = imClient.getUrl(SERVICE_NAME, CREATE_GROUP_COMMAND); String url = imClient.getUrl(SERVICE_NAME, CREATE_GROUP_COMMAND);
return HttpUtil.post(url, createGroupRequest, CreateGroupResult.class, imClient.getConfig()); return HttpUtil.post(url, createGroupRequest, CreateGroupResult.class, imClient.getConfig());
} }
......
...@@ -43,7 +43,7 @@ public class Message { ...@@ -43,7 +43,7 @@ public class Message {
* @return 结果 * @return 结果
* @throws IOException 异常 * @throws IOException 异常
*/ */
public SendMsgResult sendMsg(SendMsgRequest sendMsgRequest) throws IOException { public SendMsgResult sendMsg(SendMsgRequest sendMsgRequest) throws Exception {
String url = imClient.getUrl(SERVICE_NAME, SEND_MSG_COMMAND); String url = imClient.getUrl(SERVICE_NAME, SEND_MSG_COMMAND);
return HttpUtil.post(url, sendMsgRequest, SendMsgResult.class, imClient.getConfig()); return HttpUtil.post(url, sendMsgRequest, SendMsgResult.class, imClient.getConfig());
} }
......
...@@ -17,6 +17,10 @@ public class CreateGroupRequest extends GroupInfo { ...@@ -17,6 +17,10 @@ public class CreateGroupRequest extends GroupInfo {
super(builder); super(builder);
} }
public CreateGroupRequest() {
}
public static class Builder extends GroupInfo.Builder<CreateGroupRequest.Builder> { public static class Builder extends GroupInfo.Builder<CreateGroupRequest.Builder> {
@Override @Override
public CreateGroupRequest build() { public CreateGroupRequest build() {
......
package io.github.doocs.im.mongo;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
@Data
@Document(collection= "im_account")
@ToString
public class AccountEntity {
// 来源
private String id;
// 昵称
private String nick;
// 头像
private String faceUrl;
// 状态 1-正常 2-封号 3-删除
private int status;
// 时间
private long updateTime = System.currentTimeMillis();
public AccountEntity(String id, String nick, String faceUrl,int status) {
this.id = id;
this.nick = nick;
this.faceUrl = faceUrl;
this.status = status;
}
}
package io.github.doocs.im.servie;
import java.util.HashMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import io.github.doocs.im.ImClient;
import io.github.doocs.im.config.BusinessException;
import io.github.doocs.im.config.CommonError;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.config.ErrorEnum;
import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.constant.MongoAccoutStatus;
import io.github.doocs.im.core.Account;
import io.github.doocs.im.model.request.AccountImportRequest;
import io.github.doocs.im.model.request.QueryOnlineStatusRequest;
import io.github.doocs.im.model.response.AccountImportResult;
import io.github.doocs.im.model.response.QueryOnlineStatusResult;
import io.github.doocs.im.mongo.AccountEntity;
import io.github.doocs.im.vo.AccountVO;
import io.github.doocs.im.vo.QueryOnlineStatusRequestVO;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class AccountService extends GeneraService {
@Autowired
ImClient imClient;
public CommonResult accountImport(AccountVO accountVO) {
// 先从mongo获取 有直接返回成功
String id = accountVO.getSource() + "_" + accountVO.getOriginalId();
AccountEntity accountEntity =
mongoTemplate.findOne(Query.query(Criteria.where("_id").is(id)), AccountEntity.class);
if (accountEntity != null) {
if (accountEntity.getStatus() == MongoAccoutStatus.EFFECTIVED) {
return CommonResult.success(id);
}
if (accountEntity.getStatus() == MongoAccoutStatus.KILLED) {
return CommonResult.fail(ErrorEnum.ACCOUNT_KILLED);
}
if (accountEntity.getStatus() == MongoAccoutStatus.DELETEED) {
return CommonResult.fail(ErrorEnum.ACCOUNT_DELETE);
}
}
Account account = imClient.getAccount();
AccountImportRequest accountImportRequest = new AccountImportRequest();
accountImportRequest.setIdentifier(id);
accountImportRequest.setFaceUrl(accountVO.getFaceUrl());
accountImportRequest.setNick(accountVO.getNick());
AccountImportResult accountImportResult;
try {
accountImportResult = account.accountImport(accountImportRequest);
log.info("腾讯result:{}", accountImportResult.toString());
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", accountVO.toString());
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
return conver(accountImportResult, accountVO);
}
/**
* 注册账号结果转换
*
* @param accountImportResult
* @param accountVO
* @return
*/
public CommonResult conver(AccountImportResult accountImportResult, AccountVO accountVO) {
String actionStatus = accountImportResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
saveToMongo(accountVO);
return CommonResult.success(accountVO.getSource() + "_" + accountVO.getOriginalId());
}
return CommonResult.fail(
new CommonError(String.valueOf(accountImportResult.getErrorCode()), accountImportResult.getErrorInfo()));
}
/**
* 账号信息保存到mongo
*
* @param accountVO
*/
public void saveToMongo(AccountVO accountVO) {
executor.execute(() -> {
// int i = 2 / 0; 异步线程的异常不会在主线程被捕获
AccountEntity accountEntity = new AccountEntity(accountVO.getSource() + "_" + accountVO.getOriginalId(),
accountVO.getNick(), accountVO.getFaceUrl(), 1); // 有效
try {
mongoTemplate.save(accountEntity);
log.info("保存im_account成功:{}", accountEntity.toString());
} catch (Exception e) {
log.error("保存im_account失败:{}", accountEntity.toString());
}
});
}
/**
* 查询账号在线状态 个别账号无效返回someError 全部无效返回fali
*
* @param
* @return
*/
public CommonResult queryOnlineStatus(QueryOnlineStatusRequestVO queryOnlineStatusRequestVO) {
Account account = imClient.getAccount();
QueryOnlineStatusRequest queryOnlineStatusRequest = new QueryOnlineStatusRequest();
BeanUtils.copyProperties(queryOnlineStatusRequestVO, queryOnlineStatusRequest);
QueryOnlineStatusResult queryOnlineStatusResult;
try {
queryOnlineStatusResult = account.queryOnlineStatus(queryOnlineStatusRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(queryOnlineStatusRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
log.info("结果:{}", queryOnlineStatusResult.toString());
String actionStatus = queryOnlineStatusResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus) || ActionStatus.SOMEERROR.equalsIgnoreCase(actionStatus)) {
HashMap<String, Object> result = Maps.newHashMap();
result.put("queryResult", queryOnlineStatusResult.getQueryResult());
result.put("errorList", queryOnlineStatusResult.getErrorList());
return CommonResult.success(result);
}
return CommonResult.fail(new CommonError(String.valueOf(queryOnlineStatusResult.getErrorCode()),
queryOnlineStatusResult.getErrorInfo()));
}
}
package io.github.doocs.im.servie;
import java.util.concurrent.Executor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
public abstract class GeneraService {
@Autowired
MongoTemplate mongoTemplate;
@Qualifier("mypool")
@Autowired
Executor executor;
ObjectMapper mapper = new ObjectMapper();
}
package io.github.doocs.im.servie;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import io.github.doocs.im.ImClient;
import io.github.doocs.im.config.BusinessException;
import io.github.doocs.im.config.CommonError;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.config.ErrorEnum;
import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.core.Group;
import io.github.doocs.im.model.request.AddGroupMemberRequest;
import io.github.doocs.im.model.request.CreateGroupRequest;
import io.github.doocs.im.model.request.DeleteGroupMemberRequest;
import io.github.doocs.im.model.request.DestroyGroupRequest;
import io.github.doocs.im.model.request.GroupMsgRecallRequest;
import io.github.doocs.im.model.request.ModifyGroupBaseInfoRequest;
import io.github.doocs.im.model.request.SetUnreadMsgNumRequest;
import io.github.doocs.im.model.response.AddGroupMemberResult;
import io.github.doocs.im.model.response.CreateGroupResult;
import io.github.doocs.im.model.response.DeleteGroupMemberResult;
import io.github.doocs.im.model.response.DestroyGroupResult;
import io.github.doocs.im.model.response.GroupMsgRecallResult;
import io.github.doocs.im.model.response.ModifyGroupBaseInfoResult;
import io.github.doocs.im.model.response.SetUnreadMsgNumResult;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class GroupService extends GeneraService {
@Autowired
ImClient imClient;
public CommonResult createGroup(CreateGroupRequest createGroupRequest) {
Group group = imClient.getGroup();
CreateGroupResult groupResult;
try {
groupResult = group.createGroup(createGroupRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(createGroupRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = groupResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
HashMap<String, Object> result = Maps.newHashMap();
result.put("groupId", groupResult.getGroupId());
return CommonResult.success(result);
}
return CommonResult
.fail(new CommonError(String.valueOf(groupResult.getErrorCode()), groupResult.getErrorInfo()));
}
public CommonResult addGroupMember(AddGroupMemberRequest addGroupMemberRequest) {
Group group = imClient.getGroup();
AddGroupMemberResult addGroupMemberResult;
try {
addGroupMemberResult = group.addGroupMember(addGroupMemberRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(addGroupMemberRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = addGroupMemberResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
HashMap<String, Object> result = Maps.newHashMap();
result.put("MemberList", addGroupMemberResult.getMemberList());
return CommonResult.success(result);
}
return CommonResult.fail(
new CommonError(String.valueOf(addGroupMemberResult.getErrorCode()), addGroupMemberResult.getErrorInfo()));
}
public CommonResult deleteGroupMember(DeleteGroupMemberRequest addGroupMemberRequest) {
Group group = imClient.getGroup();
DeleteGroupMemberResult deleteGroupMemberResult;
try {
deleteGroupMemberResult = group.deleteGroupMember(addGroupMemberRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(addGroupMemberRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = deleteGroupMemberResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
return CommonResult.success();
}
return CommonResult.fail(new CommonError(String.valueOf(deleteGroupMemberResult.getErrorCode()),
deleteGroupMemberResult.getErrorInfo()));
}
public CommonResult destroyGroup(DestroyGroupRequest destroyGroupRequest) {
Group group = imClient.getGroup();
DestroyGroupResult destroyGroupResult;
try {
destroyGroupResult = group.destroyGroup(destroyGroupRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(destroyGroupRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = destroyGroupResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
return CommonResult.success();
}
return CommonResult.fail(
new CommonError(String.valueOf(destroyGroupResult.getErrorCode()), destroyGroupResult.getErrorInfo()));
}
public CommonResult modifyGroupBaseInfo(ModifyGroupBaseInfoRequest modifyGroupBaseInfoRequest) {
Group group = imClient.getGroup();
ModifyGroupBaseInfoResult modifyGroupBaseInfoResult;
try {
modifyGroupBaseInfoResult = group.modifyGroupBaseInfo(modifyGroupBaseInfoRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(modifyGroupBaseInfoRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = modifyGroupBaseInfoResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
return CommonResult.success();
}
return CommonResult.fail(new CommonError(String.valueOf(modifyGroupBaseInfoResult.getErrorCode()),
modifyGroupBaseInfoResult.getErrorInfo()));
}
public CommonResult setUnreadMsgNum(SetUnreadMsgNumRequest setUnreadMsgNumRequest) {
Group group = imClient.getGroup();
SetUnreadMsgNumResult setUnreadMsgNumResult;
try {
setUnreadMsgNumResult = group.setUnreadMsgNum(setUnreadMsgNumRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(setUnreadMsgNumRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = setUnreadMsgNumResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
return CommonResult.success();
}
return CommonResult.fail(new CommonError(String.valueOf(setUnreadMsgNumResult.getErrorCode()),
setUnreadMsgNumResult.getErrorInfo()));
}
public CommonResult groupMsgRecall(GroupMsgRecallRequest groupMsgRecallRequest) {
Group group = imClient.getGroup();
GroupMsgRecallResult groupMsgRecallResult;
try {
groupMsgRecallResult = group.groupMsgRecall(groupMsgRecallRequest);
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JSON.toJSONString(groupMsgRecallRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
log.info("返回结果:{}",groupMsgRecallResult.toString());
String actionStatus = groupMsgRecallResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
return CommonResult.success(groupMsgRecallResult.getRecallRetList());
}
return CommonResult.fail(
new CommonError(String.valueOf(groupMsgRecallResult.getErrorCode()), groupMsgRecallResult.getErrorInfo()));
}
}
package io.github.doocs.im.servie;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Maps;
import io.github.doocs.im.ImClient;
import io.github.doocs.im.config.BusinessException;
import io.github.doocs.im.config.CommonError;
import io.github.doocs.im.config.CommonResult;
import io.github.doocs.im.config.ErrorEnum;
import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.core.Message;
import io.github.doocs.im.model.request.SendMsgRequest;
import io.github.doocs.im.model.response.SendMsgResult;
import io.github.doocs.im.util.JsonUtil;
import io.github.doocs.im.util.RandomUtil;
import io.github.doocs.im.vo.SimpleMessageVO;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class MessageService extends GeneraService {
@Autowired
ImClient imClient;
public CommonResult sendMessage(SimpleMessageVO simpleMessageVO) throws JsonProcessingException {
Message message = imClient.getMessage();
// 组装数据
SendMsgRequest sendMsgRequest = new SendMsgRequest();
sendMsgRequest.setFromAccount(simpleMessageVO.getFromAccount());
sendMsgRequest.setToAccount(simpleMessageVO.getToAccount());
sendMsgRequest.setMsgBody(simpleMessageVO.getMsgBody());
sendMsgRequest.setMsgRandom(RandomUtil.getRandomLong());
// 同步到发送方
sendMsgRequest.setSyncOtherMachine(1);
SendMsgResult sendMsgResult;
try {
sendMsgResult = message.sendMsg(sendMsgRequest);
log.info("结果:{}", sendMsgResult.toString());
} catch (Exception e) {
log.error("请求qcloud失败,参数:{}", JsonUtil.obj2Str(sendMsgRequest));
throw new BusinessException(ErrorEnum.REQUEST_ERROR);
}
String actionStatus = sendMsgResult.getActionStatus();
if (ActionStatus.OK.equalsIgnoreCase(actionStatus)) {
HashMap<String, Object> result = Maps.newHashMap();
result.put("msgTime", sendMsgResult.getMsgTime());
result.put("msgKey", sendMsgResult.getMsgKey());
return CommonResult.success(result);
}
return CommonResult
.fail(new CommonError(String.valueOf(sendMsgResult.getErrorCode()), sendMsgResult.getErrorInfo()));
}
}
package io.github.doocs.im.util; package io.github.doocs.im.util;
import io.github.doocs.im.ClientConfiguration; import io.github.doocs.im.ClientConfiguration;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*; import okhttp3.*;
import java.io.IOException; import java.io.IOException;
...@@ -15,6 +16,7 @@ import java.util.concurrent.TimeUnit; ...@@ -15,6 +16,7 @@ import java.util.concurrent.TimeUnit;
* @author bingo * @author bingo
* @since 2021/10/31 15:57 * @since 2021/10/31 15:57
*/ */
@Slf4j
public class HttpUtil { public class HttpUtil {
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
...@@ -66,7 +68,9 @@ public class HttpUtil { ...@@ -66,7 +68,9 @@ public class HttpUtil {
} }
public static <T> T post(String url, Object data, Class<T> cls, ClientConfiguration config) throws IOException { public static <T> T post(String url, Object data, Class<T> cls, ClientConfiguration config) throws IOException {
String result = post(url, JsonUtil.obj2Str(data), config); String param = JsonUtil.obj2Str(data);
log.info("请求参数:{}",param);
String result = post(url, param, config);
return JsonUtil.str2Obj(result, cls); return JsonUtil.str2Obj(result, cls);
} }
......
package io.github.doocs.im.util;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class RandomUtil {
/**
* 生成一个n位的随机数字符串
*
* @param n
* @return
*/
public static String getRandomNum(int length) {
String str = "0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; ++i) {
int number = random.nextInt(9);// [1,9)
sb.append(str.charAt(number + 1));
}
return sb.toString();
}
/**
* 生成一个n位的随机字符串
*
* @param length
* @return
*/
public static String getRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; ++i) {
int number = random.nextInt(36);// [0,36)
sb.append(str.charAt(number));
}
return sb.toString();
}
/**
* 获取当前时间,年月日时
*
* @return
*/
public static String getDate() {
String str = "";
DateFormat df = new SimpleDateFormat("yyyyMMddHH");
Date date = new Date();
str = df.format(date);
return str;
}
/**
* 生成用户id,10位,纯数字
*
* @return
*/
public static String userId() {
String userId = "";
userId = getRandomNum(10);
return userId;
}
/**
* 生成订单号,13位,纯数字
*
* @return
*/
public static String orderId() {
String orderId = "";
String date = getDate();
String rand = getRandomNum(13);
orderId = date + rand;
return orderId;
}
/**
* 生成商品id,10位,纯数字
*
* @return
*/
public static String proId() {
String userId = "";
userId = getRandomNum(10);
return userId;
}
/**
* 随机取list数据
*
* @param list
* @param n
* 取几条
* @return
*/
@SuppressWarnings({"rawtypes", "unused", "unchecked"})
public static List getRandomList(List list, int n) {
Map map = new HashMap();
List listNew = new ArrayList();
if (list.size() <= n) {
return list;
} else {
while (map.size() < n) {
int random = (int)(Math.random() * list.size());
if (!map.containsKey(random)) {
map.put(random, "");
listNew.add(list.get(random));
}
}
return listNew;
}
}
/**
* 获取随机数字
* @return
*/
public static Long getRandomLong() {
return Long.parseLong(getRandomNum((9)));
}
/**
* 取数组随机数
*
* @param arr
* @param n
* @return
*/
@SuppressWarnings({"unused", "unchecked"})
public static Long[] createRandomArray(Long[] arr, int n) {
// TODO Auto-generated method stub
@SuppressWarnings("rawtypes")
Map map = new HashMap();
Long[] arrNew = new Long[n];
if (arr.length <= n) {
return arr;
} else {
int count = 0;// 新数组下标计数
while (map.size() < n) {
int random = (int)(Math.random() * arr.length);
if (!map.containsKey(random)) {
map.put(random, "");
arrNew[count++] = arr[random];
}
}
return arrNew;
}
}
public static void main(String[] args) {
String randomNum = getRandomNum(10);
System.out.println(randomNum);
}
}
package io.github.doocs.im.vo;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
@Data
@ToString
public class AccountVO {
// 来源
@NotBlank(message = "应用名称不可为空!")
private String source;
// 原id
@NotBlank(message = "应用用户id不可为空!")
private String originalId;
// 昵称
private String nick;
// 头像
private String faceUrl;
}
package io.github.doocs.im.vo;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
public class QueryOnlineStatusRequestVO {
private Integer isNeedDetail;
@NotEmpty(message = "im_id不可为空!")
private List<@Valid String> toAccount;
}
\ No newline at end of file
package io.github.doocs.im.vo;
import java.util.List;
import io.github.doocs.im.model.message.TIMMsgElement;
import lombok.Data;
@Data
public class SimpleMessageVO {
// 发送方
private String fromAccount;
// 接收方
private String toAccount;
// 消息
List<TIMMsgElement> msgBody;
}
sdkAppId:
1400599792
key:
cacfa51c0e3789a34b322fd1209f237ba363b8279f3ad483a302804b4e9fcab8
userId:
administrator
mongodb:
address: 10.244.4.39:27017
authenticationDatabase: admin
clientName: ${spring.application.name}
connectionTimeoutMs: 5000
connectionsPerHost: 30
database: im
heartbeatConnectionTimeoutMs: 10000
heartbeatFrequencyMs: 20000
heartbeatReadTimeoutMs: 15000
maxConnectionIdleTimeMs: 60000
maxConnectionLifeTimeMs: 300000
maxWaitTimeMs: 5000
minConnectionsPerHost: 2
minHeartbeatFrequencyMs: 8000
password:
readTimeoutMs: 15000
threadsAllowedToBlockForConnectionMultiplier: 5
username:
spring:
application:
name: im
# yml配置的优先级高于java配置;如果yml配置和java配置同时存在,则yml配置会覆盖java配置
http-client:
pool:
#连接池的最大连接数,0代表不限;如果取0,需要考虑连接泄露导致系统崩溃的后果
maxTotalConnect: 1000
#每个路由的最大连接数,如果只调用一个地址,可以将其设置为最大连接数
maxConnectPerRoute: 200
# 指客户端和服务器建立连接的超时时间,ms , 最大约21秒,因为内部tcp在进行三次握手建立连接时,默认tcp超时时间是20秒
connectTimeout: 3000
# 指客户端从服务器读取数据包的间隔超时时间,不是总读取时间,也就是socket timeout,ms
readTimeout: 5000
# 从连接池获取连接的timeout,不宜过大,ms
connectionRequestTimout: 200
# 重试次数
retryTimes: 3
charset: UTF-8
# 长连接保持时间 单位s,不宜过长
keepAliveTime: 10
# 针对不同的网址,长连接保持的存活时间,单位s,如果是频繁而持续的请求,可以设置小一点,不建议设置过大,避免大量无用连接占用内存资源
keepAliveTargetHost:
www.baidu.com: 5
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
This is the JRebel configuration file. It maps the running application to your IDE workspace, enabling JRebel reloading for this project.
Refer to https://manuals.jrebel.com/jrebel/standalone/config.html for more information.
-->
<application generated-by="intellij" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_3.xsd">
<id>im-server-sdk-java</id>
<classpath>
<dir name="D:/ideaproject/qcloud-im-server-sdk-java/target/classes">
</dir>
</classpath>
</application>
package io.github.doocs.im; package io.github.doocs.im;
import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.constant.IsNeedDetail;
import io.github.doocs.im.model.request.*;
import io.github.doocs.im.model.response.*;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -14,6 +7,23 @@ import java.util.Arrays; ...@@ -14,6 +7,23 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.junit.Assert;
import org.junit.Test;
import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.model.request.AccountCheckItem;
import io.github.doocs.im.model.request.AccountCheckRequest;
import io.github.doocs.im.model.request.AccountDeleteItem;
import io.github.doocs.im.model.request.AccountDeleteRequest;
import io.github.doocs.im.model.request.AccountImportRequest;
import io.github.doocs.im.model.request.KickRequest;
import io.github.doocs.im.model.request.MultiAccountImportRequest;
import io.github.doocs.im.model.response.AccountCheckResult;
import io.github.doocs.im.model.response.AccountDeleteResult;
import io.github.doocs.im.model.response.AccountImportResult;
import io.github.doocs.im.model.response.KickResult;
import io.github.doocs.im.model.response.MultiAccountImportResult;
/** /**
* @author bingo * @author bingo
* @since 2021/7/30 16:17 * @since 2021/7/30 16:17
...@@ -37,7 +47,7 @@ public class AccountTest { ...@@ -37,7 +47,7 @@ public class AccountTest {
@Test @Test
public void testAccountImport() throws IOException { public void testAccountImport() throws Exception {
AccountImportRequest request = AccountImportRequest.builder() AccountImportRequest request = AccountImportRequest.builder()
.identifier("admin") .identifier("admin")
.faceUrl("https://avatars.githubusercontent.com/u/43716716?s=200&v=4") .faceUrl("https://avatars.githubusercontent.com/u/43716716?s=200&v=4")
...@@ -96,14 +106,14 @@ public class AccountTest { ...@@ -96,14 +106,14 @@ public class AccountTest {
@Test @Test
public void testQueryOnlineStatus() throws IOException { public void testQueryOnlineStatus() throws IOException {
List<String> toAccount = Arrays.asList("user1", "user2"); // List<String> toAccount = Arrays.asList("user1", "user2");
QueryOnlineStatusRequest request = QueryOnlineStatusRequest.builder() // QueryOnlineStatusRequest request = QueryOnlineStatusRequest.builder()
.toAccount(toAccount) // .toAccount(toAccount)
.isNeedDetail(IsNeedDetail.YES) // .isNeedDetail(IsNeedDetail.YES)
.build(); // .build();
//
QueryOnlineStatusResult result = client.account.queryOnlineStatus(request); // QueryOnlineStatusResult result = client.account.queryOnlineStatus(request);
System.out.println(result); // System.out.println(result);
Assert.assertEquals(ActionStatus.OK, result.getActionStatus()); // Assert.assertEquals(ActionStatus.OK, result.getActionStatus());
} }
} }
...@@ -49,7 +49,7 @@ public class GroupTest { ...@@ -49,7 +49,7 @@ public class GroupTest {
} }
@Test @Test
public void testCreateGroup() throws IOException { public void testCreateGroup() throws Exception {
CreateGroupRequest request = CreateGroupRequest.builder() CreateGroupRequest request = CreateGroupRequest.builder()
.type(GroupType.PUBLIC) .type(GroupType.PUBLIC)
.name("TestGroup") .name("TestGroup")
......
package io.github.doocs.im; package io.github.doocs.im;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import org.junit.Assert;
import org.junit.Test;
import io.github.doocs.im.constant.ActionStatus; import io.github.doocs.im.constant.ActionStatus;
import io.github.doocs.im.constant.MsgType; import io.github.doocs.im.constant.MsgType;
import io.github.doocs.im.constant.SyncOtherMachine; import io.github.doocs.im.constant.SyncOtherMachine;
import io.github.doocs.im.model.message.TIMCustomMsgElement; import io.github.doocs.im.model.message.TIMCustomMsgElement;
import io.github.doocs.im.model.message.TIMMsgElement; import io.github.doocs.im.model.message.TIMMsgElement;
import io.github.doocs.im.model.message.TIMTextMsgElement; import io.github.doocs.im.model.message.TIMTextMsgElement;
import io.github.doocs.im.model.request.*; import io.github.doocs.im.model.request.AdminGetRoamMsgRequest;
import io.github.doocs.im.model.response.*; import io.github.doocs.im.model.request.AdminMsgWithdrawRequest;
import org.junit.Assert; import io.github.doocs.im.model.request.AdminSetMsgReadRequest;
import org.junit.Test; import io.github.doocs.im.model.request.BatchSendMsgRequest;
import io.github.doocs.im.model.request.GetC2cUnreadMsgRequest;
import java.io.IOException; import io.github.doocs.im.model.request.ImportMsgRequest;
import java.io.InputStream; import io.github.doocs.im.model.request.SendMsgRequest;
import java.util.*; import io.github.doocs.im.model.response.AdminMsgWithdrawResult;
import io.github.doocs.im.model.response.AdminRoamMsgResult;
import io.github.doocs.im.model.response.AdminSetMsgReadResult;
import io.github.doocs.im.model.response.BatchSendMsgResult;
import io.github.doocs.im.model.response.C2cUnreadMsgNumResult;
import io.github.doocs.im.model.response.ImportMsgResult;
import io.github.doocs.im.model.response.MsgListItem;
import io.github.doocs.im.model.response.SendMsgResult;
/** /**
* @author bingo * @author bingo
...@@ -21,23 +38,23 @@ import java.util.*; ...@@ -21,23 +38,23 @@ import java.util.*;
*/ */
public class MessageTest { public class MessageTest {
private static final Properties properties = new Properties(); private static final Properties properties = new Properties();
private static final ImClient client; private static final ImClient client = null;
static { // static {
InputStream resourceAsStream = MessageTest.class.getClassLoader().getResourceAsStream("app.properties"); // InputStream resourceAsStream = MessageTest.class.getClassLoader().getResourceAsStream("app.properties");
try { // try {
properties.load(resourceAsStream); // properties.load(resourceAsStream);
} catch (IOException e) { // } catch (IOException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
String key = properties.getProperty("key"); // String key = properties.getProperty("key");
String userId = properties.getProperty("userId"); // String userId = properties.getProperty("userId");
Long appId = Long.parseLong(properties.getProperty("appId")); // Long appId = Long.parseLong(properties.getProperty("appId"));
client = ImClient.getInstance(appId, userId, key); // client = ImClient.getInstance(appId, userId, key);
} // }
@Test @Test
public void testSendMsg() throws IOException { public void testSendMsg() throws Exception {
TIMTextMsgElement msg = new TIMTextMsgElement("hello world"); TIMTextMsgElement msg = new TIMTextMsgElement("hello world");
List<TIMMsgElement> msgBody = Collections.singletonList(msg); List<TIMMsgElement> msgBody = Collections.singletonList(msg);
SendMsgRequest request = SendMsgRequest.builder() SendMsgRequest request = SendMsgRequest.builder()
......
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