Browse Source

oss上传 & 邀请码注册

master
nili 5 months ago
parent
commit
baf0f492a1
  1. 18
      game-dao/src/main/java/awesome/group/game/dao/bean/MatrixUser.java
  2. 14
      game-dao/src/main/java/awesome/group/game/dao/mapper/MatrixUserMapper.java
  3. 21
      game-service/pom.xml
  4. 115
      game-service/src/main/java/awesome/group/game/service/OSSService.java
  5. 69
      game-service/src/main/java/awesome/group/game/service/RegisterService.java
  6. 108
      game-service/src/main/java/awesome/group/game/service/SmsService.java
  7. 20
      game-service/src/main/java/awesome/group/game/service/bo/MatrixAppBo.java
  8. 8
      game-service/src/main/java/awesome/group/game/service/bo/RegisterBo.java
  9. 26
      game-service/src/main/java/awesome/group/game/service/bo/STSInfo.java
  10. 18
      game-service/src/main/java/awesome/group/game/service/cache/CacheKey.java
  11. 166
      game-service/src/main/java/awesome/group/game/service/cache/JedisManager.java
  12. 42
      game-web/src/main/java/awesome/group/game/web/rest/citrus/RegisterController.java
  13. 1
      game-web/src/main/java/awesome/group/game/web/rest/citrus/readme
  14. 15
      game-web/src/main/java/awesome/group/game/web/rest/matrix/AdminController.java
  15. 8
      game-web/src/main/resources/application-default.yml
  16. 7
      game-web/src/main/resources/application-test.yml
  17. 29
      pom.xml

18
game-dao/src/main/java/awesome/group/game/dao/bean/MatrixUser.java

@ -0,0 +1,18 @@
package awesome.group.game.dao.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
@Data
public class MatrixUser {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String mobile;
private Integer appId;
private String name;
private String aliPayAccount;
private String pwd;
private String inviteCode;
private Integer upUid;
}

14
game-dao/src/main/java/awesome/group/game/dao/mapper/MatrixUserMapper.java

@ -0,0 +1,14 @@
package awesome.group.game.dao.mapper;
import awesome.group.game.dao.bean.MatrixUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
public interface MatrixUserMapper extends BaseMapper<MatrixUser> {
@Select("select * from matrix_user where invite_code = #{inviteCode}")
MatrixUser selectByInviteCode(String inviteCode);
@Select("select * from matrix_user where app_id = #{appId} and mobile = #{mobile}")
MatrixUser selectByAppIdAndMobile(int appId, String mobile);
}

21
game-service/pom.xml

@ -74,6 +74,27 @@
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-sts -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>

115
game-service/src/main/java/awesome/group/game/service/OSSService.java

