一、业务背景
web前端发送一系列数据给后台,这些数据包含字符串和字符串数组,现在的业务需求就是怎样动态的把这些数据动态映射到DAO的字段中,而dao中的字段有java的基本类型,数组类型还有集合类型,后台应该怎样处理?
封装带来的好处:HTTP传过来的字符串自动的映射到dao中相应字段的类型,其字段类型包括java基本类型、数组类型、集合类型
二、代码详解
这个是测试代码
package com.hewen.java.frame;
/**
* 测试类,因为httpRequest请求一般都是以字符串,或者是字符串数组传过来的
* @author Administrator
*
*/
public class DTOTest {
public static void main(String[] args) {
MyRequest request = new MyRequest();
request.setParameter("id", "9527");
request.setParameter("name", "name9527");
request.setParameterValues("friendsIds", new String[]{"1", "2", "3", "4", "5"});
request.setParameterValues("memTimes", new String[]{"2000-01-02 03:04:05", "2012-06-07 08:09:10"});
//UserQueryDTO dto = new UserQueryDTO();
//dto.initFromRequest(request);
//DTOUtil.initFromRequest(request, dto);
UserQueryDTO dto = (UserQueryDTO) DTOUtil.initFromRequest(request, UserQueryDTO.class);
System.out.println(dto);
}
}
把所有的httpRequest请求都放到Map中,这个类是MyRequest,实现了HttpServletRequest接口
package com.hewen.java.frame;
import java.io.BufferedReader;
/**
* 这个是一个测试的request请求
* @author Administrator
*
*/
public class MyRequest implements HttpServletRequest{
private Map<String, String> parameters = new HashMap<String, String>();
private Map<String, String[]> listParameters = new HashMap<String, String[]>();
//这个是设置键值对给request,key是String ,value-String
public void setParameter(String key, String value){
parameters.put(key, value);
}
//这个是给request设置键值对,key-String,value-String[]
public void setParameterValues(String key, String[] value){
listParameters.put(key, value);
}
// @Override
//获取设置request的键值对value-String
public String getParameter(String name) {
return parameters.get(name);
}
//获取设置request的键值对value-String[]
// @Override
public String[] getParameterValues(String name) {
return listParameters.get(name);
}
}
封装的DAO类
package com.hewen.java.frame;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.List;
//public class UserQueryDTO extends BaseDTO{
public class UserQueryDTO {
private long id;
private String name;
private long[] friendsIds;
private List<Timestamp> memTimes;
public List<Timestamp> getMemTimes() {
return memTimes;
}
public void setMemTimes(List<Timestamp> memTimes) {
this.memTimes = memTimes;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long[] getFriendsIds() {
return friendsIds;
}
public void setFriendsIds(long[] friendsIds) {
this.friendsIds = friendsIds;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("id:" + id).append("\nname:").append(name);
sb.append("\nfriendsIds:[");
for(long fid: friendsIds){
sb.append(fid).append(" ");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sb.append("\nmemTimes:[");
for(Timestamp mem: memTimes){
sb.append(sdf.format(mem)).append(" ");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("]");
return sb.toString();
}
}
后台是怎么样把请求的值映射到封装的dao类中,这个类是DTOUtil,用了反射机制
package com.hewen.java.frame;
import java.lang.reflect.Method;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
public class DTOUtil {
private static final String SETFLAG = "set";
private static final int ARRAY_TYPE_VECTOR =1;//dao类中字段的集合是Vector,List,ArrayList
private static final int ARRAY_TYPE_LIST = 2;
private static final int ARRAY_TYPE_ARRAYLIST = 3;
/**
* 为request请求初始数据至dao
* @param request Http请求
* @param dto Http请求所有数据,映射到相应的Dao类中
* @return
*/
public static Object initFromRequest(HttpServletRequest request, Object dto){
Method []methods = dto.getClass().getMethods();//得到dao中所有的方法
for(Method method: methods){
//因为要对dao中各个字段进行映射,所以要过滤掉get开头的方法,
//只需要判断带有set开头的方法
if(method.getName().startsWith(SETFLAG)){
/*
* 得到set开头方法字符串对应的字段值,如setName,转变后name
*/
String fieldName = method.getName().substring(SETFLAG.length());
fieldName = fieldName.replaceFirst(fieldName.substring(0, 1), fieldName.substring(0, 1).toLowerCase());
if(isArrayField(method)){//判断dao映射的字段是否是数组字段或者是集合类型
String[] fieldValue = request.getParameterValues(fieldName);
//System.out.println("==initFromRequest==fieldName:" + fieldName + "\tfieldValue:" + fieldValue);
//检查得到的request的值是否是数组类型
if(fieldValue == null || !checkArrayField(fieldValue)){
System.err.println("null value when initFromRequest,fieldName:" + fieldName + " fieldValue:" + fieldValue);
continue;
}
//把request所传过来的数组值映射到dao字段
initArrayField(dto, method, fieldValue);
}else{
String fieldValue = request.getParameter(fieldName);
//System.out.println("==initFromRequest==fieldName:" + fieldName + "\tfieldValue:" + fieldValue);
if(fieldValue == null){
System.err.println("null value when initFromRequest,fieldName:" + fieldName + " fieldValue:" + fieldValue);
continue;
}
initField(dto, method, fieldValue);
}
}
}
return dto;
}
public static Object initFromRequest(HttpServletRequest request, Class<?> dtoClass){
Object dto;
try {
dto = dtoClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("exception when newInstance:" + dtoClass.getName());
}
initFromRequest(request, dto);
return dto;
}
//检查得到的request的值是否是数组类型
private static boolean checkArrayField(String[] fieldValue){
if(fieldValue.length == 1 && fieldValue[0].trim().length() == 0){
return false;
}
return true;
}
//初始化非数组类型
private static void initField(Object o, Method method, String fieldValue){
Class<?> pType = method.getParameterTypes()[0];
try
{
if(pType.equals(int.class) || pType.equals(Integer.class)){
method.invoke(o, Integer.parseInt(fieldValue));
}else if(pType.equals(float.class) || pType.equals(Float.class)){
method.invoke(o, Float.parseFloat(fieldValue));
}else if(pType.equals(double.class) || pType.equals(Double.class)){
method.invoke(o, Double.parseDouble(fieldValue));
}else if(pType.equals(long.class) || pType.equals(Long.class)){
method.invoke(o, Long.parseLong(fieldValue));
}else if(pType.equals(String.class)){
method.invoke(o, fieldValue);
}else if(pType.equals(Timestamp.class)){
method.invoke(o, Timestamp.valueOf(fieldValue));
}else if(pType.equals(Date.class)){
method.invoke(o, Date.valueOf(fieldValue));
}else if(pType.equals(Time.class)){
method.invoke(o, Time.valueOf(fieldValue));
}else{
throw new RuntimeException("unsupport type exception when initField, method is:" + method.getName());
}
}catch(Exception e){
//e.printStackTrace();
System.err.println("exception when initFromRequest,method is:" + method.getName() + " fieldValue:" + fieldValue);
}
}
/**
* 判断dao映射的字段是否是数组字段或者是集合类型
* @param m 该字段对应的set方法
* @return
*/
private static boolean isArrayField(Method m){
if(m.getParameterTypes().length < 1){
return false;
}
//得到该字段对应的set方法参数类型
Class<?> p0 = m.getParameterTypes()[0];
//判断set方法对应的参数类型是数组或者是集合类型
return p0.isArray() || Collection.class.isAssignableFrom(p0);
}
/**
* 把request所传过来的值映射到dao字段
* @param obj 需要映射的dao对象
* @param m dao字段对应的set方法如:setName(String name)
* @param fieldValue request请求所得到的值,要映射到dao字段里
*/
private static void initArrayField(Object obj, Method m, String[] fieldValue){
Class<?> p0 = m.getParameterTypes()[0];
try {
if(p0.isArray()){
//p0.getComponentType()返回数组类型中包含哪个基本类型
m.invoke(obj, getArray(p0.getComponentType(), fieldValue));
}else if(Collection.class.isAssignableFrom(p0)){
//因为dao中set方法参数中有List、vector,ArrayList,故需知道集合里面中包含的是什么数据基本类型
//ArrayList.class.isAssignableFrom(p0)判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,
//或是否是其超类或超接口。如果是则返回 true;否则返回 false。
// 如果该 Class 表示一个基本类型,且指定的 Class 参数正是该 Class 对象,
//则该方法返回 true;否则返回 false。
String innerType = getInnerType(m.getGenericParameterTypes()[0].toString());
if(Vector.class.isAssignableFrom(p0)){
m.invoke(obj, getArray(innerType, fieldValue, ARRAY_TYPE_VECTOR));
}else if(ArrayList.class.isAssignableFrom(p0)){
m.invoke(obj, getArray(innerType, fieldValue, ARRAY_TYPE_ARRAYLIST));
}else if(List.class.isAssignableFrom(p0)){
m.invoke(obj, getArray(innerType, fieldValue, ARRAY_TYPE_LIST));
}
}
} catch (Exception e) {
throw new RuntimeException("exception when init arrayField, method is:" + m.getName());
}
}
/***
*
* @param componentType 数组是哪个基本类型
* @param fieldValue request请求的数据值
* @return 请求的数据值转换成数组中
*/
private static Object getArray(Class<?> componentType, String[] fieldValue){
int i;
if(componentType.equals(int.class) || componentType.equals(Integer.class)){
int []a = new int[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Integer.parseInt(fieldValue[i]);
}
return a;
}else if(componentType.equals(short.class) || componentType.equals(Short.class)){
short []a = new short[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Short.parseShort(fieldValue[i]);
}
return a;
}else if(componentType.equals(float.class) || componentType.equals(Float.class)){
float []a = new float[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Float.parseFloat(fieldValue[i]);
}
return a;
}else if(componentType.equals(double.class) || componentType.equals(Double.class)){
double []a = new double[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Double.parseDouble(fieldValue[i]);
}
return a;
}else if(componentType.equals(long.class) || componentType.equals(Long.class)){
long []a = new long[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Long.parseLong(fieldValue[i]);
}
return a;
}else if(componentType.equals(String.class)){
String []a = new String[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = fieldValue[i];
}
return a;
}else if(componentType.equals(Timestamp.class)){
Timestamp []a = new Timestamp[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Timestamp.valueOf(fieldValue[i]);
}
return a;
}else if(componentType.equals(Date.class)){
Date []a = new Date[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Date.valueOf(fieldValue[i]);
}
return a;
}else if(componentType.equals(Time.class)){
Time []a = new Time[fieldValue.length];
for(i = 0; i < fieldValue.length; i++){
a[i] = Time.valueOf(fieldValue[i]);
}
return a;
}else{
throw new RuntimeException("unsupport type exception when get array, type:" + componentType);
}
}
/***
* 初始化集合类型数据包含Vector=ARRAY_TYPE_VECTOR=1,
* ARRAY_TYPE_ARRAYLIST=ArrayList=3
* ARRAY_TYPE_LIST=List=2
* @param innerType 集合类型包含的基本数据类型
* @param fieldValue request请求的数据值
* @param arrayType 是集合类型的哪个类型
* @return 请求的数据方法集合类中
*/
private static Object getArray(String innerType, String[] fieldValue, int arrayType){
/**
* 判断集合里面是哪种类型如:
* "java.sql.Time","java.sql.Date","java.sql.Timestamp","java.lang.String",
* "java.lang.Double","java.lang.Long","java.lang.Float","java.lang.Integer","java.lang.Short"
* 然后把fieldValue值添加到指定的集合(arrayType)中
*/
if(innerType == null){
// default type: String
List<String> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<String>();
}else{
l = new ArrayList<String>();
}
for(String value: fieldValue){
l.add(value);
}
return l;
}else if(innerType.equals("java.lang.Short")){
List<Short> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Short>();
}else{
l = new ArrayList<Short>();
}
for(String value: fieldValue){
l.add(Short.parseShort(value));
}
return l;
}else if(innerType.equals("java.lang.Integer")){
List<Integer> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Integer>();
}else{
l = new ArrayList<Integer>();
}
for(String value: fieldValue){
l.add(Integer.parseInt(value));
}
return l;
}else if(innerType.equals("java.lang.Float")){
List<Float> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Float>();
}else{
l = new ArrayList<Float>();
}
for(String value: fieldValue){
l.add(Float.parseFloat(value));
}
return l;
}else if(innerType.equals("java.lang.Double")){
List<Double> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Double>();
}else{
l = new ArrayList<Double>();
}
for(String value: fieldValue){
l.add(Double.parseDouble(value));
}
return l;
}else if(innerType.equals("java.lang.Long")){
List<Long> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Long>();
}else{
l = new ArrayList<Long>();
}
for(String value: fieldValue){
l.add(Long.parseLong(value));
}
return l;
}else if(innerType.equals("java.lang.String")){
List<String> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<String>();
}else{
l = new ArrayList<String>();
}
for(String value: fieldValue){
l.add(value);
}
return l;
}else if(innerType.equals("java.sql.Timestamp")){
List<Timestamp> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Timestamp>();
}else{
l = new ArrayList<Timestamp>();
}
for(String value: fieldValue){
l.add(Timestamp.valueOf(value));
}
return l;
}else if(innerType.equals("java.sql.Date")){
List<Date> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Date>();
}else{
l = new ArrayList<Date>();
}
for(String value: fieldValue){
l.add(Date.valueOf(value));
}
return l;
}else if(innerType.equals("java.sql.Time")){
List<Time> l;
if(arrayType == ARRAY_TYPE_VECTOR){
l = new Vector<Time>();
}else{
l = new ArrayList<Time>();
}
for(String value: fieldValue){
l.add(Time.valueOf(value));
}
return l;
}else{
throw new RuntimeException("unsupport type exception when get list, type:" + innerType);
}
}
/**
* 获取List、Vector,ArrayList中包含的具体类型,
* 如gp="java.util.List<java.sql.Timestamp>",装换成"java.sql.Timestamp"
* @param gp
* @return
*/
private static String getInnerType(String gp){
int startIndex = gp.indexOf("<");
int endIndex = gp.indexOf(">");
if(startIndex == -1 || endIndex == -1 || startIndex >= endIndex){
return null;
}
return gp.substring(startIndex + 1, endIndex);
}
}
id:9527 name:name9527 friendsIds:[1 2 3 4 5] memTimes:[2000-01-02 03:04:05 2012-06-07 08:09:10]