实现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. Python 对于分表的操作

    在操作数据库的业务里,我们系统采用了orm框架 ,避免了过多的写sql,利用实体对数据库进行操作 需求: 账户系统里的account表是进行了分表,分表规则为accountid进行20取模,测试环境分 ...

  2. 洛谷 P1801 黑匣子 题解

    题面 离线处理: 大体思路就是将数组排序,然后对于第k次询问把不可行的数打上标记,然后从头开始寻找第k个没打标记的点的值(排序后的数组保证了它是第k小的). 实现方法:首先离散化原始数组,得到数组fi ...

  3. c++ Convert struct to bytes

    D:\stock\Tskingfromgoogle\src\NetTS\TW.cpp Convert struct  to bytes //Convert struct to bytes 2019/0 ...

  4. Luogu P2839 [国家集训队]middle

    题目 首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\). 对于询问\(a,b,c,d\),二分完\( ...

  5. 赛道修建 NOIP 2018 d1t3

    题目大意 最小值最大 考虑二分 二分答案 判断能不能构成m条路径 很明显满足单调性 可行 思考如何判断 对于一个节点 它的儿子会传上来一些路径 这些路径只有三种处理方式 一.传上去(只能传一条) 二. ...

  6. phpstorm配合xdebug进行本地调试代码

    笔者在使用的环境是wamp3.1.6和phpstorm2018 ,php选择的环境是php7.2 1. 在php.ini中添加xdebug的配置信息 首先建议是先找对php.ini的位置,可以在php ...

  7. list 小练习

    li = ["alex", "WuSir", "ritian", "barry", "wenzhou" ...

  8. Java基础——Modifier类

    转自:https://www.cnblogs.com/baiqiantao/p/7478523.html   反射 Reflect Modifier 修饰符工具类 在查看反射相关的Class.Fiel ...

  9. npm 命令行基本操作

    npm命令选项选项            说明search 在存储库中查找模块包 npm search expressinstall  使用在存储库或本地位置上的一个package.json文件来安装 ...

  10. atxserver2-rethinkdb的一些基础操作

    因为我只需要一些基础操作就好,所以在web端的 Data Explorer 操作,首先启动  rethinkdb.exe,然后登陆网页端, 下面是一些基础操作的语句, 一.创建表r.db(‘atxse ...