浅说动态生成Class实现MVC
2019獨角獸企業重金招聘Python工程師標準>>>
<h1>前言</h1> <p>java web的MVC,一個爛的不能再爛的一個話題了,可以說,現在市面上或者網上一搜,都有很多很優秀的MVC框架。那么這里為什么還要寫一篇著相關的文章呢,在這介紹下本文的背景,之前幫一個朋友做個網站,由于本人只會java,所以就用java寫了一個,但是由于資金有限,只能找一些便宜的jsp空間,那么這樣隨之而來的問題就是,這樣的空間實在是給的東西有限,最主要的問題就是內存不夠。所以就想,如果我不用任何框架,純servlet編寫,是否就能節約內存和提高執行效率,于是選擇了直接采用servlet編寫,但是這樣確實帶來很多維護和編程上的不便。于是就想能否寫一個MVC框架,在程序執行之前按照規則自動生成各種代理類,那么在程序運行的時候就不需要什么反射,注入等等。既然目標已經確定,那么就按照這個思路繼續往下走吧,就是如何按照規則自動生成我們想要的class。</p> <h1>Action規則制定</h1> <p>首先我們希望定義Action的規則,他的主要作用就是告訴程序,不同的請求是由哪些類和方法處理的。看看下面的代碼: </p> <pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼1: @Action("/MockServlet") public class MockServletAction {
@UrlMapping(value="/execute.action",method="GET",result="SUCCESS",path="/servlet/test.jsp" ) public String execute() throws IOException {return "SUCCESS"; }}</pre>
<p>這段代碼很容易讀懂,@Action注解告訴程序,所有以/MockServlet開頭的請求由這個類處理,而@UrlMapping中的value告訴程序在/MockServlet之后又是"/execute.action"由execute()這個方法處理,并且必須是GET方式發送過來的請求;到到目前位置,這些注解有點Spring Mvc的味道了,接下來就是@UrlMapping的result和path屬性了,其實他的意思就是當這個方法返回的是SUCCESS的時候采用"/servlet/test.jsp" 這個頁面做圖片的渲染。</p>
<p>接下來就是如何生成我們想要的代碼了,首先讓我們使用最原始的Servlet實現上面的功能,假設我們的Action沒有任何注解,代碼如下: </p>
<pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼2: public class MockServletAction { public String execute() throws IOException { return "SUCCESS"; } }</pre>
<p>我們同樣想讓這個Action去處理/MockServlet/execute.action這個GET請求,那么我們應該按照如下代碼做:</p>
<pre style="overflow: auto" class="brush:java;gutter:true;first-line:1;tab-size:4;toolbar:true;">代碼3: public class ActionServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String servletPath = req.getServletPath(); if(servletPath.equals("/MockServlet/execute.action")){ String result = new MockServletAction().execute(); if(result.equals("SUCCESS")){ req.getRequestDispatcher("/servlet/test.jsp").forward(request, response); } } } }</pre>
<p>通過上面就能夠明白,我們希望有這么一個框架,它能夠通過代碼1中的注解的中所定義的請求轉發規則來自定生成代碼3。這樣就既能夠高效率的運行,減少系統運行時資源的損耗,同時也也能提高開發效率。 </p>
<p>我們也可以為事務做自動修改class,無非就是在方法前后加入事務啟動和事務提交的代碼;依賴注入的話就在構造方法中生成注入的代碼等等. </p>
<h1>Class自動生成的策略</h1>
<p>有人也有疑問,就是我自動生成class,同樣也是消耗資源的。沒錯不僅僅消耗資源,而且還消耗的非常多。但是這種消耗是一次性的,也就是說我程序運行開始就將class生成好,以后就直接使用這個class而無需重復生成。但是有的時候server的配置實在太爛,或者我就是個極端主義者,我就是希望server損耗的越少越好。那么為此這個就有以下兩種策略供選擇: </p>
<h2>1.運行時自動生成Class </h2>
<p>程序運行開始將所有需要的class自動生成或者將修改后的class替換成原有的class。當然這種方式的優點就是開發階段快,但是弊端就是,我們無法在server中替換已經load的class,并且大多數的server提供商也不讓你使用自定義系統級別的classloader,所以我們自動生成的class都將以反射的方式調用。 </p>
<h2>2.在開發階段自動生成Class</h2>
<p>在開發階段就自動生成class,然后打包到war包中,這樣在server上運行的時候使用我們生成的class就和一般的方法調用沒有任何區別,也就是這一點使得我們能夠規避掉策略1中的弊端。原則上講著一種方式在開發和打包這兩個階段中多了一個步驟,就是添加自動生成的class,但是由于項目采用MAVEN開發,我們能夠編寫一個maven插件,自動的執行自動生成類的打包。所以建議使用這種方式。 </p>
<h1>實現</h1>
<p>目前上述構想已經實現,項目名稱為Wheel,而maven插件名稱為wheel-maven-plugin。但是wheel所使用的依賴包asmsupport-0.3-SNAPSHOT,classgrep-1.2-SNAPSHOT都還沒有release,還沒有發布到maven,所以需要手動maven install到本地的maven倉庫。各個包編譯打包順序如下: </p>
<ul> <ol>asmsupport執行maven clean install</ol>
<ol>classgrep執行maven clean install</ol>
<ol>wheel執行maven clean install</ol>
<ol>wheel-maven-plugin執行maven clean install</ol> </ul>
<p>這里也有一個簡單是實例WheelSampleApp, 里面展示了大部分的功能,如AOP,注入等等。</p>
<p>以上涉及到的項目的源碼地址:</p>
<ul> <ol><b>asmsupport:</b>http://code.taobao.org/svn/asmsupport/trunk</ol>
<ol><b>classgrep:</b>http://code.taobao.org/svn/classgrep/trunk</ol>
<ol><b>wheel:</b>http://code.taobao.org/svn/wheel/trunk</ol>
<ol><b>wheel-maven-plugin:</b>http://code.taobao.org/svn/wheel-maven-plugin/trunk</ol>
<ol><b>WheelSampleApp:</b>http://code.taobao.org/svn/WheelSampleApp/trunk</ol> </ul>
<p>Wheel和wheel-maven-plugin正在醞釀發布第一個版本,而calssgrep-1.1和asmsupport-0.2都已經發布,只是wheel所依賴的classgrep-1.2和asmsupport-0.3 這兩個新版本還為發布,后續也將補全新功能和bug陸續發布。 </p>
轉載于:https://my.oschina.net/wensiqun/blog/169494
總結
以上是生活随笔為你收集整理的浅说动态生成Class实现MVC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)开源 Apache 服务器安全防护
- 下一篇: Linux vi格式化文件命令