實現spring HandlerMethodArgumentResolver
接口
經過使用@JsonArg
自定義註解來解析json數據(經過fastjson的jsonPath),支持多個參數(@RequestBody只支持單個參數
)java
自定義註解@JsonArg
@Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface JsonArg { /** * @see <a href="https://github.com/alibaba/fastjson/wiki/JSONPath">https://github.com/alibaba/fastjson/wiki/JSONPath</a> */ String value() default ""; }
參數解析器實現
@Slf4j public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver { private static final String JSONBODYATTRIBUTE = "JSON_REQUEST_BODY"; @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(JsonArg.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String body = getRequestBody(webRequest); String value = parameter.getParameterAnnotation(JsonArg.class).value(); if (StringUtils.isBlank(value)) { value = parameter.getParameterName(); } Object val = JSONPath.read(body, value); if (log.isDebugEnabled()) { log.debug("resolveArgument return class type:{}", val == null ? null : val.getClass().getName()); log.debug("value:{}", val); } if (val instanceof JSONObject) { return JSON.parseObject(((JSONObject) val).toJSONString(), parameter.getParameterType()); } if (val instanceof JSONArray) { ParameterizedType genericParameterType = (ParameterizedType) parameter.getGenericParameterType(); // 泛型參數可能有多個,如今只處理了一個 Type[] actualTypeArguments = genericParameterType.getActualTypeArguments(); String typeName = actualTypeArguments[0].getTypeName(); return JSON.parseArray(((JSONArray) val).toJSONString(), Class.forName(typeName)); } //TODO 未實現基本類型之間互相轉換 return val; } private String getRequestBody(NativeWebRequest webRequest) { HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); String jsonBody = (String) servletRequest.getAttribute(JSONBODYATTRIBUTE); if (jsonBody == null) { try { String body = IOUtils.toString(servletRequest.getInputStream(), StandardCharsets.UTF_8); servletRequest.setAttribute(JSONBODYATTRIBUTE, body); return body; } catch (Exception e) { log.error("read request body error:{}", e.getMessage()); throw new RuntimeException(e); } } return jsonBody; } }
配置
自定義參數解析器優先級低於spring提供的默認解析器,會被默認解析器處理git
@Configuration @EnableWebMvc // springboot 2.0實現 WebMvcConfigurer 接口 public class WebMvcConfigurer extends WebMvcConfigurerAdapter { /** * prioritize Custom ArgumentMethodHandlers */ @Autowired public void prioritizeCustomArgumentMethodHandlers(RequestMappingHandlerAdapter adapter) { List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(adapter.getArgumentResolvers()); List<HandlerMethodArgumentResolver> customResolvers = adapter.getCustomArgumentResolvers(); argumentResolvers.removeAll(customResolvers); argumentResolvers.addAll(0, customResolvers); adapter.setArgumentResolvers(argumentResolvers); } /** * registry argumentResolvers */ @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new JsonPathArgumentResolver()); } }
使用
@PostMapping("/test.do") public void test(@JsonArg String name) { log.debug("name:{}", name); }