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