【step by step 構建輕量級web框架】MVC模塊的實現

本系列博文,將會一步一步介紹如何構建一個輕量級的web框架jbeer git地址:http://git.oschina.net/bieber/jbeer前端

本文主要分享一下在JBeer中MVC模塊的Controller解析,主要分享JBeer如何解析一個Controller,映射到各個action處理的路徑以及Request參數注入。 ###1、Controller解析### 下面列舉出簡單的Action實例<br/>java

<!-- lang: java -->
@Controller(urlPattern="/first")
public class FirstController extends BaseController{


@Action(urlPatterns="invoke_${id}_${name}.htm")
public String pathParam(@PathParam("id")Integer id,@PathParam("name")String name){
    
    return "view";
}
}

下面對框架解析一個Controller以及分析Action進行分享:<br/> 一) 應用啓動,觸發JBeerWeb的init()方法<br/> 二) 經過ClassUtils的scanClassesByAnnotation方法獲取全部註解了@Controller的類,並解析類中方法,並判斷是否被@Action註解過。<br/> 三) 對每一個註解了@Action的方法,生成一個ActionEntity,該類中描述了一個Action接受的處理路徑,須要調用哪一個方法以及是哪一個controller類。下面粘貼處ActionEntity的類定義:<br/>git

<!-- lang:java -->
/**
 * action須要調用的方法對象
 */
private Method actionInvokeMethod;

/**
 * action須要調用的className
 */
private String controllerClassName;
/**
 * 存儲當前Action的方法參數信息
 */
private Collection<ActionMethodParam> methodParams;
/**
 * 當前Action處理的請求方式
 */
private RequestType requestType;


/**
 * 當前Action能夠匹配的請求路徑集合
 */
private Collection<PatternableUrl> patternedUrls;

其中定義了該Action方法觸發的上下文。上面對一些屬性進行了封裝,好比方法入參和匹配的路徑。web

一、ActionMethodParam封裝了Action的各個入參信息,若是Action沒有入參,則methodParams爲空,下面看看ActionMethodParam中定義了什麼<br/>正則表達式

<!-- lang:java -->
 /**
	 * 方法參數名
	 */
 private String paramName;
	/**
	 * 方法參數位置
	 */
	private int paramIndex;

	private Class<?> parameterType;
	/**
	 * 關聯的ID,能夠是bean的ID,也能夠是引用Properties或者IN18消息信息
	 */
	private String refId;
	
	private String[] in18Args;

paramName表示匹配url上面佔位符的內容,paramIndex表示該參數是Action的第幾個位置的入參,parameterType是參數的類型,用於進行類型轉換,上面三個屬性就能夠完成在路徑上進行佔位符配置的參數注入。而refId則是經過配置@RefBean,@Properties或者@Message註解來關聯框架內的資源,好比依賴一個bean,配置信息等。而in18Args是當引用的是IN18的message配置信息時候,須要傳遞的參數。經過上面幾個參數,就能夠實現Action的入參的實際來源。數組

二、PatternableUrl定義了匹配路徑的信息,具體定義以下:框架

<!-- lang:java -->
/**
	 * 匹配路徑的正則表達式
	 */
	private String urlMatcher;
	/**
	 * 配置的url路徑佔位符相關信息
	 */
	private Collection<URLParam> urlParams;

其中urlMatcher是待匹配的路徑正則表達式,而urlParams則是路徑上面的參數信息。關於URLParam定義信息以下:工具

<!-- lang:java -->
/**
		 * 佔位符參數名
		 */
		private String paramName;
		/**
		 * 佔位符參數所在的位置是第幾個,方面在請求時,肯定第幾個佔位符的值是當前參數的值
		 */
		private int urlParamIndex;

上面經過解析配置的url,獲取佔位符中的內容賦值到paramName中,以及記錄當前佔位符的位置(urlParamIndex)。這裏的paramName是和ActionMethodParam中的paramName保持一直的,否則沒法匹配對應的路徑參數值。url

