用過 原生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;
}
}