This commit is contained in:
六如
2024-09-12 21:52:54 +08:00
parent cccafde158
commit 95072a02f6
24 changed files with 442 additions and 182 deletions

View File

@@ -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() {
}
}

View File

@@ -23,6 +23,13 @@
<artifactId>sop-index-api</artifactId> <artifactId>sop-index-api</artifactId>
<version>5.0.0-SNAPSHOT</version> <version>5.0.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.gitee.sop</groupId>
<artifactId>sop-spring-boot-starter</artifactId>
<version>5.0.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>
@@ -67,6 +74,10 @@
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>

View File

@@ -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;
}

View File

@@ -1,5 +1,6 @@
package com.gitee.sop.index.common; package com.gitee.sop.index.common;
import com.gitee.sop.index.request.ApiRequestContext;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

View File

@@ -1,13 +1,12 @@
package com.gitee.sop.index.controller; package com.gitee.sop.index.controller;
import com.gitee.sop.index.common.ApiRequest; import com.gitee.sop.index.request.ApiRequest;
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.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.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.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;

View File

@@ -1,6 +1,6 @@
package com.gitee.sop.index.exception; 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; import com.gitee.sop.index.common.ApiResponse;
/** /**

View File

@@ -1,6 +1,6 @@
package com.gitee.sop.index.exception.impl; 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.common.ApiResponse;
import com.gitee.sop.index.exception.ApiException; import com.gitee.sop.index.exception.ApiException;
import com.gitee.sop.index.exception.ExceptionExecutor; import com.gitee.sop.index.exception.ExceptionExecutor;

View File

@@ -1,4 +1,4 @@
package com.gitee.sop.index.common; package com.gitee.sop.index.request;
import com.alibaba.fastjson2.annotation.JSONField; import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;

View File

@@ -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.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -33,5 +34,5 @@ public class ApiRequestContext {
/** /**
* 上传文件 * 上传文件
*/ */
private List<FileInfo> files; private UploadContext uploadContext;
} }

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -1,6 +1,6 @@
package com.gitee.sop.index.service; 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; import com.gitee.sop.index.common.ApiResponse;
/** /**

View File

@@ -3,15 +3,16 @@ package com.gitee.sop.index.service;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.gitee.sop.index.common.ApiInfoDTO; import com.gitee.sop.index.common.ApiInfoDTO;
import com.gitee.sop.index.common.ApiRequest; import com.gitee.sop.index.request.ApiRequest;
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.common.ApiResponse;
import com.gitee.sop.index.common.AttachmentNames; import com.gitee.sop.index.common.AttachmentNames;
import com.gitee.sop.index.common.ParamInfoDTO; 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.exception.ExceptionExecutor;
import com.gitee.sop.index.request.UploadContext;
import com.gitee.sop.index.service.validate.Validator; import com.gitee.sop.index.service.validate.Validator;
import com.gitee.sop.index.util.ClassUtil; import com.gitee.sop.index.util.ClassUtil;
import com.gitee.sop.support.request.FileData;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcContext;
@@ -23,6 +24,7 @@ import javax.annotation.Resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
/** /**
* 接口路由 * 接口路由
@@ -69,7 +71,7 @@ public class RouteServiceImpl implements RouteService {
apiInfo.getInterfaceClassName(), apiInfo.getInterfaceClassName(),
apiInfo.getMethodName(), apiInfo.getMethodName(),
buildParamType(paramInfoList), buildParamType(paramInfoList),
buildInvokeParam(apiRequest, paramInfoList) buildInvokeParam(apiRequestContext, paramInfoList)
); );
if (result instanceof Map) { if (result instanceof Map) {
((Map<?, ?>) result).remove(CLASS); ((Map<?, ?>) result).remove(CLASS);
@@ -98,28 +100,38 @@ public class RouteServiceImpl implements RouteService {
.toArray(String[]::new); .toArray(String[]::new);
} }
protected Object[] buildInvokeParam(ApiRequest apiRequest, List<ParamInfoDTO> paramInfoList) { protected Object[] buildInvokeParam(ApiRequestContext apiRequestContext, List<ParamInfoDTO> paramInfoList) {
if (ObjectUtils.isEmpty(paramInfoList)) { if (ObjectUtils.isEmpty(paramInfoList)) {
return new Object[0]; return new Object[0];
} }
ApiRequest apiRequest = apiRequestContext.getApiRequest();
String bizContent = apiRequest.getBiz_content(); String bizContent = apiRequest.getBiz_content();
JSONObject jsonObject = JSON.parseObject(bizContent); JSONObject jsonObject = JSON.parseObject(bizContent);
List<Object> params = new ArrayList<>(); List<Object> params = new ArrayList<>();
for (ParamInfoDTO paramInfoDTO : paramInfoList) { for (ParamInfoDTO paramInfoDTO : paramInfoList) {
if (ClassUtil.isPrimitive(paramInfoDTO.getType())) { String type = paramInfoDTO.getType();
// 如果是文件上传
if (Objects.equals(type, FileData.class.getName())) {
UploadContext uploadContext = apiRequestContext.getUploadContext();
if (uploadContext == null) {
continue;
}
} else {
if (ClassUtil.isPrimitive(type)) {
String paramName = paramInfoDTO.getName(); String paramName = paramInfoDTO.getName();
try { try {
Object value = jsonObject.getObject(paramName, ClassUtils.forName(paramInfoDTO.getType())); Object value = jsonObject.getObject(paramName, ClassUtils.forName(type));
params.add(value); params.add(value);
jsonObject.remove(paramName); jsonObject.remove(paramName);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
log.error("找不到参数class, paramInfoDTO={}, apiRequest={}", paramInfoDTO, apiRequest, e); log.error("找不到参数class, paramInfoDTO={}, apiRequest={}", paramInfoDTO, apiRequest, e);
throw new RuntimeException("找不到class:" + paramInfoDTO.getType(), e); throw new RuntimeException("找不到class:" + type, e);
} }
} else { } else {
params.add(jsonObject); params.add(jsonObject);
} }
} }
}
return params.toArray(new Object[0]); return params.toArray(new Object[0]);
} }

View File

@@ -1,7 +1,7 @@
package com.gitee.sop.index.service.validate; package com.gitee.sop.index.service.validate;
import com.gitee.sop.index.common.ApiRequest; import com.gitee.sop.index.request.ApiRequest;
import com.gitee.sop.index.common.ApiRequestContext; import com.gitee.sop.index.request.ApiRequestContext;
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 lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;

View File

@@ -1,13 +1,14 @@
package com.gitee.sop.index.service.validate; package com.gitee.sop.index.service.validate;
import com.gitee.sop.index.common.ApiInfoDTO; import com.gitee.sop.index.common.ApiInfoDTO;
import com.gitee.sop.index.common.ApiRequest; import com.gitee.sop.index.request.ApiRequest;
import com.gitee.sop.index.common.ApiRequestContext; import com.gitee.sop.index.request.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.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.request.UploadContext;
import com.gitee.sop.index.service.ApiInfoService; 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;
@@ -47,10 +48,16 @@ public class ApiValidator implements Validator {
private final Signer signer = new AlipaySigner(); private final Signer signer = new AlipaySigner();
/** /**
* 单个文件大小 * 单个文件内容最大值
*/ */
@Value("${upload.max-file-size:${spring.servlet.multipart.max-file-size:10MB}}") @Value("${upload.one-file-max-size}")
private String maxFileSize; private DataSize oneFileMaxSize;
/**
* 总文件最大值
*/
@Value("${upload.total-file-max-size}")
private DataSize maxFileSize;
@Resource @Resource
private ApiConfig apiConfig; private ApiConfig apiConfig;
@@ -122,6 +129,9 @@ public class ApiValidator implements Validator {
public void checkField(ApiRequestContext apiRequestContext) { public void checkField(ApiRequestContext apiRequestContext) {
ApiRequest apiRequest = apiRequestContext.getApiRequest(); ApiRequest apiRequest = apiRequestContext.getApiRequest();
if (apiRequest == null) {
throw new ApiException(ErrorEnum.ISV_INVALID_PARAMETER, apiRequestContext.getLocale());
}
Locale locale = apiRequestContext.getLocale(); Locale locale = apiRequestContext.getLocale();
if (ObjectUtils.isEmpty(apiRequest.getApp_id())) { if (ObjectUtils.isEmpty(apiRequest.getApp_id())) {
throw new ApiException(ErrorEnum.ISV_MISSING_APP_ID, locale); throw new ApiException(ErrorEnum.ISV_MISSING_APP_ID, locale);
@@ -165,7 +175,27 @@ public class ApiValidator implements Validator {
* @param apiRequestContext apiRequestContext * @param apiRequestContext apiRequestContext
*/ */
protected void checkUploadFile(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) { private void checkSingleFileSize(ApiRequestContext apiRequestContext, MultipartFile file) {
long fileSize = file.getSize(); long fileSize = file.getSize();
if (fileSize > DataSize.parse(maxFileSize).toBytes()) { long maxSize = oneFileMaxSize.toBytes();
throw new ApiException(ErrorEnum.ISV_INVALID_FILE_SIZE, apiRequestContext.getLocale(), fileSize, maxFileSize); if (fileSize > maxSize) {
throw new ApiException(ErrorEnum.ISV_INVALID_FILE_SIZE, apiRequestContext.getLocale(), fileSize, maxSize);
} }
} }

View File

@@ -1,6 +1,6 @@
package com.gitee.sop.index.service.validate; package com.gitee.sop.index.service.validate;
import com.gitee.sop.index.common.ApiRequestContext; import com.gitee.sop.index.request.ApiRequestContext;
/** /**
* 负责签名校验 * 负责签名校验

View File

@@ -1,7 +1,7 @@
package com.gitee.sop.index.service.validate; package com.gitee.sop.index.service.validate;
import com.gitee.sop.index.common.ApiInfoDTO; import com.gitee.sop.index.common.ApiInfoDTO;
import com.gitee.sop.index.common.ApiRequestContext; import com.gitee.sop.index.request.ApiRequestContext;
/** /**
* 校验接口 * 校验接口

View File

@@ -1,8 +1,8 @@
package com.gitee.sop.index.service.validate.alipay; package com.gitee.sop.index.service.validate.alipay;
import com.gitee.sop.index.common.ApiRequest; import com.gitee.sop.index.request.ApiRequest;
import com.gitee.sop.index.common.ApiRequestContext; import com.gitee.sop.index.request.ApiRequestContext;
import com.gitee.sop.index.common.ParamNames; import com.gitee.sop.index.common.ParamNames;
import com.gitee.sop.index.exception.ApiException; import com.gitee.sop.index.exception.ApiException;
import com.gitee.sop.index.exception.SignException; import com.gitee.sop.index.exception.SignException;

View File

@@ -1,18 +1,40 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.gitee.sop.index.util; package com.gitee.sop.index.util;
import javax.servlet.http.HttpServletRequest; import com.alibaba.fastjson2.JSONObject;
import java.net.InetAddress; import com.gitee.sop.index.common.SopConstants;
import java.net.UnknownHostException; 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 { public class RequestUtil {
private static final String UTF8 = "UTF-8";
private static final String IP_UNKNOWN = "unknown"; private static final String IP_UNKNOWN = "unknown";
private static final String IP_LOCAL = "127.0.0.1"; private static final String IP_LOCAL = "127.0.0.1";
private static final int IP_LEN = 15; 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 * 获取客户端IP
@@ -21,14 +43,14 @@ public class RequestUtil {
* @return 返回ip * @return 返回ip
*/ */
public static String getIP(HttpServletRequest request) { public static String getIP(HttpServletRequest request) {
String ipAddress = request.getHeader("x-forwarded-for"); String ipAddress = request.getHeader(X_FORWARDED_FOR);
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) { if (ipAddress == null || ipAddress.isEmpty() || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP"); ipAddress = request.getHeader(PROXY_CLIENT_IP);
} }
if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) { if (ipAddress == null || ipAddress.isEmpty() || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP"); 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(); ipAddress = request.getRemoteAddr();
if (IP_LOCAL.equals(ipAddress)) { if (IP_LOCAL.equals(ipAddress)) {
// 根据网卡取本机配置的IP // 根据网卡取本机配置的IP
@@ -50,4 +72,106 @@ public class RequestUtil {
} }
return ipAddress; 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;
}
} }

View File

@@ -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 # 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
# 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 config #######
mysql.host=127.0.0.1:3306 mysql.host=127.0.0.1:3306

View File

@@ -10,6 +10,7 @@ import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
@@ -44,8 +45,14 @@ public class SopAutoConfiguration implements InitializingBean {
@DubboReference @DubboReference
private ApiRegisterService apiRegisterService; private ApiRegisterService apiRegisterService;
@Value("${open.register.enable:true}")
private boolean enableRegister;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if (!enableRegister) {
return;
}
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()) {

View File

@@ -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;
}

View File

@@ -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;
}