以一個案例介紹反射機制的一種常見的使用場景,以及具體實現。
1.本文案例
在編寫Java Web應用程序時,使用表單提交數據是一個必不可少的環節,后台對於前台使用表單提交的數據需要能夠從請求中解析,並封裝到相應的實體中,也就是封裝到一個Java對象中。
那么,能否有某種方式使程序能夠自動的將表單提交的數據設置到一個相應的對象中呢?
2.創建用於提交表單的頁面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>利用反射自動填充數據</title> </head> <body> <form action="LoginServlet" method="POST"> <span>UserName: </span><input name="userName" type="text" /><br/> <span>Password: </span><input name="password" type="password"><br/> <button type="submit">Login</button> </form> </body> </html>
注意,此處的表單中的name屬性后面會用到,這個那么屬性,需要與存放這兩個值的class的屬性名稱相同
3.創建用於存放從表單提交的數據的類
創建一個 UserBean,其實就是個普通的Java類,其中包含與表單中屬性name值同名的屬性,並且有相應的 getter、setter方法
public class UserBean { @Override public String toString() { return "Username: " + this.userName + " Password: " + this.password; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } private String userName; private String password; }
這個UserBean中的 toString() 方法是為了測試的時候便於打印輸出而添加的,不是必須的
4.創建實現自動填充功能的工具類
接下來這步是關鍵部分了,能夠實現將表單數據自動填充到一個類中就主要是在這里實現了。
import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; public class AutoFillBeanUtil { public static <T> T fillBean(HttpServletRequest request, Class<T> cls) { T bean = null; try { bean = cls.newInstance(); Field[] fields = cls.getDeclaredFields(); for(Field field : fields) { String fieldName = field.getName(); Method method = cls.getDeclaredMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), String.class); String value = request.getParameter(fieldName); method.invoke(bean, value); } } catch(Exception e) { e.printStackTrace(); } return bean; } }
這里利用反射機制,首先獲取需要被填充的JavaBean(也就是這里的cls參數)的所有屬性,然后逐一嘗試從請求中獲取相應的參數,然后調用這個JavaBean的setter方法,將從請求中獲取的值設置到這個JavaBean中,最后返回這個JavaBean。
5.創建接受表單請求的Servlet進行測試
接下來創建用於接受表單請求的Servlet,然后在Servlet中調用這個實現,測試效果
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.oolong.javawebreflect.bean.UserBean; import com.oolong.javawebreflect.util.AutoFillBeanUtil; @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public LoginServlet() { super(); } protected void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("Served at: ") .append(request.getContextPath()); } protected void doPost(HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException { UserBean bean = AutoFillBeanUtil.fillBean(request, UserBean.class); System.out.println(bean.toString()); doGet(request, response); } }
這里可以看到,調用了
UserBean bean = AutoFillBeanUtil.fillBean(request, UserBean.class);
然后會從請求中將表單中的數據解析出來,填充到一個UserBean中,之后會打印這個UserBean中的內容,查看是否獲取成功。
結果:
控制台打印:
測試成功!