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