From 2270c508864686943d05ae0645d805bfdfb88d52 Mon Sep 17 00:00:00 2001 From: tanghc Date: Wed, 2 Sep 2020 09:50:33 +0800 Subject: [PATCH] 4.0.3 --- .../param/ApiArgumentResolver.java | 12 ++ .../param/ByteArrayStreamWrapper.java | 53 +++++++++ .../param/MyServletRequestWrapper.java | 106 ++++++++++++++++++ .../Example1001_BaseController.java | 7 +- 4 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ByteArrayStreamWrapper.java create mode 100644 sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/MyServletRequestWrapper.java diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ApiArgumentResolver.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ApiArgumentResolver.java index 4e94e389..0cfcb3a5 100644 --- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ApiArgumentResolver.java +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ApiArgumentResolver.java @@ -13,6 +13,7 @@ import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.WebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; @@ -25,6 +26,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ServletRequestMetho import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.InputStream; import java.io.OutputStream; @@ -117,6 +119,10 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver { , NativeWebRequest nativeWebRequest , WebDataBinderFactory webDataBinderFactory ) throws Exception { + nativeWebRequest = new SopServletWebRequest( + (HttpServletRequest) nativeWebRequest.getNativeRequest(), + (HttpServletResponse) nativeWebRequest.getNativeResponse() + ); if (openApiParams.contains(methodParameter)) { Object paramObj = this.getParamObject(methodParameter, nativeWebRequest); if (paramObj != null) { @@ -221,4 +227,10 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver { public void setParamValidator(ParamValidator paramValidator) { this.paramValidator = paramValidator; } + + private static final class SopServletWebRequest extends ServletWebRequest { + public SopServletWebRequest(HttpServletRequest request, HttpServletResponse response) { + super(new MyServletRequestWrapper(request), response); + } + } } \ No newline at end of file diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ByteArrayStreamWrapper.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ByteArrayStreamWrapper.java new file mode 100644 index 00000000..64ede5fa --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ByteArrayStreamWrapper.java @@ -0,0 +1,53 @@ +package com.gitee.sop.servercommon.param; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import java.io.IOException; + +/** + * byte数组流包装 + * + * @author tanghc + */ +public class ByteArrayStreamWrapper extends ServletInputStream { + + private byte[] data; + private int idx = 0; + + /** + * Creates a new ByteArrayStreamWrapper instance. + * + * @param data a byte[] value + */ + public ByteArrayStreamWrapper(byte[] data) { + if (data == null) { + data = new byte[0]; + } + this.data = data; + } + + @Override + public int read() throws IOException { + if (idx == data.length) { + return -1; + } + // I have to AND the byte with 0xff in order to ensure that it is returned as an unsigned integer + // the lack of this was causing a weird bug when manually unzipping gzipped request bodies + return data[idx++] & 0xff; + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } +} \ No newline at end of file diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/MyServletRequestWrapper.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/MyServletRequestWrapper.java new file mode 100644 index 00000000..0c14c6eb --- /dev/null +++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/MyServletRequestWrapper.java @@ -0,0 +1,106 @@ +package com.gitee.sop.servercommon.param; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; + +/** + * 包装HttpServletRequest + */ +@Slf4j +public class MyServletRequestWrapper extends HttpServletRequestWrapper { + + private final byte[] body; + private final Map parameterMap; + + public MyServletRequestWrapper(HttpServletRequest request) { + super(request); + // 先缓存请求参数,不然获取不到,原因: + // 调用getInputStream方法时,usingInputStream会变成true + // 之后再调用request.getParameterMap(),就一直返回空map + // 因此要先调用request.getParameterMap()缓存起来 + // 详见org.apache.catalina.connector.Request.parseParameters()中 + // if (usingInputStream || usingReader) { + // success = true; + // return; + // } + parameterMap = request.getParameterMap(); + try { + body = IOUtils.toByteArray(super.getInputStream()); + } catch (IOException e) { + log.error("cache body error, url:{}",request.getRequestURI(), e); + throw new RuntimeException("cache body error", e); + } + } + + @Override + public Map getParameterMap() { + return parameterMap; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new ByteArrayStreamWrapper(body); + } + + /** + * byte数组流包装 + * + * @author tanghc + */ + public static class ByteArrayStreamWrapper extends ServletInputStream { + + private byte[] data; + private int idx = 0; + + /** + * Creates a new ByteArrayStreamWrapper instance. + * + * @param data a byte[] value + */ + public ByteArrayStreamWrapper(byte[] data) { + if (data == null) { + data = new byte[0]; + } + this.data = data; + } + + @Override + public int read() throws IOException { + if (idx == data.length) { + return -1; + } + // I have to AND the byte with 0xff in order to ensure that it is returned as an unsigned integer + // the lack of this was causing a weird bug when manually unzipping gzipped request bodies + return data[idx++] & 0xff; + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } +} \ No newline at end of file diff --git a/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java index b2eb6e2c..e056c99e 100644 --- a/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java +++ b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1001_BaseController.java @@ -12,7 +12,9 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.nio.charset.StandardCharsets; @@ -83,9 +85,10 @@ public class Example1001_BaseController { // 忽略验证 @ApiOperation(value = "忽略签名验证", notes = "忽略签名验证") @Open(value = "story.get.ignore", ignoreValidate = true) - @RequestMapping("/get/ignore/v1") - public StoryResult getStory21(StoryParam story) { + @RequestMapping(value = "/get/ignore/v1", method = {RequestMethod.GET, RequestMethod.POST}) + public StoryResult getStory21(@RequestBody StoryParam story) { StoryResult result = new StoryResult(); + result.setId((long) story.getId()); result.setName(story.getName() + ", ignoreValidate = true"); return result; }