上篇說過,所有提交到web程式的url都被此UrlFilter攔截。攔截到請求後,UrlFilter則召集它的好多個得力幹將Router 們, 詢問他們:“誰能處理此URL啊 ?”
這時一位叫做AMP的Router 首當其衝 說:“這個url交給我了”。這時filter就會把此url全權交給AMPRouter來辦,至於如何去處理,filter也不再過問,它覺得:“我把任務都交給你了,怎麼解決是你的事”。
根據單一職責的原則,UrlFilter就負責上面情景中的分發url到Router中的差事,url如何分發交給Router處理。並且Router實際是一個介面,使用架構的使用者完全可以自己實現Router,這樣使用者可以自主定義的url分發的策略。另外呢,架構初始化的一些操作它也是 推脫不掉的,像根據unicorn-config.xml初始化系統中的Router和Action'。下面是具體的代碼:
@Overridepublic void init(FilterConfig config) throws ServletException {application = config.getServletContext();String loadPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();String classPath = loadPath.substring(1, loadPath.length());ArrayList<String> actions = XMLReader.getNodeValues(classPath + "unicorn-config.xml", "actions");this.initActions(actions);ArrayList<String> routers = XMLReader.getNodeValues(classPath + "unicorn-config.xml", "routers");this.initRouters(routers);}
@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;String path = request.getContextPath();String uri = request.getRequestURI();String relativeUri = uri.substring(path.length(), uri.length());this.request = request;this.session = request.getSession();this.response = (HttpServletResponse) servletResponse;// 使用者自訂的Router優先順序最高,url先通過使用者定義的Iterator<IPathRouter> iterator = routerList.iterator();while(iterator.hasNext()) {IPathRouter router = iterator.next();if(router.route(relativeUri, this)) {return ;}}// 攔截不到的繼續訪問filterChain.doFilter(servletRequest, servletResponse);}
其中Router類的初始化,Action類的初始化於這個類似:
private void initRouters(ArrayList<String> routers) {routerList = new ArrayList<IPathRouter>();for (int i = 0; i < routers.size(); i++) {String routerName = routers.get(i);try {Class<?> clz = Class.forName(routers.get(i));// 單例模式通過方法擷取對象執行個體IPathRouter router = (IPathRouter) clz.newInstance();routerList.add(router);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}// 最後把架構預設的Router加入進來routerList.add(new AMPPathRouter());}
其中unicorn-config.xml檔案的編寫,拿其中我一個項目裡的這個檔案來舉例:
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<routers>
<router class="com.mh.router.MySessionCheckRouter"></router>
</routers>
<actions>
<action class="com.mh.action.UserAction"></action>
<action class="com.mh.action.InformationAction"></action>
<action class="com.mh.action.UploadInformationIconAction"></action>
<action class="com.mh.action.TempPicAction"></action>
<action class="com.mh.action.MobileAction"></action>
</actions>
</config>
這裡即定義了Action,也定義了自己的Router,並且從名稱上可以看出,這個SessionCheckRouter是要判斷所有提交到伺服器的指定url的請求 是否已經登入過,沒有登入,可能會把此請求遣送會登入頁。以及初始化所有的Action,在Router處理完請求,分發給action時,可以從filter裡面去取。