diff --git a/common/src/main/java/ink/wgink/common/rpc/rest/handler/RestRemoteHandler.java b/common/src/main/java/ink/wgink/common/rpc/rest/handler/RestRemoteHandler.java index 9603ef1d..b8578436 100644 --- a/common/src/main/java/ink/wgink/common/rpc/rest/handler/RestRemoteHandler.java +++ b/common/src/main/java/ink/wgink/common/rpc/rest/handler/RestRemoteHandler.java @@ -6,6 +6,8 @@ import ink.wgink.annotation.rpc.rest.method.RemoteGetMethod; import ink.wgink.annotation.rpc.rest.method.RemotePostMethod; import ink.wgink.annotation.rpc.rest.method.RemotePutMethod; import ink.wgink.annotation.rpc.rest.params.*; +import ink.wgink.common.rpc.rest.pojo.RemoteFileInputStream; +import ink.wgink.common.rpc.rest.pojo.RemoteRequest; import ink.wgink.common.rpc.rest.request.RestRemoteRequest; import ink.wgink.exceptions.ParamsException; import ink.wgink.exceptions.base.SystemException; @@ -15,6 +17,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMethod; +import java.io.File; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; @@ -63,6 +66,8 @@ public class RestRemoteHandler implements InvocationHandler { MultiValueMap formVariableParams = null; String uri; Object requestBody = null; + Map fileInputStreamVariableParams = null; + Map fileVariableParams = null; RequestMethod requestMethod; if (method.isAnnotationPresent(RemoteGetMethod.class)) { // GET请求 @@ -79,8 +84,18 @@ public class RestRemoteHandler implements InvocationHandler { requestMethod = RequestMethod.POST; RemotePostMethod postMethod = method.getAnnotation(RemotePostMethod.class); uri = postMethod.value(); + // 1. 先判断是否有文件 + fileVariableParams = getFileParams(method.getParameters(), args); + if (fileVariableParams.isEmpty()) { + // 2. 判断是否是文件流 + fileInputStreamVariableParams = getFileInputStreamParams(method.getParameters(), args); + } + // 3. 判断表单 formVariableParams = getFormVariableParams(method.getParameters(), args); - if (formVariableParams.isEmpty()) { + if ((fileInputStreamVariableParams == null || fileInputStreamVariableParams.isEmpty()) && + fileVariableParams.isEmpty() && + formVariableParams.isEmpty()) { + // 4. 文件与表单都不存在、判断json requestBody = getRequestBody(method.getParameters(), args); } } else if (method.isAnnotationPresent(RemotePutMethod.class)) { @@ -97,8 +112,18 @@ public class RestRemoteHandler implements InvocationHandler { checkPathVariableParams(pathVariable, pathVariableParams); uri = buildUri(baseUri, uri, pathVariable, pathVariableParams); String remoteFullPath = buildFullUri(remotePath, uri, queryVariableParams, queryMapParams); - RestRemoteRequest restRemoteRequest = new RestRemoteRequest(); - return restRemoteRequest.request(requestMethod, remoteFullPath, headerVariableParams, formVariableParams, requestBody, method.getGenericReturnType()); + + // 发起请求 + RemoteRequest remoteRequest = new RemoteRequest(); + remoteRequest.setRequestMethod(requestMethod); + remoteRequest.setRemoteUri(remoteFullPath); + remoteRequest.setHeaders(headerVariableParams); + remoteRequest.setFormVariableParams(formVariableParams); + remoteRequest.setFileVariableParams(fileVariableParams); + remoteRequest.setFileInputStreamVariableParams(fileInputStreamVariableParams); + remoteRequest.setJsonBody(requestBody); + remoteRequest.setResultType(method.getGenericReturnType()); + return new RestRemoteRequest().request(remoteRequest); } /** @@ -172,6 +197,68 @@ public class RestRemoteHandler implements InvocationHandler { return queryVariableParamsMap; } + /** + * 文件 + * + * @param parameters + * @param args + * @return + */ + private Map getFileParams(Parameter[] parameters, Object[] args) { + Map fileParams = new HashMap<>(0); + for (int i = 0; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + if (!parameter.isAnnotationPresent(RemoteFileParams.class)) { + continue; + } + RemoteFileParams annotation = parameter.getAnnotation(RemoteFileParams.class); + String variableName = annotation.value(); + if (StringUtils.isBlank(variableName)) { + throw new ParamsException("参数 " + parameter.getName() + " 名称不能为空"); + } + Object arg = args[i]; + if (arg == null) { + throw new ParamsException("参数 " + parameter.getName() + " 不能为空"); + } + if (!(arg instanceof File)) { + throw new ParamsException("参数 " + parameter.getName() + " 类型需为 java.io.File"); + } + fileParams.put(variableName, (File) arg); + } + return fileParams; + } + + /** + * 文件流 + * + * @param parameters + * @param args + * @return + */ + private Map getFileInputStreamParams(Parameter[] parameters, Object[] args) { + Map inputStreamParams = new HashMap<>(0); + for (int i = 0; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + if (!parameter.isAnnotationPresent(RemoteFileInputStreamParams.class)) { + continue; + } + RemoteFileInputStreamParams annotation = parameter.getAnnotation(RemoteFileInputStreamParams.class); + String variableName = annotation.value(); + if (StringUtils.isBlank(variableName)) { + throw new ParamsException("参数 " + parameter.getName() + " 名称不能为空"); + } + Object arg = args[i]; + if (arg == null) { + throw new ParamsException("参数 " + parameter.getName() + " 不能为空"); + } + if (!(arg instanceof RemoteFileInputStream)) { + throw new ParamsException("参数 " + parameter.getName() + " 类型需为 ink.wgink.common.rpc.rest.pojo.RemoteFileInputStream"); + } + inputStreamParams.put(variableName, (RemoteFileInputStream) arg); + } + return inputStreamParams; + } + /** * 表单参数 * diff --git a/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteFileInputStream.java b/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteFileInputStream.java new file mode 100644 index 00000000..32dcc473 --- /dev/null +++ b/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteFileInputStream.java @@ -0,0 +1,41 @@ +package ink.wgink.common.rpc.rest.pojo; + +import java.io.InputStream; + +/** + * @ClassName: RemoteFileInputStream + * @Description: 远程文件流 + * @Author: wanggeng + * @Date: 2022/8/4 14:44 + * @Version: 1.0 + */ +public class RemoteFileInputStream { + + private String fileName; + private long fileSize; + private InputStream inputStream; + + public String getFileName() { + return fileName == null ? "" : fileName.trim(); + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + public InputStream getInputStream() { + return inputStream; + } + + public void setInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } +} diff --git a/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteRequest.java b/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteRequest.java new file mode 100644 index 00000000..f4fbb7ff --- /dev/null +++ b/common/src/main/java/ink/wgink/common/rpc/rest/pojo/RemoteRequest.java @@ -0,0 +1,94 @@ +package ink.wgink.common.rpc.rest.pojo; + +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.io.File; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +/** + * @ClassName: RemoteRequest + * @Description: 远程请求 + * @Author: wanggeng + * @Date: 2022/8/4 14:43 + * @Version: 1.0 + */ +public class RemoteRequest { + + private RequestMethod requestMethod; + private String remoteUri; + private Map headers; + private MultiValueMap formVariableParams; + private Object jsonBody; + private Map fileVariableParams; + private Map fileInputStreamVariableParams; + private Type resultType; + + public RequestMethod getRequestMethod() { + return requestMethod; + } + + public void setRequestMethod(RequestMethod requestMethod) { + this.requestMethod = requestMethod; + } + + public String getRemoteUri() { + return remoteUri == null ? "" : remoteUri.trim(); + } + + public void setRemoteUri(String remoteUri) { + this.remoteUri = remoteUri; + } + + public Map getHeaders() { + return headers == null ? new HashMap<>() : headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public MultiValueMap getFormVariableParams() { + return formVariableParams == null ? new LinkedMultiValueMap<>() : formVariableParams; + } + + public void setFormVariableParams(MultiValueMap formVariableParams) { + this.formVariableParams = formVariableParams; + } + + public Object getJsonBody() { + return jsonBody; + } + + public void setJsonBody(Object jsonBody) { + this.jsonBody = jsonBody; + } + + public Map getFileVariableParams() { + return fileVariableParams == null ? new HashMap<>() : fileVariableParams; + } + + public void setFileVariableParams(Map fileVariableParams) { + this.fileVariableParams = fileVariableParams; + } + + public Map getFileInputStreamVariableParams() { + return fileInputStreamVariableParams; + } + + public void setFileInputStreamVariableParams(Map fileInputStreamVariableParams) { + this.fileInputStreamVariableParams = fileInputStreamVariableParams; + } + + public Type getResultType() { + return resultType; + } + + public void setResultType(Type resultType) { + this.resultType = resultType; + } + +} diff --git a/common/src/main/java/ink/wgink/common/rpc/rest/request/RestRemoteRequest.java b/common/src/main/java/ink/wgink/common/rpc/rest/request/RestRemoteRequest.java index c8ad3fc3..1a1f7feb 100644 --- a/common/src/main/java/ink/wgink/common/rpc/rest/request/RestRemoteRequest.java +++ b/common/src/main/java/ink/wgink/common/rpc/rest/request/RestRemoteRequest.java @@ -3,19 +3,28 @@ package ink.wgink.common.rpc.rest.request; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import ink.wgink.common.rpc.rest.pojo.RemoteFileInputStream; +import ink.wgink.common.rpc.rest.pojo.RemoteRequest; +import ink.wgink.exceptions.FileException; import ink.wgink.exceptions.ParamsException; import ink.wgink.exceptions.rpc.RemoteRequestException; import ink.wgink.exceptions.rpc.RemoteResponseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.InputStreamResource; import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; import java.lang.reflect.Type; import java.util.Collection; import java.util.Map; @@ -48,7 +57,15 @@ public class RestRemoteRequest { this.httpsTemplate = new RestTemplate(httpsClientRequestFactory); } - public Object request(RequestMethod requestMethod, String remoteUri, Map headers, MultiValueMap formVariableParams, Object jsonBody, Type resultType) { + public Object request(RemoteRequest remoteRequest) { + RequestMethod requestMethod = remoteRequest.getRequestMethod(); + String remoteUri = remoteRequest.getRemoteUri(); + Map headers = remoteRequest.getHeaders(); + MultiValueMap formVariableParams = remoteRequest.getFormVariableParams(); + Map fileVariableParams = remoteRequest.getFileVariableParams(); + Map fileInputVariableParams = remoteRequest.getFileInputStreamVariableParams(); + Object jsonBody = remoteRequest.getFormVariableParams(); + Type resultType = remoteRequest.getResultType(); String result; if (RequestMethod.GET.equals(requestMethod)) { result = get(remoteUri, headers); @@ -56,8 +73,8 @@ public class RestRemoteRequest { result = delete(remoteUri, headers); } else if (RequestMethod.POST.equals(requestMethod)) { // form表单优先 - if (!formVariableParams.isEmpty()) { - result = post(remoteUri, headers, formVariableParams); + if (!fileVariableParams.isEmpty() || !fileInputVariableParams.isEmpty() || !formVariableParams.isEmpty()) { + result = post(remoteUri, headers, fileVariableParams, fileInputVariableParams, formVariableParams); } else { result = post(remoteUri, headers, jsonBody); } @@ -66,7 +83,7 @@ public class RestRemoteRequest { } else { throw new ParamsException("请求方法不支持"); } - // 除了结合其余均按对象 + // 除了集合其余均按对象 return JSONObject.parseObject(result, resultType); } @@ -79,7 +96,7 @@ public class RestRemoteRequest { */ public String get(String remoteUri, Map headers) { try { - HttpEntity httpEntity = getHttpEntity(headers, null, null); + HttpEntity httpEntity = getHttpEntity(headers, null, null, null, null); ResponseEntity responseEntity = getRestTemplate(remoteUri).exchange(remoteUri, HttpMethod.GET, httpEntity, String.class); return getStringResponse(responseEntity); } catch (Exception e) { @@ -96,7 +113,7 @@ public class RestRemoteRequest { */ public String delete(String remoteUri, Map headers) { try { - HttpEntity httpEntity = getHttpEntity(headers, null, null); + HttpEntity httpEntity = getHttpEntity(headers, null, null, null, null); ResponseEntity responseEntity = getRestTemplate(remoteUri).exchange(remoteUri, HttpMethod.DELETE, httpEntity, String.class); return getStringResponse(responseEntity); } catch (Exception e) { @@ -114,7 +131,7 @@ public class RestRemoteRequest { public String post(String remoteUri, Map headers, Object jsonBody) { LOG.debug("Request POST Json: {}", jsonBody); try { - HttpEntity httpEntity = getHttpEntity(headers, null, jsonBody); + HttpEntity httpEntity = getHttpEntity(headers, null, null, null, jsonBody); ResponseEntity responseEntity = getRestTemplate(remoteUri).exchange(remoteUri, HttpMethod.POST, httpEntity, String.class); return getStringResponse(responseEntity); } catch (Exception e) { @@ -129,10 +146,14 @@ public class RestRemoteRequest { * @param headers * @return */ - public String post(String remoteUri, Map headers, MultiValueMap formVariableParams) { + public String post(String remoteUri, + Map headers, + Map fileMap, + Map fileInputStreamMap, + MultiValueMap formVariableParams) { LOG.debug("Request POST Form: {}", formVariableParams); try { - HttpEntity httpEntity = getHttpEntity(headers, formVariableParams, null); + HttpEntity httpEntity = getHttpEntity(headers, fileMap, fileInputStreamMap, formVariableParams, null); ResponseEntity responseEntity = getRestTemplate(remoteUri).exchange(remoteUri, HttpMethod.POST, httpEntity, String.class); return getStringResponse(responseEntity); } catch (Exception e) { @@ -149,7 +170,7 @@ public class RestRemoteRequest { */ public String put(String remoteUri, Map headers, Object jsonBody) { try { - HttpEntity httpEntity = getHttpEntity(headers, null, jsonBody); + HttpEntity httpEntity = getHttpEntity(headers, null, null, null, jsonBody); ResponseEntity responseEntity = getRestTemplate(remoteUri).exchange(remoteUri, HttpMethod.PUT, httpEntity, String.class); return getStringResponse(responseEntity); } catch (Exception e) { @@ -164,7 +185,11 @@ public class RestRemoteRequest { * @param jsonBody * @return */ - private HttpEntity getHttpEntity(Map headerMap, MultiValueMap formVariableParams, Object jsonBody) { + private HttpEntity getHttpEntity(Map headerMap, + Map fileMap, + Map fileInputStreamMap, + MultiValueMap formVariableParams, + Object jsonBody) { LOG.debug("Request Header: {}", headerMap); HttpEntity httpEntity; if (jsonBody != null) { @@ -175,16 +200,93 @@ public class RestRemoteRequest { } else { httpEntity = new HttpEntity(JSONObject.toJSONString(jsonBody), httpHeaders); } - } else if (formVariableParams != null) { + } else if (!fileMap.isEmpty() || !fileInputStreamMap.isEmpty() || !formVariableParams.isEmpty()) { HttpHeaders httpHeaders = getHttpHeaders(headerMap); - httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - httpEntity = new HttpEntity(formVariableParams, httpHeaders); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + if (!fileMap.isEmpty()) { + httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + setFileVariable(multiValueMap, fileMap); + } else if (!fileInputStreamMap.isEmpty()) { + httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + setFileInputStreamVariable(multiValueMap, fileInputStreamMap); + } else { + httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + } + if (!formVariableParams.isEmpty()) { + formVariableParams.forEach(multiValueMap::add); + } + httpEntity = new HttpEntity(multiValueMap, httpHeaders); } else { httpEntity = new HttpEntity(getHttpHeaders(headerMap)); } return httpEntity; } + /** + * 设置文件 + * + * @param multiValueMap + * @param fileMap + */ + private void setFileVariable(MultiValueMap multiValueMap, Map fileMap) { + try { + for (Map.Entry kv : fileMap.entrySet()) { + String key = kv.getKey(); + File file = kv.getValue(); + FileInputStream fileInputStream = new FileInputStream(file); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + // 1M + byte[] buf = new byte[1024 * 1000]; + for (int len = 0; (len = fileInputStream.read(buf)) > -1; ) { + byteArrayOutputStream.write(buf, 0, len); + } + ByteArrayResource fileAsResource = new ByteArrayResource(byteArrayOutputStream.toByteArray()) { + @Override + public String getFilename() { + return file.getName(); + } + + @Override + public long contentLength() { + return file.length(); + } + }; + multiValueMap.add(key, fileAsResource); + } + } catch (Exception e) { + throw new FileException(e); + } + } + + /** + * 设置文件 + * + * @param multiValueMap + * @param fileInputStreamMap + */ + private void setFileInputStreamVariable(MultiValueMap multiValueMap, Map fileInputStreamMap) { + try { + for (Map.Entry kv : fileInputStreamMap.entrySet()) { + String key = kv.getKey(); + RemoteFileInputStream remoteFileInputStream = kv.getValue(); + InputStreamResource inputStreamResource = new InputStreamResource(remoteFileInputStream.getInputStream()) { + @Override + public String getFilename() { + return remoteFileInputStream.getFileName(); + } + + @Override + public long contentLength() { + return remoteFileInputStream.getFileSize(); + } + }; + multiValueMap.add(key, inputStreamResource); + } + } catch (Exception e) { + throw new FileException(e); + } + } + /** * 得到HTTP请求头 * diff --git a/common/src/test/java/RemoteTest.java b/common/src/test/java/RemoteTest.java index 6f037f0c..c79d1a9e 100644 --- a/common/src/test/java/RemoteTest.java +++ b/common/src/test/java/RemoteTest.java @@ -3,17 +3,13 @@ import ink.wgink.annotation.rpc.rest.method.RemoteDeleteMethod; import ink.wgink.annotation.rpc.rest.method.RemoteGetMethod; import ink.wgink.annotation.rpc.rest.method.RemotePostMethod; import ink.wgink.annotation.rpc.rest.method.RemotePutMethod; -import ink.wgink.annotation.rpc.rest.params.RemoteJsonBodyParams; -import ink.wgink.annotation.rpc.rest.params.RemotePathParams; -import ink.wgink.annotation.rpc.rest.params.RemoteQueryParams; -import ink.wgink.annotation.rpc.rest.params.RemoteServerParams; +import ink.wgink.annotation.rpc.rest.params.*; import ink.wgink.common.rpc.rest.proxy.RestRemoteProxy; import ink.wgink.pojo.dtos.user.UserDTO; import ink.wgink.pojo.result.SuccessResult; import ink.wgink.pojo.result.SuccessResultList; -import java.util.ArrayList; -import java.util.HashMap; +import java.io.File; import java.util.List; import java.util.Map; @@ -48,43 +44,50 @@ public class RemoteTest { @RemoteDeleteMethod("/app/user-expand/delete-release/{userIds}") SuccessResult deleteRelease(@RemoteServerParams String remotePath, @RemotePathParams("userIds") String userIds); + + @RemotePostMethod("/api/file/v2/upload-file") + String file(@RemoteServerParams String remotePath, @RemoteFileParams("file") File file); } public static void main(String[] args) { String remotePath = "http://127.0.0.1:7008/study"; IDemo instance = RestRemoteProxy.getInstance(IDemo.class); - UserDTO userDTO = instance.getUser(remotePath, "e48e9c4a-995e-4061-abcd-a3c260c11333"); - System.out.println(userDTO); - System.out.println(); +// UserDTO userDTO = instance.getUser(remotePath, "e48e9c4a-995e-4061-abcd-a3c260c11333"); +// System.out.println(userDTO); +// System.out.println(); +// +// List userDTOs = instance.listUser(remotePath); +// System.out.println(userDTOs.size()); +// System.out.println(); +// +// SuccessResultList> successResultUserList = instance.listPageUser(remotePath, 1, 5); +// System.out.println(successResultUserList.getPage()); +// System.out.println(); +// +// Map requestBody = new HashMap<>(); +// requestBody.put("aaa", "aaa1"); +// SuccessResult successResult = instance.postRelease(remotePath, requestBody); +// System.out.println(successResult); +// System.out.println(); +// +// List> listBody = new ArrayList<>(); +// listBody.add(requestBody); +// SuccessResult successResult1 = instance.postListRelease(remotePath, listBody); +// System.out.println(successResult1); +// System.out.println(); +// +// requestBody.put("aaa", "aaa2"); +// SuccessResult successResult2 = instance.putRelease(remotePath, requestBody); +// System.out.println(successResult2); +// System.out.println(); +// +// SuccessResult successResult3 = instance.deleteRelease(remotePath, "abc_def_ghi"); +// System.out.println(successResult3); +// System.out.println(); - List userDTOs = instance.listUser(remotePath); - System.out.println(userDTOs.size()); - System.out.println(); - - SuccessResultList> successResultUserList = instance.listPageUser(remotePath, 1, 5); - System.out.println(successResultUserList.getPage()); - System.out.println(); - - Map requestBody = new HashMap<>(); - requestBody.put("aaa", "aaa1"); - SuccessResult successResult = instance.postRelease(remotePath, requestBody); - System.out.println(successResult); - System.out.println(); - - List> listBody = new ArrayList<>(); - listBody.add(requestBody); - SuccessResult successResult1 = instance.postListRelease(remotePath, listBody); - System.out.println(successResult1); - System.out.println(); - - requestBody.put("aaa", "aaa2"); - SuccessResult successResult2 = instance.putRelease(remotePath, requestBody); - System.out.println(successResult2); - System.out.println(); - - SuccessResult successResult3 = instance.deleteRelease(remotePath, "abc_def_ghi"); - System.out.println(successResult3); - System.out.println(); + File file = new File("/Users/wanggeng/Desktop/UploadFiles/files/20220413/b92bcd7e553d4074afd4b36efc3b0899.docx"); + String file1 = instance.file(remotePath, file); + System.out.println(file1); } }