@ -0,0 +1,115 @@
package awesome.group.game.service;
import awesome.group.game.service.bo.STSInfo;
import awesome.group.game.service.cache.CacheKey;
import awesome.group.game.service.cache.JedisManager;
import awesome.group.game.service.common.exception.PaganiException;
import awesome.group.game.service.common.exception.PaganiExceptionCode;
import awesome.group.game.service.common.log.L;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* @author nidaren
*/
@Service
public class OSSService {
private static final String accessKeyId = "LTAI5tHker5udo3UNAjxjykg";
private static final String accessKeySecret = "WT7BLX9w1muzYYmI0ZdMsyI15Iq7v5";
private static final String roleArn = "acs:ram::1464656672772974:role/oss-upload";
private static final String endpoint = "oss-cn-beijing.aliyuncs.com";
private static final String bucket = "bzgames";
public static final String resourcePrefix = "https://bzgames.oss-cn-beijing.aliyuncs.com";
private IAcsClient client = null;
@Resource
private JedisManager jedisManager;
public synchronized IAcsClient getOrCreatClient() {
if (client != null) {
return client;
}
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
client = new DefaultAcsClient(profile);
return this.client;
}
public STSInfo getSTS(Integer uid) {
String key = CacheKey.stsKey(uid);
String res = jedisManager.get(key);
Gson gson = new Gson();
if (StringUtils.isNotBlank(res)) {
return gson.fromJson(res, STSInfo.class);
}
String roleSessionName = "uid_" + uid;
AssumeRoleRequest request = new AssumeRoleRequest();
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setDurationSeconds(900L);
try {
AssumeRoleResponse response = getOrCreatClient().getAcsResponse(request);
STSInfo info = new STSInfo(response.getCredentials());
info.stsRole = roleArn;
info.bucket = bucket;
info.endpoint = endpoint;
jedisManager.set(key, gson.toJson(info), 900);
return info;
} catch (ClientException e) {
L.trace("aliyun_sts_fail", "", e);
}
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "请稍后再试");
}
public static String getFullResourceUrl(String path) {
if (path.startsWith("http")) {
return path;
}
if (path.startsWith("/")) {
return resourcePrefix + path;
}
return resourcePrefix + "/" + path;
}
public String simpleUpload(String url, Integer uid) {
STSInfo info = getSTS(uid);
OSS ossClient = new OSSClientBuilder().build("https://oss-cn-hangzhou.aliyuncs.com", info.accessKeyId, info.accessKeySecret, info.securityToken);
try {
URLConnection connection = new URL(url).openConnection();
String mimeType = connection.getContentType();
InputStream inputStream = connection.getInputStream();
String fileType = mimeType.split("/")[1];
String fileName = "mario/" + System.currentTimeMillis() + "." + fileType;
String msg = String.format("url:%s, uid: %s, fileName: %s", url, uid, fileName);
ossClient.putObject(bucket, fileName, inputStream);
L.trace("upload_success", msg);
return String.format("https://%s.%s/%s", bucket, endpoint, fileName);
} catch (OSSException e) {
L.trace("upload_success", "url:" + url + ",uid:" + uid);
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "上传失败");
} catch (IOException e) {
L.trace("download_fail", "url:" + url + ",uid:" + uid);
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "非法url");
}
}
}

69
game-service/src/main/java/awesome/group/game/service/RegisterService.java

@ -0,0 +1,69 @@
package awesome.group.game.service;
import awesome.group.game.dao.bean.MatrixApp;
import awesome.group.game.dao.bean.MatrixUser;
import awesome.group.game.dao.mapper.MatrixAppMapper;
import awesome.group.game.dao.mapper.MatrixUserMapper;
import awesome.group.game.service.bo.MatrixAppBo;
import awesome.group.game.service.bo.RegisterBo;
import awesome.group.game.service.common.exception.PaganiException;
import awesome.group.game.service.common.exception.PaganiExceptionCode;
import awesome.group.game.service.util.EncryptUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.concurrent.ThreadLocalRandom;
@Service
public class RegisterService {
@Autowired
private MatrixAppMapper appMapper;
@Autowired
private MatrixUserMapper userMapper;
@Autowired
private SmsService smsService;
public MatrixAppBo getApp(String inviteCode) {
MatrixUser user = userMapper.selectByInviteCode(inviteCode);
if (user == null) {
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "邀请码非法");
}
int appId = user.getAppId();
MatrixApp app = appMapper.selectById(appId);
return new MatrixAppBo(app);
}
public void register(RegisterBo bo) {
Assert.isTrue(StringUtils.hasText(bo.mobile), "手机号不能为空");
Assert.isTrue(StringUtils.hasText(bo.inviteCode), "邀请码不能为空");
Assert.isTrue(StringUtils.hasText(bo.code), "验证码不能为空");
Assert.isTrue(StringUtils.hasText(bo.pwd), "密码不能为空");
if (smsService.verifyAndUseCaptcha(bo.mobile, "register", bo.code)) {
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "验证码错误");
}
MatrixUser prev = userMapper.selectByInviteCode(bo.inviteCode);
if (prev == null) {
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "邀请码非法");
}
int appId = prev.getAppId();
MatrixUser u = userMapper.selectByAppIdAndMobile(appId, bo.mobile);
if (u != null) {
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "手机号已注册");
}
u = new MatrixUser();
u.setMobile(bo.mobile);
u.setAppId(appId);
u.setPwd(EncryptUtil.sha1(bo.pwd));
u.setInviteCode(RandomStringUtils.randomAlphabetic(12));
u.setUpUid(prev.getId());
userMapper.insert(u);
}
}

