最全面阐述WebDataBinder理解Spring的数据绑定 (2)

下面以一个示例来演示使用它增强的这些功能:

@Getter @Setter @ToString public class Person { public String name; public Integer age; // 基本数据类型 public Boolean flag; public int index; public List<String> list; public Map<String, String> map; }

演示使用!手动精确控制字段的默认值:

public static void main(String[] args) { Person person = new Person(); WebDataBinder binder = new WebDataBinder(person, "person"); // 设置属性(此处演示一下默认值) MutablePropertyValues pvs = new MutablePropertyValues(); // 使用!来模拟各个字段手动指定默认值 //pvs.add("name", "fsx"); pvs.add("!name", "不知火舞"); pvs.add("age", 18); pvs.add("!age", 10); // 上面有确切的值了,默认值不会再生效 binder.bind(pvs); System.out.println(person); }

打印输出(符合预期):

Person(name=null, age=null, flag=false, index=0, list=[], map={})

请用此打印结果对比一下上面的结果,你是会有很多发现,比如能够发现基本类型的默认值就是它自己
另一个很显然的道理:若你啥都不做特殊处理,包装类型默认值那铁定都是null了~

了解了WebDataBinder后,继续看看它的一个重要子类ServletRequestDataBinder

ServletRequestDataBinder

前面说了这么多,亲有没有发现还木有聊到过我们最为常见的Web场景API:javax.servlet.ServletRequest。本类从命名上就知道,它就是为此而生。

它的目标就是:data binding from servlet request parameters to JavaBeans, including support for multipart files.从Servlet Request里把参数绑定到JavaBean里,支持multipart。

备注:到此类为止就已经把web请求限定为了Servlet Request,和Servlet规范强绑定了。

public class ServletRequestDataBinder extends WebDataBinder { ... // 沿用父类构造 // 注意这个可不是父类的方法,是本类增强的~~~~意思就是kv都从request里来~~当然内部还是适配成了一个MutablePropertyValues public void bind(ServletRequest request) { // 内部最核心方法是它:WebUtils.getParametersStartingWith() 把request参数转换成一个Map // request.getParameterNames() MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class); // 调用父类的bindMultipart方法,把MultipartFile都放进MutablePropertyValues里去~~~ if (multipartRequest != null) { bindMultipart(multipartRequest.getMultiFileMap(), mpvs); } // 这个方法是本类流出来的一个扩展点~~~子类可以复写此方法自己往里继续添加 // 比如ExtendedServletRequestDataBinder它就复写了这个方法,进行了增强(下面会说) 支持到了uriTemplateVariables的绑定 addBindValues(mpvs, request); doBind(mpvs); } // 这个方法和父类的close方法类似,很少直接调用 public void closeNoCatch() throws ServletRequestBindingException { if (getBindingResult().hasErrors()) { throw new ServletRequestBindingException("Errors binding onto object '" + getBindingResult().getObjectName() + "'", new BindException(getBindingResult())); } } }

下面就以MockHttpServletRequest为例作为Web 请求实体,演示一个使用的小Demo。说明:MockHttpServletRequest它是HttpServletRequest的实现类~

Demo示例 public static void main(String[] args) { Person person = new Person(); ServletRequestDataBinder binder = new ServletRequestDataBinder(person, "person"); // 构造参数,此处就不用MutablePropertyValues,以HttpServletRequest的实现类MockHttpServletRequest为例吧 MockHttpServletRequest request = new MockHttpServletRequest(); // 模拟请求参数 request.addParameter("name", "fsx"); request.addParameter("age", "18"); // flag不仅仅可以用true/false 用0和1也是可以的? request.addParameter("flag", "1"); // 设置多值的 request.addParameter("list", "4", "2", "3", "1"); // 给map赋值(Json串) // request.addParameter("map", "{'key1':'value1','key2':'value2'}"); // 这样可不行 request.addParameter("map['key1']", "value1"); request.addParameter("map['key2']", "value2"); //// 一次性设置多个值(传入Map) //request.setParameters(new HashMap<String, Object>() {{ // put("name", "fsx"); // put("age", "18"); //}}); binder.bind(request); System.out.println(person); }

打印输出:

Person(name=fsx, age=18, flag=true, index=0, list=[4, 2, 3, 1], map={key1=value1, key2=value2})

完美。

思考题:小伙伴可以思考为何给Map属性传值是如上,而不是value写个json就行呢?

ExtendedServletRequestDataBinder

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdjfj.html