mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
5.0
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
package com.gitee.sop.storyweb;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class SopStoryApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,6 +23,13 @@
|
||||
<artifactId>sop-index-api</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-spring-boot-starter</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
@@ -67,6 +74,10 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
|
@@ -1,21 +0,0 @@
|
||||
package com.gitee.sop.index.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Data
|
||||
public class FileInfo {
|
||||
|
||||
/**
|
||||
* 文件名,包含后缀,如:aa.jpg
|
||||
*/
|
||||
private String filename;
|
||||
|
||||
/**
|
||||
* 文件内容
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.gitee.sop.index.common;
|
||||
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
@@ -1,13 +1,12 @@
|
||||
package com.gitee.sop.index.controller;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequest;
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequest;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ApiResponse;
|
||||
import com.gitee.sop.index.service.RouteService;
|
||||
import com.gitee.sop.index.util.RequestUtil;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.gitee.sop.index.exception;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ApiResponse;
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.gitee.sop.index.exception.impl;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ApiResponse;
|
||||
import com.gitee.sop.index.exception.ApiException;
|
||||
import com.gitee.sop.index.exception.ExceptionExecutor;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.gitee.sop.index.common;
|
||||
package com.gitee.sop.index.request;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
@@ -1,5 +1,6 @@
|
||||
package com.gitee.sop.index.common;
|
||||
package com.gitee.sop.index.request;
|
||||
|
||||
import com.gitee.sop.support.request.FileData;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -33,5 +34,5 @@ public class ApiRequestContext {
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
private List<FileInfo> files;
|
||||
private UploadContext uploadContext;
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
package com.gitee.sop.index.request;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.gitee.sop.index.common.SopConstants;
|
||||
import com.gitee.sop.index.util.RequestUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiRequestContextFactory {
|
||||
|
||||
private static final String CONTENT_TYPE = "content-type";
|
||||
private static final String JSON_NAME = "json";
|
||||
private static final String TEXT_NAME = "text";
|
||||
private static final String MULTIPART = "multipart";
|
||||
public static final String FORM = "form";
|
||||
|
||||
public static ApiRequestContext build(HttpServletRequest request) {
|
||||
String contentType = request.getHeader(CONTENT_TYPE);
|
||||
if (contentType == null) {
|
||||
contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE;
|
||||
}
|
||||
ApiRequest apiRequest = new ApiRequest();
|
||||
String ip = RequestUtil.getIP(request);
|
||||
byte[] body;
|
||||
try {
|
||||
body = IOUtils.toByteArray(request.getInputStream());
|
||||
} catch (IOException e) {
|
||||
log.error("获取请求体失败", e);
|
||||
body = new byte[0];
|
||||
}
|
||||
JSONObject params = null;
|
||||
UploadContext uploadContext = null;
|
||||
String contentTypeStr = contentType.toLowerCase();
|
||||
// 如果是json方式提交
|
||||
if (StringUtils.containsAny(contentTypeStr, JSON_NAME, TEXT_NAME)) {
|
||||
apiRequest = JSON.parseObject(body, ApiRequest.class);
|
||||
} else if (StringUtils.containsIgnoreCase(contentTypeStr, MULTIPART)) {
|
||||
// 如果是文件上传请求
|
||||
RequestUtil.UploadInfo uploadInfo = RequestUtil.getUploadInfo(request);
|
||||
params = uploadInfo.getApiParam();
|
||||
uploadContext = uploadInfo.getUploadContext();
|
||||
} else if (StringUtils.containsIgnoreCase(contentTypeStr, FORM)) {
|
||||
// APPLICATION_FORM_URLENCODED请求
|
||||
params = RequestUtil.parseQuerystring(new String(body, SopConstants.CHARSET_UTF8));
|
||||
} else {
|
||||
// get请求,参数跟在url后面
|
||||
params = RequestUtil.parseParameterMap(request.getParameterMap());
|
||||
}
|
||||
if (params != null) {
|
||||
apiRequest = params.toJavaObject(ApiRequest.class);
|
||||
}
|
||||
|
||||
return ApiRequestContext.builder()
|
||||
.apiRequest(apiRequest)
|
||||
.locale(request.getLocale())
|
||||
.ip(ip)
|
||||
.uploadContext(uploadContext)
|
||||
.traceId(UUID.randomUUID().toString().replace("-", ""))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.gitee.sop.index.request;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 存放上传文件
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public class ApiUploadContext implements UploadContext {
|
||||
|
||||
/**
|
||||
* key: 表单name
|
||||
*/
|
||||
private Map<String, List<MultipartFile>> fileMap;
|
||||
private List<MultipartFile> allFile;
|
||||
|
||||
public ApiUploadContext(Map<String, List<MultipartFile>> map) {
|
||||
if (map == null) {
|
||||
map = Collections.emptyMap();
|
||||
}
|
||||
this.fileMap = map;
|
||||
this.allFile = new ArrayList<>();
|
||||
map.values().forEach(list -> this.allFile.addAll(list));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartFile getFile(int index) {
|
||||
return this.allFile.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartFile> getFile(String name) {
|
||||
return fileMap.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartFile> getAllFile() {
|
||||
return this.allFile;
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package com.gitee.sop.index.request;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取上传文件
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface UploadContext {
|
||||
/**
|
||||
* 根据索引获取上传文件,从0开始
|
||||
*
|
||||
* @param index
|
||||
* @return 返回上传文件信息
|
||||
*/
|
||||
MultipartFile getFile(int index);
|
||||
|
||||
/**
|
||||
* 根据表单名获取上传文件
|
||||
*
|
||||
* @param name
|
||||
* 表单名称
|
||||
* @return 返回上传文件信息
|
||||
*/
|
||||
List<MultipartFile> getFile(String name);
|
||||
|
||||
/**
|
||||
* 获取所有的上传文件
|
||||
*
|
||||
* @return 返回所有的上传文件
|
||||
*/
|
||||
List<MultipartFile> getAllFile();
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
package com.gitee.sop.index.service;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ApiResponse;
|
||||
|
||||
/**
|
||||
|
@@ -3,15 +3,16 @@ 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.request.ApiRequest;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ApiResponse;
|
||||
import com.gitee.sop.index.common.AttachmentNames;
|
||||
import com.gitee.sop.index.common.ParamInfoDTO;
|
||||
import com.gitee.sop.index.common.ParamNames;
|
||||
import com.gitee.sop.index.exception.ExceptionExecutor;
|
||||
import com.gitee.sop.index.request.UploadContext;
|
||||
import com.gitee.sop.index.service.validate.Validator;
|
||||
import com.gitee.sop.index.util.ClassUtil;
|
||||
import com.gitee.sop.support.request.FileData;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.common.utils.ClassUtils;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
@@ -23,6 +24,7 @@ import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 接口路由
|
||||
@@ -69,7 +71,7 @@ public class RouteServiceImpl implements RouteService {
|
||||
apiInfo.getInterfaceClassName(),
|
||||
apiInfo.getMethodName(),
|
||||
buildParamType(paramInfoList),
|
||||
buildInvokeParam(apiRequest, paramInfoList)
|
||||
buildInvokeParam(apiRequestContext, paramInfoList)
|
||||
);
|
||||
if (result instanceof Map) {
|
||||
((Map<?, ?>) result).remove(CLASS);
|
||||
@@ -98,26 +100,36 @@ public class RouteServiceImpl implements RouteService {
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
protected Object[] buildInvokeParam(ApiRequest apiRequest, List<ParamInfoDTO> paramInfoList) {
|
||||
protected Object[] buildInvokeParam(ApiRequestContext apiRequestContext, List<ParamInfoDTO> paramInfoList) {
|
||||
if (ObjectUtils.isEmpty(paramInfoList)) {
|
||||
return new Object[0];
|
||||
}
|
||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||
String bizContent = apiRequest.getBiz_content();
|
||||
JSONObject jsonObject = JSON.parseObject(bizContent);
|
||||
List<Object> params = new ArrayList<>();
|
||||
for (ParamInfoDTO paramInfoDTO : paramInfoList) {
|
||||
if (ClassUtil.isPrimitive(paramInfoDTO.getType())) {
|
||||
String paramName = paramInfoDTO.getName();
|
||||
try {
|
||||
Object value = jsonObject.getObject(paramName, ClassUtils.forName(paramInfoDTO.getType()));
|
||||
params.add(value);
|
||||
jsonObject.remove(paramName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("找不到参数class, paramInfoDTO={}, apiRequest={}", paramInfoDTO, apiRequest, e);
|
||||
throw new RuntimeException("找不到class:" + paramInfoDTO.getType(), e);
|
||||
String type = paramInfoDTO.getType();
|
||||
// 如果是文件上传
|
||||
if (Objects.equals(type, FileData.class.getName())) {
|
||||
UploadContext uploadContext = apiRequestContext.getUploadContext();
|
||||
if (uploadContext == null) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
params.add(jsonObject);
|
||||
if (ClassUtil.isPrimitive(type)) {
|
||||
String paramName = paramInfoDTO.getName();
|
||||
try {
|
||||
Object value = jsonObject.getObject(paramName, ClassUtils.forName(type));
|
||||
params.add(value);
|
||||
jsonObject.remove(paramName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("找不到参数class, paramInfoDTO={}, apiRequest={}", paramInfoDTO, apiRequest, e);
|
||||
throw new RuntimeException("找不到class:" + type, e);
|
||||
}
|
||||
} else {
|
||||
params.add(jsonObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
return params.toArray(new Object[0]);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package com.gitee.sop.index.service.validate;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequest;
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequest;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.exception.ApiException;
|
||||
import com.gitee.sop.index.message.ErrorEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@@ -1,13 +1,14 @@
|
||||
package com.gitee.sop.index.service.validate;
|
||||
|
||||
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.request.ApiRequest;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
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.exception.ApiException;
|
||||
import com.gitee.sop.index.message.ErrorEnum;
|
||||
import com.gitee.sop.index.request.UploadContext;
|
||||
import com.gitee.sop.index.service.ApiInfoService;
|
||||
import com.gitee.sop.index.service.manager.IpBlacklistManager;
|
||||
import com.gitee.sop.index.service.manager.IsvApiPermissionManager;
|
||||
@@ -47,10 +48,16 @@ public class ApiValidator implements Validator {
|
||||
private final Signer signer = new AlipaySigner();
|
||||
|
||||
/**
|
||||
* 单个文件大小
|
||||
* 单个文件内容最大值
|
||||
*/
|
||||
@Value("${upload.max-file-size:${spring.servlet.multipart.max-file-size:10MB}}")
|
||||
private String maxFileSize;
|
||||
@Value("${upload.one-file-max-size}")
|
||||
private DataSize oneFileMaxSize;
|
||||
|
||||
/**
|
||||
* 总文件最大值
|
||||
*/
|
||||
@Value("${upload.total-file-max-size}")
|
||||
private DataSize maxFileSize;
|
||||
|
||||
@Resource
|
||||
private ApiConfig apiConfig;
|
||||
@@ -122,6 +129,9 @@ public class ApiValidator implements Validator {
|
||||
|
||||
public void checkField(ApiRequestContext apiRequestContext) {
|
||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||
if (apiRequest == null) {
|
||||
throw new ApiException(ErrorEnum.ISV_INVALID_PARAMETER, apiRequestContext.getLocale());
|
||||
}
|
||||
Locale locale = apiRequestContext.getLocale();
|
||||
if (ObjectUtils.isEmpty(apiRequest.getApp_id())) {
|
||||
throw new ApiException(ErrorEnum.ISV_MISSING_APP_ID, locale);
|
||||
@@ -165,7 +175,27 @@ public class ApiValidator implements Validator {
|
||||
* @param apiRequestContext apiRequestContext
|
||||
*/
|
||||
protected void checkUploadFile(ApiRequestContext apiRequestContext) {
|
||||
// todo:校验上传文件内容
|
||||
// 校验上传文件内容
|
||||
UploadContext uploadContext = apiRequestContext.getUploadContext();
|
||||
if (uploadContext != null) {
|
||||
List<MultipartFile> allFiles = uploadContext.getAllFile();
|
||||
if (ObjectUtils.isEmpty(allFiles)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MultipartFile multipartFile : allFiles) {
|
||||
checkSingleFileSize(apiRequestContext, multipartFile);
|
||||
}
|
||||
|
||||
long totalSize = allFiles.stream()
|
||||
.map(MultipartFile::getSize)
|
||||
.mapToLong(Long::longValue)
|
||||
.sum();
|
||||
|
||||
if (totalSize > maxFileSize.toBytes()) {
|
||||
throw new ApiException(ErrorEnum.ISV_INVALID_FILE_SIZE, apiRequestContext.getLocale(), totalSize, maxFileSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,8 +205,9 @@ public class ApiValidator implements Validator {
|
||||
*/
|
||||
private void checkSingleFileSize(ApiRequestContext apiRequestContext, MultipartFile file) {
|
||||
long fileSize = file.getSize();
|
||||
if (fileSize > DataSize.parse(maxFileSize).toBytes()) {
|
||||
throw new ApiException(ErrorEnum.ISV_INVALID_FILE_SIZE, apiRequestContext.getLocale(), fileSize, maxFileSize);
|
||||
long maxSize = oneFileMaxSize.toBytes();
|
||||
if (fileSize > maxSize) {
|
||||
throw new ApiException(ErrorEnum.ISV_INVALID_FILE_SIZE, apiRequestContext.getLocale(), fileSize, maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.gitee.sop.index.service.validate;
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
|
||||
/**
|
||||
* 负责签名校验
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package com.gitee.sop.index.service.validate;
|
||||
|
||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
|
||||
/**
|
||||
* 校验接口
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package com.gitee.sop.index.service.validate.alipay;
|
||||
|
||||
|
||||
import com.gitee.sop.index.common.ApiRequest;
|
||||
import com.gitee.sop.index.common.ApiRequestContext;
|
||||
import com.gitee.sop.index.request.ApiRequest;
|
||||
import com.gitee.sop.index.request.ApiRequestContext;
|
||||
import com.gitee.sop.index.common.ParamNames;
|
||||
import com.gitee.sop.index.exception.ApiException;
|
||||
import com.gitee.sop.index.exception.SignException;
|
||||
|
@@ -1,18 +1,40 @@
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
|
||||
package com.gitee.sop.index.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.gitee.sop.index.common.SopConstants;
|
||||
import com.gitee.sop.index.request.ApiUploadContext;
|
||||
import com.gitee.sop.index.request.UploadContext;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.commons.CommonsMultipartFile;
|
||||
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class RequestUtil {
|
||||
private static final String UTF8 = "UTF-8";
|
||||
private static final String IP_UNKNOWN = "unknown";
|
||||
private static final String IP_LOCAL = "127.0.0.1";
|
||||
private static final int IP_LEN = 15;
|
||||
private static final String X_FORWARDED_FOR = "x-forwarded-for";
|
||||
private static final String PROXY_CLIENT_IP = "Proxy-Client-IP";
|
||||
private static final String PROXY_CLIENT_IP1 = "WL-Proxy-Client-IP";
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
@@ -21,14 +43,14 @@ public class RequestUtil {
|
||||
* @return 返回ip
|
||||
*/
|
||||
public static String getIP(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("x-forwarded-for");
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||
String ipAddress = request.getHeader(X_FORWARDED_FOR);
|
||||
if (ipAddress == null || ipAddress.isEmpty() || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader(PROXY_CLIENT_IP);
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||
if (ipAddress == null || ipAddress.isEmpty() || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader(PROXY_CLIENT_IP1);
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
if (ipAddress == null || ipAddress.isEmpty() || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
if (IP_LOCAL.equals(ipAddress)) {
|
||||
// 根据网卡取本机配置的IP
|
||||
@@ -50,4 +72,106 @@ public class RequestUtil {
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将get类型的参数转换成JSONObject
|
||||
*
|
||||
* @param query charset=utf-8&biz_content=xxx
|
||||
* @return 返回map参数
|
||||
*/
|
||||
public static JSONObject parseQuerystring(String query) {
|
||||
if (query == null) {
|
||||
return new JSONObject();
|
||||
}
|
||||
String[] queryList = StringUtils.split(query, '&');
|
||||
JSONObject params = new JSONObject();
|
||||
for (String param : queryList) {
|
||||
String[] paramArr = param.split("=");
|
||||
if (paramArr.length == 2) {
|
||||
try {
|
||||
params.put(paramArr[0], URLDecoder.decode(paramArr[1], UTF8));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (paramArr.length == 1) {
|
||||
params.put(paramArr[0], "");
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public static JSONObject parseParameterMap(Map<String, String[]> parameterMap) {
|
||||
if (parameterMap == null || parameterMap.isEmpty()) {
|
||||
return new JSONObject();
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
parameterMap.forEach((key, value) -> jsonObject.put(key, value[0]));
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传文件内容
|
||||
*
|
||||
* @param request request
|
||||
* @return 返回文件内容和表单内容
|
||||
*/
|
||||
public static UploadInfo getUploadInfo(HttpServletRequest request) {
|
||||
if (request instanceof StandardMultipartHttpServletRequest) {
|
||||
return getUploadInfo((StandardMultipartHttpServletRequest) request);
|
||||
}
|
||||
UploadInfo uploadInfo = new UploadInfo();
|
||||
// 创建一个文件上传解析器
|
||||
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
|
||||
UploadContext uploadContext = null;
|
||||
JSONObject uploadParams = new JSONObject();
|
||||
try {
|
||||
List<MultipartFile> multipartFileList = new ArrayList<>(8);
|
||||
List<FileItem> fileItems = upload.parseRequest(request);
|
||||
for (FileItem fileItem : fileItems) {
|
||||
if (fileItem.isFormField()) {
|
||||
uploadParams.put(fileItem.getFieldName(), fileItem.getString(SopConstants.UTF8));
|
||||
} else {
|
||||
multipartFileList.add(new CommonsMultipartFile(fileItem));
|
||||
}
|
||||
}
|
||||
if (!multipartFileList.isEmpty()) {
|
||||
Map<String, List<MultipartFile>> multipartFileMap = multipartFileList
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(MultipartFile::getName));
|
||||
uploadContext = new ApiUploadContext(multipartFileMap);
|
||||
}
|
||||
|
||||
JSONObject apiParam = parseParameterMap(request.getParameterMap());
|
||||
uploadParams.putAll(apiParam);
|
||||
uploadInfo.setApiParam(uploadParams);
|
||||
uploadInfo.setUploadContext(uploadContext);
|
||||
} catch (Exception e) {
|
||||
log.error("参数解析错误", e);
|
||||
}
|
||||
return uploadInfo;
|
||||
}
|
||||
|
||||
public static UploadInfo getUploadInfo(StandardMultipartHttpServletRequest request) {
|
||||
UploadInfo uploadInfo = new UploadInfo();
|
||||
MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
|
||||
List<MultipartFile> multipartFileList = new ArrayList<>(multiFileMap.size());
|
||||
for (String key : multiFileMap.keySet()) {
|
||||
multipartFileList.addAll(multiFileMap.get(key));
|
||||
}
|
||||
Map<String, List<MultipartFile>> multipartFileMap = multipartFileList
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(MultipartFile::getName));
|
||||
UploadContext uploadContext = new ApiUploadContext(multipartFileMap);
|
||||
|
||||
JSONObject apiParam = parseParameterMap(request.getParameterMap());
|
||||
uploadInfo.setApiParam(apiParam);
|
||||
uploadInfo.setUploadContext(uploadContext);
|
||||
return uploadInfo;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class UploadInfo {
|
||||
private JSONObject apiParam;
|
||||
private UploadContext uploadContext;
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,22 @@ 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
|
||||
# ------
|
||||
dubbo.registry.address=nacos://localhost:8848
|
||||
# max payload size, 10MB
|
||||
# 1KB = 1024
|
||||
# 1MB = 1048576
|
||||
# 1GB = 1073741824
|
||||
# 1TB = 1099511627776
|
||||
dubbo.protocol.payload=10485760
|
||||
|
||||
####### file upload config #######
|
||||
# one file max size limit, unit:KB/MB
|
||||
upload.one-file-max-size=1MB
|
||||
# total files max size limit
|
||||
upload.total-file-max-size=5MB
|
||||
# Ensure that this configuration is larger than {upload.one-file-max-size}
|
||||
spring.servlet.multipart.max-file-size=5MB
|
||||
# Ensure that this configuration is larger than {upload.total-file-max-size} and {dubbo.protocol.payload}
|
||||
spring.servlet.multipart.max-request-size=20MB
|
||||
|
||||
####### mysql config #######
|
||||
mysql.host=127.0.0.1:3306
|
||||
|
@@ -10,6 +10,7 @@ import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -44,8 +45,14 @@ public class SopAutoConfiguration implements InitializingBean {
|
||||
@DubboReference
|
||||
private ApiRegisterService apiRegisterService;
|
||||
|
||||
@Value("${open.register.enable:true}")
|
||||
private boolean enableRegister;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (!enableRegister) {
|
||||
return;
|
||||
}
|
||||
String appName = environment.getProperty("spring.application.name");
|
||||
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(DubboService.class);
|
||||
for (Object serviceObj : beanMap.values()) {
|
||||
|
@@ -0,0 +1,34 @@
|
||||
package com.gitee.sop.support.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Data
|
||||
public class FileData implements Serializable {
|
||||
private static final long serialVersionUID = -7588392091014943373L;
|
||||
|
||||
/**
|
||||
* 上传文件表单名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 原始文件名称,可能为null
|
||||
*/
|
||||
private String originalFilename;
|
||||
|
||||
/**
|
||||
* 文件的contentType,可能为null
|
||||
*/
|
||||
private String contentType;
|
||||
|
||||
/**
|
||||
* 文件内容
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
}
|
@@ -1,92 +0,0 @@
|
||||
package com.gitee.sop.support.request;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Data
|
||||
public class OpenRequest<T> implements Serializable {
|
||||
private static final long serialVersionUID = -6703437435180048422L;
|
||||
|
||||
private Class<T> clazz;
|
||||
|
||||
public OpenRequest() {
|
||||
clazz = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), OpenRequest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分配给开发者的应用ID
|
||||
*
|
||||
* @mock 2014072300007148
|
||||
*/
|
||||
private String app_id;
|
||||
|
||||
/**
|
||||
* 接口名称
|
||||
*
|
||||
* @mock alipay.trade.fastpay.refund.query
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 仅支持JSON
|
||||
*
|
||||
* @mock json
|
||||
*/
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 请求使用的编码格式,如utf-8,gbk,gb2312等
|
||||
*
|
||||
* @mock utf-8
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
|
||||
*
|
||||
* @mock RSA2
|
||||
*/
|
||||
private String sign_type;
|
||||
|
||||
/**
|
||||
* 商户请求参数的签名串,详见签名
|
||||
*/
|
||||
private String sign;
|
||||
|
||||
/**
|
||||
* 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
|
||||
*
|
||||
* @mock 2014-07-24 03:07:50
|
||||
*/
|
||||
private String timestamp;
|
||||
|
||||
/**
|
||||
* 调用的接口版本,固定为:1.0
|
||||
*
|
||||
* @mock 1.0
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 支付宝服务器主动通知商户服务器里指定的页面http/https路径
|
||||
*
|
||||
* @mock http://ww.xx.com/callback
|
||||
*/
|
||||
private String notify_url;
|
||||
|
||||
/**
|
||||
* 授权token,详见应用授权概述
|
||||
*/
|
||||
private String app_auth_token;
|
||||
|
||||
/**
|
||||
* 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档
|
||||
*/
|
||||
private String biz_content;
|
||||
|
||||
}
|
Reference in New Issue
Block a user