如果你知道怎么做,这实际上是一件容易的事。你需要的一切都已经嵌入到 FreeMarker 中,例如它是TaglibFactory.ClasspathMetaInfTldSource
类。我花了几个小时来调查这个问题,所以我想分享一个解决方案。
我实现它是BeanPostProcessor
因为现在无法在bean 初始化TaglibFactory
之前进行设置。FreeMarkerConfigurer
import freemarker.ext.jsp.TaglibFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* A {@link BeanPostProcessor} that enhances {@link FreeMarkerConfigurer} bean, adding
* {@link freemarker.ext.jsp.TaglibFactory.ClasspathMetaInfTldSource} to {@code metaInfTldSources}
* of {@link TaglibFactory}, containing in corresponding {@link FreeMarkerConfigurer} bean.
*
* <p>
* This allows JSP Taglibs ({@code *.tld} files) to be found in classpath ({@code /META-INF/*.tld}) in opposition
* to default FreeMarker behaviour, where it searches them only in ServletContext, which doesn't work
* when we run in embedded servlet container like {@code tomcat-embed}.
*
* @author Ruslan Stelmachenko
* @since 20.02.2019
*/
@Component
public class JspTagLibsFreeMarkerConfigurerBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof FreeMarkerConfigurer) {
FreeMarkerConfigurer freeMarkerConfigurer = (FreeMarkerConfigurer) bean;
TaglibFactory taglibFactory = freeMarkerConfigurer.getTaglibFactory();
TaglibFactory.ClasspathMetaInfTldSource classpathMetaInfTldSource =
new TaglibFactory.ClasspathMetaInfTldSource(Pattern.compile(".*"));
taglibFactory.setMetaInfTldSources(Arrays.asList(classpathMetaInfTldSource));
// taglibFactory.setClasspathTlds(Arrays.asList("/META-INF/tld/common.tld"));
}
return bean;
}
}
唯一的限制是*.tld
文件里面必须有<uri>
xml 标签。所有标准的弹簧/弹簧安全 TLD 都有它。而且这些文件必须在META-INF
类路径的文件夹中,比如META-INF/mytaglib.tld
. 所有标准 spring/spring-security TLD 也都遵循此约定。
注释行仅举例说明*.tld
如果由于某种原因您不能将它们放置到标准位置(可能是一些不符合约定的外部 jar),您如何添加文件的“自定义”路径。它可以扩展到某种类路径扫描,搜索所有*.tld
文件并将它们添加到classpathTlds
. META-INF
但通常,如果您的 TLD 遵循 JSP 约定放置在目录中,则不需要这样做。
我已经在我的 FreeMarker 模板中对此进行了测试,它可以工作:
<#assign common = JspTaglibs["http://my-custom-tag-library/tags"]>
<#assign security = JspTaglibs["http://www.springframework.org/security/tags"]>
<#assign form = JspTaglibs["http://www.springframework.org/tags/form"]>
<#assign spring = JspTaglibs["http://www.springframework.org/tags"]>
要使自定义标签(“ http://my-custom-tag-library/tags ”)起作用,它必须是*.tld
文件,src/main/resources/META-INF/some.tld
并且它必须包含<uri>
xml 标签,例如<uri>http://my-custom-tag-library/tags</uri>
. 然后它会被 FreeMarker 找到。
我希望它可以帮助某人节省几个小时来为这个问题找到“正确”的解决方案。
使用 spring-boot v2.0.5.RELEASE 测试