到此,當一個請求路徑,經過匹配ActionEntity.patternedUrls集合中的某一個來肯定當前的ActionEntity是否可以處理當前一個請求,若是匹配經過,那麼在解析請求的路徑,從而實例化須要傳入Action方法的入參。<br/> 四)當解析完畢Controller中的Action後,那麼將會把Contrller放入到IOC容器中,後面須要引用Controller類的實體,將會從IOC中獲取。 ###2、Request參數注入### Jbeer框架的參數注入提供了兩種方式,一種是經過配置Controller非單例模式,框架自動注入到Controller類的屬性,這點相似struts2的風格。第二種是Controller單例模式,開發人員經過框架提供的工具類來獲取Request請求的參數。下面對這兩種原理進行介紹。 首先來看看JBeer是如何處理用戶一個請求的吧。 處理請求時序圖.net

上圖闡述了框架在接收到一個請求,通過哪些過程來進行處理。那麼ControllerInitialization負責對Controller的實例化,包括對Controller對象的實例化(從IOC容器中獲取)和Action方法參數的實例化。而Request參數注入發生在generateController方法中,而initActionMethodParams方法則是初始化Action方法的參數。下面將主要分享這兩個方法。 ####一)、generateController####

  1. 從IOC容器中獲取Controller實體,IOC將會根據該實體是單例仍是非單例進行初始化Controller實體,IOC將會注入Controller依賴的Bean。<br>
  2. 獲取Request中的全部參數(分包含上傳文件和普通POST/GET請求),將全部參數封裝到一個Map<String,Object>(其中文件上傳的文件也在其中)。<br/>
  3. 分析步驟2獲得的Map<String,Object>對象,咱們知道前端傳遞過來的參數是鍵值對的,好比name="bieber",user.name="bieber",names[0]="bieber0"或者users[0].name="bieber0"這種形式,這三種分別表示普通的鍵值對,對象的屬性鍵值對,數組形式鍵值對,對象數組鍵值對。上面這種層級關係,能夠經過對象引用樹來進行分析,那麼能夠假設這些對象屬性的公共父節點是Controller實體,那麼name則是這個Controller的字符串屬性,user則是Controller的對象屬性,一次類推names,users則是對象的數組屬性或者是集合。下面則給出下面樹形結構圖。 對象引用樹 那麼分析Map<String,Object>的目的,就是把無結構Map解析成樹形結構。經過「.」來對Map的key進行分析,以及經過正則表達式來匹配key是否存在\[[0-9]{1,}\]結構,能夠分析每一個.則是一個樹的分層,.以前的是父節點,以後的是子節點。經過該步驟對Map<String,Object>分析,會獲得樹的第一層子節點。Map<String,Object>若是其中key對不包含.,其value則是一個Object[]數組,若是包含.,則value則是一個Map<String,Object>[]數組。這兩經過樹的深度優先遍歷,可完成整個Request參數注入。固然,這一步先只分析一個深度,並把獲得的Map<String,Object>放到JBeerWebContext中。<br/>
  4. 判斷框架的Controller是不是單例模式,若是是單例模式,則不自動將步驟3分析獲得的Map<String,Object>自動注入到Controller的對應屬性中。若是是單例,則完成自動注入。
  5. 當單例模式的時候,能夠經過RequestParameterUtil來手動獲取請求參數。下圖展現了提供的接口。 <br/> ####二)、initActionMethodParams#### 該方法則是完成url上面的參數(經過@PathParam來指定參數名),以及系統層面的參數(好比:HttpServletRequest,HttpServletResponse等等)。分析規則,則是按照解析Action方法時生成的對應信息。具體可見上面內容。<br/>

關於具體實現,還但願經過項目源碼進行分析,此處只是進行簡單的分享。若是有什麼意見還但願你們可以提點意見。

相關文章
相關標籤/搜索