Freemarker知识点整理

关于自定义Directive的介绍:https://freemarker.apache.org/docs/pgui_datamodel_directive.html

还可以这样初始化:

<#-- Maybe you have directives that you have implemented in FTL -->
<#macro something>
  ...
</#macro>

<#-- Now you can't use <#macro upper>, but instead you can: -->
<#assign upper = "com.example.UpperDirective"?new()>

?new()一个directive

标准上还是用Configuration.setSharedVariable("content",contentDirective); 这种写法比较好。

(2) Directive设定输出内容时,c为null时也需要输出,这样页面才能通过

[#if value??]进行为空的判断
env.setVariable("value", ObjectWrapper.DEFAULT_WRAPPER.wrap(c));

(3)自定义组件控制内容输出,freemarker自定义权限检查逻辑也可用这种机制实现
                [@content_attach_list type="doc"]
                    附件列表:
                    [#list value as item]
                        <p>附件${item_index+1}:<a href="${item.attachPath}" target="_blank">${item.attachOriname}</a></p>
                    [/#list]
                [/@content_attach_list]

如自定义附件列表组件,若想没有附件时不显示附件列表文字,需要在自定义组件控制输出:

        //没有数据则不输出组件内容
        if (body != null && list!= null && !list.isEmpty()) {
            body.render(env.getOut());
        }

 (4)自定义组件加入freemarker配置

方法1:直接加入,页面可直接用content_attach_list作为名字

configuration.setSharedVariable("content_attach_list",contentAttachListDirective);

方法2:通过hash加入,一次性加入多个,这样页面可以使用cms.hasPermission,cms.hasAnyRoles等形式访问组件

configuration.setSharedVariable("cms", new ShiroTags());

//其中ShiroTags为
public class ShiroTags extends SimpleHash {
    public ShiroTags() {
        this.put("authenticated", new AuthenticatedTag());
        this.put("guest", new GuestTag());
        this.put("hasAnyRoles", new HasAnyRolesTag());
        this.put("hasPermission", new HasPermissionTag());
    }
}

 (5) 与SpringBoot+Freemarker 国际化支持

  需要注意freemarker的一个配置项(默认为true,但有的项目可能设置为了false):

spring.freemarker.expose-spring-macro-helpers=true

需要为true,否则spring.ftl中的springMacroRequestContext会找不到。
另外通过application.properties设定message路径不起作用(Springboot 2.0.5),

    spring.messages.basename=i18n/messages
    spring.messages.encoding=UTF-8

经过debug时发现,在org.springframework.context.support.AbstractApplicationContext中初始化MessageSource是按beanName来找的,调试发现没有找到,
不太清楚为啥,感觉可能是版本问题,找不到然后就用的Empty的资源类,那肯定是找不到对应的消息的【此处SpringBoot处理的不太好,还不如报个错了,弄个空的类,搞的莫名其妙】
	protected void initMessageSource() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			DelegatingMessageSource dms = new DelegatingMessageSource();
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;

 

因此改为通过java配置设定,代码如下:
@Configuration
public class WebConfig implements WebMvcConfigurer {
    ...

    @Bean
    public MessageSource messageSource(){
        //wanghc 
        //设定文件加载类,通过配置文件设置无效,在此处直接通过bean来设定
        //注意,必须为messageSource这个bean名字才可以
        //另外文字可直接写入配置文件,指定编码即可,不需要再转换文件ascii了
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("i18n/messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }



posted on 2021-01-21 22:41  webjlwang  阅读(172)  评论(0编辑  收藏  举报

导航