108
game-service/src/main/java/awesome/group/game/service/SmsService.java

@ -0,0 +1,108 @@
package awesome.group.game.service;
import awesome.group.game.service.cache.CacheKey;
import awesome.group.game.service.cache.JedisManager;
import awesome.group.game.service.common.exception.PaganiException;
import awesome.group.game.service.common.exception.PaganiExceptionCode;
import awesome.group.game.service.common.log.L;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* @author nidaren
*/
@Service
public class SmsService {
public static final String accessKeyId = "LTAI5tD27oA2VTasbZcjCQN7";
public static final String accessSecret = "1kGGBrLy4yIjAEUXCGKaOHTfjJegK8";
public static final String signName = "瑞双科技";
public static final String templateCode = "SMS_217850700";
public static final int expireTime = 1800;
private static Client client;
@Resource
private JedisManager jedisManager;
public SmsService() {
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(accessKeyId)
// 您的AccessKey Secret
.setAccessKeySecret(accessSecret);
config.endpoint = "dysmsapi.aliyuncs.com";
try {
client = new Client(config);
} catch (Exception e) {
L.trace("init_sms_client_error", "", e);
}
}
public void sendCaptcha(String phone, String scene) {
List<String> sceneList = Arrays.asList("register");
if (!sceneList.contains(scene)) {
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "非法scene");
}
String key = CacheKey.captchaKey(scene, phone);
if (!StringUtils.isEmpty(jedisManager.get(key))) {
return;//验证码有效期内只发一次
}
SendSmsRequest request = new SendSmsRequest();
request.phoneNumbers = phone;
request.signName = signName;
request.templateCode = templateCode;
String code = getRandom();
request.templateParam = String.format("{\"code\": \"%s\"}", code);
Gson gson = new Gson();
try {
SendSmsResponse response = client.sendSms(request);
String msg = String.format("request: %s, response: %s", gson.toJson(request), gson.toJson(response.body));
if (response.body.code.equals("OK")) {
L.trace("send_sms_success", msg);
} else {
L.trace("send_sms_fail", msg);
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "短信发送失败");
}
jedisManager.set(key, code, expireTime);
} catch (Exception e) {
L.trace("send_sms_fail", gson.toJson(request), e);
throw new PaganiException(PaganiExceptionCode.GENERAL_ERROR, "短信发送失败");
}
}
public boolean verifyAndUseCaptcha(String phone, String scene, String code) {
String key = CacheKey.captchaKey(scene, phone);
String redisCode = jedisManager.get(key);
if (StringUtils.isEmpty(redisCode)) {
return false;
}
if (!redisCode.equals(code)) {
return false;
}
jedisManager.del(key);
return true;
}
public static String getRandom() {
StringBuilder builder = new StringBuilder();
Random ran = new Random();
for (int i = 0; i < 6; i++) {
builder.append(ran.nextInt(10));
}
return builder.toString();
}
}

20
game-service/src/main/java/awesome/group/game/service/bo/MatrixAppBo.java

@ -0,0 +1,20 @@
package awesome.group.game.service.bo;
import awesome.group.game.dao.bean.MatrixApp;
public class MatrixAppBo {
public String name;
public String code;
public String img;
public String url;
public MatrixAppBo() {
}
public MatrixAppBo(MatrixApp app) {
this.name = app.getName();
this.code = app.getCode();
this.img = app.getImg();
this.url = app.getUrl();
}
}

8
game-service/src/main/java/awesome/group/game/service/bo/RegisterBo.java

@ -0,0 +1,8 @@
package awesome.group.game.service.bo;
public class RegisterBo {
public String mobile;
public String code;//验证码
public String pwd;
public String inviteCode;
}

26
game-service/src/main/java/awesome/group/game/service/bo/STSInfo.java

