首页 > 代码库 > request 请求的参数封装为model
request 请求的参数封装为model
在一些应用中使用较为方便,比如你插入一行数据,通过Post或Get请求得到所有参数,而在一些时候我们是要直接操作对于数据行的一个bean对象,下面的是一个扩展性较好的方法。
注:常规编程时可以简单操作,如下一个bean
- public class Student implements java.io.Serializable{
- private static final long serialVersionUID = 1L;
- private String studentid;
- private String studentname;
- private String studentbir;
- private String studentsex;
- public String getStudentid() {
- return studentid;
- }
- public void setStudentid(String studentid) {
- this.studentid = studentid;
- }
- public String getStudentname() {
- return studentname;
- }
- public void setStudentname(String studentname) {
- this.studentname = studentname;
- }
- public String getStudentbir() {
- return studentbir;
- }
- public void setStudentbir(String studentbir) {
- this.studentbir = studentbir;
- }
- public String getStudentsex() {
- return studentsex;
- }
- public void setStudentsex(String studentsex) {
- this.studentsex = studentsex;
- }
- }
假设视图层将通过Post表单提交一个这样的参数集合:studentid=001,studentname=‘xiaoli‘,studentbir=‘1992-1-27‘,studentsex=‘男‘
我们在控制层通过多个getParameter()得到对于数据,接下来new Student(),对象赋值得到一个Student的bean,后面再使用什么spring之类的Dao层就插入数据库中持久化了。
以上方法简单也比较好理解,但是扩展性不好,你要是有成百上千个bean,那代码量都是这样,可想而知,冗余,维修性差……
2、下面是在一个项目中借鉴的操作性较好的方法,将任何请求(Post/ Get),参数混乱中的情况下拿到bean:
面向对象好处在之一少不了封装:下面是将任何请求所有参数封装为一个Map<String ,Object>,直接在控制层执行Map<String, Object> m=RequestUtils.getQueryParams(request);就可以啦,下面就是在工具类RequestUtils实现这个静态方 法:
- @SuppressWarnings("unchecked")
- public static Map<String, Object> getQueryParams(HttpServletRequest request) {
- Map<String, String[]> map;
- if (request.getMethod().equalsIgnoreCase(POST)) {
- map = request.getParameterMap();
- } else {
- //为GET请求时就获取其请求参数的那段信息
- String s = request.getQueryString();
- if (StringUtils.isBlank(s)) {
- return new HashMap<String, Object>();
- }
- try {
- //将得到的HTML数据用UTF-8转码
- s = URLDecoder.decode(s, UTF8);
- } catch (UnsupportedEncodingException e) {
- log.error("encoding " + UTF8 + " not support?", e);
- }
- map = parseQueryString(s);
- }
- Map<String, Object> params = new HashMap<String, Object>(map.size());
- int len;
- for (Map.Entry<String, String[]> entry : map.entrySet()) {
- len = entry.getValue().length;
- if (len == 1) {
- params.put(entry.getKey(), entry.getValue()[0]);
- } else if (len > 1) {
- params.put(entry.getKey(), entry.getValue());
- }
- }
- return params;
- }
上面看出,两种请求下做了不同处理,最后将所有参数键值转化为一个Map,
这样之后就可以在控制层用String action=m.get("action").toString();的形式得到各种参数;
前面说了一个项目bean成百个,所有将参数集转化为bean也进行封装,如调用时:Student s=(OrgList) BeanConverter.toJavaBean(new Student(), m,true);m为上面得到的Map参数映射表,具体实现要使用到了Java的反射机制处理,也就是根据传入的bean对象,得到这个对象所在类,并获 取到这个类的所有声明了的方法:Method[] methods = javabean.getClass().getDeclaredMethods();再循环得到打头为set的方法,拿到这个方法的名字如 setStudentsex转换为一个参数studentsex,然后将这个参数与map中的key做识别,有相同的key便将其value插入该 bean中,具体实现如下:
- public static Object toJavaBean(Object javabean, Map<String, Object> m,Boolean zhuanma)
- {
- //System.out.println(m);
- //所有声明了的方法
- Method[] methods = javabean.getClass().getDeclaredMethods();
- for (Method method : methods)
- {
- if (method.getName().startsWith("set"))
- {
- //得到该方法的参数类型
- Class<?>[] params = method.getParameterTypes();
- String field = method.getName();
- field = field.substring(field.indexOf("set") + 3);
- field = field.toLowerCase().charAt(0) + field.substring(1);
- //System.out.println(field+"----"+m.get(field.toString()));
- Object value=http://www.mamicode.com/m.get(field.toString());
- try {
- // convert types for some popular ones
- if (value != null&&!"".equals(value)) {
- String pa=params[0].getName().toString();
- //if (value instanceof java.util.Date) {
- if (pa.equals("java.util.Date")) {
- value = new java.util.Date(((java.util.Date) value).getTime());
- }
- // }
- else if(pa.equals("java.lang.String")){
- //value=http://www.mamicode.com/ new java.lang.String(Function.PageToDb(value.toString()));
- if(zhuanma)value=http://www.mamicode.com/ new java.lang.String(Function.PageToDb(value.toString()));
- }
- else if(pa.equals("java.lang.Integer")||pa.equals("int")){
- value=http://www.mamicode.com/ new java.lang.Integer(value.toString());
- }else if (pa.equals("java.lang.Long")) {
- value=http://www.mamicode.com/ new java.lang.Long(value.toString());
- } else if (pa.equals("java.lang.Double")) {
- value=http://www.mamicode.com/ new java.lang.Double(value.toString());
- } else if (pa.equals("java.lang.Float")) {
- value=http://www.mamicode.com/ new java.lang.Float(value.toString());
- } else if (pa.equals("java.lang.Short")) {
- value=http://www.mamicode.com/ new java.lang.Short(value.toString());
- } else if (pa.equals("java.lang.Byte")) {
- value=http://www.mamicode.com/ new java.lang.Byte(value.toString());
- } else if (pa.equals("java.lang.Character")) {
- // value=http://www.mamicode.com/ new java.lang.Character(value);
- } else if (pa.equals("java.lang.Boolean")) {
- value=http://www.mamicode.com/ new java.lang.Boolean(value.toString());
- }
- // Don‘t call setter if the value object isn‘t the right type
- if (isCompatibleType(value, params[0])) {
- method.invoke(javabean, new Object[] { value });
- } else {
- throw new Exception(
- "Cannot set " + field.toString() + ": incompatible types.");
- }
- }
- } catch(Exception e){
- e.printStackTrace();
- }
- }
- }
- return javabean;
- }
- /////////////
-
本文前提:参数名称与实体属性一致!
Java的Web项目中,经常有servlet中接收参数赋值给实体,参数如果多了就很麻烦,这里提供两个简单通用的方法:
比如实体为Student
1.使用org.apache.commons.beanutils.BeanUtils:
?12Student stu =newStudent();BeanUtils.populate(stu, request.getParameterMap());当然实际工作中,有些参数值为空或者参数类型与实体属性类型不匹配,这就会报异常,因此这个不太可靠,这时可以用方法3
2.利用反射:
获得所有set方法,排除掉Object基类本身的set方法,从get方法中可以得到属性名,而属性名即是request的参数名
3.(最推荐,经过测试) 改装populate方法:
?1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465importjava.lang.reflect.Method;importjava.util.Date;importjavax.servlet.http.HttpServletRequest;importorg.apache.commons.lang3.ArrayUtils;importorg.apache.commons.lang3.StringUtils;importorg.apache.commons.lang3.math.NumberUtils;importorg.apache.commons.lang3.time.DateUtils;/**Servlet业务中实体工具* @author LiuDing* 2014-2-16-下午08:10:06*/publicclassServletBeanTools {/**自动匹配参数赋值到实体bean中* @author LiuDing* 2014-2-16 下午10:23:37* @param bean* @param request*/publicstaticvoidpopulate(Object bean, HttpServletRequest request){Class<!--?extendsObject--> clazz = bean.getClass();Method ms[] = clazz.getDeclaredMethods();String mname;String field;String fieldType;String value;for(Method m : ms){mname = m.getName();if(!mname.startsWith("set")|| ArrayUtils.isEmpty(m.getParameterTypes())){continue;}try{field = mname.toLowerCase().charAt(3) + mname.substring(4, mname.length());value = http://www.mamicode.com/request.getParameter(field); >if(StringUtils.isEmpty(value)){continue;}fieldType = m.getParameterTypes()[0].getName();//以下可以确认value为String类型if(String.class.getName().equals(fieldType)){m.invoke(bean, (String)value);}elseif(Integer.class.getName().equals(fieldType) && NumberUtils.isDigits((String)value)){m.invoke(bean, Integer.valueOf((String)value));}elseif(Short.class.getName().equals(fieldType) && NumberUtils.isDigits((String)value)){m.invoke(bean, Short.valueOf((String)value));}elseif(Float.class.getName().equals(fieldType) && NumberUtils.isNumber((String)value)){m.invoke(bean, Float.valueOf((String)value));}elseif(Double.class.getName().equals(fieldType) && NumberUtils.isNumber((String)value)){m.invoke(bean, Double.valueOf((String)value));}elseif(Date.class.getName().equals(fieldType)){m.invoke(bean, DateUtils.parseDate((String)value,"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"));}else{m.invoke(bean, value);}}catch(Exception e){e.printStackTrace();continue;}}}} -
- public class RequestUtil {
- /**
- * 将request中的所有参数设置到entityClass类型的对象上
- * @param entityClass
- * @param request
- * @return
- */
- public static Object copyParam(Class entityClass,HttpServletRequest request){
- try {
- Object entity = entityClass.newInstance();
- //把请求中的参数取出
- Map allParams = request.getParameterMap();
- Set entries = allParams.entrySet();
- for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
- Map.Entry entry = (Map.Entry) iterator.next();
- String name = (String)entry.getKey();
- String[] value = (String[])entry.getValue();
- if(value != null){
- if(value.length == 1){
- BeanUtils.copyProperty(entity, name, value[0]);
- }else{
- BeanUtils.copyProperty(entity, name, value);
- }
- }
- }
- return entity;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- }
在到servlet页面上就可以直接写
Java代码- Article a = (Article)RequestUtil.copyParam(Article.class, request);
-
Jakarta-Commons- BeanUtils学习笔记:
Author:Tony.zhang Date:April 22, 2009 Mail:setpsw@gmail.com
1.什么是BeanUtils:
BeanUtils主要提供了对于JavaBean进行各种操作。
2.BeanUtils的作用:
在一般的写bean组件的时候,都必须要写setter和getter方法,当然假如我们事先已经知道bean的相关属性和方法,写bean是比较简单的,但是组件太多的时候,重复编写经常是枯燥乏味令人厌烦的。但当有些时候我么需要调用动态对象的属性的时候,我们应该怎么来设定和获取对象的属性呢?BeanUtils就可以帮助我们来解决这个问题。它需要Jakarta-Commons -Collections包和Jakarta-Commons -logging包的支持。
3. org.apache.commons.beanutils:
这个包主要提供用于操作JavaBean的工具类,Jakarta-Common-BeanUtils的主要功能都在这个包里实现。
BeanUtils可以直接get和set一个属性的值。它将property分成3种类型:
1Simple——简单类型,如Stirng、Int……
(对于Simple类型,第二个参数直接是属性名即可,详见代码)
2Indexed——索引类型,如 数组、arrayList……
(对于Indexed,则为“属性名[索引值]”,注意这里对于ArrayList和数组都可以用一样的方式进行操作,详见代码)
3Maped——这个不用说也该知道,就是指Map,比如HashMap……
(对于Map类型,则需要以“属性名(key值)”的形式,详见代码)
访问不同类型的数据可以直接调用函数getProperty和setProperty。它们都只有2个参数,第一个是JavaBean对象,第二个是要操作的属性名。
4.Converter 把Request或ResultSet中的字符串绑定到对象的属性
经常要从request,resultSet等对象取出值来赋入bean中,如果不用MVC框架的绑定功能的话,下面的代码谁都写腻了。
String a = request.getParameter("a"); bean.setA(a);String b = request.getParameter("b"); bean.setB(b);
…
不妨写一个Binder自动绑定所有属性:
MyBean bean = ;
HashMap map = new HashMap();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements())
{
String name = (String) names.nextElement();
map.put(name, request.getParameterValues(name));
}
BeanUtils.populate(bean, map);
其中BeanUtils的populate方法(Struts用于将一个map的值填充到一个bean中)或者getProperty,setProperty方法其实都会调用convert进行转换。
但Converter只支持一些基本的类型,甚至连java.util.Date类型也不支持。而且它比较笨的一个地方是当遇到不认识的类型时,居然会抛出异常来。 对于Date类型,我参考它的sqldate类型实现了一个Converter,而且添加了一个设置日期格式的函数。
要把这个Converter注册,需要如下语句://因为要注册converter,所以不能再使用BeanUtils的静态方法了,必须创建BeanUtilsBean实例:
BeanUtilsBean beanUtils =
new BeanUtilsBean( convertUtils, new PropertyUtilsBean() ) ;
beanUtils.setProperty( bean, name, value ) ;
5.BeanUtils在Struts中的应用:
下面的代码是我们经常在Struts中为了获得浏览器带来的参数的方法:
User user = new User() ;
user.setId( daf.getString( " id " ) ) ;
user.setPassword( daf.getString( " password " ) ) ;
user.setUsername( daf.getString( " password " ) ) ;
…
是不是觉得每次写这些都是在重复造轮子呢?
在看看用BeanUtils写的:
J
BeanUtils.copyProperties( user, daf ) ;就是这么简单
6.实例
private String name;
private HashMap address = new HashMap();
private String[] otherInfo;
private ArrayList product;
private ArrayList employee;
private HashMap telephone;
省略get / set
}
MainClass:
Jakarta-Commons- BeanUtils1.8.jar+JDK1.5
import java.util.HashMap ;
import org.apache.commons.beanutils.BeanUtils ;
/**
* @Author:Tony.Zhang setpsw@gmail.com Apr 22, 2009 1:34:16 PM
*/
public class MainClass {
/**
* @param args
* @throws Exception
*/
public static void main( String[] args ) throws Exception{
Test test = new Test();
test.setName( " zhangyi " );
// BeanUtils.getProperty( bean, name )
// 动态取得
System.out.println(BeanUtils.getProperty( test, " name " ));
HashMap map = new HashMap();
map.put( " 1 " , " 13880808080 " );
map.put( " 2 " , " 13550505050 " );
// BeanUtils.setProperty( bean, name, value )
BeanUtils.setProperty( test, " telephone " , map );
// 动态取得
System.out.println(BeanUtils.getProperty( test, " telephone(1) " ));
/**
* 直接进行Bean之间的clone 复制后的2个Bean的同一个属性可能拥有同一个对象的ref,
* 这个在使用时要小心,特别是对于属性为类的情况。
*/
Test test2 = new Test();
BeanUtils.copyProperties( test2, test );
System.out.println(BeanUtils.getProperty( test2, " name " ));
}
}
注:以上实例使用
其余的功能大家继续挖掘吧,可以参考官方API的说明J
DateConverter dateConverter = new DateConverter();
convertUtils.register(dateConverter,Date.class);