javaweb 自动封装请求头中的数据到指定实体类中
写在开头的话:
这篇笔记是学习web开发时研究反射和泛型的产物,实际开发都是使用spring框架+mybatis 即常说的ssm框架,springMVC已经将servlet封装好了,所以下面的探究过程仅供参考。
引入
在编写向数据库添加数据的方法时,我们需要根据sql的添加语句中需要的"?"去获取request请求中传过来的数据,先用set方法将其封存在对象中,然后再到daoimpl下使用get方法调出数据传给sql语句。根据添加语句的不同,我们就要不断的去改这个过程中使用的set/get方法以及对象的成员变量。
这一切都是重复的,近机械的操作。
因此就生发出“如果java能自动将我请求头中传输的所有数据都存到指定的对象中就好了” 的想法,这样就简化了使用set函数的环节。
实际上是可以实现上面说的想法的,我们只需要编写一个工具类
编写工具类
第一步
既然我们希望能自动将请求中的数据传给我们定义好的对象,而且能实现复用,那么我们就要编写一个工具类用于实现这种操作,这个工具类需要用户传入所有请求参数以及作为容器的class对象,然后传出一个实体对象,这实体对象我们使用泛型表示。
第二步
现在我们需要思考如何将map集合中的数据对应到容器中的各个成员变量上:
首先要明确知道一个前提——请求头中传过来的数据,他们的变量名要与作为容器的对象中的成员变量名相符。
在变量名一致的前提下,那么就有两种思路
①map中的key既是请求头中的数据名,又直接对应实体类中成员变量的名字,那么我们就能通过拼接set获得一个set方法
然后将对应key的value数据——string[]的数值以这个set方法存到实体对中对应名字的成员变量中
②使用getDeclaredFields() 获得当前类中所有的成员变量,然后循环使用field对象的set方法
第一种方法算是最底层最原始的方法,我们使用java封装好的方法——即第二种思路
第三步
根据思路写出整个框架:
①首先声明对象用于后面返回
②使用getDeclaredFields()获取指定类中所有的成员变量,返回一个Field数组(注意这个field是一个专门用于java反射的内置的对象,不是我们自定义的对象)
③遍历Field数组,使用getName()获取单个成员变量名
④在传入的储存了所有请求数据的map集合中基于成员变量名获取对应的value——map的k-v为string-string[] 因此返回类型为string[]
⑤非空判断,确定当前循环取到的值不为空时设定暴力破解,然后进行存值
第四步
下面详细说明在设定暴力破解后,如何进行存值。
对于请求头中的value,存在多种可能,但是直观表现上可以分为“数组”和“非数组”
①如果此时value的长度大于1,说明取到的值就是一个字符串数组,此时直接使用写好的工具类,将字符串数组拼接成一个字符串,再使用field.set()方法存到对象中
②如果此时value的长度等于1,说明取到的值只是存在字符串数组中,未必就是字符串的值,它可能是下拉框、复选框或者时间的值,此时就需要分别进行类型判断,再用对应类型的变量去存储数据。
相比情况①,情况②需要使用 .getType().getName()获取数据的类型,再进行判断,以确定要使用的数据类型转换工具类,最后再使用field.set()方法存到对象中
第五步
外部调用该工具类,只需要传入请求头中所有的请求参数构成的map集合变量以及作为容器的class对象
其中步骤②返回给外部时可能是一个对象也可能为空,这是因为工具类中使用了这个方法,这样就便于外部进行非空判定
使用到的数据类型转换工具类一览
实际上使用第三方jar包就行了,不需要手动封装这种工具类
使用
在写好工具类后,在整个添加数据的流程中,我们只需要:
①根据数据库的表对应着创建对象
②根据sql代码的"?"(需求) 手动使用get方法从对象中取值
(实际上 后面的mybatis+springboots将这个环节也给简化了,配置了对象的成员变量和数据库表的列名的映射后,即可自动实现取值,不过复杂一点的连表查询还是得自己手写sql代码)
说明:这个“sql代码中的?" 指的就是daoImpl中写各种sql语句时的占位符,如图,使用?占位,再使用get方法分别传值。
实例: