寫一個自己的視圖解析器-MyView

用過 原生jsp 的解析器?用過 Thymeleaf ?用過 Freemark ?隨心所欲,好,我們寫一個自己的視圖解析器吧

/**
*	首先實現 ViewResolver
*	實現 Ordered 優先加載我們自己的隨心所欲視圖解析器
*/
// 聲明成組件,讓掃描器掃到,大功告成
@Component 
public class MyView implements ViewResolver, Ordered {

	// 用來緩存頁面,這樣就不用每次都讀模版文件,減少IO
	// key是視圖路徑,value是html文本內容
	// 當然你這裏可以用redis、memcached 等等,隨心所欲
    Map<String, String> cache = new HashMap<>();
	// 路徑前綴 這裏是放在 resources 下,也就是打包之後的classpath下,當然你也可以放在任何盤符之下
    private String prefix = "static/pages";
    // 模版文件後綴
    private String suffix = ".html";
    // 是否要緩存模版,開發環境當然 不
    private boolean cached = false;

    @Override
    public int getOrder() {
    	// 最先加載
        return 1;
    }

	/**
	* view:controller return過來的視圖地址
	* locale:國際化環境
	*/
    @Override
    public View resolveViewName(String view, Locale locale) {
    	// 直接實現接口,返回視圖
        return new View() {
			// 最重要的方法,渲染頁面
            @Override
            public void render(Map<String, ?> map, HttpServletRequest request, HttpServletResponse response) {
                String html = getHtml(view);
                // 設置響應頭
                response.setContentType("text/html;charset=utf-8");
                try {
                // 寫數據到瀏覽器
                    IOUtils.write(html, response.getOutputStream(), "UTF-8");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

			// 設置可以處理的request格式
            @Override
            public String getContentType() {
                return "text/html";
            }
        };
    }

	// 實現的主要方法
    private String getHtml(String path) {
    	// 緩存中取
        String s = cache.get(path);
        if (null == s) {
            try {
            	// 獲取模版文件
                ClassPathResource resource = new ClassPathResource(prefix + path + suffix);
                // 讀取爲字符串
                s = IOUtils.toString(resource.getInputStream(), "UTF-8");
            } catch (FileNotFoundException e) {
                throw new NullPointerException(String.format("視圖[%s]不存在", path));
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 處理包含標籤
            s = processInclude(s);

            if (cached) {
                cache.put(path, s);
            }
        }
        return s;
    }

	/**
	* jstl有 include標籤,我們的隨心所欲當然也不能少,至於其他標籤,自己實現吧
	*/
    private String processInclude(String s) {
    	// 這則匹配,並且分組
    	// 例: 
    	// <p>123</p>
    	// <include   src="test.html" />
    	// <p>123</p>
        Matcher matcher = Pattern.compile("\\<include\\s+src\\=[\"|\'](.+?)[\"|\']\\s+\\/\\>").matcher(s);

        while (matcher.find()) {
            String source = matcher.group();
            String path = matcher.group(1);
            String html = getHtml(path);
            s = s.replace(source, html);
        }

        return s;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章