`
he_wen
  • 浏览: 239454 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

HTTP请求的数据映射到封装的DAO

阅读更多

一、业务背景

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]

  

0
0
分享到:
评论
1 楼 rexlee 2010-09-08  
干嘛不用Dozer

相关推荐

    基于Annotation并对DAO层封装具有分页功能的S2SH整合实例

    这样,我们可以在Service层调用DAO的分页查询方法,获取到所需的数据并传递给Struts2的Action,最后由Action将结果传递给视图进行展示。 为了实现这个整合实例,我们需要完成以下步骤: 1. 配置Struts2、Spring和...

    前端 如何把请求发到 后端 的 Controller

    - **后端**:接收HTTP请求,并通过Controller、Service、DAO等层次进行处理,最终将处理结果封装为HTTP响应返回给前端。 #### 2. 前端发起请求的方式 前端向后端发送请求的方式主要有以下几种: - **GET方法**:...

    关于DAO的相关论文

    Service层负责业务逻辑,调用DAO层进行数据操作,而Controller层处理用户请求并调用Service层。 7. 扩展性:DAO模式使得添加新的数据源变得容易,只需要创建新的DAO实现即可。例如,如果需要支持NoSQL数据库,可以...

    struts+DAO登陆例子

    Action定义了请求与Action类之间的映射,ActionForm则用于封装用户提交的数据。 **总结** "Struts+DAO登陆例子"是一个典型的Java Web应用开发示例,它展示了如何使用Struts框架来处理用户请求,以及如何利用DAO模式...

    ssm(Spring-springMVC-Mybatis)通用Dao框架

    SpringMVC通过DispatcherServlet接收HTTP请求,然后根据请求映射找到对应的处理器(Controller),执行业务逻辑后,将结果返回给视图层进行渲染。 **Mybatis**是一个轻量级的持久层框架,它将SQL语句与Java代码解耦...

    Struts+DAO

    1. **动作调度器(ActionServlet)**:它是Struts框架的核心,负责接收HTTP请求,根据配置文件将请求映射到相应的动作类。 2. **配置文件**:主要包括struts-config.xml,用于配置Action、Form Bean、Action ...

    使用hibernate封装方法

    - Struts2的配置文件(struts.xml)定义Action及其结果,将HTTP请求映射到特定的方法。 - Action类执行业务逻辑,调用Service层,然后返回一个结果(可能跳转到一个新的JSP页面或显示一个JSON响应)。 6. **JSP...

    基于MVC的论坛(用到struts+dao设计模式)

    2. **动作映射**:ActionMapping定义了Action类与URL的映射关系,使得不同的HTTP请求能被正确地导向到对应的处理方法。 3. **动作处理**:Action类实现了控制器的功能,执行业务逻辑并返回ActionForward对象,指示...

    Spring+ibatis+struts框架整合+springmvc数据接口封装含数据表可直接运行

    6. **数据接口封装**:Spring MVC的Controller层通常负责处理HTTP请求,调用Service层进行业务处理,再返回JSON或其他格式的数据。这里的“数据接口封装”可能指的是将数据库查询或更新操作包装成服务接口,供前端...

    spring,springMVC,Hibernate全注解案例加dao的封装

    `@RequestMapping`用于定义URL到处理方法的映射,而`@GetMapping`和`@PostMapping`则分别对应HTTP的GET和POST请求。 Hibernate是Java中的一个ORM(对象关系映射)框架,它简化了数据库操作。通过注解如`@Entity`、`...

    43-Hibernate数据关联实现〖MVSN〗_Struts + DAO + Hibernate(6).rar

    **数据关联**:在Hibernate中,数据关联指的是对象之间的关系映射到数据库表之间的关联。这包括一对一、一对多、多对一和多对多四种关联类型。例如,一个用户可以有多个订单,这是一种一对多的关系;反之,每个订单...

    J2EE之DAO设计模式

    - DAO实现类接收到请求后,构造适当的SQL语句或者使用ORM框架(如Hibernate或MyBatis)进行数据操作。 - 数据操作完成后,DAO将结果封装成实体对象,然后返回给客户端。 4. J2EE环境中的DAO模式应用: 在J2EE...

    struts + DAO + Hibernate可直接运行程序

    **DAO层**是应用程序与数据库交互的接口,它的主要任务是封装对数据库的操作,使业务逻辑层与具体的数据存储方式解耦。DAO类通常包含了增删改查等基本操作,通过调用Hibernate提供的API来执行SQL语句。这样做的好处...

    dao.zip_dao_java dao_java数据库连接_struts_struts dao

    在Java开发中,DAO(Data Access Object)模式是一种常见的设计模式,用于封装对数据库的访问操作,以解耦业务逻辑层和数据存储层。标题"dao.zip_dao_java dao_java数据库连接_struts_struts dao"暗示了这个压缩包...

    ssh.rar_Action!_service dao_ssh action_ssh com.dao_ssh dao

    在“service_dao”标签中,Service层是业务逻辑的封装,负责处理复杂的业务规则和事务管理。它通常调用DAO层来与数据库交互。DAO接口定义了数据库操作,而其实现类则使用Hibernate等ORM(对象关系映射)工具来完成...

    struts+dao实现的登录(连接数据库)

    配置文件(struts.xml)定义了Action与URL的映射关系以及处理特定请求的方法。 **DAO设计模式** DAO模式是一种软件设计模式,它提供了一种隔离应用程序和数据存储的方式。DAO类封装了对数据库的所有操作,使得业务...

    dao.rar_spring-dao

    DAO(Data Access Object)模式是Java开发中常用的一种设计模式,用于封装对数据库的操作,使得业务逻辑层与数据访问层解耦。Spring框架提供了对DAO的支持,通过依赖注入(DI)和面向切面编程(AOP)简化了数据访问...

    DWR的访问DAO和Servlet

    DWR提供了一种高效的方法来调用服务器端的业务逻辑,而DAO模式则确保了数据访问的封装和独立性,Servlet则作为中间层,协调HTTP请求和响应。这种架构有利于代码的组织和扩展,同时提高了应用的性能和用户体验。

    使用Annotation并对DAO层封装具有分页功能的S2SH整合实例_好资源0分送

    - **控制器**:通过注解如`@Action`来指定控制器的请求映射。 - **拦截器**:可以使用注解来控制拦截器的执行顺序等。 ##### 3. Hibernate中的注解支持 - **实体映射**:使用注解如`@Entity`、`@Table`等来描述...

Global site tag (gtag.js) - Google Analytics