通過前面幾回反射機制的學習,此次用反射的知識寫一個相似於Struts框架處理機制的小demo。html
在引入反射知識前,先簡單介紹下Sturts框架和Servlet。
在沒有一些Web框架以前,當咱們要寫Java Web應用使用的就是Servlet。一個簡單的Servletdemo就是以下所示。前端
public class HelloWorld extends HttpServlet { private String message; public void init() throws ServletException { message = "Hello World"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<h1>" + message + "</h1>"); } public void destroy() { } }
servlet會提供出來doGet和doPost,同時接收用戶傳入的參數,進行業務處理,再返回視圖。那麼Servlet如何與URL對應起來呢,答案就是在web.xml,綁定servlet和url之間的映射關係。java
<servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/HelloWorld</url-pattern> </servlet-mapping>
映射、業務邏輯處理、視圖返回所有在servlet中完成,耦合度比較高,隨着url的增多,servlet會愈來愈多,須要在web.xml配置不少映射關係,不利於維護。同時servlet的入參以及返回的參數很依賴於當前運行的容器,自己也是線程不安全的,當入參很是多時,須要屢次調用getParm方法,代碼很冗餘。
以後Struts框架誕生,經過統一的ActionServlet處理具體的url請求和參數映射以及根據不一樣的返回結果跳轉不一樣的視圖,開發者只須要關心本身的業務邏輯,就能夠實現web應用的開發。具體的Struts的配置文件,大體以下面XML所示。web
<?xml version="1.0" encoding="UTF-8"?> <struts> <action name="login" class="com.coderising.kailuncen.LoginAction"> <result name="success">/jsp/homepage.jsp</result> <result name="fail">/jsp/showLogin.jsp</result> </action> <action name="logout" class="com.coderising.kailuncen.LogoutAction"> <result name="success">/jsp/welcome.jsp</result> <result name="error">/jsp/error.jsp</result> </action> </struts>
咱們只須要分別實現視圖和業務邏輯,再經過struts將他們綁定起來,就能夠完成開發工做,也更便於理解,方便維護。有興趣的讀者能夠自行深刻學習下servlet和struts的思想。後端
我想寫的小demo就是利用讀取xml,利用反射加載不一樣的action,進行業務邏輯處理,最後輸出返回的視圖,整個邏輯思路仍是比較簡單,純當反射學習的練手。
首先是定義配置類,把xml中action對應的映射關係保存下來安全
private class ActionConfig { private String name; private String className; private Map<String, String> viewResult = new HashMap<>();
當初始化讀取xml完畢後,獲得以下結構,action的名字對應着具體的action配置app
Map<String, ActionConfig> actionConfigMap = new HashMap<>();
模擬Struts ActionServlet的運做方式框架
public View runAction(String actionName, Map<String, String> params) { String className = cfg.getClassName(actionName); if (className == null) { return null; } try { Class<?> clz = Class.forName(className); Object action = clz.newInstance(); ReflectionUtil.invokeSetMethods(action, params); String resultName = (String) clz.getDeclaredMethod("execute").invoke(action); Map<String, Object> result = ReflectionUtil.invokeGetMethods(action); String resultView = cfg.getViewResult(actionName, resultName); return new View(resultView, result);
經過actionName從配置類中拿到具體的執行類的全類名,其實Struts框架就是直接解析url,而後對應到xml配置的對應action名稱,將url和具體的執行類綁定在一塊兒。
以後是使用Class.forName建立類類型,而後建立對應的實例。ReflectionUtil裏面作的事情就是,先獲取action中對應的field的Name,而後從變量中,根據filed名稱找對應的值,而後使用set方法對action的field進行賦值操做,就是LoginAction中的相關信息。jsp
public class LoginAction { private String name; private String password; private String message;
這一步就省去了使用servlet時,重複去get賦值的繁瑣操做,利用反射機制,直接對成員變量進行賦值,開發者只須要將前端會傳入的參數名稱和後端類中的名稱作好事先的確認便可。
而後就是經過反射調用execute方法,使用了Method.invoke方法。再次使用反射獲取field的最新值,組成map返回,同時根據方法的返回值,去actionConfigMap中獲取對應的view。
最後根據field的返回值map和view的名稱組成最終展現的視圖。學習
以上其實就是根據反射知識模仿的struts核心運行流程的小demo,整個web框架處理了很是多的其餘的事情好比參數映射,安全,Json處理等,若是有興趣,能夠進一步作學習。