1 反射
什么是java
反射呢椅亚?簡單的說恢恼,對于java中任意一個類副瀑,利用反射都可以獲取該類中的所有屬性和方法弓熏,而對于一個java
對象,反射也都可以動態(tài)的去調用該對象中的屬性和方法糠睡。
對于正在學習Servlet
的童鞋來說挽鞠,最痛苦的無疑是對請求參數的處理,譬如:對請求參數的類型轉換狈孔,繁瑣的setter
方法和getter
方法等信认。這樣無疑是 大大的降低了開發(fā)效率。
而對于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);
}
}
可以看到潦蝇,每當我們發(fā)送一個請求時,都需要手動的去對請求參數進行數據類型轉換深寥,然后在封裝到對應的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 對參數類型進行轉換持灰,執(zhí)行對應的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);
}
}
在使用了反射后,我們可以動態(tài)的去對請求的參數進行處理负饲,對其封裝堤魁,不在需要我們去手動的處理。
當然咯返十,這只是一個簡單屬性的封裝妥泉,其中還有一些需要優(yōu)化的部分洞坑。后期會給大家實現
struts2
的復雜javaBean
封裝功能、action
方法的選用以及自動轉發(fā)刽沾、重定向等侧漓。