首页 >> 知识 >> thymeleaf源码解读

thymeleaf源码解读

thymeleaf重要的三个组件 1 模版解析器 org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolverorg.thymeleaf.templateresolver.ITemplateResolver

AbstractConfigurableTemplateResolver实现了ITemplateResolver接口,是一个抽象类,是thymeleaf用来配置模板引擎的一些参数的,包括模板文件支持什么配置、前缀也就是存放位置,后缀,是否启用缓冲等配置

// 默认的model是html,支持 XML TEXT JAVASCRIPT CSS RAW public static final TemplateMode DEFAULT_TEMPLATE_MODE = TemplateMode.HTML;// 默认开启缓冲 public static final boolean DEFAULT_CACHEABLE = true;// 缓冲过期时间 public static final Long DEFAULT_CACHE_TTL_MS = null;// 前缀,实际是模板存放位置 private String prefix = null; // 后缀 private String suffix = null; private boolean forceSuffix = false; private String characterEncoding = null; // 模板别名存放在这里 private final HashMap templateAliases = new HashMap(8); // patthern private final PatternSpec xmlTemplateModePatternSpec = new PatternSpec(); private final PatternSpec htmlTemplateModePatternSpec = new PatternSpec(); private final PatternSpec textTemplateModePatternSpec = new PatternSpec(); private final PatternSpec javaScriptTemplateModePatternSpec = new PatternSpec(); private final PatternSpec cssTemplateModePatternSpec = new PatternSpec(); private final PatternSpec rawTemplateModePatternSpec = new PatternSpec(); private final PatternSpec cacheablePatternSpec = new PatternSpec(); private final PatternSpec nonCacheablePatternSpec = new PatternSpec();

使用可以用spring的SpringResourceTemplateResolver类,继承了AbstractConfigurableTemplateResolver

SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); templateResolver.setTemplateMode(TemplateMode.HTML); templateResolver.setCacheable(Boolean.FALSE); templateResolver.setPrefix("classpath:/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCacheTTLMs(3600000L); 2 模版引擎

thymeleaf的引擎驱动,执行入口

private static final int NANOS_IN_SECOND = 1000000; private volatile boolean initialized = false;// 方言配置 private final Set dialectConfigurations = new LinkedHashSet(3); // 模板解析器配置,是用一个set存储的 private final Set templateResolvers = new LinkedHashSet(3); // 消息解析器 private final Set messageResolvers = new LinkedHashSet(3); // 构造方法,会初始化默认的缓冲管理,引擎上下文驱动,方言等 public TemplateEngine() { super(); setCacheManager(new StandardCacheManager()); setEngineContextFactory(new StandardEngineContextFactory()); setMessageResolver(new StandardMessageResolver()); setLinkBuilder(new StandardLinkBuilder()); setDecoupledTemplateLogicResolver(new StandardDecoupledTemplateLogicResolver()); setDialect(new StandardDialect()); }

使用也简单,草莓视频在线观看APP主要是想要配置自己的解析器去找路径,所以只需要将上文的模板解析器赛进去就好

TemplateEngine templateEngine = new TemplateEngine();templateEngine.setTemplateResolver(templateResolver); 3 模板上下文 org.thymeleaf.context.IWebContext

与大多数上下文的功能一样,是theymeleaf携带存储数据的

WebContext ctx = new WebContext(request, response, servletContext, request.getLocale(),/**模板中配置的key规则数据载体*/variables);templateEngine.process(/**模版名称*/"home", ctx, response.getWriter());

只需要调用process,thymeleaf便会根据配置的Resolver路径找到模板并解析通过io返回

二 引擎process过程

org.thymeleaf.TemplateEngine#process process中主要关注三个地方,一个是初始化 configuration,一个是处理模板,最后是刷新io

if (!this.initialized) {// 1.初始化 configuration initialize(); } try { final long startNanos = System.nanoTime(); final TemplateManager templateManager = this.configuration.getTemplateManager(); // 2.找到模板并且处理 templateManager.parseAndProcess(templateSpec, context, writer); final long endNanos = System.nanoTime(); try { // 3.io刷新到请求页面 writer.flush(); } catch (final IOException e) { throw new TemplateOutputException("An error happened while flushing output writer", templateSpec.getTemplate(), -1, -1, e); }

initialize方法很简单,就是根据initialized这个状态码去判断是否初始化过configuration,然后将TemplateEngine中的那几个解析器塞到configuration中 templateManager模版管理器是调度process的地方

public void parseAndProcess(final TemplateSpec templateSpec,final IContext context,final Writer writer) { // 这一步很关键,获取ITemplateResolver绑定的ITemplateResource,thymeleaf通过ITemplateResource根据classpath去io读取模板数据 final TemplateResolution templateResolution = resolveTemplate(this.configuration, null, template, templateResolutionAttributes, true); // 构建templateData final TemplateData templateData = buildTemplateData(templateResolution, template, templateSelectors, templateMode, true); /* * 处理request与response放入到IEngineContext中,处理varilable */ final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, templateResolutionAttributes, context); /* * 真正执行模板解析的工具 */ final ITemplateParser parser = getParserForTemplateMode(engineContext.getTemplateMode());// ... // 解析模板 parser.parseStandalone( this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), processingHandlerChain); }

parser.parseStandalone最终会调用AbstractMarkupTemplateParser#parse方法,有两个关键,一个是读取模板,一个是解析模板

// 读取模板,会调用之前绑定的resource解析器Reader templateReader = (resource != null? resource.reader() : new StringReader(template));

SpringResourceTemplateResource#reader

public Reader reader() throws IOException {// spring resource 解析final InputStream inputStream = this.resource.getInputStream();if (!StringUtils.isEmptyOrWhitespace(this.characterEncoding)) { return new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream), this.characterEncoding));}return new BufferedReader(new InputStreamReader(new BufferedInputStream(inputStream)));}

解析模板

// Add the required reader wrappers in order to process parser-level and prototype-only comment blockstemplateReader = new ParserLevelCommentMarkupReader(new PrototypeOnlyCommentMarkupReader(templateReader));this.parser.parse(templateReader, handler);
网站地图