实现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);
}

自定义springmvc参数解析器的更多相关文章

  1. 一步一步自定义SpringMVC参数解析器

    随心所欲,自定义参数解析器绑定数据. 题图:from Zoommy 干货 SpringMVC解析器用于解析request请求参数并绑定数据到Controller的入参上. 自定义一个参数解析器需要实现 ...

  2. 自定义HandlerMethodArgumentResolver参数解析器和源码分析

    在初学springmvc框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequest或HttpServletRe ...

  3. 实现自定义的参数解析器——HandlerMethodArgumentResolver

    1.为什么需要自己实现参数解析器 我们都知道在有注解的接口方法中加上@RequestBody等注解,springMVC会自动的将消息体等地方的里面参数解析映射到请求的方法参数中. 如果我们想要的信息不 ...

  4. Spring boot中自定义Json参数解析器

    转载请注明出处... 一.介绍 用过springMVC/spring boot的都清楚,在controller层接受参数,常用的都是两种接受方式,如下 /** * 请求路径 http://127.0. ...

  5. SpringMVC自动封装List对象 —— 自定义参数解析器

    前台传递的参数为集合对象时,后台Controller希望用一个List集合接收数据. 原生SpringMVC是不支持,Controller参数定义为List类型时,接收参数会报如下错误: org.sp ...

  6. springmvc 源码分析(三) -- 自定义处理器映射器和自定义处理器适配器,以及自定义参数解析器 和错误跳转自定页面

    测试环境搭建: 本次搭建是基于springboot来实现的,代码在码云的链接:https://gitee.com/yangxioahui/thymeleaf.git DispatcherServlet ...

  7. SpringMVC 自定义参数解析器.

    一.简述 有没有想过像 @RequestParam.@RequestBody 这些注解的工作原理呢?为什么 form 表单.application/json 的参数能够直接封装进 Bean 对象中呢? ...

  8. SpringBoot系列教程web篇之如何自定义参数解析器

    title: 190831-SpringBoot系列教程web篇之如何自定义参数解析器 banner: /spring-blog/imgs/190831/logo.jpg tags: 请求参数 cat ...

  9. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

随机推荐

  1. windows jenkins 发布 springboot项目脚本

    windows  jenkins 发布 springboot项目脚本 1.关闭现有程序 (按端口关闭) [与按应用关闭 二选一] @echo off for /f "tokens=1-5&q ...

  2. HDU 2809 God of War (状压DP)

    God of War Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. TIDB学习资料

    TiDB 源码阅读系列文章(一)序 TiDB 源码阅读系列文章(二)初识 TiDB 源码 TiDB 源码阅读系列文章(三)SQL 的一生 TiDB 源码阅读系列文章(四)Insert 语句概览 TiD ...

  4. 小记----采集之Xpath

    一.XPATH简介   Xpath是XML路径语言,它是一种确定XML文档中某部分位置的语言 二.XPATH语法  XPATH使用路径表达式在XML文档中选取节点.节点是通过沿着路径或者step来选取 ...

  5. MySQL表存在外键关系无法清空数据的解决方案

    先 SET FOREIGN_KEY_CHECKS=0; 然后delete删除,再 SET FOREIGN_KEY_CHECKS=1;

  6. RabbitMQ入门教程(九):首部交换机Headers

    原文:RabbitMQ入门教程(九):首部交换机Headers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...

  7. vue-搜索功能-实时监听搜索框的输入,N毫秒请求一次数据

    <template> <div class="search-box"> <input class="box" :placehold ...

  8. java 约瑟夫问题

    题目: 给定一个数组及数组的长度,另外给定一个数m,从数组的第一个元素出发,数到第m个元素出列(如果到最后则回到第一个元素).出列元素的值作为m的新值,从出列元素的下一元素继续开始数下去,直到所有元素 ...

  9. neutron网络服务部署

    控制节点执行 #第一步 登陆数据库 mysql -u root -p #导入neutron这个库 CREATE DATABASE neutron; #创建neutron这个用户和密码,并允许本地登陆和 ...

  10. httprunner如何提取数据串联上下游接口

    httprunner进行接口测试时,从上一个接口提取参数传递给下游接口,如何获取数据里最后一个值? 突然被学员问道一个httprunner的问题,惭愧的是大猫之前没有是通过httprunner,又不好 ...