@ -0,0 +1,26 @@
package awesome.group.game.service.bo;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
/**
* @author nidaren
*/
public class STSInfo {
public String securityToken;
public String expiration;
public String accessKeySecret;
public String accessKeyId;
public String stsRole;
public String bucket;
public String endpoint;
public STSInfo() {
}
public STSInfo(AssumeRoleResponse.Credentials credentials) {
this.securityToken = credentials.getSecurityToken();
this.accessKeyId = credentials.getAccessKeyId();
this.accessKeySecret = credentials.getAccessKeySecret();
this.expiration = credentials.getExpiration();
}
}

18
game-service/src/main/java/awesome/group/game/service/cache/CacheKey.java

@ -0,0 +1,18 @@
package awesome.group.game.service.cache;
/**
* @author nidaren
*/
public class CacheKey {
public static final String captchaKey(String scene, String phone) {
return String.format("captcha_%s_%s", scene, phone);
}
public static final String stsKey(Integer uid) {
return String.format("aliyun_sts_%s", uid);
}
public static final String activateTryTimes(Integer uid) {
return String.format("vip_activate_times_%s", uid);
}
}

166
game-service/src/main/java/awesome/group/game/service/cache/JedisManager.java

@ -0,0 +1,166 @@
package awesome.group.game.service.cache;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Component
public class JedisManager {
@Value("${spring.redis.maxTotal}")
private int maxTotal;
@Value("${spring.redis.poolMaxWaitMs}")
private int poolMaxWaitMs;
@Value("${spring.redis.timeOutMs}")
private int timeOutMs;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
private JedisPool jedisPool = null;
@PostConstruct
public void init() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxWaitMillis(poolMaxWaitMs);
config.setMaxIdle(maxTotal);
config.setMinIdle(4);
config.setBlockWhenExhausted(true);
config.setTestWhileIdle(true);
if (StringUtils.isEmpty(password)) {
password = null;
}
jedisPool = new JedisPool(config, host, port, timeOutMs, password);
}
@PreDestroy
public void destroy() {
jedisPool.close();
}
public Jedis getJedis() {
return jedisPool.getResource();
}
public void batchWriteCache(ArrayList<String> keys, ArrayList<String> values, int expire) {
Assert.notEmpty(keys, "keys is empty");
Assert.notEmpty(values, "values is empty");
Assert.isTrue(expire > 0, "expire is required");
Assert.isTrue(keys.size() == values.size(), "key size not eq values size");
List<String> kvs = new ArrayList<>(keys.size() * 2);
for (int i = 0; i < keys.size(); i++) {
kvs.add(keys.get(i));
kvs.add(values.get(i));
}
try (Jedis jedis = getJedis()) {
Pipeline pipeline = jedis.pipelined();
pipeline.mset(kvs.toArray(new String[kvs.size()]));
keys.forEach(k -> pipeline.expire(k, expire));
pipeline.sync();
} catch (Exception e) {
throw e;
}
}
/**
* 不存在的key,数组中对应位置值为null
*
* @param keys
* @return
*/
public List<String> batchGet(List<String> keys) {
Assert.notEmpty(keys, "keys is empty");
try (Jedis jedis = getJedis()) {
return jedis.mget(keys.toArray(new String[keys.size()]));
} catch (Exception e) {
throw e;
}
}
public String get(String key) {
Assert.notNull(key, "key is null");
try (Jedis jedis = getJedis()) {
return jedis.get(key);
} catch (Exception e) {
throw e;
}
}
public void set(String key, String value, int expireSeconds) {
Assert.notNull(key, "key is null");
Assert.notNull(value, "value is null");
try (Jedis jedis = getJedis()) {
jedis.setex(key, expireSeconds, value);
} catch (Exception e) {
throw e;
}
}
public void del(String key) {
try (Jedis jedis = getJedis()) {
jedis.del(key);
} catch (Exception e) {
throw e;
}
}
public long setnx(String key, String v) {
try (Jedis jedis = getJedis()) {
return jedis.setnx(key, v);
} catch (Exception e) {
throw e;
}
}
public Set<String> sMember(String key) {
Assert.notNull(key, "key is null");
try (Jedis jedis = getJedis()) {
return jedis.smembers(key);
} catch (Exception e) {
throw e;
}
}
public long incr(String key) {
Assert.notNull(key, "key is null");
try (Jedis jedis = getJedis()) {
return jedis.incr(key);
} catch (Exception e) {
throw e;
}
}
public void setExpire(String key, Integer seconds) {
Assert.notNull(key, "key is null");
try (Jedis jedis = getJedis()) {
jedis.expire(key, seconds);
} catch (Exception e) {
throw e;
}
}
}

