首页 > 编程语言 >Spring源码学习之Web数据绑定器WebDataBinder

Spring源码学习之Web数据绑定器WebDataBinder

时间:2023-11-30 13:47:03浏览次数:54  
标签:Web pv String Spring 绑定 mpvs field 源码 fieldType

WebDataBinder

1.描述

特殊的数据绑定器用于从web请求参数到JavaBean对象的数据绑定。专为web环境,但不依赖于Servlet API;作为更具体的DataBinder变体的基类,例如ServletRequestDataBinder。

2.注意:数据绑定会暴露对象图中不打算被外部客户端访问或修改的部分,从而导致安全问题。因此,数据绑定的设计和使用应该仔细考虑安全性。

3.包括对字段标记的支持,它解决了HTML复选框和选择选项的一个常见问题:检测字段是表单的一部分,但因为它是空的而没有生成请求参数。字段标记允许检测该状态并相应地重置相应的bean属性。对于不存在的参数,默认值可以为字段指定一个值,而不是空值。


public class WebDataBinder extends DataBinder {

//字段标记参数开头的默认前缀,后面跟着字段名
	public static final String DEFAULT_FIELD_MARKER_PREFIX = "_";//默认字段标记前缀
	public static final String DEFAULT_FIELD_DEFAULT_PREFIX = "!";//默认字段默认前缀
	@Nullable//该注解代表修饰属性可以为空
	
	//此类的有参构造  参数代表要绑定的目标对象
	public WebDataBinder(@Nullable Object target) {
		super(target);
	}
	
	//重载的有参构造  参数是绑定目标对象和目标对象名称
	public WebDataBinder(@Nullable Object target, String objectName) {
		super(target, objectName);
	}
	
	//设置字段标记前缀方法
	public void setFieldMarkerPrefix(@Nullable String fieldMarkerPrefix) {
		this.fieldMarkerPrefix = fieldMarkerPrefix;
	}

	//获取字段标记前缀
	@Nullable  //可以为空用于声明注释元素在某些情况下可以为空
	public String getFieldMarkerPrefix() {
		return this.fieldMarkerPrefix;
	}
	
	//获取字段默认前缀
	public void setFieldDefaultPrefix(@Nullable String fieldDefaultPrefix) {
		this.fieldDefaultPrefix = fieldDefaultPrefix;
	}
	
	
	//设置“绑定空多部分文件”
	public void setBindEmptyMultipartFiles(boolean bindEmptyMultipartFiles) {
		this.bindEmptyMultipartFiles = bindEmptyMultipartFiles;
	}
	
	//绑定是空的多部分文件
	public boolean isBindEmptyMultipartFiles() {
		return this.bindEmptyMultipartFiles;
	}
	
	//这个重写的方法 在委托给超类绑定过程之前 执行字段默认值和标记检查
	//MutablePropertyValues 可变属性值
	@Override
	protected void doBind(MutablePropertyValues mpvs) {
		checkFieldDefaults(mpvs);
		checkFieldMarkers(mpvs);
		adaptEmptyArrayIndices(mpvs);
		super.doBind(mpvs);
	}
	
	
	//检查字段默认值的给定属性值,即以字段默认前缀开头的字段
	protected void checkFieldDefaults(MutablePropertyValues mpvs) {
		String fieldDefaultPrefix = getFieldDefaultPrefix();
		if (fieldDefaultPrefix != null) {
			PropertyValue[] pvArray = mpvs.getPropertyValues();
			for (PropertyValue pv : pvArray) {
				if (pv.getName().startsWith(fieldDefaultPrefix)) {
					String field = pv.getName().substring(fieldDefaultPrefix.length());
					if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
						mpvs.add(field, pv.getValue());
					}
					mpvs.removePropertyValue(pv);
				}
			}
		}
	}
	
	//检查字段标记的给定属性值,即以字段标记前缀开头的字段
	protected void checkFieldMarkers(MutablePropertyValues mpvs) {
		String fieldMarkerPrefix = getFieldMarkerPrefix();
		if (fieldMarkerPrefix != null) {
			PropertyValue[] pvArray = mpvs.getPropertyValues();
			for (PropertyValue pv : pvArray) {
				if (pv.getName().startsWith(fieldMarkerPrefix)) {
					String field = pv.getName().substring(fieldMarkerPrefix.length());
					if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
						Class<?> fieldType = getPropertyAccessor().getPropertyType(field);
						mpvs.add(field, getEmptyValue(field, fieldType));
					}
					mpvs.removePropertyValue(pv);
				}
			}
		}
	}
	
	//检查名称以{@code "[]"}结尾的属性值。这被一些客户端用于没有显式索引值的数组语法。如果找到了这样的值,请去掉括号,以适应数据绑定目的所期望的表示相同值的方式。
	protected void adaptEmptyArrayIndices(MutablePropertyValues mpvs) {
		for (PropertyValue pv : mpvs.getPropertyValues()) {
			String name = pv.getName();
			if (name.endsWith("[]")) {
				String field = name.substring(0, name.length() - 2);
				if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
					mpvs.add(field, pv.getValue());
				}
				mpvs.removePropertyValue(pv);
			}
		}
	}
	
	//获取空值  确定指定字段的空值
	@Nullable
	protected Object getEmptyValue(String field, @Nullable Class<?> fieldType) {
		return (fieldType != null ? getEmptyValue(fieldType) : null);
	}
	
	//获取空值  参数:字段类型
	@Nullable
	public Object getEmptyValue(Class<?> fieldType) {
		try {
			if (boolean.class == fieldType || Boolean.class == fieldType) {
				// Special handling of boolean property.
				return Boolean.FALSE;
			}
			else if (fieldType.isArray()) {
				// Special handling of array property.
				return Array.newInstance(fieldType.getComponentType(), 0);
			}
			else if (Collection.class.isAssignableFrom(fieldType)) {
				return CollectionFactory.createCollection(fieldType, 0);
			}
			else if (Map.class.isAssignableFrom(fieldType)) {
				return CollectionFactory.createMap(fieldType, 0);
			}
		}
		catch (IllegalArgumentException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to create default value - falling back to null: " + ex.getMessage());
			}
		}
		// Default value: null.
		return null;
	}
	
	//绑定给定请求中包含的所有多部分文件(如果有的话)(对于多部分请求)。被子类调用
	protected void bindMultipart(Map<String, List<MultipartFile>> multipartFiles, MutablePropertyValues mpvs) {
		multipartFiles.forEach((key, values) -> {
			if (values.size() == 1) {
				MultipartFile value = values.get(0);
				if (isBindEmptyMultipartFiles() || !value.isEmpty()) {
					mpvs.add(key, value);
				}
			}
			else {
				mpvs.add(key, values);
			}
		});
	}
}

