mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
5.0
This commit is contained in:
55
pom.xml
55
pom.xml
@@ -20,7 +20,7 @@
|
|||||||
<!-- <module>sop-common</module>-->
|
<!-- <module>sop-common</module>-->
|
||||||
<!-- <module>sop-auth</module>-->
|
<!-- <module>sop-auth</module>-->
|
||||||
<module>sop-example</module>
|
<module>sop-example</module>
|
||||||
<module>sop-admin</module>
|
<!-- <module>sop-admin</module>-->
|
||||||
<!-- <module>sop-gateway</module>-->
|
<!-- <module>sop-gateway</module>-->
|
||||||
<module>sop-test</module>
|
<module>sop-test</module>
|
||||||
<module>sop-sdk</module>
|
<module>sop-sdk</module>
|
||||||
@@ -47,8 +47,6 @@
|
|||||||
<!-- dubbo版本 -->
|
<!-- dubbo版本 -->
|
||||||
<dubbo.version>3.2.10</dubbo.version>
|
<dubbo.version>3.2.10</dubbo.version>
|
||||||
|
|
||||||
|
|
||||||
<logback.version>1.2.3</logback.version>
|
|
||||||
<junit.version>4.11</junit.version>
|
<junit.version>4.11</junit.version>
|
||||||
<fastjson.version>1.2.83</fastjson.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
<commons-io.version>2.5</commons-io.version>
|
<commons-io.version>2.5</commons-io.version>
|
||||||
@@ -60,11 +58,7 @@
|
|||||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||||
<hibernate-validator.version>6.0.13.Final</hibernate-validator.version>
|
<hibernate-validator.version>6.0.13.Final</hibernate-validator.version>
|
||||||
<fastmybatis.version>3.0.10</fastmybatis.version>
|
<fastmybatis.version>3.0.10</fastmybatis.version>
|
||||||
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
|
|
||||||
<guava.version>29.0-jre</guava.version>
|
<guava.version>29.0-jre</guava.version>
|
||||||
<knife4j.version>3.0.2</knife4j.version>
|
|
||||||
<swagger.version>1.5.21</swagger.version>
|
|
||||||
<springfox.version>3.0.0</springfox.version>
|
|
||||||
<easyopen.version>1.16.9</easyopen.version>
|
<easyopen.version>1.16.9</easyopen.version>
|
||||||
<asm.version>6.2</asm.version>
|
<asm.version>6.2</asm.version>
|
||||||
<pagehelper.version>5.2.0</pagehelper.version>
|
<pagehelper.version>5.2.0</pagehelper.version>
|
||||||
@@ -125,51 +119,12 @@
|
|||||||
<version>${fastmybatis.version}</version>
|
<version>${fastmybatis.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
|
||||||
<version>${springfox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-spring-web</artifactId>
|
|
||||||
<version>${springfox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-swagger-ui</artifactId>
|
|
||||||
<version>${springfox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-boot-starter</artifactId>
|
|
||||||
<version>${springfox.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
|
||||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
|
||||||
<version>${knife4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.oschina.durcframework</groupId>
|
|
||||||
<artifactId>easyopen</artifactId>
|
|
||||||
<version>${easyopen.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>3.14.7</version>
|
<version>3.14.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.oschina.durcframework</groupId>
|
|
||||||
<artifactId>easyopen-spring-boot-starter</artifactId>
|
|
||||||
<version>${easyopen.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
<artifactId>validation-api</artifactId>
|
<artifactId>validation-api</artifactId>
|
||||||
@@ -181,12 +136,6 @@
|
|||||||
<version>${hibernate-validator.version}</version>
|
<version>${hibernate-validator.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-classic</artifactId>
|
|
||||||
<version>${logback.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- commons -->
|
<!-- commons -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
@@ -234,7 +183,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.4</version>
|
<version>1.18.30</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
|
@@ -15,4 +15,12 @@ public interface StoryService {
|
|||||||
@Open("story.get")
|
@Open("story.get")
|
||||||
StoryResponse getById(Integer id);
|
StoryResponse getById(Integer id);
|
||||||
|
|
||||||
|
@Open("story.find")
|
||||||
|
default StoryResponse getById(Integer id, String name) {
|
||||||
|
StoryResponse storyResponse = new StoryResponse();
|
||||||
|
storyResponse.setId(id);
|
||||||
|
storyResponse.setName(name);
|
||||||
|
return storyResponse;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -21,9 +21,12 @@ public class RegisterDTO implements Serializable {
|
|||||||
|
|
||||||
private String methodName;
|
private String methodName;
|
||||||
|
|
||||||
private String paramName;
|
/**
|
||||||
|
* 字段信息
|
||||||
private String paramTypeName;
|
*
|
||||||
|
* [{"name":"id": "type":"java.lang.Integer"}]
|
||||||
|
*/
|
||||||
|
private String paramInfo;
|
||||||
|
|
||||||
private Integer isPermission;
|
private Integer isPermission;
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
<groupId>io.gitee.durcframework</groupId>
|
<groupId>io.gitee.durcframework</groupId>
|
||||||
<artifactId>fastmybatis-spring-boot-starter</artifactId>
|
<artifactId>fastmybatis-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
@@ -80,13 +81,6 @@
|
|||||||
|
|
||||||
<!-- provided -->
|
<!-- provided -->
|
||||||
|
|
||||||
<!-- 仅在开发中使用 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 仅在开发中使用 -->
|
<!-- 仅在开发中使用 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
@@ -21,11 +21,7 @@ public class ApiInfoDTO implements Serializable {
|
|||||||
|
|
||||||
private String methodName;
|
private String methodName;
|
||||||
|
|
||||||
private String paramName;
|
private String paramInfo;
|
||||||
|
|
||||||
private String paramTypeName;
|
|
||||||
|
|
||||||
private Integer isIgnoreValidate;
|
|
||||||
|
|
||||||
private Integer isPermission;
|
private Integer isPermission;
|
||||||
|
|
||||||
|
@@ -67,17 +67,17 @@ public class ApiResponse {
|
|||||||
/**
|
/**
|
||||||
* 网关异常信息
|
* 网关异常信息
|
||||||
*/
|
*/
|
||||||
private String msg;
|
private String msg = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务异常码
|
* 业务异常码
|
||||||
*/
|
*/
|
||||||
private String sub_code;
|
private String sub_code = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务异常信息
|
* 业务异常信息
|
||||||
*/
|
*/
|
||||||
private String sub_msg;
|
private String sub_msg = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回对象
|
* 返回对象
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
package com.gitee.sop.index.common;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ParamInfoDTO {
|
||||||
|
private String name;
|
||||||
|
private String type;
|
||||||
|
}
|
@@ -10,7 +10,7 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum StatusEnum {
|
public enum StatusEnum {
|
||||||
ENABLE(1),
|
ENABLE(1),
|
||||||
DISABLE(0);
|
DISABLE(2);
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
|
@@ -3,8 +3,10 @@ package com.gitee.sop.index.config;
|
|||||||
import com.gitee.sop.index.message.ErrorFactory;
|
import com.gitee.sop.index.message.ErrorFactory;
|
||||||
import com.gitee.sop.index.service.manager.impl.LocalApiCacheManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.LocalApiCacheManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.LocalIsvManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.LocalIsvManagerImpl;
|
||||||
|
import com.gitee.sop.index.service.manager.impl.LocalSecretManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.RedisApiCacheManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.RedisApiCacheManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.RedisIsvManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.RedisIsvManagerImpl;
|
||||||
|
import com.gitee.sop.index.service.manager.impl.RedisSecretManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -43,6 +45,18 @@ public class IndexConfig {
|
|||||||
return new RedisIsvManagerImpl();
|
return new RedisIsvManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(value = "manager.secret", havingValue = "local", matchIfMissing = true)
|
||||||
|
public LocalSecretManagerImpl localSecretManager() {
|
||||||
|
return new LocalSecretManagerImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(value = "manager.secret", havingValue = "redis")
|
||||||
|
public RedisSecretManager redisSecretManager() {
|
||||||
|
return new RedisSecretManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
|
@@ -5,13 +5,12 @@ import com.gitee.sop.index.common.ApiRequestContext;
|
|||||||
import com.gitee.sop.index.common.ApiResponse;
|
import com.gitee.sop.index.common.ApiResponse;
|
||||||
import com.gitee.sop.index.service.RouteService;
|
import com.gitee.sop.index.service.RouteService;
|
||||||
import com.gitee.sop.index.util.RequestUtil;
|
import com.gitee.sop.index.util.RequestUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +21,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
@RestController
|
@RestController
|
||||||
public class IndexController {
|
public class IndexController {
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private RouteService routeService;
|
private RouteService routeService;
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
|
@@ -48,14 +48,9 @@ public class ApiInfo {
|
|||||||
private String methodName;
|
private String methodName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数名称
|
* 参数信息
|
||||||
*/
|
*/
|
||||||
private String paramName;
|
private String paramInfo;
|
||||||
|
|
||||||
/**
|
|
||||||
* 参数类型名称
|
|
||||||
*/
|
|
||||||
private String paramTypeName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接口是否需要授权访问
|
* 接口是否需要授权访问
|
||||||
@@ -70,7 +65,7 @@ public class ApiInfo {
|
|||||||
/**
|
/**
|
||||||
* 状态,1-启用,0-禁用
|
* 状态,1-启用,0-禁用
|
||||||
*/
|
*/
|
||||||
private Integer apiStatus;
|
private Integer status;
|
||||||
|
|
||||||
private LocalDateTime addTime;
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
@@ -0,0 +1,45 @@
|
|||||||
|
package com.gitee.sop.index.dao.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.annotation.Pk;
|
||||||
|
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||||
|
import com.gitee.fastmybatis.annotation.Table;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表名:isv_info
|
||||||
|
* 备注:isv信息表
|
||||||
|
*
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Table(name = "isv_info", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
|
||||||
|
@Data
|
||||||
|
public class IsvInfo {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* appKey
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1启用,2禁用
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
package com.gitee.sop.index.dao.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.annotation.Pk;
|
||||||
|
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||||
|
import com.gitee.fastmybatis.annotation.Table;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表名:isv_keys
|
||||||
|
* 备注:ISV秘钥管理
|
||||||
|
*
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Table(name = "isv_keys", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT))
|
||||||
|
@Data
|
||||||
|
public class IsvKeys {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)
|
||||||
|
*/
|
||||||
|
private Integer keyFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开发者生成的公钥
|
||||||
|
*/
|
||||||
|
private String publicKeyIsv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开发者生成的私钥(交给开发者)
|
||||||
|
*/
|
||||||
|
private String privateKeyIsv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台生成的公钥(交给开发者)
|
||||||
|
*/
|
||||||
|
private String publicKeyPlatform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台生成的私钥
|
||||||
|
*/
|
||||||
|
private String privateKeyPlatform;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
package com.gitee.sop.index.dao.mapper;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.mapper.BaseMapper;
|
||||||
|
import com.gitee.sop.index.dao.entity.IsvInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public interface IsvInfoMapper extends BaseMapper<IsvInfo> {
|
||||||
|
|
||||||
|
default IsvInfo getByAppId(String appId) {
|
||||||
|
return this.get(IsvInfo::getAppId, appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
package com.gitee.sop.index.dao.mapper;
|
||||||
|
|
||||||
|
import com.gitee.fastmybatis.core.mapper.BaseMapper;
|
||||||
|
import com.gitee.sop.index.dao.entity.IsvKeys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public interface IsvKeysMapper extends BaseMapper<IsvKeys> {
|
||||||
|
|
||||||
|
}
|
@@ -4,7 +4,7 @@ import com.gitee.sop.index.common.ApiInfoDTO;
|
|||||||
import com.gitee.sop.index.dao.entity.ApiInfo;
|
import com.gitee.sop.index.dao.entity.ApiInfo;
|
||||||
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
||||||
import org.springframework.beans.BeanUtils;
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -13,7 +13,7 @@ import javax.annotation.Resource;
|
|||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class ApiService {
|
public class ApiInfoService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiCacheManager apiCacheManager;
|
private ApiCacheManager apiCacheManager;
|
||||||
@@ -23,12 +23,8 @@ public class ApiService {
|
|||||||
|
|
||||||
public ApiInfoDTO getApi(String apiName, String apiVersion) {
|
public ApiInfoDTO getApi(String apiName, String apiVersion) {
|
||||||
return apiCacheManager.getOrElse(apiName, apiVersion, () -> {
|
return apiCacheManager.getOrElse(apiName, apiVersion, () -> {
|
||||||
ApiInfoDTO record = new ApiInfoDTO();
|
|
||||||
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiName, apiVersion);
|
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiName, apiVersion);
|
||||||
if (apiInfo != null) {
|
return CopyUtil.copyBean(apiInfo, ApiInfoDTO::new);
|
||||||
BeanUtils.copyProperties(apiInfo, record);
|
|
||||||
}
|
|
||||||
return record;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@@ -1,8 +1,10 @@
|
|||||||
package com.gitee.sop.index.service;
|
package com.gitee.sop.index.service;
|
||||||
|
|
||||||
|
import org.apache.dubbo.common.config.ReferenceCache;
|
||||||
import org.apache.dubbo.config.ApplicationConfig;
|
import org.apache.dubbo.config.ApplicationConfig;
|
||||||
import org.apache.dubbo.config.ReferenceConfig;
|
import org.apache.dubbo.config.ReferenceConfig;
|
||||||
import org.apache.dubbo.config.RegistryConfig;
|
import org.apache.dubbo.config.RegistryConfig;
|
||||||
|
import org.apache.dubbo.config.utils.SimpleReferenceCache;
|
||||||
import org.apache.dubbo.rpc.service.GenericService;
|
import org.apache.dubbo.rpc.service.GenericService;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -16,10 +18,8 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
public class GenericServiceInvoker implements InitializingBean {
|
public class GenericServiceInvoker implements InitializingBean {
|
||||||
private static final String TRUE = "true";
|
private static final String TRUE = "true";
|
||||||
private ApplicationConfig applicationConfig;
|
|
||||||
|
|
||||||
@Value("${nacos.host:localhost:8848}")
|
private ApplicationConfig applicationConfig;
|
||||||
private String nacosHost;
|
|
||||||
|
|
||||||
@Value("${register.address:${register.type}://${register.host}")
|
@Value("${register.address:${register.type}://${register.host}")
|
||||||
private String registerAddress;
|
private String registerAddress;
|
||||||
@@ -32,13 +32,13 @@ public class GenericServiceInvoker implements InitializingBean {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
RegistryConfig registryConfig = buildRegistryConfig(nacosHost);
|
RegistryConfig registryConfig = buildRegistryConfig();
|
||||||
applicationConfig = new ApplicationConfig();
|
applicationConfig = new ApplicationConfig();
|
||||||
applicationConfig.setName(appName + "-generic");
|
applicationConfig.setName(appName + "-generic");
|
||||||
applicationConfig.setRegistry(registryConfig);
|
applicationConfig.setRegistry(registryConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RegistryConfig buildRegistryConfig(String nacosHost) {
|
private RegistryConfig buildRegistryConfig() {
|
||||||
RegistryConfig config = new RegistryConfig();
|
RegistryConfig config = new RegistryConfig();
|
||||||
config.setAddress(registerAddress);
|
config.setAddress(registerAddress);
|
||||||
return config;
|
return config;
|
||||||
@@ -50,25 +50,9 @@ public class GenericServiceInvoker implements InitializingBean {
|
|||||||
reference.setApplication(applicationConfig);
|
reference.setApplication(applicationConfig);
|
||||||
reference.setInterface(interfaceName);
|
reference.setInterface(interfaceName);
|
||||||
reference.setTimeout(timeout);
|
reference.setTimeout(timeout);
|
||||||
try {
|
ReferenceCache referenceCache = SimpleReferenceCache.getCache();
|
||||||
removeGenericSymbol(parameterTypes);
|
GenericService genericService = referenceCache.get(reference);
|
||||||
GenericService genericService = reference.get();
|
return genericService.$invoke(method, parameterTypes, params);
|
||||||
return genericService.$invoke(method, parameterTypes, params);
|
|
||||||
} finally {
|
|
||||||
reference.destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove generic from parameterTypes
|
|
||||||
*/
|
|
||||||
private void removeGenericSymbol(String[] parameterTypes) {
|
|
||||||
for (int i = 0; i < parameterTypes.length; i++) {
|
|
||||||
int index = parameterTypes[i].indexOf('<');
|
|
||||||
if (index > -1) {
|
|
||||||
parameterTypes[i] = parameterTypes[i].substring(0, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,91 +1,21 @@
|
|||||||
package com.gitee.sop.index.service;
|
package com.gitee.sop.index.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
|
||||||
import com.gitee.sop.index.common.ApiRequest;
|
|
||||||
import com.gitee.sop.index.common.ApiRequestContext;
|
import com.gitee.sop.index.common.ApiRequestContext;
|
||||||
import com.gitee.sop.index.common.ApiResponse;
|
import com.gitee.sop.index.common.ApiResponse;
|
||||||
import com.gitee.sop.index.exception.ExceptionExecutor;
|
|
||||||
import com.gitee.sop.index.service.validate.Validator;
|
|
||||||
import com.gitee.sop.index.util.ClassUtil;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.dubbo.common.utils.ClassUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 接口路由
|
* 接口路由
|
||||||
*
|
*
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
@Service
|
public interface RouteService {
|
||||||
@Slf4j
|
|
||||||
public class RouteService {
|
|
||||||
|
|
||||||
@Resource
|
/**
|
||||||
private Validator validator;
|
* 路由
|
||||||
|
*
|
||||||
@Resource
|
* @param apiRequestContext 接口上下文
|
||||||
private GenericServiceInvoker genericServiceInvoker;
|
* @return 返回结果
|
||||||
|
*/
|
||||||
@Resource
|
ApiResponse route(ApiRequestContext apiRequestContext);
|
||||||
private ExceptionExecutor exceptionExecutor;
|
|
||||||
|
|
||||||
public ApiResponse route(ApiRequestContext apiRequestContext) {
|
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
|
||||||
log.info("收到客户端请求, ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest);
|
|
||||||
try {
|
|
||||||
// 接口校验
|
|
||||||
ApiInfoDTO apiInfoDTO = validator.validate(apiRequestContext);
|
|
||||||
return doRoute(apiRequestContext, apiInfoDTO);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("接口请求报错, , ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest, e);
|
|
||||||
return exceptionExecutor.executeException(apiRequestContext, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApiResponse doRoute(ApiRequestContext apiRequestContext, ApiInfoDTO apiInfo) {
|
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
|
||||||
Object result = genericServiceInvoker.invoke(
|
|
||||||
apiInfo.getInterfaceClassName(),
|
|
||||||
apiInfo.getMethodName(),
|
|
||||||
buildParamType(apiInfo),
|
|
||||||
buildInvokeParam(apiRequest, apiInfo)
|
|
||||||
);
|
|
||||||
return ApiResponse.success(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] buildParamType(ApiInfoDTO apiInfo) {
|
|
||||||
String paramTypeName = apiInfo.getParamTypeName();
|
|
||||||
if (StringUtils.hasText(paramTypeName)) {
|
|
||||||
return new String[]{apiInfo.getParamTypeName()};
|
|
||||||
} else {
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object[] buildInvokeParam(ApiRequest apiRequest, ApiInfoDTO apiInfo) {
|
|
||||||
if (ObjectUtils.isEmpty(apiInfo.getParamTypeName())) {
|
|
||||||
return new Object[0];
|
|
||||||
}
|
|
||||||
String bizContent = apiRequest.getBiz_content();
|
|
||||||
JSONObject jsonObject = JSON.parseObject(bizContent);
|
|
||||||
if (ClassUtil.isPrimitive(apiInfo.getParamTypeName())) {
|
|
||||||
try {
|
|
||||||
Object value = jsonObject.getObject(apiInfo.getParamName(), ClassUtils.forName(apiInfo.getParamTypeName()));
|
|
||||||
return new Object[]{value};
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
log.error("找不到参数class, paramTypeName={}, apiRequest={}, apiInfo={}",
|
|
||||||
apiInfo.getParamTypeName(), apiRequest, apiInfo, e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new Object[]{jsonObject};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,108 @@
|
|||||||
|
package com.gitee.sop.index.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
|
import com.gitee.sop.index.common.ApiRequest;
|
||||||
|
import com.gitee.sop.index.common.ApiRequestContext;
|
||||||
|
import com.gitee.sop.index.common.ApiResponse;
|
||||||
|
import com.gitee.sop.index.common.ParamInfoDTO;
|
||||||
|
import com.gitee.sop.index.exception.ExceptionExecutor;
|
||||||
|
import com.gitee.sop.index.service.validate.Validator;
|
||||||
|
import com.gitee.sop.index.util.ClassUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.common.utils.ClassUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口路由
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class RouteServiceImpl implements RouteService {
|
||||||
|
|
||||||
|
private static final String CLASS = "class";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Validator validator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected GenericServiceInvoker genericServiceInvoker;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected ExceptionExecutor exceptionExecutor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResponse route(ApiRequestContext apiRequestContext) {
|
||||||
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
|
log.info("收到客户端请求, ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest);
|
||||||
|
try {
|
||||||
|
// 接口校验
|
||||||
|
ApiInfoDTO apiInfoDTO = validator.validate(apiRequestContext);
|
||||||
|
// 微服务结果
|
||||||
|
Object result = doRoute(apiRequestContext, apiInfoDTO);
|
||||||
|
return ApiResponse.success(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("接口请求报错, , ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest, e);
|
||||||
|
return exceptionExecutor.executeException(apiRequestContext, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object doRoute(ApiRequestContext apiRequestContext, ApiInfoDTO apiInfo) {
|
||||||
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
|
String paramInfo = apiInfo.getParamInfo();
|
||||||
|
List<ParamInfoDTO> paramInfoList = JSON.parseArray(paramInfo, ParamInfoDTO.class);
|
||||||
|
Object result = genericServiceInvoker.invoke(
|
||||||
|
apiInfo.getInterfaceClassName(),
|
||||||
|
apiInfo.getMethodName(),
|
||||||
|
buildParamType(paramInfoList),
|
||||||
|
buildInvokeParam(apiRequest, paramInfoList)
|
||||||
|
);
|
||||||
|
if (result instanceof Map) {
|
||||||
|
((Map<?, ?>) result).remove(CLASS);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] buildParamType(List<ParamInfoDTO> paramInfoList) {
|
||||||
|
if (ObjectUtils.isEmpty(paramInfoList)) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
return paramInfoList.stream()
|
||||||
|
.map(ParamInfoDTO::getType)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object[] buildInvokeParam(ApiRequest apiRequest, List<ParamInfoDTO> paramInfoList) {
|
||||||
|
if (ObjectUtils.isEmpty(paramInfoList)) {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
String bizContent = apiRequest.getBiz_content();
|
||||||
|
JSONObject jsonObject = JSON.parseObject(bizContent);
|
||||||
|
List<Object> params = new ArrayList<>();
|
||||||
|
for (ParamInfoDTO paramInfoDTO : paramInfoList) {
|
||||||
|
if (ClassUtil.isPrimitive(paramInfoDTO.getType())) {
|
||||||
|
try {
|
||||||
|
Object value = jsonObject.getObject(paramInfoDTO.getName(), ClassUtils.forName(paramInfoDTO.getType()));
|
||||||
|
params.add(value);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
log.error("找不到参数class, paramInfoDTO={}, apiRequest={}", paramInfoDTO, apiRequest, e);
|
||||||
|
throw new RuntimeException("找不到class:" + paramInfoDTO.getType(), e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object value = jsonObject.getObject(paramInfoDTO.getName(), Object.class);
|
||||||
|
params.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params.toArray(new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -7,14 +7,11 @@ import com.gitee.sop.index.common.StatusEnum;
|
|||||||
import com.gitee.sop.index.dao.entity.ApiInfo;
|
import com.gitee.sop.index.dao.entity.ApiInfo;
|
||||||
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
||||||
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.dubbo.config.annotation.DubboService;
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
@@ -32,18 +29,14 @@ public class ApiRegisterServiceImpl implements ApiRegisterService {
|
|||||||
@Override
|
@Override
|
||||||
public void register(RegisterDTO registerDTO) {
|
public void register(RegisterDTO registerDTO) {
|
||||||
log.info("收到接口注册, registerDTO={}", registerDTO);
|
log.info("收到接口注册, registerDTO={}", registerDTO);
|
||||||
ApiInfoDTO apiInfoDTO = new ApiInfoDTO();
|
ApiInfoDTO apiInfoDTO = CopyUtil.copyBean(registerDTO, ApiInfoDTO::new);
|
||||||
BeanUtils.copyProperties(registerDTO, apiInfoDTO);
|
apiInfoDTO.setStatus(StatusEnum.ENABLE.getValue());
|
||||||
|
|
||||||
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiInfoDTO.getApiName(), apiInfoDTO.getApiVersion());
|
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiInfoDTO.getApiName(), apiInfoDTO.getApiVersion());
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
if (apiInfo == null) {
|
if (apiInfo == null) {
|
||||||
apiInfo = new ApiInfo();
|
apiInfo = new ApiInfo();
|
||||||
apiInfo.setApiStatus(StatusEnum.ENABLE.getValue());
|
|
||||||
apiInfo.setAddTime(now);
|
|
||||||
}
|
}
|
||||||
apiInfo.setUpdateTime(now);
|
CopyUtil.copyPropertiesIgnoreNull(apiInfoDTO, apiInfo);
|
||||||
BeanUtils.copyProperties(apiInfoDTO, apiInfo);
|
|
||||||
// 保存到数据库
|
// 保存到数据库
|
||||||
apiInfoMapper.saveOrUpdate(apiInfo);
|
apiInfoMapper.saveOrUpdate(apiInfo);
|
||||||
// 保存到缓存
|
// 保存到缓存
|
||||||
|
@@ -10,9 +10,6 @@ public class IsvDTO {
|
|||||||
|
|
||||||
private String appId;
|
private String appId;
|
||||||
|
|
||||||
private String publicKey;
|
|
||||||
|
|
||||||
private String privateKeyPlatform;
|
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,31 +1,29 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.dao.entity.IsvInfo;
|
||||||
|
import com.gitee.sop.index.dao.mapper.IsvInfoMapper;
|
||||||
import com.gitee.sop.index.service.manager.IsvManager;
|
import com.gitee.sop.index.service.manager.IsvManager;
|
||||||
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
||||||
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.Resource;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class LocalIsvManagerImpl implements IsvManager {
|
public class LocalIsvManagerImpl implements IsvManager {
|
||||||
|
|
||||||
private static final Map<String, IsvDTO> ISV_MAP = new HashMap<>();
|
@Resource
|
||||||
|
private IsvInfoMapper isvInfoMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IsvDTO getIsv(String appId) {
|
public IsvDTO getIsv(String appId) {
|
||||||
return ISV_MAP.get(appId);
|
IsvInfo isvInfo = isvInfoMapper.getByAppId(appId);
|
||||||
|
return CopyUtil.copyBean(isvInfo, IsvDTO::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(String appId) {
|
public void reload(String appId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,23 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.dao.entity.IsvKeys;
|
||||||
|
import com.gitee.sop.index.dao.mapper.IsvKeysMapper;
|
||||||
import com.gitee.sop.index.service.manager.SecretManager;
|
import com.gitee.sop.index.service.manager.SecretManager;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import javax.annotation.Resource;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class LocalSecretManagerImpl implements SecretManager {
|
public class LocalSecretManagerImpl implements SecretManager {
|
||||||
|
|
||||||
static Map<String, String> PUB_KEY_MGR = new HashMap<>();
|
@Resource
|
||||||
static {
|
private IsvKeysMapper isvKeysMapper;
|
||||||
PUB_KEY_MGR.put("2019032617262200001", "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyb9aUBaljQP/vjmBFe1mF8HsWSvyfC2NTlpT/V9E+sBxTr8TSkbzJCeeeOEm4LCaVXL0Qz63MZoT24v7AIXTuMdj4jyiM/WJ4tjrWAgnmohNOegfntTto16C3l234vXz4ryWZMR/7W+MXy5B92wPGQEJ0LKFwNEoLspDEWZ7RdE53VH7w6y6sIZUfK+YkXWSwehfKPKlx+lDw3zRJ3/yvMF+U+BAdW/MfECe1GuBnCFKnlMRh3UKczWyXWkL6ItOpYHHJi/jx85op5BWDje2pY9QowzfN94+0DB3T7UvZeweu3zlP6diwAJDzLaFQX8ULfWhY+wfKxIRgs9NoiSAQIDAQAB");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIsvPublicKey(String appId) {
|
public String getIsvPublicKey(String appId) {
|
||||||
return PUB_KEY_MGR.get(appId);
|
return isvKeysMapper.query()
|
||||||
|
.eq(IsvKeys::getAppId, appId)
|
||||||
|
.getValue(IsvKeys::getPublicKeyIsv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.service.manager.SecretManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class RedisSecretManager implements SecretManager {
|
||||||
|
@Override
|
||||||
|
public String getIsvPublicKey(String appId) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
@@ -4,25 +4,26 @@ import com.gitee.sop.index.common.ApiInfoDTO;
|
|||||||
import com.gitee.sop.index.common.ApiRequest;
|
import com.gitee.sop.index.common.ApiRequest;
|
||||||
import com.gitee.sop.index.common.ApiRequestContext;
|
import com.gitee.sop.index.common.ApiRequestContext;
|
||||||
import com.gitee.sop.index.common.ParamNames;
|
import com.gitee.sop.index.common.ParamNames;
|
||||||
|
import com.gitee.sop.index.common.StatusEnum;
|
||||||
import com.gitee.sop.index.config.ApiConfig;
|
import com.gitee.sop.index.config.ApiConfig;
|
||||||
import com.gitee.sop.index.exception.ApiException;
|
import com.gitee.sop.index.exception.ApiException;
|
||||||
import com.gitee.sop.index.message.ErrorEnum;
|
import com.gitee.sop.index.message.ErrorEnum;
|
||||||
import com.gitee.sop.index.service.ApiService;
|
import com.gitee.sop.index.service.ApiInfoService;
|
||||||
import com.gitee.sop.index.service.manager.IpBlacklistManager;
|
import com.gitee.sop.index.service.manager.IpBlacklistManager;
|
||||||
import com.gitee.sop.index.service.manager.IsvApiPermissionManager;
|
import com.gitee.sop.index.service.manager.IsvApiPermissionManager;
|
||||||
import com.gitee.sop.index.service.manager.IsvManager;
|
import com.gitee.sop.index.service.manager.IsvManager;
|
||||||
|
import com.gitee.sop.index.service.manager.SecretManager;
|
||||||
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
||||||
import com.gitee.sop.index.service.validate.alipay.AlipaySigner;
|
import com.gitee.sop.index.service.validate.alipay.AlipaySigner;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.unit.DataSize;
|
import org.springframework.util.unit.DataSize;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -36,14 +37,12 @@ import java.util.Locale;
|
|||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Service
|
@Service
|
||||||
public class ApiValidator implements Validator {
|
public class ApiValidator implements Validator {
|
||||||
|
|
||||||
private static final int MILLISECOND_OF_ONE_SECOND = 1000;
|
private static final int MILLISECOND_OF_ONE_SECOND = 1000;
|
||||||
private static final int STATUS_FORBIDDEN = 2;
|
|
||||||
|
|
||||||
private static List<String> FORMAT_LIST = Arrays.asList("json", "xml");
|
private static final List<String> FORMAT_LIST = Arrays.asList("json", "xml");
|
||||||
|
|
||||||
private final Signer signer = new AlipaySigner();
|
private final Signer signer = new AlipaySigner();
|
||||||
|
|
||||||
@@ -53,20 +52,24 @@ public class ApiValidator implements Validator {
|
|||||||
@Value("${upload.max-file-size:${spring.servlet.multipart.max-file-size:10MB}}")
|
@Value("${upload.max-file-size:${spring.servlet.multipart.max-file-size:10MB}}")
|
||||||
private String maxFileSize;
|
private String maxFileSize;
|
||||||
|
|
||||||
private final ApiConfig apiConfig;
|
@Resource
|
||||||
|
private ApiConfig apiConfig;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private ApiService apiService;
|
private ApiInfoService apiInfoService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private IpBlacklistManager ipBlacklistManager;
|
private IpBlacklistManager ipBlacklistManager;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private IsvApiPermissionManager isvApiPermissionManager;
|
private IsvApiPermissionManager isvApiPermissionManager;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private IsvManager isvManager;
|
private IsvManager isvManager;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SecretManager secretManager;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiInfoDTO validate(ApiRequestContext apiRequestContext) {
|
public ApiInfoDTO validate(ApiRequestContext apiRequestContext) {
|
||||||
@@ -84,7 +87,7 @@ public class ApiValidator implements Validator {
|
|||||||
checkIP(apiRequestContext);
|
checkIP(apiRequestContext);
|
||||||
|
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
ApiInfoDTO apiInfo = apiService.getApi(apiRequest.getMethod(), apiRequest.getVersion());
|
ApiInfoDTO apiInfo = apiInfoService.getApi(apiRequest.getMethod(), apiRequest.getVersion());
|
||||||
// 检查接口信息
|
// 检查接口信息
|
||||||
checkApiInfo(apiRequestContext, apiInfo);
|
checkApiInfo(apiRequestContext, apiInfo);
|
||||||
|
|
||||||
@@ -189,7 +192,7 @@ public class ApiValidator implements Validator {
|
|||||||
throw new ApiException(ErrorEnum.ISV_INVALID_APP_ID, apiRequestContext.getLocale());
|
throw new ApiException(ErrorEnum.ISV_INVALID_APP_ID, apiRequestContext.getLocale());
|
||||||
}
|
}
|
||||||
// 禁止访问
|
// 禁止访问
|
||||||
if (isv.getStatus() == null || isv.getStatus() == STATUS_FORBIDDEN) {
|
if (isv.getStatus() == null || isv.getStatus() == StatusEnum.DISABLE.getValue()) {
|
||||||
throw new ApiException(ErrorEnum.ISV_ACCESS_FORBIDDEN, apiRequestContext.getLocale());
|
throw new ApiException(ErrorEnum.ISV_ACCESS_FORBIDDEN, apiRequestContext.getLocale());
|
||||||
}
|
}
|
||||||
return isv;
|
return isv;
|
||||||
@@ -203,7 +206,7 @@ public class ApiValidator implements Validator {
|
|||||||
apiRequest.takeNameVersion(), ParamNames.SIGN_NAME);
|
apiRequest.takeNameVersion(), ParamNames.SIGN_NAME);
|
||||||
}
|
}
|
||||||
// ISV上传的公钥
|
// ISV上传的公钥
|
||||||
String publicKey = isv.getPublicKey();
|
String publicKey = secretManager.getIsvPublicKey(isv.getAppId());
|
||||||
if (ObjectUtils.isEmpty(publicKey)) {
|
if (ObjectUtils.isEmpty(publicKey)) {
|
||||||
throw new ApiException(ErrorEnum.ISV_MISSING_SIGNATURE_CONFIG, apiRequestContext.getLocale(),
|
throw new ApiException(ErrorEnum.ISV_MISSING_SIGNATURE_CONFIG, apiRequestContext.getLocale(),
|
||||||
apiRequest.takeNameVersion());
|
apiRequest.takeNameVersion());
|
||||||
|
@@ -0,0 +1,344 @@
|
|||||||
|
package com.gitee.sop.index.util;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.FatalBeanException;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性拷贝工具类
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class CopyUtil extends BeanUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
|
||||||
|
* 注意:当第一个参数中的属性有null值时,不会拷贝进去
|
||||||
|
*
|
||||||
|
* @param from 源对象
|
||||||
|
* @param to 目标对象
|
||||||
|
* @param ignoreProperties 忽略的字段
|
||||||
|
* @throws BeansException
|
||||||
|
*/
|
||||||
|
public static void copyPropertiesIgnoreNull(Object from, Object to, String... ignoreProperties)
|
||||||
|
throws BeansException {
|
||||||
|
Assert.notNull(from, "Source must not be null");
|
||||||
|
Assert.notNull(to, "Target must not be null");
|
||||||
|
|
||||||
|
Class<?> actualEditable = to.getClass();
|
||||||
|
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
|
||||||
|
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : Collections.emptyList());
|
||||||
|
|
||||||
|
for (PropertyDescriptor targetPd : targetPds) {
|
||||||
|
if (ignoreList.contains(targetPd.getName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Method writeMethod = targetPd.getWriteMethod();
|
||||||
|
if (writeMethod != null) {
|
||||||
|
PropertyDescriptor sourcePd = getPropertyDescriptor(from.getClass(), targetPd.getName());
|
||||||
|
if (sourcePd != null) {
|
||||||
|
Method readMethod = sourcePd.getReadMethod();
|
||||||
|
if (readMethod != null &&
|
||||||
|
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
|
||||||
|
try {
|
||||||
|
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||||
|
readMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
Object value = readMethod.invoke(from);
|
||||||
|
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
||||||
|
writeMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
// 这里判断value是否为空 当然这里也能进行一些特殊要求的处理
|
||||||
|
// 例如绑定时格式转换等等
|
||||||
|
if (value != null) {
|
||||||
|
writeMethod.invoke(to, value);
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new FatalBeanException(
|
||||||
|
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝指定的字段
|
||||||
|
*
|
||||||
|
* @param from 源对象
|
||||||
|
* @param to 目标对象
|
||||||
|
* @param includeFields 指定字段
|
||||||
|
*/
|
||||||
|
public static void copyPropertiesInclude(Object from, Object to, Set<String> includeFields) {
|
||||||
|
Objects.requireNonNull(includeFields, "includeFields can not null");
|
||||||
|
Assert.notNull(from, "Source must not be null");
|
||||||
|
Assert.notNull(to, "Target must not be null");
|
||||||
|
if (includeFields.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Class<?> actualEditable = to.getClass();
|
||||||
|
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
|
||||||
|
|
||||||
|
for (PropertyDescriptor targetPd : targetPds) {
|
||||||
|
if (!includeFields.contains(targetPd.getName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Method writeMethod = targetPd.getWriteMethod();
|
||||||
|
if (writeMethod != null) {
|
||||||
|
PropertyDescriptor sourcePd = getPropertyDescriptor(from.getClass(), targetPd.getName());
|
||||||
|
if (sourcePd != null) {
|
||||||
|
Method readMethod = sourcePd.getReadMethod();
|
||||||
|
if (readMethod != null &&
|
||||||
|
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
|
||||||
|
try {
|
||||||
|
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||||
|
readMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
Object value = readMethod.invoke(from);
|
||||||
|
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
||||||
|
writeMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
writeMethod.invoke(to, value);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
throw new FatalBeanException(
|
||||||
|
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝属性
|
||||||
|
*
|
||||||
|
* @param from 被拷贝类
|
||||||
|
* @param to 目标类
|
||||||
|
*/
|
||||||
|
public static void copyProperties(Object from, Object to) {
|
||||||
|
BeanUtils.copyProperties(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝bean成为一个新类
|
||||||
|
*
|
||||||
|
* @param from 被拷贝类
|
||||||
|
* @param supplier 新的类获取回调
|
||||||
|
* @param <T> 新的类
|
||||||
|
* @return 返回新的类实例,from为null时,返回null
|
||||||
|
*/
|
||||||
|
public static <T> T copyBean(Object from, Supplier<T> supplier) {
|
||||||
|
if (from == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
T to = supplier.get();
|
||||||
|
BeanUtils.copyProperties(from, to);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝实例
|
||||||
|
*
|
||||||
|
* @param from 被拷贝类
|
||||||
|
* @param supplier 新的类获取回调
|
||||||
|
* @param after 对新的类最后续处理回调
|
||||||
|
* @param <T> 新的类
|
||||||
|
* @return 返回新的类
|
||||||
|
*/
|
||||||
|
public static <T> T copyBean(Object from, Supplier<T> supplier, Consumer<T> after) {
|
||||||
|
if (from == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
T to = supplier.get();
|
||||||
|
BeanUtils.copyProperties(from, to);
|
||||||
|
after.accept(to);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝List,将list中的类转换成新的对象
|
||||||
|
*
|
||||||
|
* @param collection 被拷贝的集合
|
||||||
|
* @param toElement List新元素
|
||||||
|
* @param <T> 新元素类型
|
||||||
|
* @return 返回新的List
|
||||||
|
*/
|
||||||
|
public static <T> List<T> copyList(Collection<?> collection, Supplier<T> toElement) {
|
||||||
|
if (collection == null || collection.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return collection.stream()
|
||||||
|
.map(source -> {
|
||||||
|
T target = toElement.get();
|
||||||
|
BeanUtils.copyProperties(source, target);
|
||||||
|
return target;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E, R> List<R> copyList(Collection<E> fromList, Function<E, R> function) {
|
||||||
|
if (fromList == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return fromList.stream()
|
||||||
|
.map(source -> {
|
||||||
|
R target = function.apply(source);
|
||||||
|
BeanUtils.copyProperties(source, target);
|
||||||
|
return target;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝List,并做后续处理
|
||||||
|
*
|
||||||
|
* @param fromList 被拷贝的list
|
||||||
|
* @param toElement 新元素
|
||||||
|
* @param after 对新元素做后续处理
|
||||||
|
* @param <T> 新类型
|
||||||
|
* @return 返回新的List
|
||||||
|
*/
|
||||||
|
public static <T> List<T> copyList(Collection<?> fromList, Supplier<T> toElement, Consumer<T> after) {
|
||||||
|
if (fromList == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return fromList.stream()
|
||||||
|
.map(source -> {
|
||||||
|
T target = toElement.get();
|
||||||
|
BeanUtils.copyProperties(source, target);
|
||||||
|
after.accept(target);
|
||||||
|
return target;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝List,并做后续处理
|
||||||
|
*
|
||||||
|
* @param fromList 被拷贝的list
|
||||||
|
* @param toElement 新元素
|
||||||
|
* @param after 对新元素做后续处理
|
||||||
|
* @param <T> 新类型
|
||||||
|
* @return 返回新的List
|
||||||
|
*/
|
||||||
|
public static <T, F> List<T> copyList(Collection<F> fromList, Supplier<T> toElement, CopyConsumer<F, T> after) {
|
||||||
|
if (fromList == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return fromList.stream()
|
||||||
|
.map(source -> {
|
||||||
|
T target = toElement.get();
|
||||||
|
BeanUtils.copyProperties(source, target);
|
||||||
|
after.apply(source, target);
|
||||||
|
return target;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 深层次拷贝,通过json转换的方式实现
|
||||||
|
*
|
||||||
|
* @param from 待转换的类
|
||||||
|
* @param toClass 目标类class
|
||||||
|
* @param <T> 目标类
|
||||||
|
* @return 返回目标类
|
||||||
|
*/
|
||||||
|
public static <T> T deepCopy(Object from, Class<T> toClass) {
|
||||||
|
String json = JSON.toJSONString(from);
|
||||||
|
return JSON.parseObject(json, toClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 深层次拷贝,通过json转换的方式实现
|
||||||
|
*
|
||||||
|
* @param from 待转换的类
|
||||||
|
* @param toClass 目标类class
|
||||||
|
* @param <T> 目标类
|
||||||
|
* @return 返回目标类
|
||||||
|
*/
|
||||||
|
public static <T> List<T> deepCopyList(Object from, Class<T> toClass) {
|
||||||
|
String json = JSON.toJSONString(from);
|
||||||
|
return JSON.parseArray(json, toClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝map
|
||||||
|
*
|
||||||
|
* @param srcMap 原map
|
||||||
|
* @param valueGetter 值转换
|
||||||
|
* @param <K> Key类型
|
||||||
|
* @param <V> Value类型
|
||||||
|
* @return 返回新map
|
||||||
|
*/
|
||||||
|
public static <K, V> Map<K, V> copyMap(Map<K, ?> srcMap, Supplier<V> valueGetter) {
|
||||||
|
Map<K, V> ret = new LinkedHashMap<>(srcMap.size() * 2);
|
||||||
|
for (Map.Entry<K, ?> entry : srcMap.entrySet()) {
|
||||||
|
V value = copyBean(entry.getValue(), valueGetter);
|
||||||
|
ret.put(entry.getKey(), value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝map
|
||||||
|
*
|
||||||
|
* @param srcMap 原map
|
||||||
|
* @param function 值转换
|
||||||
|
* @param <K> Key类型
|
||||||
|
* @param <V> Value类型
|
||||||
|
* @return 返回新map
|
||||||
|
*/
|
||||||
|
public static <K, V, V0> Map<K, V> copyMap(Map<K, V0> srcMap, Function<V0, V> function) {
|
||||||
|
Map<K, V> ret = new LinkedHashMap<>(srcMap.size() * 2);
|
||||||
|
for (Map.Entry<K, V0> entry : srcMap.entrySet()) {
|
||||||
|
V value = function.apply(entry.getValue());
|
||||||
|
ret.put(entry.getKey(), value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拷贝map,value是list
|
||||||
|
*
|
||||||
|
* @param srcMap 原map
|
||||||
|
* @param valueGetter 值转换
|
||||||
|
* @param <K> Key类型
|
||||||
|
* @param <V> Value类型
|
||||||
|
* @return 返回新map
|
||||||
|
*/
|
||||||
|
public static <K, V, V2> Map<K, List<V2>> copyMapList(Map<K, List<V>> srcMap, Function<List<V>, List<V2>> valueGetter) {
|
||||||
|
Map<K, List<V2>> ret = new LinkedHashMap<>(srcMap.size() * 2);
|
||||||
|
for (Map.Entry<K, List<V>> entry : srcMap.entrySet()) {
|
||||||
|
List<V2> value = valueGetter.apply(entry.getValue());
|
||||||
|
ret.put(entry.getKey(), value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CopyConsumer<F, T> {
|
||||||
|
void apply(F from, T to);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
dubbo.registry.address=zookeeper://localhost:2181
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
|
|
||||||
spring.datasource.driver-class-name=org.h2.Driver
|
# mysql config
|
||||||
spring.datasource.url=jdbc:h2:mem:test
|
mysql.host=127.0.0.1:3306
|
||||||
spring.sql.init.schema-locations=classpath:schema.sql
|
mysql.username=root
|
||||||
spring.datasource.username=${mysql.username}
|
mysql.password=root
|
||||||
spring.datasource.password=${mysql.password}
|
|
||||||
|
@@ -12,17 +12,26 @@ dubbo.protocol.port=-1
|
|||||||
# redis://localhost:6379 Cluster config:redis://10.20.153.10:6379?backup=10.20.153.11:6379,10.20.153.12:6379
|
# redis://localhost:6379 Cluster config:redis://10.20.153.10:6379?backup=10.20.153.11:6379,10.20.153.12:6379
|
||||||
# ------
|
# ------
|
||||||
dubbo.registry.address=nacos://localhost:8848
|
dubbo.registry.address=nacos://localhost:8848
|
||||||
####### dubbo config end #######
|
|
||||||
|
|
||||||
|
|
||||||
####### mysql config #######
|
####### mysql config #######
|
||||||
mysql.host=127.0.0.1:3306
|
mysql.host=127.0.0.1:3306
|
||||||
mysql.username=root
|
mysql.username=
|
||||||
mysql.password=root
|
mysql.password=
|
||||||
mysql.db=sop
|
mysql.db=sop
|
||||||
|
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
spring.datasource.url=jdbc:mysql://${mysql.host}/${mysql.db}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
spring.datasource.url=jdbc:mysql://${mysql.host}/${mysql.db}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
|
||||||
spring.datasource.username=${mysql.username}
|
spring.datasource.username=${mysql.username}
|
||||||
spring.datasource.password=${mysql.password}
|
spring.datasource.password=${mysql.password}
|
||||||
####### mysql config end #######
|
|
||||||
|
####### mybatis config #######
|
||||||
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillInsert=add_time
|
||||||
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillUpdate=update_time
|
||||||
|
# mybatis config file
|
||||||
|
mybatis.config-location=classpath:mybatis/mybatisConfig.xml
|
||||||
|
|
||||||
|
# print SQL
|
||||||
|
logging.level.com.gitee.sop.index.dao=error
|
||||||
|
logging.level.com.gitee.fastmybatis=debug
|
||||||
|
mybatis.print-sql=true
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||||
|
<configuration>
|
||||||
|
<settings>
|
||||||
|
<!-- 全局映射器启用缓存 -->
|
||||||
|
<setting name="cacheEnabled" value="true" />
|
||||||
|
<!-- 查询时,关闭关联对象即时加载以提高性能 -->
|
||||||
|
<setting name="lazyLoadingEnabled" value="true" />
|
||||||
|
<!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
|
||||||
|
<setting name="multipleResultSetsEnabled" value="true" />
|
||||||
|
<!-- 允许使用列标签代替列名 -->
|
||||||
|
<setting name="useColumnLabel" value="true" />
|
||||||
|
<!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 -->
|
||||||
|
<setting name="useGeneratedKeys" value="false" />
|
||||||
|
<!-- 对于批量更新操作缓存SQL以提高性能:BATCH -->
|
||||||
|
<setting name="defaultExecutorType" value="SIMPLE" />
|
||||||
|
<!-- 超时设置 -->
|
||||||
|
<setting name="defaultStatementTimeout" value="25000" />
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin interceptor="com.gitee.fastmybatis.core.support.plugin.SqlFormatterPlugin">
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</configuration>
|
@@ -1,16 +0,0 @@
|
|||||||
CREATE TABLE `api_info`
|
|
||||||
(
|
|
||||||
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
`application` varchar(64) NOT NULL DEFAULT '' COMMENT '应用名称',
|
|
||||||
`api_name` varchar(128) NOT NULL DEFAULT '' COMMENT '接口名称',
|
|
||||||
`api_version` varchar(16) NOT NULL DEFAULT '1.0' COMMENT '版本号',
|
|
||||||
`interface_class_name` varchar(128) NOT NULL DEFAULT '' COMMENT '接口class',
|
|
||||||
`method_name` varchar(128) NOT NULL DEFAULT '' COMMENT '方法名称',
|
|
||||||
`param_name` varchar(128) NOT NULL DEFAULT '' COMMENT '参数名称',
|
|
||||||
`param_type_name` varchar(128) NOT NULL DEFAULT '' COMMENT '参数类型名称',
|
|
||||||
is_permission tinyint(4) NOT NULL DEFAULT '0' COMMENT '接口是否需要授权访问',
|
|
||||||
is_need_Token tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否需要appAuthToken',
|
|
||||||
api_status tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态,1-启用,0-禁用',
|
|
||||||
`add_time` datetime NOT NULL DEFAULT null,
|
|
||||||
`update_time` datetime NOT NULL DEFAULT null
|
|
||||||
);
|
|
@@ -1,8 +1,10 @@
|
|||||||
package com.gitee.sop.support.config;
|
package com.gitee.sop.support.config;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.gitee.sop.index.api.ApiRegisterService;
|
import com.gitee.sop.index.api.ApiRegisterService;
|
||||||
import com.gitee.sop.index.api.RegisterDTO;
|
import com.gitee.sop.index.api.RegisterDTO;
|
||||||
import com.gitee.sop.support.annotation.Open;
|
import com.gitee.sop.support.annotation.Open;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
import org.apache.dubbo.config.annotation.DubboService;
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
@@ -15,10 +17,15 @@ import org.springframework.core.env.Environment;
|
|||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +49,6 @@ public class SopAutoConfiguration implements InitializingBean {
|
|||||||
String appName = environment.getProperty("spring.application.name");
|
String appName = environment.getProperty("spring.application.name");
|
||||||
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(DubboService.class);
|
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(DubboService.class);
|
||||||
for (Object serviceObj : beanMap.values()) {
|
for (Object serviceObj : beanMap.values()) {
|
||||||
Class<?> objClass = serviceObj.getClass();
|
|
||||||
Class<?> interfaceClass = findInterfaceClass(serviceObj);
|
Class<?> interfaceClass = findInterfaceClass(serviceObj);
|
||||||
ReflectionUtils.doWithMethods(interfaceClass, method -> {
|
ReflectionUtils.doWithMethods(interfaceClass, method -> {
|
||||||
regApi(appName, interfaceClass, method);
|
regApi(appName, interfaceClass, method);
|
||||||
@@ -64,18 +70,14 @@ public class SopAutoConfiguration implements InitializingBean {
|
|||||||
if (open == null) {
|
if (open == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Parameter[] parameters = method.getParameters();
|
List<ParamInfo> paramInfos = buildParamInfo(method);
|
||||||
Optional<Parameter> paramOpt = filterParameter(parameters);
|
|
||||||
String paramName = paramOpt.map(Parameter::getName).orElse("");
|
|
||||||
String paramTypeName = paramOpt.map(Parameter::getType).map(Class::getName).orElse("");
|
|
||||||
RegisterDTO registerDTO = new RegisterDTO();
|
RegisterDTO registerDTO = new RegisterDTO();
|
||||||
registerDTO.setApplication(appName);
|
registerDTO.setApplication(appName);
|
||||||
registerDTO.setApiName(open.value());
|
registerDTO.setApiName(open.value());
|
||||||
registerDTO.setApiVersion(open.version());
|
registerDTO.setApiVersion(open.version());
|
||||||
registerDTO.setInterfaceClassName(interfaceClass.getName());
|
registerDTO.setInterfaceClassName(interfaceClass.getName());
|
||||||
registerDTO.setMethodName(method.getName());
|
registerDTO.setMethodName(method.getName());
|
||||||
registerDTO.setParamName(paramName);
|
registerDTO.setParamInfo(JSON.toJSONString(paramInfos));
|
||||||
registerDTO.setParamTypeName(paramTypeName);
|
|
||||||
registerDTO.setIsPermission(parseBoolean(open.permission()));
|
registerDTO.setIsPermission(parseBoolean(open.permission()));
|
||||||
registerDTO.setIsNeedToken(parseBoolean(open.needToken()));
|
registerDTO.setIsNeedToken(parseBoolean(open.needToken()));
|
||||||
log.info("注册开放接口, apiInfo={}", registerDTO);
|
log.info("注册开放接口, apiInfo={}", registerDTO);
|
||||||
@@ -86,6 +88,21 @@ public class SopAutoConfiguration implements InitializingBean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ParamInfo> buildParamInfo(Method method) {
|
||||||
|
Parameter[] parameters = method.getParameters();
|
||||||
|
if (parameters.length == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return Stream.of(parameters)
|
||||||
|
.map(parameter -> {
|
||||||
|
ParamInfo paramInfo = new ParamInfo();
|
||||||
|
paramInfo.setName(parameter.getName());
|
||||||
|
paramInfo.setType(parameter.getType().getName());
|
||||||
|
return paramInfo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
private Optional<Parameter> filterParameter(Parameter[] parameters) {
|
private Optional<Parameter> filterParameter(Parameter[] parameters) {
|
||||||
if (ObjectUtils.isEmpty(parameters)) {
|
if (ObjectUtils.isEmpty(parameters)) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@@ -96,4 +113,13 @@ public class SopAutoConfiguration implements InitializingBean {
|
|||||||
private int parseBoolean(boolean b) {
|
private int parseBoolean(boolean b) {
|
||||||
return b ? 1 : 0;
|
return b ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class ParamInfo implements Serializable {
|
||||||
|
private static final long serialVersionUID = -404173450677698875L;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,41 @@ public class AlipayClientPostTest extends TestBase {
|
|||||||
System.out.println(responseData);
|
System.out.println(responseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFind() throws Exception {
|
||||||
|
|
||||||
|
// 公共请求参数
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("app_id", appId);
|
||||||
|
params.put("method", "story.find");
|
||||||
|
params.put("format", "json");
|
||||||
|
params.put("charset", "utf-8");
|
||||||
|
params.put("sign_type", "RSA2");
|
||||||
|
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||||
|
params.put("version", "1.0");
|
||||||
|
|
||||||
|
// 业务参数
|
||||||
|
Map<String, Object> bizContent = new HashMap<>();
|
||||||
|
bizContent.put("id", "122");
|
||||||
|
bizContent.put("name", "葫芦娃");
|
||||||
|
|
||||||
|
params.put("biz_content", JSON.toJSONString(bizContent));
|
||||||
|
String content = AlipaySignature.getSignContent(params);
|
||||||
|
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
System.out.println("----------- 请求信息 -----------");
|
||||||
|
System.out.println("请求参数:" + buildParamQuery(params));
|
||||||
|
System.out.println("商户秘钥:" + privateKey);
|
||||||
|
System.out.println("待签名内容:" + content);
|
||||||
|
System.out.println("签名(sign):" + sign);
|
||||||
|
System.out.println("URL参数:" + buildUrlQuery(params));
|
||||||
|
|
||||||
|
System.out.println("----------- 返回结果 -----------");
|
||||||
|
String responseData = postJson(url, params);// 发送请求
|
||||||
|
System.out.println(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSave() throws Exception {
|
public void testSave() throws Exception {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user