42
game-web/src/main/java/awesome/group/game/web/rest/citrus/RegisterController.java

@ -0,0 +1,42 @@
package awesome.group.game.web.rest.citrus;
import awesome.group.game.service.RegisterService;
import awesome.group.game.service.SmsService;
import awesome.group.game.service.bo.MatrixAppBo;
import awesome.group.game.service.bo.RegisterBo;
import awesome.group.game.service.common.response.R;
import awesome.group.game.web.aop.RestApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/citrus/register")
public class RegisterController {
@Autowired
private RegisterService registerService;
@Autowired
private SmsService smsService;
@PostMapping("/sendCode")
@RestApi
public R<Void> sendCode(@RequestParam String mobile) {
smsService.sendCaptcha(mobile, "register");
return new R<>(null);
}
@GetMapping("/getApp")
@RestApi
public R<MatrixAppBo> getApp(@RequestParam String inviteCode) {
return new R<>(registerService.getApp(inviteCode));
}
@PostMapping("/submitRegister")
@RestApi
public R<Void> submitRegister(@RequestBody RegisterBo bo) {
registerService.register(bo);
return new R<>(null);
}
}

1
game-web/src/main/java/awesome/group/game/web/rest/citrus/readme

@ -0,0 +1 @@
citrus名字是乱起的,对应的前端项目是pomelo,这个名字是我随便起的,因为我喜欢吃柑橘和柚子,所以就叫citrus和pomelo了,没有任何含义,只是为了区分不同的项目而已。

15
game-web/src/main/java/awesome/group/game/web/rest/matrix/AdminController.java

@ -6,6 +6,7 @@ import awesome.group.game.dao.bean.MatrixMockSchedule;
import awesome.group.game.dao.bean.MatrixWhiteDevice;
import awesome.group.game.service.AdminService;
import awesome.group.game.service.MatrixService;
import awesome.group.game.service.OSSService;
import awesome.group.game.service.bo.*;
import awesome.group.game.service.common.response.R;
import awesome.group.game.service.util.JwtUtils;
@ -29,6 +30,9 @@ public class AdminController {
@Resource
private MatrixService matrixService;
@Resource
private OSSService ossService;
@PostMapping("/login")
@RestApi
public R<Void> adminLogin(@RequestParam String name, @RequestParam String pwd) {
@ -131,4 +135,15 @@ public class AdminController {
adminService.addMockSchedule(bo);
return new R<>(R.CODE_SUCCESS, "ok", null);
}
/**
* OSS上传token
* 上传文件的路径必须是/mario/xxxxx即oss上mario文件夹下
*/
@GetMapping("/getSTS")
@RestApi
public R<STSInfo> getSTS() {
return new R<>(ossService.getSTS(RequestContext.getAdminID()));
}
}

8
game-web/src/main/resources/application-default.yml

@ -9,6 +9,14 @@ spring:
proxy-target-class: true
pid:
file: pid #pid文件名
redis:
host: 127.0.0.1
port: 6379
password:
maxTotal: 128
poolMaxWaitMs: 50
timeOutMs: 100
datasource:
game:
type: com.zaxxer.hikari.HikariDataSource

7
game-web/src/main/resources/application-test.yml

@ -9,6 +9,13 @@ spring:
proxy-target-class: true
pid:
file: pid #pid文件名
redis:
host: 127.0.0.1
port: 6379
password:
maxTotal: 128
poolMaxWaitMs: 50
timeOutMs: 100
datasource:
game:

29
pom.xml

@ -61,14 +61,41 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-sts -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>

Loading…
Cancel
Save