提交 00fdc6ce 作者: zhenjie

用户登录注册相关

上级 d80538b2
# Created by .ignore support plugin (hsz.mobi) # Created by .ignore support plugin (hsz.mobi)
target
*.class
.project
.classpath
.prefs
.settings
.idea
*.iml
*/application.yml
## 新云享飞-用户管理
\ No newline at end of file
...@@ -8,8 +8,39 @@ ...@@ -8,8 +8,39 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<artifactId>cms-common-model</artifactId> <artifactId>cms-common-model</artifactId>
<dependencies>
<!-- apache 提供的一些工具类 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
</dependency>
<dependency>
<groupId>com.mmc.iuav.cms</groupId>
<artifactId>cms-common-util</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project> </project>
\ No newline at end of file
package com.mmc.iuav.user.model.vo; package com.mmc.iuav.user.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 15:17 * @Date: 2023/5/16 15:17
*/ */
public class AppUserSucVO { @Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AppUserSucVO implements Serializable {
private static final long serialVersionUID = 7491711282161485720L;
@ApiModelProperty(value = "用户id")
private Integer userAccountId;
@ApiModelProperty(value = "openId")
private String openId;
@ApiModelProperty(value = "unionId")
private String unionId;
@ApiModelProperty(value = "token")
private String token;
} }
package com.mmc.iuav.user.model.vo; package com.mmc.iuav.user.model.vo;
import com.mmc.iuav.group.Insert;
import com.mmc.iuav.group.Update;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:56 * @Date: 2023/5/16 13:56
*/ */
public class WxLoginVO { @Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "com.mmc.iuav.user.model.vo.WxLoginVO", description = "登录参数")
public class WxLoginVO implements Serializable {
private static final long serialVersionUID = 2500957724470423989L;
@ApiModelProperty(value = "请求code")
@NotNull(message = "code不能为空", groups = {Insert.class})
private String code;
@ApiModelProperty(value = "登录来源, 0小程序登录, 1pc登录", example = "0", allowableValues = "0,1")
@NotNull(message = "登录来源不能为空", groups = {Insert.class})
private Integer fromPort;
@ApiModelProperty(value = "用户来源:0自然流,1海报,2抖音,3公众号,4社群,5招投标,默认0", example = "0", required = true)
private Integer source;
} }
...@@ -8,8 +8,53 @@ ...@@ -8,8 +8,53 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<artifactId>cms-common-util</artifactId> <artifactId>cms-common-util</artifactId>
<dependencies>
<!-- apache 提供的一些工具类 -->
<!-- <dependency>-->
<!-- <groupId>commons-codec</groupId>-->
<!-- <artifactId>commons-codec</artifactId>-->
<!-- <version>1.15</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>commons-lang</groupId>-->
<!-- <artifactId>commons-lang</artifactId>-->
<!-- <version>2.6</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<target>1.8</target>
<source>1.8</source>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
...@@ -5,4 +5,13 @@ package com.mmc.iuav.auth; ...@@ -5,4 +5,13 @@ package com.mmc.iuav.auth;
* @Date: 2023/5/16 20:18 * @Date: 2023/5/16 20:18
*/ */
public interface JwtConstant { public interface JwtConstant {
public final static String BASE64KEY = "IUAV&&iuavhhh@20230516888888";
public final static String SUBJECT = "mmc_iuav888";
public final static String ISSUER = "mmc_uav";
public final static long EXPIRATION = 1 * 24 * 60 * 60 * 1000L;
public final static String TOKEN_TYPE = "TOKEN_TYPE";
public final static String M_TOKEN = "M_TOKEN"; //后台管理用户token
public final static String IUAV_TOKEN = "IUAV_TOKEN"; //小程序token
public final static String USER_ACCOUNT_ID = "USER_ACCOUNT_ID";
public final static String ROLE_ID = "ROLE_ID";
} }
package com.mmc.iuav.auth; package com.mmc.iuav.auth;
import com.mmc.iuav.general.CodeUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.Map;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 20:14 * @Date: 2023/5/16 20:14
*/ */
public class JwtUtil { public class JwtUtil {
/**
* 根据map中的信息生成token, tokenId为随机生成码,有效时间为24h
*
* @param claims 封装到token中的map
* @return
*/
public static String createJwt(Map<String, Object> claims) {
return createJwt(claims, JwtConstant.EXPIRATION);
}
public static String createJwt(Map<String, Object> claims, long expiration) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(JwtConstant.BASE64KEY);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
long nowMillis = System.currentTimeMillis();
long expMillis = nowMillis + expiration;
Date now = new Date(nowMillis);
Date exp = new Date(expMillis);
JwtBuilder builder = Jwts.builder().setClaims(claims).setId(CodeUtil.randomCode(6)).setIssuedAt(now)
.setSubject(JwtConstant.SUBJECT).setIssuer(JwtConstant.ISSUER).signWith(signatureAlgorithm, signingKey)
.setExpiration(exp);
return builder.compact();
}
/**
* 解析前端传来的token,解析成功则返回Claims,解析失败返回null;解析成功后可通过claims获取信息
*
* @param jwt
* @return
*/
public static Claims parseJwt(String jwt) {
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(JwtConstant.BASE64KEY))
.parseClaimsJws(jwt).getBody();
return claims;
}
} }
package com.mmc.iuav.general; package com.mmc.iuav.general;
import java.util.Random;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 20:01 * @Date: 2023/5/16 20:01
*/ */
public class CodeUtil { public class CodeUtil {
private static Random random = new Random();
public static String getRandomNum(int length) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = 0; i < length; i++) {
sb.append(String.valueOf(random.nextInt(10)));
}
return sb.toString();
}
public static String generateUserUID() {
return CodeUtil.getRandomNum(9);
}
public static String randomCode(int i) {
return CodeUtil.getRandomNum(i);
}
} }
package com.mmc.iuav.http; package com.mmc.iuav.http;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.springframework.stereotype.Component;
import javax.net.ssl.*;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 15:27 * @Date: 2023/5/16 15:27
*/ */
@Component
public class HttpsRequestUtil { public class HttpsRequestUtil {
public static String httpsRequest(String url, String method, Map<String, String> headerMap, String bodyData)
throws Exception {
HttpsURLConnection conn = null;
OutputStream out = null;
String rsp = null;
byte[] byteArray = bodyData.getBytes("utf-8");
try {
URL uri = new URL(url);
conn = (HttpsURLConnection) uri.openConnection();
// 忽略证书验证--Begin
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
// 忽略证书验证--End
conn.setRequestMethod(method);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Host", uri.getHost());
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
if (headerMap != null) {
Iterator<Map.Entry<String, String>> it = headerMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
out = conn.getOutputStream();
out.write(byteArray);
out.close();
if (conn.getResponseCode() == 200) {
rsp = getStreamAsString(conn.getInputStream(), "utf-8");
} else {
rsp = getStreamAsString(conn.getErrorStream(), "utf-8");
}
} catch (Exception e) {
if (null != out) {
out.close();
}
e.printStackTrace();
}
return rsp;
}
/**
* 获取小程序二维码
*
* @param url
* @param method
* @param headerMap
* @param bodyData
* @return
* @throws Exception
*/
public static String getACodeBase64(String url, String method, Map<String, String> headerMap, String bodyData)
throws Exception {
HttpsURLConnection conn = null;
OutputStream out = null;
String rsp = null;
byte[] byteArray = bodyData.getBytes("utf-8");
try {
URL uri = new URL(url);
conn = (HttpsURLConnection) uri.openConnection();
// 忽略证书验证--Begin
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
// 忽略证书验证--End
conn.setRequestMethod(method);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Host", uri.getHost());
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
if (headerMap != null) {
Iterator<Map.Entry<String, String>> it = headerMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
out = conn.getOutputStream();
out.write(byteArray);
out.close();
if (conn.getResponseCode() == 200) {
byte[] bytes = InputStreamToByte(conn.getInputStream());
//rsp = Base64.encodeBase64String(bytes);
rsp = Base64.encode(bytes);
} else {
rsp = getStreamAsString(conn.getErrorStream(), "utf-8");
}
} catch (Exception e) {
if (null != out) {
out.close();
}
e.printStackTrace();
}
return rsp;
}
/**
* 输入流转字节流
*/
private static byte[] InputStreamToByte(InputStream in) throws IOException {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int ch;
while ((ch = in.read(buffer)) != -1) {
bytestream.write(buffer, 0, ch);
}
byte data[] = bytestream.toByteArray();
bytestream.close();
return data;
}
private static String getStreamAsString(InputStream stream, String charset) throws IOException {
try {
Reader reader = new InputStreamReader(stream, charset);
StringBuilder response = new StringBuilder();
final char[] buff = new char[1024];
int read = 0;
while ((read = reader.read(buff)) > 0) {
response.append(buff, 0, read);
}
return response.toString();
} finally {
if (stream != null) {
stream.close();
}
}
}
/**
* HTTPS GET请求
*
* @param url
* @param headerMap
* @return
*/
public static String httpsGet(String url, Map<String, String> headerMap) {
String str_return = "";
HttpsURLConnection conn = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
URL console = new URL(url);
conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
if (headerMap != null) {
Iterator<Map.Entry<String, String>> it = headerMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is, ("ISO-8859-1")));
String ret = "";
while (ret != null) {
ret = br.readLine();
if (ret != null && !ret.trim().equals("")) {
str_return = str_return + new String(ret.getBytes("ISO-8859-1"), "utf-8");
}
}
} catch (ConnectException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return str_return;
}
}
// 定制Verifier
class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
class TrustAnyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
} }
...@@ -5,4 +5,17 @@ package com.mmc.iuav.response; ...@@ -5,4 +5,17 @@ package com.mmc.iuav.response;
* @Date:2023/5/16 10:42 * @Date:2023/5/16 10:42
*/ */
public interface BaseErrorInfoInterface { public interface BaseErrorInfoInterface {
/**
* 错误码
*
* @return
*/
String getResultCode();
/**
* 错误描述
*
* @return
*/
String getResultMsg();
} }
package com.mmc.iuav.response; package com.mmc.iuav.response;
import com.alibaba.fastjson2.JSONObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 10:51 * @Date: 2023/5/16 10:51
*/ */
public class ResultBody { @Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "com.mmc.iuav.response.ResultBody", description = "请求响应体")
public class ResultBody<T> implements Serializable {
private static final long serialVersionUID = -6913505187877217885L;
/**
* 响应代码
*/
@ApiModelProperty(value = "响应代码")
private String code;
/**
* 响应消息
*/
@ApiModelProperty(value = "响应消息")
private String message;
/**
* 响应结果
*/
@ApiModelProperty(value = "响应结果")
private T result;
public ResultBody(BaseErrorInfoInterface errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
/**
* 成功
*
* @return
*/
public static ResultBody success() {
return success(null);
}
/**
* 成功
*
* @param data
* @return
*/
public static <T> ResultBody success(T data) {
ResultBody rb = new ResultBody();
rb.setCode(ResultEnum.SUCCESS.getResultCode());
rb.setMessage(ResultEnum.SUCCESS.getResultMsg());
rb.setResult(data);
return rb;
}
/**
* 成功
*
* **/
public static ResultBody success1(ResultEnum enums){
ResultBody rb = new ResultBody();
rb.setCode("200");
rb.setMessage(enums.getResultMsg());
rb.setResult(null);
return rb;
}
public void buildSuccess() {
this.setCode(ResultEnum.SUCCESS.getResultCode());
this.setMessage(ResultEnum.SUCCESS.getResultMsg());
}
/**
* 失败
*/
public static ResultBody error(BaseErrorInfoInterface errorInfo) {
ResultBody rb = new ResultBody();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static ResultBody error(String code, String message) {
ResultBody rb = new ResultBody();
rb.setCode(code);
rb.setMessage(message);
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static ResultBody error(ResultEnum enums) {
ResultBody rb = new ResultBody();
rb.setCode(enums.getResultCode());
rb.setMessage(enums.getResultMsg());
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static ResultBody error(String message) {
ResultBody rb = new ResultBody();
rb.setCode("-1");
rb.setMessage(message);
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static ResultBody error(ResultEnum enums, Object data) {
ResultBody rb = new ResultBody();
rb.setCode(enums.getResultCode());
rb.setMessage(enums.getResultMsg());
rb.setResult(data);
return rb;
}
public static boolean isSuccess(ResultBody res) {
return res.getCode().equals(ResultEnum.SUCCESS.getResultCode());
}
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
} }
package com.mmc.iuav.response; package com.mmc.iuav.response;
/** /**
* @author:zhenjie * @author: zj
* @Date:2023/5/16 10:41 * @Date: 2023/5/16 10:41
*/ */
public enum ResultEnum { public enum ResultEnum implements BaseErrorInfoInterface{
SUCCESS("200", "success"),
FAIL("500", "fail"),
PARAM_ERROR("400", "参数错误"),
APPLET_PORT_TYPE_ERROR("7001", "小程序端口类型错误"),
APPLET_LOGIN_ERROR("7002", "获取小程序登录失败");
/**
* 错误码
*
* @return
*/
String resultCode;
/**
* 错误描述
*
* @return
*/
String resultMsg;
ResultEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return null;
}
@Override
public String getResultMsg() {
return null;
}
} }
...@@ -10,6 +10,11 @@ ...@@ -10,6 +10,11 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>cms-common</artifactId> <artifactId>cms-common</artifactId>
<packaging>pom</packaging>
<modules>
<module>cms-common-model</module>
<module>cms-common-util</module>
</modules>
</project> </project>
\ No newline at end of file
...@@ -11,5 +11,89 @@ ...@@ -11,5 +11,89 @@
<artifactId>cms-service-user</artifactId> <artifactId>cms-service-user</artifactId>
<dependencies>
<dependency>
<groupId>com.mmc.iuav.cms</groupId>
<artifactId>cms-common-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.mmc.iuav.cms</groupId>
<artifactId>cms-common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入 Web 功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 健康监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 引入 Feign, 可以以声明的方式调用微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 使用okhttp-feign-连接池技术 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- mybatis驱动&Druid数据源-start -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis驱动&Druid数据源-end -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<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>-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> </project>
\ No newline at end of file
package com.mmc.iuav.user; package com.mmc.iuav.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/** /**
* @author:zhenjie * @author:zhenjie
* @Date:2023/5/15 15:35 * @Date:2023/5/15 15:35
*/ */
@SpringBootApplication
public class UserApplication { public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
} }
package com.mmc.iuav.user.config; package com.mmc.iuav.user.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/** /**
* @author:zhenjie * @author:zhenjie
* @Date:2023/5/16 10:07 * @Date:2023/5/16 10:07
*/ */
@Configuration
@EnableSwagger2
@EnableKnife4j
public class Knife4jConfiguration { public class Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//分组名称
.groupName("用户服务")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.mmc.iuav.user.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("iuav用户相关")
.description("swagger-bootstrap-ui-demo RESTful APIs")
.termsOfServiceUrl("https://www.iuav.com/")
.contact("group@qq.com")
.version("1.0")
.build();
}
} }
package com.mmc.iuav.user.constant; package com.mmc.iuav.user.constant;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:34 * @Date: 2023/5/16 13:34
*/ */
@Data
@Component
public class UserSystemConstant { public class UserSystemConstant {
@Value("${wx.app.id}")
private String wxAppId;
@Value("${wx.app.secret}")
private String wxAppSecret;
@Value("${wx.app.miniprogram-state}")
private String miniProgramState;
@Value("${wx.app.env-version}")
private String envVersion;
@Value("${wx.sub.appid}")
private String wxSubAppId;
@Value("${wx.sub.secret}")
private String wxSubSecret;
} }
package com.mmc.iuav.user.constant; package com.mmc.iuav.user.constant;
import org.springframework.stereotype.Component;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 16:02 * @Date: 2023/5/16 16:02
*/ */
public interface WxConstant { public class WxConstant {
public static final Integer APP = 0;
public static final Integer WEB = 1;
public static final String CODE2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
public static final String GRANT_TYPE = "authorization_code";
public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
public static final String OPEN_ID = "openid";
public static final String UNION_ID = "unionid";
public static final String SESSION_KEY = "session_key";
} }
package com.mmc.iuav.user.controller; package com.mmc.iuav.user.controller;
import com.mmc.iuav.group.Insert;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.user.model.vo.AppUserSucVO;
import com.mmc.iuav.user.model.vo.WxLoginVO;
import com.mmc.iuav.user.service.AuthService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/** /**
* @author:zhenjie * @author: zj
* @Date:2023/5/15 15:50 * @Date: 2023/5/15 15:50
*/ */
@Api(tags = "登录")
@RequestMapping("/auth/")
@RestController
public class AuthController { public class AuthController {
@Autowired
private AuthService authService;
@ApiOperation(value = "小程序登录/注册")
@ApiResponses({ @ApiResponse(code = 200, message = "OK", response = AppUserSucVO.class) })
@PostMapping("appletLogin")
public ResultBody appletLogin(@Validated(value = {Insert.class})@RequestBody WxLoginVO wxLoginVO){
return authService.appletLogin(wxLoginVO);
}
} }
package com.mmc.iuav.user.controller; package com.mmc.iuav.user.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* @author:zhenjie * @author:zhenjie
* @Date:2023/5/15 15:32 * @Date:2023/5/15 15:32
*/ */
@Api(tags = "账号相关接口")
@RequestMapping("/user-account/")
@RestController
public class UserAccountController { public class UserAccountController {
@ApiOperation(value = "获取用户信息")
@GetMapping("info")
public String info(){
return "account";
}
} }
package com.mmc.iuav.user.dao; package com.mmc.iuav.user.dao;
import com.mmc.iuav.user.entity.UserAccountDO;
import org.apache.ibatis.annotations.Mapper;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 19:26 * @Date: 2023/5/16 19:26
*/ */
@Mapper
public interface UserServiceDao { public interface UserServiceDao {
/**
* 根据用户unionId查询用户信息
* @param unionId
* @return
*/
UserAccountDO getUserAccountInfoByUnionId(String unionId);
/**
* 插入用户信息
* @param userAccountDO
*/
void insertUserAccount(UserAccountDO userAccountDO);
} }
package com.mmc.iuav.user.entity; package com.mmc.iuav.user.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 17:00 * @Date: 2023/5/16 17:00
*/ */
public class UserAccountDO { @Data
@NoArgsConstructor
@AllArgsConstructor
public class UserAccountDO implements Serializable {
private static final long serialVersionUID = 5007589179946146721L;
private Integer id;
private Integer accountType;
private String uid;
private String phoneNum;
private String userName;
private String nickName;
private String userImg;
private String openId;
private String unionId;
private Integer userSex;
private String email;
private Integer source;
private Integer accountStatus;
private String remark;
private Integer portType;
private Integer deleted;
private Date createTime;
private Date updateTime;
} }
package com.mmc.iuav.user.service; package com.mmc.iuav.user.service;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.user.model.vo.WxLoginVO;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:50 * @Date: 2023/5/16 13:50
*/ */
public interface AuthService { public interface AuthService {
/**
* 小程序用户登录接口
* @param wxLoginVO
* @return
*/
ResultBody appletLogin(WxLoginVO wxLoginVO);
} }
package com.mmc.iuav.user.service; package com.mmc.iuav.user.service;
import com.mmc.iuav.user.entity.UserAccountDO;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:48 * @Date: 2023/5/16 13:48
*/ */
public interface UserAccountService { public interface UserAccountService {
/**
* Get the user account
* @param unionId
* @return
*/
UserAccountDO getUserAccountInfoByUnionId(String unionId);
/**
* Insert the user account
* @param userAccountDO
*/
void insertUserAccount(UserAccountDO userAccountDO);
} }
package com.mmc.iuav.user.service; package com.mmc.iuav.user.service;
import com.mmc.iuav.user.model.vo.WxLoginVO;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:43 * @Date: 2023/5/16 13:43
*/ */
public interface WxService { public interface WxService {
/**
* 小程序登录调用接口
* @param wxLoginVO
* @return
*/
String appLogin(WxLoginVO wxLoginVO);
/**
* pc扫码登录
* @param wxLoginVO
* @return
*/
String pcLogin(WxLoginVO wxLoginVO);
} }
package com.mmc.iuav.user.service.impl; package com.mmc.iuav.user.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mmc.iuav.auth.JwtConstant;
import com.mmc.iuav.auth.JwtUtil;
import com.mmc.iuav.general.CodeUtil;
import com.mmc.iuav.response.ResultBody;
import com.mmc.iuav.response.ResultEnum;
import com.mmc.iuav.user.constant.UserSystemConstant;
import com.mmc.iuav.user.constant.WxConstant;
import com.mmc.iuav.user.entity.UserAccountDO;
import com.mmc.iuav.user.model.vo.AppUserSucVO;
import com.mmc.iuav.user.model.vo.WxLoginVO;
import com.mmc.iuav.user.service.AuthService;
import com.mmc.iuav.user.service.UserAccountService;
import com.mmc.iuav.user.service.WxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:51 * @Date: 2023/5/16 13:51
*/ */
public class AuthServiceImpl { @Slf4j
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private WxService wxService;
@Autowired
private UserAccountService userAccountService;
@Override
public ResultBody appletLogin(WxLoginVO wxLoginVO) {
String unionId;
String openId;
if (wxLoginVO.getFromPort().toString().equals(WxConstant.APP.toString())) {
//调用小程序登录接口,里面包含unionId
String appWxJson = wxService.appLogin(wxLoginVO);
if (appWxJson == null) {
return ResultBody.error(ResultEnum.APPLET_PORT_TYPE_ERROR);
}
JSONObject json = JSON.parseObject(appWxJson);
if (!json.containsKey(WxConstant.OPEN_ID) || !json.containsKey(WxConstant.SESSION_KEY)) {
log.error("wx appLogin error==>" + json);
return ResultBody.error(ResultEnum.APPLET_LOGIN_ERROR, json);
}
unionId = json.getString(WxConstant.UNION_ID);
openId = json.getString(WxConstant.OPEN_ID);
}else if (wxLoginVO.getFromPort().equals(WxConstant.WEB)){
//获取access_token接口,里面包含unionId
String pcWxJson = wxService.pcLogin(wxLoginVO);
if (pcWxJson == null) {
return ResultBody.error(ResultEnum.APPLET_PORT_TYPE_ERROR);
}
JSONObject json = JSON.parseObject(pcWxJson);
if (!json.containsKey(WxConstant.OPEN_ID) ||!json.containsKey(WxConstant.SESSION_KEY)) {
log.error("wx pcLogin error==>" + json);
return ResultBody.error(ResultEnum.APPLET_LOGIN_ERROR, json);
}
unionId = json.getString(WxConstant.UNION_ID);
openId = json.getString(WxConstant.OPEN_ID);
}else {
return ResultBody.error(ResultEnum.PARAM_ERROR);
}
//数据库查询用户信息
UserAccountDO userAccountDO = userAccountService.getUserAccountInfoByUnionId(unionId);
if (userAccountDO == null) {
userAccountDO = new UserAccountDO();
userAccountDO.setUnionId(unionId);
userAccountDO.setOpenId(openId);
userAccountDO.setUid(CodeUtil.generateUserUID());
userAccountDO.setAccountType(0);
userAccountDO.setPortType(100);
userAccountService.insertUserAccount(userAccountDO);
}
Map<String, Object> map = new HashMap<String, Object>();
map.put(JwtConstant.USER_ACCOUNT_ID, userAccountDO.getId());
map.put(JwtConstant.ROLE_ID, 0);
map.put(JwtConstant.TOKEN_TYPE, JwtConstant.IUAV_TOKEN);
String token = JwtUtil.createJwt(map);
return ResultBody.success(AppUserSucVO.builder().openId(userAccountDO.getOpenId()).unionId(userAccountDO.getUnionId()).token(token).userAccountId(userAccountDO.getId()).build());
}
} }
package com.mmc.iuav.user.service.impl; package com.mmc.iuav.user.service.impl;
import com.mmc.iuav.user.dao.UserServiceDao;
import com.mmc.iuav.user.entity.UserAccountDO;
import com.mmc.iuav.user.service.UserAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:48 * @Date: 2023/5/16 13:48
*/ */
public class UserAccountServiceImpl { @Service
public class UserAccountServiceImpl implements UserAccountService {
@Autowired
private UserServiceDao userServiceDao;
@Override
public UserAccountDO getUserAccountInfoByUnionId(String unionId) {
UserAccountDO userAccountDO = userServiceDao.getUserAccountInfoByUnionId(unionId);
return userAccountDO;
}
@Override
public void insertUserAccount(UserAccountDO userAccountDO) {
userServiceDao.insertUserAccount(userAccountDO);
}
} }
package com.mmc.iuav.user.service.impl; package com.mmc.iuav.user.service.impl;
import com.mmc.iuav.http.HttpsRequestUtil;
import com.mmc.iuav.user.constant.UserSystemConstant;
import com.mmc.iuav.user.constant.WxConstant;
import com.mmc.iuav.user.model.vo.WxLoginVO;
import com.mmc.iuav.user.service.WxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/** /**
* @author: zj * @author: zj
* @Date: 2023/5/16 13:44 * @Date: 2023/5/16 13:44
*/ */
public class WxServiceImpl { @Service
public class WxServiceImpl implements WxService {
@Autowired
private UserSystemConstant userSystemConstant;
@Override
public String appLogin(WxLoginVO wxLoginVO) {
String url = WxConstant.CODE2_SESSION_URL + "?appid=" + userSystemConstant.getWxAppId() + "&secret=" + userSystemConstant.getWxAppSecret() + "&js_code=" + wxLoginVO.getCode()
+ "&grant_type=" + WxConstant.GRANT_TYPE;
String data = HttpsRequestUtil.httpsGet(url, null);
return data;
}
@Override
public String pcLogin(WxLoginVO wxLoginVO) {
String url = WxConstant.ACCESS_TOKEN_URL + "?appid=" + userSystemConstant.getWxAppId() + "&secret=" + userSystemConstant.getWxAppSecret() + "&code=" + wxLoginVO.getCode()
+ "&grant_type=" + WxConstant.GRANT_TYPE;
String data = HttpsRequestUtil.httpsGet(url, null);
return data;
}
} }
server:
port: 35150
servlet:
context-path: /userapp
#spring
spring:
application:
name: userapp
#Database
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://rm-wz9dd796t4j1giz6t2o.mysql.rds.aliyuncs.com:3306/iuav_cms?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
username: tmj
password: MMC@2022&MYSQL
# Druid数据源配置
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 10 #初始化连接池大小
min-idle: 10 #最小大小
max-active: 50 #最大大小
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #配置一个连接在池中最小生存的时间,单位是毫秒
validation-query: SELECT 1 FROM DUAL #用来检测连接是否有效的sql
test-while-idle: true #申请连接的时候检测,建议配置为true,不影响性能,并且保证安全性
testOnBorrow: false #获取连接时执行检测,建议关闭,影响性能
testOnReturn: false #归还连接时执行检测,建议关闭,影响性能
pool-prepared-statements: false #是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭
filters: stat,wall #配置扩展插件,常用的插件有=>stat:监控统计 log4j:日志 wall:防御sql注入
filter:
wall:
config:
multi-statement-allow: true
db-type: mysql
enabled: true
connection-properties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 #打开慢sql记录和延迟时间
web-stat-filter:
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
enabled: true
stat-view-servlet:
enabled: true
login-username: druid
login-password: druid
#mybatis
mybatis:
executor-type: simple
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.mmc.iuav.user
configuration:
map-underscore-to-camel-case: true
wx:
sub:
appid: wx5c6a105a0ddca4c5
secret: 96c75255dd26f82f8d55e15b59e101c7
app:
id: wx18b7883acd204278
secret: 28afe74ba373830237a8133a7431ee82
miniprogram-state: trial
env-version: trial
token-path: /userservlet/wechat/getAppletUserAccessToken
port: user
\ No newline at end of file
spring:
profiles:
active: dev
---
spring:
profiles: dev
---
spring:
profiles: beta
---
spring:
profiles: product
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mmc.iuav.user.dao.UserServiceDao">
<resultMap id="userAccountResultMap" type="com.mmc.iuav.user.entity.UserAccountDO">
<id property="id" column="id"/>
<result property="accountType" column="account_type"/>
<result property="uid" column="uid"/>
<result property="phoneNum" column="phone_num"/>
<result property="userName" column="user_name"/>
<result property="nickName" column="nick_name"/>
<result property="userImg" column="user_img"/>
<result property="openId" column="open_id"/>
<result property="unionId" column="union_id"/>
<result property="userSex" column="user_sex"/>
<result property="email" column="email"/>
<result property="source" column="source"/>
<result property="accountStatus" column="account_status"/>
<result property="remark" column="remark"/>
<result property="portType" column="port_type"/>
<result property="deleted" column="is_deleted"/>
<result property="createTime" column="createTime"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<insert id="insertUserAccount" parameterType="com.mmc.iuav.user.entity.UserAccountDO"
useGeneratedKeys="true" keyProperty="id">
insert into user_account(account_type, uid, phone_num, user_name, nick_name, user_img, open_id, union_id, user_sex, email, source, remark, port_type, create_time)
values(#{accountType}, #{uid}, #{phoneNum}, #{userName}, #{nickName}, #{userImg}, #{userImg}, #{openId}, #{unionId}, #{userSex}, #{email}, #{source}, #{accountStatus},
#{remark}, #{portType}, NOW())
</insert>
<select id="getUserAccountInfoByUnionId" resultType="com.mmc.iuav.user.entity.UserAccountDO">
select id, account_type, uid, phone_num, user_name, nick_name, user_img, open_id, union_id, user_sex, email, source, account_status, remark,
port_type, is_deleted, create_time, update_time
from user_account
where union_id = #{unionId} and is_deleted = 0
</select>
</mapper>
\ No newline at end of file
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>csm-service</artifactId> <artifactId>csm-service</artifactId>
<packaging>pom</packaging>
<modules>
<module>cms-service-user</module>
</modules>
</project> </project>
\ No newline at end of file
...@@ -4,9 +4,202 @@ ...@@ -4,9 +4,202 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 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> <modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId> <groupId>com.mmc.iuav.cms</groupId>
<artifactId>iuav-cms</artifactId> <artifactId>iuav-cms</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<modules>
<module>cms-common</module>
<module>csm-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath />
</parent>
<properties>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
<springfox.version>2.9.2</springfox.version>
<spring-cloud-alibaba-seata.version>2.2.1.RELEASE</spring-cloud-alibaba-seata.version>
<seata.version>1.1.0</seata.version>
</properties>
<dependencies>
<!-- lombok 工具通过在代码编译时期动态的将注解替换为具体的代码, IDEA 需要添加 lombok 插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.29</version>
</dependency>
<!-- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<!-- 引入swagger-bootstrap-ui包 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${springfox.version}</version>
</dependency>
<!--logback 日志 -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.3</version>
</dependency>
</dependencies>
<!-- 标识 SpringCloud 的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>${spring-cloud-alibaba-seata.version}</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>${seata.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 配置远程仓库 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project> </project>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论