databinder

环境:Springboot2.4.12

简介

@Controller或@ControllerAdvice类可以使用@InitBinder方法来初始化WebDataBinder的实例,这可以:

将请求参数(即表单或查询数据)绑定到模型对象。将基于字符串的请求值(如请求参数、路径变量、头、cookie等)转换为控制器方法参数的目标类型。渲染HTML表单时,将模型对象的值格式化为字符串值。

@InitBinder方法可以注册特定于控制器的ja.bean.PropertyEditor Spring转换器和格式化程序组件。此外,可以使用MVC配置在全局共享的FormattingConversionService中注册转换器和格式化程序类型。请参考Spring中自定义数据类型转换的详细说明。

除了@ModelAttribute(命令对象)参数之外,@InitBinder方法支持许多与@RequestMapping方法相同的参数。通常,它们是用WebDataBinder参数(用于注册)和一个void返回值声明的。

应用示例

@ rest controller @ request mapping(& # 34;/demos & # 34;)public class demo controller { @ init binder//1 public void bind(web databinder binder){//2 binder . registercustomeditor(long . class,new PropertyEditorSupport(){//3 @ Override public void setas text(String text)抛出IllegalArgumentException { setValue(long . value of(text)+666 l);} }) ;} @ get mapping(& # 34;/index & # 34;)公共对象索引(长id){ return & # 34;索引-& # 34;+id;}}注意以下几点:

使用@InitBinder注解接收WebDataBinder参数注册自定义的转换器方法返回值必须是void

在上面的示例中,注册了一个类型转换器来将字符串转换为长类型,并在原始值的基础上添加了666L。

原理解读HandlerAdapter执行

公共类RequestMappingHandlerAdapter扩展AbstractHandlerMethodAdapter实现BeanFactoryAware,InitializingBean { protected modeland view invokeHandlerMethod(http servlet request,HttpServletResponse response,Handler methodHandler方法)throw exception {/…//在这里,我们会找到当前正在执行的控制器中定义的所有由@InitBinder注释的方法:web databinder factory = get databinder factory(Handler method);servletinvocablehandler method invokablemethod = createinvokablehandler method(handler method);invokablemethod . invokeendhandhandle(webRequest,M container);// …}} Servlet invocalehandlermethod执行公共类ServletInvocableHandlerMethod扩展invocalehandler method { public void invocalehandler(Servlet webreques Twebrequest,modelandview容器mcontainer,object…provided args)throws exception {//调用父类方法object return value = invokeforrequest(webrequest,mcontainer,provided args);//…} }//执行父类方法,调用公共类invocatable handler方法{ public object invoke forrequest(native webrequest请求,@ Nullable ModelAndViewContainer M container,Object…providedArgs)抛出异常{ Object[]args = getmethoargumentvalues(request,mContainer,provide dargs);return doin voke(args);}保护对象[]getmethoargumentvalues(nativebrequest请求,@ Nullable ModelAndViewContainer M container,Object…providedArgs)引发异常{ Object[]args = new Object[parameters . length];for(int I = 0;我& lt参数.长度;I++) {//解析参数args[I]= this . resolvers . resolve argument(parameter,mcontainer,request,this . databinder factory);}}}参数解析在上面的控制器示例中,参数的解析器是RequestParamMethodParameter解析器。

调用父类的resolveArgument方法。

公共抽象类AbstractNamedValueMethodArgumentResolver { public final Object resolve argument(method parameter参数,@ Nullable ModelAndViewContainer M container,NativeWebRequest webRequest,@ Nullable webdatabinderfactory)throws exception {//此处的包方法参数名称为:id namedvalueinfo namedvalueinfo = getnamedvalueinfo(parameter);//resolved name = id Object resolved name = resolveEmbeddedValuesAndExpressions(namedvalueinfo . name);//…//获取参数名对应的请求参数值:/demos/index?Id=100,返回100 objectarg =解析名称(解析名称。tostring()、嵌套参数、webrequest);// …if (binderFactory!= null) {//根据当前请求对象和请求参数名称//内部创建的ExtendedServletRequestDataBinder对象WebDataBinder = BinderFactory创建WebDataBinder对象。CreateBinder (webrequest,null,namedvalueinfo . name);Try {//执行类型转换arg = binder . convertifnessary(arg,parameter.getparametertype(),parameter);} } }}//创建WebDataBinder对象公共类defaultdatabinder工厂实现webdatabinder工厂{ public final web data binder Create binder(native webRequest webr equest,@Nullable Object target,String objectName)抛出异常{ web data binder data binder = createbinder instance(target,objectName,webRequest);if (this.initializer!= null) {//初始化WebDataBinder对象,这里最重要的是设置类型转换器this。initializer . init binder(DataBinder,WebRequest)为其;}//初始化方法initbinder (databinder,webrequest)用于执行@InitBinder批注;返回dataBinder} }公共类InitBinderDataBinderFactory扩展DefaultDataBinderFactory { public void init binder(web data binder data binder,Native webrequest)throws exception {//遍历@InitBinder批注的所有方法for (invocatable binder方法:this。活页夹方法)。{ If(isindermethodaplicable(binder方法,databinder)){//下面是执行@InitBinder批注对象返回值= binder方法的方法。invokeforrequest (request,null,databinder);//如果@InitBinder批注的方法有返回值,则异常if (returnValue!= null){ throw new IllegalStateException(& # 34;@InitBinder方法不得返回值(应为void):& # 34;+binder method);} } } }…provided args)throws exception {//解析@InitBinder批注方法的参数对象[]args = getmethodparametervalues(request,mcontainer,provided args);//执行调用返回doin voke(args);}}执行类型转换在上面的执行流程中,我们知道我们获得了一个WebDataBinder对象和@InitBinder注释的方法的调用执行。下一步是转换类型。

公共抽象类AbstractNamedValueMethodArgumentResolver { public final Object resolve argument(method parameter参数,@ Nullable modelandview container M container,NativeWebRequest webRequest,@ Nullable WebDataBinderFactory binder factory)抛出异常{ if (binderFactory!= null) {//根据当前请求对象和请求参数名称//内部创建的ExtendedServletRequestDataBinder对象WebDataBinder = BinderFactory创建WebDataBinder对象。CreateBinder (webrequest,null,namedvalueinfo . name);Try {//执行类型转换arg = binder . convertifnessary(arg,parameter.getparametertype(),parameter);} } } }//最后,类型转换class type converter delegate { public

完毕!!!

Spring MVC异步请求模式
Spring如何解决循环依赖?
Spring中字段格式使用详解
你清楚Spring容器的这些扩展点吗?
Spring MVC异常处理方法
SpringBoot WebFlux集成Spring Security进行权限认证。

databinder

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论