上篇博客中主要介绍了Introspector的使用方法和概念,这篇博客中主要来写一些Introspector的应用。为什么要利用Introspector来对javabean进行get/set值,而不直接使用get/set方法。
例如。现在有一个User javabean。表单向后台服务器提交数据时,从表单中获取的数据会设置到User javabean中。然后利用User对象进行业务逻辑处理。
package com.ray.javaneisheng;
import java.util.Date;
public class User {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + "]";
}
}
1.一般情况下可以会利用request.getParameter()方法将数据设置到User对象中。此种方法比较繁琐,如果javabean对象中属性有多个,那每一个都要设置,这种方法显然是不够灵活,并且效率低。
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// User u = populate(User.class,request.getParameterMap());
User u = new User();
u.setName(request.getParameter("name"));
u.setPassword(request.getParameter("password"));
System.out.println(u);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.上一篇文章中可以利用Introspector来操作和管理javabean的get/set方法。那这里我们也利用Introspector和request.getParameterMap()将表单中的数据,全部设置到user对象中。此种方法有有一个弊端只能支持String类型的变量。写的不够灵活,但是能体现出可以利用Introspector来灵活操作javabean的思想。
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
User u = populate(User.class,request.getParameterMap());
System.out.println(u);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 利用java内省来将parameterMap中的值放入到javabean对象中
*/
private User populate(Class<User> class1, Map<String, String[]> parameterMap)
throws Exception, IllegalAccessException {
// 创建出user对象
User u = class1.newInstance();
BeanInfo info = Introspector.getBeanInfo(u.getClass());
PropertyDescriptor[] propertyDescriptors = info
.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String[] params = parameterMap.get(propertyDescriptor.getName());
if (params != null && params.length > 0) {
propertyDescriptor.getWriteMethod().invoke(u, params[0]);
}
}
return u;
}
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
User u = new User();
// BeanUtils 的 该方法还可以自动进行类型转换. 只能转换8中基本数据类型.
BeanUtils.populate(u, request.getParameterMap());
System.out.println(u);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果我们在 User javabean对象中加入了Date类型的属性,例如加入private Date birthday,并且提供get,set方法。这时在使用BeanUtils.populate方法时会抛出argument type mismatch异常。这种原因是BeanUtils.populate方法只支持8个基本数据类型中的转换。如果需要转换其他类型需要提供类型转化器,自定义转换规则。
public class MyConverter implements Converter {
// 参数2 就是 将要被转换的String ==> 1990-12-12
// 参数1 提示你要把 参数2转换成什么类型的. ==> Date
public Object convert(Class arg0, Object obj) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
return format.parse(obj.toString());
} catch (Exception e) {
throw new RuntimeException("类型转换失败");
}
}
}
并将该转换类注册
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
User u = new User();
// BeanUtils 的 该方法还可以自动进行类型转换. 只能转换8中基本数据类型.
// 注册一个转换器, 来转换自定义类型
ConvertUtils.register(new MyConverter(), Date.class);
BeanUtils.populate(u, request.getParameterMap());
System.out.println(u);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}
以上就是内省的应用。这种方式很显然的更加方便的操作了javabean,尤其是提现在表单提交时间,后台服务器获取这些数据时。
我在猜测一件事就是BeanUtils.populate的源码是也是利用内省的机制实现的。下一步会想办法证实一下。