• Freemarker


    Spring Boot整合

    添加pom依赖
    
    	<!-- springboot整合freemarker -->
    	<dependency>
    	    <groupId>org.springframework.boot</groupId>
    	    <artifactId>spring-boot-starter-freemarker</artifactId>
    	</dependency>
    
    
    在application.yml中添加相关配置
    
    	spring:
    	  # 配置freemarker
    	  freemarker:
    	    # 设置模板后缀名
    	    suffix: .ftl
    	    # 设置文档类型
    	    content-type: text/html
    	    # 设置页面编码格式
    	    charset: UTF-8
    	    # 设置页面缓存
    	    cache: false
    	    # 设置ftl文件路径
    	    template-loader-path:
    	      - classpath:/templates
    	  # 设置静态文件路径,js,css等
    	  mvc:
    	    static-path-pattern: /static/**
    
    
    # FREEMARKER (FreeMarkerAutoConfiguration)
    spring.freemarker.allow-request-override=false
    spring.freemarker.allow-session-override=false
    spring.freemarker.cache=false
    spring.freemarker.charset=UTF-8
    spring.freemarker.check-template-location=true
    spring.freemarker.content-type=text/html
    spring.freemarker.enabled=true
    spring.freemarker.expose-request-attributes=false
    spring.freemarker.expose-session-attributes=false
    spring.freemarker.expose-spring-macro-helpers=true
    spring.freemarker.prefer-file-system-access=true
    spring.freemarker.suffix=.ftl
    spring.freemarker.settings.template_update_delay=0
    spring.freemarker.settings.default_encoding=UTF-8
    spring.freemarker.settings.classic_compatible=true
    spring.freemarker.order=1
    # spring boot 默认的页面模板存放目录
    spring.freemarker.template-loader-path=classpath:/templates/
    

    自定义函数(继承 TemplateMethodModelEx 接口)

    1 创建自定义函数类
    
    	public class TemplateMethd implements TemplateMethodModelEx {
    	    @Override
    	    public Object exec(List list) throws TemplateModelException {
    	        SimpleSequence simpleSequence = (SimpleSequence) list.get(0);
    	        List<BigDecimal> list1 = simpleSequence.toList();
    	        Collections.sort(list1, (a, b) -> { return a.intValue() - b.intValue();});
    	        return list1;
    	    }
    	}
    
    2 将自定义函数对象传到模版中
    
    	modelAndView.setViewName("index");
    	modelAndView.addObject("sort_int_list", new TemplateMethd());
    	return modelAndView;
    
    3 在模版中使用
    
    	<#assign myList=[1,4,5,2,3,7,5,9,0]/>
    	<#list sort_int_list(myList) as item>
    	    ${item}
    	</#list>
    

    自定义标签(解决公共数据集合的重复代码问题)

    在 freemarker 中实现自定义的标签,主要就是靠 TemplateDirectiveModel 类。
    
    如字面意思:模板指令模型,主要就是用来扩展自定义的指令。
    
    public interface TemplateDirectiveModel extends TemplateModel {
    
       public void execute(Environment env, Map params, TemplateModel[] loopVars, 
                TemplateDirectiveBody body) throws TemplateException, IOException;
    }
    
    
    TemplateDirectiveModel 是一个接口,类中只有一个 execute 方法供使用者实现,而我们要做的就是通过实现 execute 方法,实现自定义标签的功能。
    当页面模板中使用自定义标签时,会自动调用该方法。
    
    
    execute 方法的参数含义:
    
        env : 
        	表示模板处理期间的运行时环境。
        	该对象会存储模板创建的临时变量集、模板设置的值、对数据模型根的引用等等,通常用它来输出相关内容,如Writer out = env.getOut()。
        
        params : 
        	传递给自定义标签的参数(如果有的话)。其中map的key是自定义标签的参数名,value值是TemplateModel实例。
        
        loopVars : 
        	循环替代变量(未发现有什么用)
        
        body : 
        	表示自定义标签中嵌套的内容。说简单点就是自定义标签内的内容体。
        	如果指令调用没有嵌套内容:
        		例如,就像<@myDirective/>或者<@myDirective></mydirective>
        	那么这个参数就会为空。
    
    
    一、实现 TemplateDirectiveModel 接口
    
    	@Component
    	public class CustomTagDirective implements TemplateDirectiveModel {
    
    	    private static final String METHOD_KEY = "method";
    
    	    @Autowired
    	    private BizTagsService bizTagsService;
    
    	    @Override
    	    public void execute(Environment environment, Map map, TemplateModel[] templateModels, TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
    	        if (map.containsKey(METHOD_KEY)) {
    				DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
    	            String method = map.get(METHOD_KEY).toString();
    	            switch (method) {
    	                case "tagsList":
    						// 将数据对象转换成对应的TemplateModel
    	                    TemplateModel tm = builder.build().wrap(bizTagsService.listAll())
    	                    environment.setVariable("tagsList", tm);
    	                    break;
    					case other...
    	                default:
    	                    break;
    	            }
    	        }
    	        templateDirectiveBody.render(environment.getOut());
    	    }
    	}
    
    二、创建 freemarker 的配置类
    
    	@Configuration
    	public class FreeMarkerConfig {
    
    	    @Autowired
    	    protected freemarker.template.Configuration configuration;
    
    	    @Autowired
    	    protected CustomTagDirective customTagDirective;
    
    	    /**
    	     * 添加自定义标签
    	     */
    	    @PostConstruct
    	    public void setSharedVariable() {
    			/*
    			 * 向freemarker配置中添加共享变量;
    			 * 它使用 Configurable.getObjectWrapper() 来包装值,因此在此之前设置对象包装器是很重要的。(即上一步的builder.build().wrap操作)
    			 */
    	        configuration.setSharedVariable("zhydTag", customTagDirective);
    	    }
    	}
    
    三、ftl模板中使用自定义标签
    
    	<@zhydTag method="tagsList">
    		<#if tagsList?? && (tagsList?size > 0)>
    			<#list tagsList as item>
    				<li>
    					<a href="${config.siteUrl}/tag/${item.id}" title="${item.name!}">
    						${item.name!}
    					</a>
    				</li>
    			</#list>
    		</#if>
    	</@zhydTag>
    
    
    自定义标签的使用方法跟自定义宏(macro)用法一样,直接使用<@标签名>${值}</@标签名>即可。
    
    注:ftl中通过@调用自定义标签时,后面可以跟任意参数,所有的参数都可以在execute方法的第二个参数(map)中获取,
    由此可以根据一个特定的属性开发一套特定的自定义标签,比如上面代码中通过method参数判断调用不同的处理方式。
    
    
    @Component
    public class MenuTagDirective implements TemplateDirectiveModel {
    
        private static final String METHOD_KEY = "method";
    
        private final MenuService menuService;
    
        public MenuTagDirective(Configuration configuration, MenuService menuService) {
            this.menuService = menuService;
            configuration.setSharedVariable("menuTag", this);
        }
    
        @Override
        public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
            final DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
    
            if (params.containsKey(HaloConst.METHOD_KEY)) {
                String method = params.get(HaloConst.METHOD_KEY).toString();
                switch (method) {
                    case "list":
                        env.setVariable("menus", builder.build().wrap(menuService.listAll()));
                        break;
                    case "tree":
                        env.setVariable("menus", builder.build().wrap(menuService.listAsTree(Sort.by(DESC, "priority"))));
                        break;
                    case "listTeams":
                        env.setVariable("teams", builder.build().wrap(menuService.listTeamVos(Sort.by(DESC, "priority"))));
                        break;
                    case "listByTeam":
                        String team = params.get("team").toString();
                        env.setVariable("menus", builder.build().wrap(menuService.listByTeam(team, Sort.by(DESC, "priority"))));
                        break;
                    case "count":
                        env.setVariable("count", builder.build().wrap(menuService.count()));
                        break;
                    default:
                        break;
                }
            }
            body.render(env.getOut());
        }
    }
    

    TemplateModel

    TemplateModel 是一个接口类型,代表 FreeMarker 模板语言(FTL)数据类型的接口的公共超接口,
    即所有的数据类型都会被 freemarker 转成对应的 TemplateModel。
    
    通常我们都使用TemplateScalarModel接口来替代它获取一个String 值,如:TemplateScalarModel.getAsString()。
    TemplateNumberModel 获取 number。
    
    类型 FreeMarker接口 FreeMarker实现
    字符串 TemplateScalarModel SimpleScalar
    数值 TemplateNumberModel SimpleNumber
    日期 TemplateDateModel SimpleDate
    布尔 TemplateBooleanModel TemplateBooleanModel.TRUE
    哈希 TemplateHashModel SimpleHash
    序列 TemplateSequenceModel SimpleSequence
    集合 TemplateCollectionModel SimpleCollection
    节点 TemplateNodeModel NodeModel

    扩展 FreeMarkerConfig

    上面提到的自定义标签,都是通过<@tagName>xxx</@tagName>方式调用的。
    
    针对我们系统中一些类环境变量的数据(全局的配置类属性等):
    
    	@Configuration
    	public class FreeMarkerConfig {
    
    	    @Autowired
    	    protected freemarker.template.Configuration configuration;
    
    	    @Autowired
    	    private SysConfigService configService;
    
    	    /**
    	     * 添加自定义标签
    	     */
    	    @PostConstruct
    	    public void setSharedVariable() {
    	        try {
    	            configuration.setSharedVariable("config", configService.get());
    	        } catch (TemplateModelException e) {
    	            e.printStackTrace();
    	        }
    	    }
    	}
    
    如此而已,在使用的时候我们可以直接在页面上通过 ${config.siteName} 调用 config 的参数即可。
    
  • 相关阅读:
    Vue——data中的属性规范
    python的字符串用法
    python笔录第一周
    Mac下python版本的更新
    我的第一篇博客
    C语言-控制语句(循环)
    C语言-控制语句(分支与跳转)
    C语言-函数
    C语言-数组与指针
    C语言-堆和栈
  • 原文地址:https://www.cnblogs.com/loveer/p/12251997.html
Copyright © 2020-2023  润新知