实现spring HandlerMethodArgumentResolver
接口
通过使用@JsonArg
自定义注解来解析json数据(通过fastjson的jsonPath),支持多个参数(@RequestBody只支持单个参数
)
自定义注解@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提供的默认解析器,会被默认解析器处理
@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);
}