1 反射
什么是java
反射呢?简单的说,对于java中任意一个类,利用反射都可以获取该类中的所有属性和方法,而对于一个java
对象,反射也都可以动态的去调用该对象中的属性和方法。
对于正在学习Servlet
的童鞋来说,最痛苦的无疑是对请求参数的处理,譬如:对请求参数的类型转换,繁琐的setter
方法和getter
方法等。这样无疑是 大大的降低了开发效率。
而对于struts
来说,我想大家也会很好奇为什么我们只需要将表单的name
属性设置成className.fieldName
后,struts
就可以完成自动封装吧。
当然,这都归功于java的反射机制
2 正题
1.1 使用传统的代码编写一个注册Servlet
实体类:Student.class
public class Student {
private String name;
private Integer age;
private Date register;
....setter getter...
Servlet : StudentServlet.class
@WebServlet(name="studentServlet",urlPatterns={"/StudentServlet"})
public class StudentServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
Student student = new Student();
Date date = null;
String name = request.getParameter("name");
Integer age = Integer.parseInt(request.getParameter("age"));
String dateString = request.getParameter("register");
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
student.setName(name);
student.setAge(age);
student.setRegister(date);
System.out.println(student);
}
}
可以看到,每当我们发送一个请求时,都需要手动的去对请求参数进行数据类型转换,然后在封装到对应的javaBean
中去。当我们使用反射机制的使用,这些重复的代码就完全可以被抽离出来。
1.2 使用反射自动封装
实体类操作工具: BeanUtil .class
public class BeanUtil {
/**
* 利用反射对javabean对象进行属性封装(参数名和属性名要保持一致)
* @param obj 需要封装的对象
* @param request 从request中获取请求参数
* @param datepatern 日期转换的格式
*/
public static void setValue(Object obj, ServletRequest request, String datepatern)
throws Exception{
Class<?> cls = obj.getClass();
// 1 获取所有的请求参数
Enumeration<String> parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
// 2 获取每个参数名
String paramName = parameterNames.nextElement();
// 3 获取参数对应的值
String paramValue = request.getParameter(paramName);
// 4 获取参数对应的属性
Field field = cls.getDeclaredField(paramName);
// 5 获取属性对应的简单类型
String fieldTypeName = field.getType().getSimpleName();
// 6 获取对应的方法(setter方法)
Method method = cls.getDeclaredMethod("set" +
StringUtil.initCap(paramName), field.getType());
// 7 对参数类型进行转换,执行对应的setter方法
if("String".equalsIgnoreCase(fieldTypeName)){
method.invoke(obj, paramValue);
}else if("integer".equalsIgnoreCase(fieldTypeName) ||
"int".equals(fieldTypeName)){
method.invoke(obj, Integer.parseInt(paramValue));
}else if("double".equalsIgnoreCase(fieldTypeName)){
method.invoke(obj, Double.parseDouble(paramValue));
}else if("date".equalsIgnoreCase(fieldTypeName)){
method.invoke(obj, new SimpleDateFormat(datepatern).parse(paramValue));
}
}
}
}
首字母大写转换:StringUtil.class
public class StringUtil {
/**
* 首字母大写
* @param str
* @return
*/
public static String initCap(String str){
return str.substring(0,1)
.toUpperCase().concat(str.substring(1).toLowerCase());
}
}
Servlet : StudentServler.class
@WebServlet(name="studentServlet",urlPatterns={"/StudentServlet"})
public class StudentServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
Student student = new Student();
try {
BeanUtil.setValue(student, request, "yyyy-MM-dd");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(student);
}
}
在使用了反射后,我们可以动态的去对请求的参数进行处理,对其封装,不在需要我们去手动的处理。
当然咯,这只是一个简单属性的封装,其中还有一些需要优化的部分。后期会给大家实现
struts2
的复杂javaBean
封装功能、action
方法的选用以及自动转发、重定向等。