UTF-8
diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml
index a0818acb..27d89f62 100644
--- a/sop-common/sop-service-common/pom.xml
+++ b/sop-common/sop-service-common/pom.xml
@@ -6,11 +6,11 @@
com.gitee.sop
sop-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
../pom.xml
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
jar
sop-service-common
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContext.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContext.java
new file mode 100644
index 00000000..20134dfd
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContext.java
@@ -0,0 +1,74 @@
+package com.gitee.sop.servercommon.bean;
+
+import java.util.Date;
+
+/**
+ * 获取开放平台请求参数。
+ * 可当做接口方法参数,泛型参数填业务参数类,如:
+ *
+ * @ApiMapping(value = "alipay.goods.get")
+ * public Goods getGoods(OpenRequest<GoodsParam> openRequest){...}
+ *
+ * 可通过OpenRequest openRequest = ServiceContext.getCurrentContext().getOpenRequest();
方式进行获取
+ * OpenContext
+ * OpenParam
+ * @author tanghc
+ *
+ */
+public interface OpenContext {
+
+ /**
+ * 返回appid
+ * @return 返回appid
+ */
+ String getAppId();
+
+ /**
+ * 返回业务参数json字符串
+ * @return 返回字符串业务参数
+ */
+ String getBizContent();
+
+ /**
+ * 返回业务对象
+ * @return 业务对象
+ */
+ T getBizObject();
+
+ /**
+ * 返回字符编码
+ * @return 如UTF-8
+ */
+ String getCharset();
+
+ /**
+ * 返回接口名
+ * @return 如:alipay.goods.get
+ */
+ String getMethod();
+
+ /**
+ * 返回版本号
+ * @return 如:1.0
+ */
+ String getVersion();
+
+ /**
+ * 返回参数格式化
+ * @return 如:json
+ */
+ String getFormat();
+
+ /**
+ * 返回签名类型
+ * @return 如:RSA2
+ */
+ String getSignType();
+
+ /**
+ * 返回时间戳
+ * @return
+ */
+ Date getTimestamp();
+
+}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java
new file mode 100644
index 00000000..138a4082
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/OpenContextImpl.java
@@ -0,0 +1,73 @@
+package com.gitee.sop.servercommon.bean;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Date;
+
+import static com.gitee.sop.servercommon.bean.ParamNames.API_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.APP_KEY_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.BIZ_CONTENT_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.CHARSET_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.FORMAT_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.SIGN_TYPE_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.TIMESTAMP_NAME;
+import static com.gitee.sop.servercommon.bean.ParamNames.VERSION_NAME;
+
+/**
+ * @author tanghc
+ */
+public class OpenContextImpl implements OpenContext {
+ private JSONObject jsonObject;
+ private T bizObject;
+
+ public OpenContextImpl(JSONObject jsonObject, Class> bizClass) {
+ this.jsonObject = jsonObject;
+ JSONObject bizJsonObj = this.jsonObject.getJSONObject(BIZ_CONTENT_NAME);
+ bizObject = (bizClass == null || bizJsonObj == null) ? null : (T) bizJsonObj.toJavaObject(bizClass);
+ }
+
+ @Override
+ public String getAppId() {
+ return jsonObject.getString(APP_KEY_NAME);
+ }
+
+ @Override
+ public T getBizObject() {
+ return bizObject;
+ }
+
+ @Override
+ public String getBizContent() {
+ return jsonObject.getString(BIZ_CONTENT_NAME);
+ }
+
+ @Override
+ public String getCharset() {
+ return jsonObject.getString(CHARSET_NAME);
+ }
+
+ @Override
+ public String getMethod() {
+ return jsonObject.getString(API_NAME);
+ }
+
+ @Override
+ public String getVersion() {
+ return jsonObject.getString(VERSION_NAME);
+ }
+
+ @Override
+ public String getFormat() {
+ return jsonObject.getString(FORMAT_NAME);
+ }
+
+ @Override
+ public String getSignType() {
+ return jsonObject.getString(SIGN_TYPE_NAME);
+ }
+
+ @Override
+ public Date getTimestamp() {
+ return jsonObject.getDate(TIMESTAMP_NAME);
+ }
+}
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceContext.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceContext.java
index 73877b2d..41e22ee5 100644
--- a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceContext.java
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/bean/ServiceContext.java
@@ -12,6 +12,7 @@ public class ServiceContext extends ConcurrentHashMap {
public static final String REQUEST_KEY = "request";
public static final String RESPONSE_KEY = "response";
+ public static final String OPEN_CONTEXT_KEY = "openContext";
protected static Class extends ServiceContext> contextClass = ServiceContext.class;
protected static final ThreadLocal extends ServiceContext> THREAD_LOCAL = new ThreadLocal() {
@@ -30,6 +31,14 @@ public class ServiceContext extends ConcurrentHashMap {
super();
}
+ public void setOpenContext(OpenContext> openContext) {
+ this.set(OPEN_CONTEXT_KEY, openContext);
+ }
+
+ public OpenContext getOpenContext() {
+ return (OpenContext) this.get(OPEN_CONTEXT_KEY);
+ }
+
public Locale getLocale() {
HttpServletRequest request = getRequest();
if (request == null) {
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 ddf3d09b..38982d29 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
@@ -1,9 +1,13 @@
package com.gitee.sop.servercommon.param;
-import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.servercommon.annotation.ApiAbility;
import com.gitee.sop.servercommon.annotation.ApiMapping;
-import com.gitee.sop.servercommon.bean.ParamNames;
+import com.gitee.sop.servercommon.bean.OpenContext;
+import com.gitee.sop.servercommon.bean.OpenContextImpl;
+import com.gitee.sop.servercommon.bean.ServiceContext;
+import com.gitee.sop.servercommon.util.OpenUtil;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -14,6 +18,9 @@ import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -23,6 +30,7 @@ import java.util.concurrent.ConcurrentHashMap;
*
* @author tanghc
*/
+@Slf4j
public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
private final Map argumentResolverCache = new ConcurrentHashMap<>(256);
@@ -69,14 +77,38 @@ public class ApiArgumentResolver implements SopHandlerMethodArgumentResolver {
* @return 没有返回null
*/
protected Object getParamObject(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) {
- String bizContent = nativeWebRequest.getParameter(ParamNames.BIZ_CONTENT_NAME);
- Object bizObj = null;
- if (bizContent != null) {
- Class> parameterType = methodParameter.getParameterType();
- bizObj = JSON.parseObject(bizContent, parameterType);
+ HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
+ JSONObject requestParams = OpenUtil.getRequestParams(request);
+ Class> parameterType = methodParameter.getParameterType();
+ // 方法参数类型
+ Class> bizObjClass = parameterType;
+ boolean isOpenRequestParam = parameterType == OpenContext.class;
+ // 参数是OpenRequest,则取OpenRequest的泛型参数类型
+ if (isOpenRequestParam) {
+ bizObjClass = this.getOpenRequestGenericParameterClass(methodParameter);
}
+ OpenContext openContext = new OpenContextImpl(requestParams, bizObjClass);
+ ServiceContext.getCurrentContext().setOpenContext(openContext);
+ Object bizObj = openContext.getBizObject();
this.bindUploadFile(bizObj, nativeWebRequest);
- return bizObj;
+ return isOpenRequestParam ? openContext : bizObj;
+ }
+
+ /**
+ * 获取泛型参数类型
+ * @param methodParameter 参数
+ * @return 返回泛型参数class
+ */
+ protected Class> getOpenRequestGenericParameterClass(MethodParameter methodParameter) {
+ Type genericParameterType = methodParameter.getGenericParameterType();
+ Class> bizObjClass = null;
+ if (genericParameterType instanceof ParameterizedType) {
+ Type[] params = ((ParameterizedType) genericParameterType).getActualTypeArguments();
+ if (params != null && params.length >= 1) {
+ bizObjClass = (Class>) params[0];
+ }
+ }
+ return bizObjClass;
}
/**
diff --git a/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
new file mode 100644
index 00000000..10f590c1
--- /dev/null
+++ b/sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/OpenUtil.java
@@ -0,0 +1,85 @@
+package com.gitee.sop.servercommon.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author tanghc
+ */
+@Slf4j
+public class OpenUtil {
+
+ private static final String CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded";
+ private static final String CONTENT_TYPE_JSON = "application/json";
+ private static final String CONTENT_TYPE_TEXT = "text/plain";
+
+ private static final String UTF8 = "UTF-8";
+
+ /**
+ * 从request中获取参数。如果提交方式是application/x-www-form-urlencoded,则组装成json格式。
+ *
+ * @param request request对象
+ * @return 返回json
+ * @throws IOException
+ */
+ public static JSONObject getRequestParams(HttpServletRequest request) {
+ String requestJson = "{}";
+ String contentType = request.getContentType();
+ if (StringUtils.isBlank(contentType)) {
+ return new JSONObject();
+ }
+ contentType = contentType.toLowerCase();
+ if (StringUtils.containsAny(contentType, CONTENT_TYPE_JSON, CONTENT_TYPE_TEXT)) {
+ try {
+ requestJson = IOUtils.toString(request.getInputStream(), UTF8);
+ } catch (IOException e) {
+ log.error("获取文本数据流失败", e);
+ }
+ } else if (StringUtils.containsAny(contentType, CONTENT_TYPE_URLENCODED)) {
+ Map params = convertRequestParamsToMap(request);
+ requestJson = JSON.toJSONString(params);
+ }
+ return JSON.parseObject(requestJson);
+ }
+
+ /**
+ * request中的参数转换成map
+ *
+ * @param request request对象
+ * @return 返回参数键值对
+ */
+ public static Map convertRequestParamsToMap(HttpServletRequest request) {
+ Map paramMap = request.getParameterMap();
+ if(paramMap == null || paramMap.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map retMap = new HashMap(paramMap.size());
+
+ Set> entrySet = paramMap.entrySet();
+
+ for (Map.Entry entry : entrySet) {
+ String name = entry.getKey();
+ String[] values = entry.getValue();
+ if (values.length == 1) {
+ retMap.put(name, values[0]);
+ } else if (values.length > 1) {
+ retMap.put(name, values);
+ } else {
+ retMap.put(name, "");
+ }
+ }
+
+ return retMap;
+ }
+
+}
diff --git a/sop-example/sop-auth/pom.xml b/sop-example/sop-auth/pom.xml
index 0baa41b7..f705c20e 100644
--- a/sop-example/sop-auth/pom.xml
+++ b/sop-example/sop-auth/pom.xml
@@ -26,7 +26,7 @@
com.gitee.sop
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml
index e758cd4a..a01339ba 100644
--- a/sop-example/sop-book/sop-book-web/pom.xml
+++ b/sop-example/sop-book/sop-book-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
com.gitee.sop
diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml
index f90b7570..9198b804 100644
--- a/sop-example/sop-easyopen/pom.xml
+++ b/sop-example/sop-easyopen/pom.xml
@@ -29,7 +29,7 @@
com.gitee.sop
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml
index 5502e361..b7ad30f7 100644
--- a/sop-example/sop-springmvc/pom.xml
+++ b/sop-example/sop-springmvc/pom.xml
@@ -20,7 +20,7 @@
com.gitee.sop
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml
index 9ab14a4c..1f09cd60 100644
--- a/sop-example/sop-story/sop-story-web/pom.xml
+++ b/sop-example/sop-story/sop-story-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.13.1-SNAPSHOT
+ 1.13.2-SNAPSHOT
com.gitee.sop
diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java
index 5ea2f8ab..e15f79e8 100644
--- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java
+++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/AlipayController.java
@@ -2,6 +2,8 @@ package com.gitee.sop.storyweb.controller;
import com.gitee.sop.servercommon.annotation.ApiAbility;
import com.gitee.sop.servercommon.annotation.ApiMapping;
+import com.gitee.sop.servercommon.bean.OpenContext;
+import com.gitee.sop.servercommon.bean.ServiceContext;
import com.gitee.sop.story.api.domain.Story;
import com.gitee.sop.storyweb.controller.param.StoryParam;
import io.swagger.annotations.Api;
@@ -14,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
-import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
@@ -97,15 +98,15 @@ public class AlipayController {
/**
* 参数绑定
* @param story 对应biz_content中的内容,并自动JSR-303校验
- * @param request
* @return
*/
@ApiOperation(value = "获取故事信息", notes = "说明接口的详细信息,介绍,用途,注意事项等。")
@ApiMapping(value = "alipay.story.find")
- public StoryVO getStory2(StoryParam story, HttpServletRequest request) {
+ public StoryVO getStory2(StoryParam story) {
log.info("获取故事信息参数, story: {}", story);
// 获取其它参数
- String app_id = request.getParameter("app_id");
+ OpenContext openContext = ServiceContext.getCurrentContext().getOpenContext();
+ String app_id = openContext.getAppId();
StoryVO storyVO = new StoryVO();
storyVO.id = 1L;
storyVO.name = "白雪公主, app_id:" + app_id;
diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/PostJsonController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/PostJsonController.java
new file mode 100644
index 00000000..0bc5e45a
--- /dev/null
+++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/PostJsonController.java
@@ -0,0 +1,41 @@
+package com.gitee.sop.storyweb.controller;
+
+import com.gitee.sop.servercommon.annotation.ApiMapping;
+import com.gitee.sop.servercommon.bean.ServiceContext;
+import com.gitee.sop.servercommon.bean.OpenContext;
+import com.gitee.sop.story.api.domain.Story;
+import com.gitee.sop.storyweb.controller.param.StoryParam;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author tanghc
+ */
+@RestController
+public class PostJsonController {
+
+ /**
+ * 演示客户端使用json方式请求(application/json)
+ * @param param
+ * @return
+ */
+ @ApiMapping("demo.post.json")
+ public Story postJson(StoryParam param) {
+ // 获取开放平台请求参数
+ OpenContext openContext = ServiceContext.getCurrentContext().getOpenContext();
+ List