标签:Web,pv,String,Spring,绑定,mpvs,field,源码,fieldType
From: https://www.cnblogs.com/guobabiancheng/p/17867091.html

相关文章

  • LIMS实验室信息管理系统源码,支持二次开发
    LIMS实验室信息管理系统源码,支持二次开发LIMS实验室信息管理系统是一种软件类型,旨在通过跟踪与样品、实验、实验室工作流程和仪器相关的数据,提高实验室产能和效率。覆盖实验室从合同审批、委托下单、样品管理、生产调度、检测记录、报告管理、财务开票结算等全业务的过程管理。1、......
  • Springboot开发的应用为什么这么占用内存
    Springboot开发的应用为什么这么占用内存Java的原罪Java程序员比c或者是c++程序员相比轻松了很多.不要管理繁杂的内存申请与释放,也不用担心因为忘记释放内存导致很严重的内存泄漏.因为JAVA使用GC垃圾回收的机制实现了内存的自动管理.自凡是自动管理,就需要有单独的内存......
  • 深入解析C# List<T>的源码
    前面的文章中解释了Array的初始化和元素插入,以及数组整体的存储结构(《深度分析C#中Array的存储结构》)。这里我们再来详细的了解另一种存储结构List<T>, List<T>是ArrayList 泛型版本,是一个泛型集合类,用于表示动态大小的数组。List<T>应该是我们在开发过程中使用的频率最......
  • Linux部署WebDAV
    1.下载在下面网址下载对应版本的WebDAV服务端https://github.com/hacdias/webdav/releases/tag/v4.2.02.运行与配置将解压后的WebDAV复制到/usr/bin路径下在适当的位置编写配置文件webdav.yaml注意需要使用单引号将用户名、密码和路径括住。#Serverrelatedsettingsadd......
  • 一些方便的webassembly 工具
    WebAssembly团队提供了一些方便的webassembly工具集包含的工具集wat2wasm 将WebAssembly文本格式(.wat)转换为WebAssembly二进制格式(.wasm)wasm2wat 是wat2wasm的反向工具,将二进制格式转换回文本格式(.wat)wasm-objdump 类似于传统的objdump工具,它打印有关WebAssembly二进制的信息......
  • 在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面通讯
    转载于在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面通讯-DCloud问答uni-app的web-view组件,支持加载远程网页,在app环境下,还支持加载本地HTML页面。在web-view加载页面中,会涉及wx、plus、uni等对象的使用。在小程序下使用wx的api,需要引入微信提供的https......
  • wasmoon 基于webassembly 的lua 虚拟机
    wasmoon是基于webassembly开发的lua虚拟机包含的特性可以嵌入到node,deno,webapp运行lua在如何操作系统中js与lua的交互不用担心内存泄漏参考使用app.jsconst{LuaFactory}=require('wasmoon') asyncfunctionmain(){//Initializean......
  • SpringMvc集成开源流量监控、限流、熔断降级、负载保护组件Sentinel
    前言:作者查阅了Sentinel官网、51CTO、CSDN、码农家园、博客园等很多技术文章都没有很准确的springmvc集成Sentinel的示例,因此整理了本文,主要介绍SpringMvc集成SentinelSpringMvc集成Sentinel一、Sentinel介绍随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel......
  • 【SpringBoot】单元测试报错java.lang.IllegalStateException: Could not load TestCo
    一、运行test类方法时候报错 二、分析原因,发现版本不一致 三、找到pom文件, 把<version>RELEASE</version>注释掉,刷新一下maven依赖 四:修改后,依赖版本一致。 这样,就可以运行了。 ......
  • ubuntu server 22 LTS 安装MySQL8(二进制源码方式)
    原作来源:https://github.com/aminglinux/daily_shell/blob/main/29.sh根据我自己情况稍作修改mysql下载地址:https://downloads.mysql.com/archives/community/ 按照顺序执行逐行执行注意执行过程的提示,报错需处理:tar-xvfmysql-8.0.34-linux-glibc2.17-x86_64.tarsudo......