浅说动态生成Class实现MVC
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
<h1>前言</h1> <p>java web的MVC,一個爛的不能再爛的一個話題了,可以說,現(xiàn)在市面上或者網(wǎng)上一搜,都有很多很優(yōu)秀的MVC框架。那么這里為什么還要寫一篇著相關(guān)的文章呢,在這介紹下本文的背景,之前幫一個朋友做個網(wǎng)站,由于本人只會java,所以就用java寫了一個,但是由于資金有限,只能找一些便宜的jsp空間,那么這樣隨之而來的問題就是,這樣的空間實在是給的東西有限,最主要的問題就是內(nèi)存不夠。所以就想,如果我不用任何框架,純servlet編寫,是否就能節(jié)約內(nèi)存和提高執(zhí)行效率,于是選擇了直接采用servlet編寫,但是這樣確實帶來很多維護(hù)和編程上的不便。于是就想能否寫一個MVC框架,在程序執(zhí)行之前按照規(guī)則自動生成各種代理類,那么在程序運行的時候就不需要什么反射,注入等等。既然目標(biāo)已經(jīng)確定,那么就按照這個思路繼續(xù)往下走吧,就是如何按照規(guī)則自動生成我們想要的class。</p> <h1>Action規(guī)則制定</h1> <p>首先我們希望定義Action的規(guī)則,他的主要作用就是告訴程序,不同的請求是由哪些類和方法處理的。看看下面的代碼: </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方式發(fā)送過來的請求;到到目前位置,這些注解有點Spring Mvc的味道了,接下來就是@UrlMapping的result和path屬性了,其實他的意思就是當(dāng)這個方法返回的是SUCCESS的時候采用"/servlet/test.jsp" 這個頁面做圖片的渲染。</p>
<p>接下來就是如何生成我們想要的代碼了,首先讓我們使用最原始的Servlet實現(xiàn)上面的功能,假設(shè)我們的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請求,那么我們應(yīng)該按照如下代碼做:</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中的注解的中所定義的請求轉(zhuǎn)發(fā)規(guī)則來自定生成代碼3。這樣就既能夠高效率的運行,減少系統(tǒng)運行時資源的損耗,同時也也能提高開發(fā)效率。 </p>
<p>我們也可以為事務(wù)做自動修改class,無非就是在方法前后加入事務(wù)啟動和事務(wù)提交的代碼;依賴注入的話就在構(gòu)造方法中生成注入的代碼等等. </p>
<h1>Class自動生成的策略</h1>
<p>有人也有疑問,就是我自動生成class,同樣也是消耗資源的。沒錯不僅僅消耗資源,而且還消耗的非常多。但是這種消耗是一次性的,也就是說我程序運行開始就將class生成好,以后就直接使用這個class而無需重復(fù)生成。但是有的時候server的配置實在太爛,或者我就是個極端主義者,我就是希望server損耗的越少越好。那么為此這個就有以下兩種策略供選擇: </p>
<h2>1.運行時自動生成Class </h2>
<p>程序運行開始將所有需要的class自動生成或者將修改后的class替換成原有的class。當(dāng)然這種方式的優(yōu)點就是開發(fā)階段快,但是弊端就是,我們無法在server中替換已經(jīng)load的class,并且大多數(shù)的server提供商也不讓你使用自定義系統(tǒng)級別的classloader,所以我們自動生成的class都將以反射的方式調(diào)用。 </p>
<h2>2.在開發(fā)階段自動生成Class</h2>
<p>在開發(fā)階段就自動生成class,然后打包到war包中,這樣在server上運行的時候使用我們生成的class就和一般的方法調(diào)用沒有任何區(qū)別,也就是這一點使得我們能夠規(guī)避掉策略1中的弊端。原則上講著一種方式在開發(fā)和打包這兩個階段中多了一個步驟,就是添加自動生成的class,但是由于項目采用MAVEN開發(fā),我們能夠編寫一個maven插件,自動的執(zhí)行自動生成類的打包。所以建議使用這種方式。 </p>
<h1>實現(xiàn)</h1>
<p>目前上述構(gòu)想已經(jīng)實現(xiàn),項目名稱為Wheel,而maven插件名稱為wheel-maven-plugin。但是wheel所使用的依賴包asmsupport-0.3-SNAPSHOT,classgrep-1.2-SNAPSHOT都還沒有release,還沒有發(fā)布到maven,所以需要手動maven install到本地的maven倉庫。各個包編譯打包順序如下: </p>
<ul> <ol>asmsupport執(zhí)行maven clean install</ol>
<ol>classgrep執(zhí)行maven clean install</ol>
<ol>wheel執(zhí)行maven clean install</ol>
<ol>wheel-maven-plugin執(zhí)行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正在醞釀發(fā)布第一個版本,而calssgrep-1.1和asmsupport-0.2都已經(jīng)發(fā)布,只是wheel所依賴的classgrep-1.2和asmsupport-0.3 這兩個新版本還為發(fā)布,后續(xù)也將補全新功能和bug陸續(xù)發(fā)布。 </p>
轉(zhuǎn)載于:https://my.oschina.net/wensiqun/blog/169494
總結(jié)
以上是生活随笔為你收集整理的浅说动态生成Class实现MVC的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)开源 Apache 服务器安全防护
- 下一篇: Linux vi格式化文件命令