关键词:
springboot自定义参数解析器
1.前言
1.springMVC是如何把参数解析完毕后注入到controller方法参数上的呢?在javaweb阶段,我们都学过使用HttpServletRequest这个对象获取参数,比如 request.getParameter(parameterName);那么springMVC其实也是用于这个来进行获取原始的参数的。
比如:@RequestBody,@RequestParam注解等
2.springMVC参数解析器
在请求经过原生的servlet过后,会将请求通过DispatchServlet将请求分发下去,然后执行到InvocableHandlerMethod.invokeForRequest()方法的时候,其中 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); 这一行就是获取请求参数的。最终会来到getMethodArgumentValues()这个方法,这个方法,最关键的其中一行就是 this.resolvers.supportsParameter(parameter) ,这个会找所有实现了 HandlerMethodArgumentResolver 接口的bean,挨个循环调用supportsParameter()这个方法,看看那个解析器能解析这个参数。如果能解析,然后执行 this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); 解析完获取到指定的参数然后返回。最后会根据请求路径找到对应的controller的method对象,然后通过反射的方式调用,并且把解析完毕的参数传递进去,这样走到我们controller的时候,controller参数就被绑定上了。
通过debug可以看到 最开始的参数解析器有31个,其中标记红色的那个是我自定义的。
HandlerMethodArgumentResolver接口就是参数解析器,supportsParameter表示是否支持解析,resolveArgument()是执行具体的解析逻辑。
public interface HandlerMethodArgumentResolver
/**
* Whether the given @linkplain MethodParameter method parameter is
* supported by this resolver.
* @param parameter the method parameter to check
* @return @code true if this resolver supports the supplied parameter;
* @code false otherwise
*/
boolean supportsParameter(MethodParameter parameter);
/**
* Resolves a method parameter into an argument value from a given request.
* A @link ModelAndViewContainer provides access to the model for the
* request. A @link WebDataBinderFactory provides a way to create
* a @link WebDataBinder instance when needed for data binding and
* type conversion purposes.
* @param parameter the method parameter to resolve. This parameter must
* have previously been passed to @link #supportsParameter which must
* have returned @code true.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating @link WebDataBinder instances
* @return the resolved argument value, or @code null if not resolvable
* @throws Exception in case of errors with the preparation of argument values
*/
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
可以看到这个接口有很多的实现类,比如::@RequestBody,@RequestParam,@CookieValue等注解,都是有对应实现的
3.如何自定义参数解析器
因为我们知道POST请求使用@RequestBody是可以接收json格式的数据直接绑定到对应的参数名对象上,而GET请求是不可以的,那接下来我们就实现一个@JsonParam注解,然后让GET请求也支持json格式的参数传递。
@JsonParam:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JsonParam
String value() default "";
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
实现HandlerMethodArgumentResolver接口,指定遇到什么参数的时候进行解析,每解析controller方法参数的每一项时都会调用HandlerMethodArgumentResolver的supportsParameter和resolveArgument方法进行解析
public class GetQueryJsonParamResolver implements HandlerMethodArgumentResolver
@Override
public boolean supportsParameter(MethodParameter parameter)
Annotation[] annotations = parameter.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++)
Annotation item = annotations[i];
if (item.annotationType().equals(JsonParam.class))
return true;
return false;
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
String parameterName = parameter.getParameterName();
Annotation[] annotations = parameter.getParameterAnnotations();
String params = request.getParameter(parameterName);
if (StringUtils.isBlank(params))
for (Annotation item : annotations)
if (item instanceof JsonParam)
JsonParam param = (JsonParam) item;
params = request.getParameter(param.value());
if (StringUtils.isBlank(params))
params = param.defaultValue();
if (StringUtils.isBlank(params) && param.required() || params.equals(ValueConstants.DEFAULT_NONE))
throw new RuntimeException(parameterName + ":不能为空");
Class<?> parameterType = parameter.getParameterType();
Object bean = JSONUtil.toBean(params, parameterType);
return bean;
最后我们在配置类中添加参数解析器 添加完毕后,参数解析器从原来的31个就会变成32个,到解析参数的时候就会走到我们自己写的参数解析器哪里,解析完毕后把对应的参数返回去。
@Configuration
public class StaticConfig implements WebMvcConfigurer
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)
resolvers.add(new GetQueryJsonParamResolver());
4测试
最后我们在controller上写一个方法进行测试即可,可以看到我们传递的参数被成功的解析到
@GetMapping("/requestParam")
public void requestParam(@JsonParam UserInfo userInfo, HttpServletResponse response)
AjaxResult<UserInfo> ajaxResult = new AjaxResult<>(200,"操作成功",0,"请求成功",userInfo);
ResponseUtil.response(response,ajaxResult);
esult ajaxResult = new AjaxResult<>(200,“操作成功”,0,“请求成功”,userInfo);
ResponseUtil.response(response,ajaxResult);
springboot一篇搞定(cookiesession跳转内容协商converter解析器thymeleaf)(代码片段)
文章目录Cookie处理设置cookie获取cookie删除Cookie小结Session处理作用域Request参数设置页面跳转通过Response通过Request内容协商Json返回XML返回基本原理说明自定义类型转换器通过特定参数获取返回类型参数解析原理解析示例自定义解析... 查看详情
springmvcargumentresoler(方法参数解析器)(代码片段)
例:先创建自定义注解//@Target(ElementType.PARAMETER)//在运行时生效//RetentionPolicy.RUNTIME给方法使用@Retention(RetentionPolicy.RUNTIME)public@interfaceCurrentUser去定义自定义注解的规则packagecom.lanou.demo.resolvers;importcom.lan 查看详情
springmvc自定义参数解析器/类型转换器(代码片段)
概述有些时候我们需要对请求的入参做自定义的处理,比较常见的就是字符串反序列化时间类型了,常用的像@DateTimeFormat注解,但是这需要在每个入参的属性上都加上这个注解,比较费手,那么我们就可以... 查看详情
实战篇:解决swagger和自定义参数解析器的功能冲突(代码片段)
...参数解析器RequestResponseBodyMethodProcessor优先级高于我们自定义的参数解析器,所以为了正常使用,需要将@RequestBody 注解去掉。这就会导致swagger无法识别正确的参数类型,将请求体识别为QueryParams,然后将body展... 查看详情
阿昌教你自定义拦截器&自定义参数解析器&自定义包装httpservletrequest(代码片段)
...全框架,但是发现,他根本没有使用,而是自定义了一系列的拦截器&过滤器来实现安全的校验。比如,通过自定义注解来决 查看详情
springmvc自定义方法属性解析器(代码片段)
使用场景例子:用户登陆系统一般会往Session里放置一个VO对象,然后在controller里会来获取用户的userId等信息。之前的写法是:@SessionAttributes配合@ModelAttribute来进行参数值的注入,但这样需要写2个注解,其中SessionAttributes加在类... 查看详情
handlermethodargumentresolver用于统一获取当前登录用户—转(代码片段)
...义方法参数解析器 3.4配置MVC 环境:SpringBoot2.0.4.RELEASE需求:很多Controller方法,刚进来要先获取当前登录用户的信息,以便做后续的用户相关操作。准备工作:前端每次请求都传token,后端封装一方法tokenUtils... 查看详情
springbootyml配置参数加密,jasypt自定义解密器(代码片段)
...解决这些事情,那么也顺便给还未了解的大伙普及一下。Springbootyml配置参数数据加密(数据加密篇一)_默默不代表沉默-CSDN博客_springboot接口加密SpringbootAOP实现指定敏感字段数据加密(数据加密篇二)_默默不代表沉默-CSDN博客&n... 查看详情
csharpjson自定义字段合同解析器(代码片段)
springboot下validation自定义验证注解(简单实现)(代码片段)
首先引入validation依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>自定义解析器importjavax.validat 查看详情
ruby自定义时间戳的时间解析器(代码片段)
java为owasp解析器创建自定义清理程序(代码片段)
springboot2----定制化原理(代码片段)
定制化原理定制化的常见方式原理分析套路定制化的常见方式修改配置文件;xxxxxCustomizer;编写自定义的配置类xxxConfiguration;+@Bean替换、增加容器中默认组件;视图解析器自定义异常视图解析器的演示:Web应... 查看详情
springmvc学习笔记2.1《自定参数解析handlermethodargumentresolver》(代码片段)
SpringMVC学习笔记2.1《自定参数解析HandlerMethodArgumentResolver》自定义对象解析Hero类型参数注册解析器参考资料自定义对象@DatapublicclassHeroprivateLongid;privateStringname;privateintage;privateList<Poem>poems;publicHero(Stringna 查看详情
springmvc学习笔记2.1《自定参数解析handlermethodargumentresolver》(代码片段)
SpringMVC学习笔记2.1《自定参数解析HandlerMethodArgumentResolver》自定义对象解析Hero类型参数注册解析器参考资料自定义对象@DatapublicclassHeroprivateLongid;privateStringname;privateintage;privateList<Poem>poems;publicHero(Stringna 查看详情
springboot中集成参数校验(代码片段)
SpringBoot中集成参数校验引入依赖自定义参数校验创建自定义注解自定义校验逻辑在校验对象的属性上加上注解分组校验定义分组接口在UserVO对象参数分配分组在需要参数校验的方法指定分组SprinBoot集成参数校验Validator,以及... 查看详情
请求参数的自定义 Spring 注释 - 从未调用自定义解析器
】请求参数的自定义Spring注释-从未调用自定义解析器【英文标题】:CustomSpringannotationforrequestparameters-customresolverneverinvoked【发布时间】:2018-08-0601:41:00【问题描述】:我在我的项目中实现了自定义注解,但从未调用实现的方法... 查看详情
阿昌教你自定义拦截器&自定义参数解析器&自定义包装httpservletrequest(代码片段)
...全框架,但是发现,他根本没有使用,而是自定义了一系列的拦截器&过滤器来实现安全的校验。比如,通过自定义注解来决定这个资源是否需要用户登录才能够访问。在项目中我发现的自定义注解有三个@Log... 查看详情