springboot2.x系列(五)-搭建非前后端分离的单体系统搭建

现在流行的前后端分离架构,但在一些小的,简单的系统,非分离的单体系统在开发效率和维护性上实际更具优势

本文讲解非前后端系统的搭建及Freemarker模板技术和springboot的集成。

一、静态资源的存放地址

静态资源如js,img,css等

(1)公共js通过pom文件引用

通过webjars的方式引入第三方资源 访问其官网: https://www.webjars.org/ 找到对应需要引入的静态资源:bootstrap、Jquery等,选择maven方式,把相应配置文件复制到我们项目的pom.xml文件中。   springboot2.x系列(五)-搭建非前后端分离的单体系统搭建  
源代码解析: org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration自动配置类
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (! this.resourceProperties.isAddMappings()) { logger.debug( "Default resource handling disabled"); } else { Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl(); if (!registry.hasMappingForPattern( "/webjars/**")) { this .customizeResourceHandlerRegistration(registry.addResourceHandler( new String[]{ "/webjars/**" }).addResourceLocations( new String[]{ "classpath:/META-INF/resources/webjars/" }).setCachePeriod( this .getSeconds(cachePeriod)).setCacheControl(cacheControl)); }   String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { this.customizeResourceHandlerRegistration(registry.addResourceHandler( new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations( this.resourceProperties.getStaticLocations())).setCachePeriod( this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); }   } }
   
1.maven <!-- jar 的方式引入 query--> < dependency> < groupId>org.webjars</ groupId> < artifactId>jquery</ artifactId> < version>3.2.0</ version> </ dependency>
2.查看jar结构 springboot2.x系列(五)-搭建非前后端分离的单体系统搭建 观察其js路径为 resource/webjars/jquery/3.2.0/jqery.js
3.调用 http://localhost:9999/demo/webjars/jquery/3.2.0/jquery.js 注意:其网络lur路径为 /webjars/jquery/3.2.0/jqery.js

 

(2)自己写静态资源放在springboot路径     也可以自己打成jar包,但太麻烦。 推荐:springboot约定将一些目录设置为静态资源的存放地  
springboot有默认的几个静态资源存放路径 项目下的: JAVA、RESOURCES都是classpath classpath:/META-INF/resources/ //下面这个几个文件夹是在resources子文件夹里,resources是maven的资源标志,不是文件路径 classpath:/resources/ classpath:/static/ classpath:/public/ / 项目根路径 springboot为以上所有路径都默认映射了起始面文件:index.html,即如果这些目录中有index.html时,访问这个目录时,页面会显示index.html的内容。 有相同资源时文件时,优先级: resouce>static>public  
springboot2.x系列(五)-搭建非前后端分离的单体系统搭建 注意: springboot2.x系列(五)-搭建非前后端分离的单体系统搭建 这个是maven路径,不是class里面的路径哈
访问: http://localhost:9999/demo/hello.html   注意:访问不得加resource/public/static这些路径哈,他们相当于WEBAPP resources这些路径下可加子路径 http://localhost:9999/demo/son/son.html
 
源码解析 org.springframework.boot.autoconfigure.web.ResourceProperties类里约定了几个可以存放静态文件的目录
private static final String[] CLASSPATH_RESOURCE_LOCATIONS =  new String[]{ "classpath:/META-INF/resources/" , "classpath:/resources/" , "classpath:/static/" , "classpath:/public/" };
  (3)设置欢迎页  传统在web.xml里面配置欢迎页, 在spring boot默认在资源文件跟节点的resouce/static/public的index.html下即可    
springboot2.x系列(五)-搭建非前后端分离的单体系统搭建
访问: http://localhost:9999/demo/
注意:如果跟Controller里冲突,以Controller里为准 @RestController public class IndexControl { WebMvcAutoConfiguration g; @Autowired private Person person; @RequestMapping( "/") public String index(){ )
 
源码解析 org.springframework.boot.autoconfigure.web.servlet. WebMvcAutoConfiguration
springboot2.x系列(五)-搭建非前后端分离的单体系统搭建
(4)设置网页标签里的favicon.ico   只要把favicon.ico保存到任何静态资源的目录下即可  
源码解析 org.springframework.boot.autoconfigure.web.servlet. WebMvcAutoConfiguration
springboot2.x系列(五)-搭建非前后端分离的单体系统搭建
HTML <head> <meta charset= "UTF-8" > <link rel= "icon" href= "favicon.ico" > </head>
  注意事项:   放在resources/static/public三个文件夹里,通过URL都可以直接访问,所以基本用来放js,img,css,静态html等文件, freemark模板文件这些不能放到这些文件夹里,没有安全性   (5)热启动 静态页面和java类修改后可立即热启动   1.pom配置
<dependency>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-devtools</artifactId>         <optional>true</optional> </dependency>
  2.idea配置 (1)File-Settings-Compiler-Build Project automatically (2)ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running【没有找到】 springboot2.x系列(五)-搭建非前后端分离的单体系统搭建   3.属性文件 application.properties中配置 好像不配置也可以
#热部署生效 spring.devtools.restart.enabled: true #设置重启的目录 #spring.devtools.restart.additional-paths: src/main/java #classpath目录下的WEB-INF文件夹内容修改不重启 spring.devtools.restart.exclude: WEB-INF/**
 

二、 springboot2集成freemarker

1.pom.xml

<dependency>

   <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-freemarker</artifactId>

</dependency>

2.

(1)配置application.properties配置文件

# 是否允许HttpServletRequest属性覆盖(隐藏)控制器生成的同名模型属性。

spring.freemarker.allow-request-override=false

# 是否允许HttpSession属性覆盖(隐藏)控制器生成的同名模型属性。

spring.freemarker.allow-session-override=false

# 是否启用模板缓存。

spring.freemarker.cache=false

# 模板编码。

spring.freemarker.charset=UTF-8

# 是否检查模板位置是否存在。

spring.freemarker.check-template-location=true

# Content-Type value.

spring.freemarker.content-type=text/html

# 是否启用freemarker

spring.freemarker.enabled=true

# 设定所有request的属性在merge到模板的时候,是否要都添加到model中.

spring.freemarker.expose-request-attributes=false

# 是否在merge模板的时候,将HttpSession属性都添加到model中

spring.freemarker.expose-session-attributes=false

# 设定是否以springMacroRequestContext的形式暴露RequestContext给Spring’s macro library使用

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

# 是否优先从文件系统加载template,以支持热加载,默认为true

spring.freemarker.prefer-file-system-access=true

# 设定模板的后缀.

spring.freemarker.suffix=.ftl

# 设定模板的加载路径,多个以逗号分隔,默认:

spring.freemarker.template-loader-path=classpath:/templates/

# 设定FreeMarker keys.

spring.freemarker.settings.template_update_delay=0

spring.freemarker.settings.default_encoding=UTF-8

spring.freemarker.settings.classic_compatible=true

spring.freemarker.settings.datetime_format=yyyy-MM-dd HH:mm:ss

spring.freemarker.settings.date_format=yyyy-MM-dd

spring.freemarker.settings.time_format=HH:mm:ss

#可采用<#或者[#作为标签

spring.freemarker.settings.tag_syntax=auto_detect

(2)application.properties文件可能不是非常的强大,可用bean配置freemarker.xml

springboot2.x系列(五)-搭建非前后端分离的单体系统搭建

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:p="http://www.springframework.org/schema/p"

       xmlns:context="http://www.springframework.org/schema/context"

       xmlns:mvc="http://www.springframework.org/schema/mvc"

       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">



    <!-- springmvc 与freemarker绑定的配置 -->
    <bean id="freemarkerConfig"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="classpath:/templates/" /><!--模板文件存放的根路径-  -->
        <property name="defaultEncoding" value="utf-8" />
        <property name="freemarkerSettings">
            <props>
                <prop key="tag_syntax">auto_detect</prop><!-- <改成[符号 -->
                <prop key="template_update_delay">10</prop>
                <prop key="locale">zh_CN</prop>
                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                <prop key="date_format">yyyy-MM-dd</prop>
                <prop key="number_format">#.##</prop>
                <!-- 配置自定义的freemarker异常处理-->
<!--
                <prop key = "template_exception_handler">com.xbsoft.comm.freemark.FreemarkerExceptionHandler</prop>
-->
            </props>
        </property>

    </bean>

    <!-- FreeMarker视图解析   在这里配置后缀名ftl和视图解析器。。-->
    <bean id="viewResolver"  class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

        <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"></property>
        <property name="suffix" value=".html" />
        <property name="contentType" value="text/html;charset=utf-8" />
        <property name="exposeRequestAttributes" value="true" />
        <property name="exposeSessionAttributes" value="true" />
        <property name="exposeSpringMacroHelpers" value="true" />
        <property name="attributesMap">
            <!-- 自定义方法和宏注入 -->
            <map>
              <!--
                <entry key="to_date" > <bean class=" com.xbsoft.comm.freemark.ToDateMethod" /></entry>

                <entry key="to_dateTime" > <bean class=" com.xbsoft.comm.freemark.ToDateTimeMethod" /></entry>

                <entry key="dict_show" > <bean class=" com.xbsoft.comm.freemark.DictMethod" /></entry>
                <entry key="formDict" > <bean class=" com.xbsoft.comm.freemark.SRCDirective" /></entry>

-->
            </map>
        </property>
    </bean>

</beans>

在启动类引入

//启动入口注解
@ImportResource(locations = {"classpath:config/freemarker.xml"})
@SpringBootApplication
public class GirlApplication {

    public static void main(String[] args) {
        //应用启动
        SpringApplication.run(GirlApplication.class, args);
    }
}

freemarker模板一般放在templates文件目录下

springboot2.x系列(五)-搭建非前后端分离的单体系统搭建

三、freemarker基础语法

1.打印

1.eg

${user.address!}

 

2、null判断

    特别注意,如果属性从map取出来为null,不处理将会出错,

    所以一般输出加!

        ${user.name},异常

    ${(user.name)!},显示空白 等价${book.name?if_exists } //用于判断如果存在,就输出这个值

    ${user.name!'vakin'},若user.name不为空则显示本身的值,否则显示vakin

    ${user.name?default('vakin')},同上

3.时间展示

 

${(obj.birthday?string("yyyy-MM-dd"))!}

${(obj.tt?string("yyyy-MM-dd HH:mm:ss"))!}

注意是整个值括起来加!,这样为null才不出错

 

4.在if里面判断

<#if user.xueli??>  #如果user.xueli不为空

user.xueli存在值

</#if>

2.if语法

 

<#if user.name?? && user.name=="蒋增奎">  //注意判断时都要加user.name?? 属性存在的前提

       真鸡巴帅

    </#if>

    注意:

     <#if... #号和if必须挨着,不用有空格

 

     <#if condition>...

    <#elseif condition2>...

    <#elseif condition3>......

    <#else>...

    </#if>

 

<#assign age=23>

<#if (age>60)>老年人

<#elseif (age>40)>中年人

<#elseif (age>20)>青年人

<#else> 少年人

</#if>

3.switch语句

<#switch value>

    <#case refValue1>

     ...

     <#break>    //break退出

    <#case refValue2>

    ...

    <#break>

    ...

    <#case refValueN>

     ...

     <#break>

    <#default>

     ...

  </#switch>

4.list语法

<#list users as user>  //usaer是迭代对象里面的别名

 

</#list>

users即可以是一个list对象,也可以是个数组

     List<User> list=new Vector<User>();

     或者

     <@my.list  items=["mouse", "elephant", "python"] title="Animals"/>

list还有数组循环如

<#macro repeat count=5>

         <#list 1..count as x>

                 <li>${x}</li>

         </#list>

</#macro>

 

判断list是否有值

   [#if newss?size==0]

    机构暂无新闻

[/#if]

 

 

  List指令还隐含了两个循环变量:

item_index:当前迭代项在所有迭代项中的位置,是数字值。

item_has_next:用于判断当前迭代项是否是所有迭代项中的最后一项。

注意:在使用上述两个循环变量时,一定要将item换成你自己定义的循环变量名,item其实就是前缀罢了。

例如,如果你使用<# list list as l>..</#list>定义,那么就要使用l_index,l_has_next。

   

   在循环过程中,如果您想跳出循环,那么可以使用结合break指令,即<#break>来完成。

 

   注意:boolean不是直接用${}输出,只能用于判断

<#if user_has_next>

还有下一个

</#if>

这样写是错的${user_has_next} ;

这样写可以:${user_has_next?String("yes","no")}

include和import包含文件

include指令的作用类似于JSP的包含指令,用于包含指定页,include指令的语法格式如下

         <#include filename [options]

          在上面的语法格式中,两个参数的解释如下

          a、filename:该参数指定被包含的模板文件

          b、options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding指定包含页面时所使用的解码集,而parse指定被

             包含是否作为FTL文件来解析。如果省略了parse选项值,则该选项值默认是true

      例:<#include   "inc.ftl">

 

 

<#include "/inc/inc1.ftl">

<#include "/inc/inc2.ftl">

${username}

两个里面都有相同变量,则将实现先后覆盖

 

出现这种情况,在两个模版中都分别存在变量名都相同的变量的时候,include包含进来,会进行覆盖,include只时候将其公共的静态文件进行包含,而里面不涉及到内部函数以及变量声明之类的,当涉及到这种问题,我们就要用import进行导入

 

 

注意1:controller里面的绑定数据,在include里面也可以读取

 

@RequestMapping("/include")

public String include(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception{

User user=new User(1,"jzk",new Date(),new BigDecimal("34.56"));

 

model.addAttribute("user",user);

return "main";

}

 

在包含文件里:

${user.userName!}

 

注意2:include会把包含页面的所有html代码读取过来,不仅仅是显示值

 

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

老子有敢抢:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

jzk

</body>

</html></body>

</html>

 

而里面不涉及到内部函数以及变量声明之类的,当涉及到这种问题,我们就要用import进行导入 会在主命名空间中创建两个变量. 如果再引入同名的变量时就会被后引入的或者新定义的覆盖.这样就不是很好,因为只想让它们在"My Test Library"命名空间中.就需要用 import代替include了     1. my_test.ftl < #macro copyright date > < p > Copyright (C) ${date} Julia Smith. All rights reserved. < br > Email: ${mail} </ p > </ #macro >   2.new file < #import "/lib/my_test.ftl" as my > < #assign mail =" fred@acme.com " > < @my .copyright date ="1999-2002" /> ${my.mail} ${mail}   输出: <p> Copyright (C) 1999-2002 Julia Smith.All rights reserved.     <br>Email : jsmith@acme.com   </p>   jsmith@acme.com   fred@acme.com
7、宏定义    
宏的定义 宏就是可以反复使用的代码块,类似其他语言的函数或者方法   <#--第一个参数[name]表示这个macro的name,后面为参数,可以N个--> <#macro name param1,param2,param3,....>     $ {param1}     $ {param2} </#macro>     注意: 使用的参数一定要事先定义;   定义的参数在使用的时候一定要进行赋值,除非在创建macro的时候给参数默认值;   参数所能赋予的值不一定是字符串,也可以是其他类型,还可以是一个预运算表达式     在使用的时候,对参数赋值顺序不确定,可随意   参数是局部变量,只能在宏定义中有效 如果变量没有默认值,则要放在有默认值的变量前面,否则要出错 如:
宏的基本案例-code   [#macro greet] < font size= "+2" > Hello Joe! </ font > [/#macro]   [#macro greet person] < font size= "+2" > Hello ${person}! </ font > [/#macro]   [#macro user name address] < font size= "+2" > Hello ${name},your address:${address}! </ font > [/#macro]   [#macro emp name address=" 九眼桥 "] < font size= "+2" > Hello ${name},your address:${address}! </ font > [/#macro]     [#macro border] < table border= 4 cellspacing= 0 cellpadding= 4 >< tr >< td > [#nested] </ tr ></ td ></ table > [/#macro]     1. 不带参数的宏 < br > [@greet][/@greet] < p ></ p > 2. 带参数的宏 < br > [@greet person=" 蒋增奎 "/] < p ></ p > 3. 带多参数的宏 , 参数顺序无所谓 < br > [@user address=" 天府大道 " name=" 蒋增奎 "/] < p ></ p >   4. 可以指定默认值 < br > [@emp address=" 天府大道 " name=" 蒋增奎 "/] < p ></ p > 不传递参数,则使用默认值 < br > [@emp name=" 蒋增奎 "/] < p ></ p > 5. 宏可以嵌套内容 ,nested < br > [@border] 我才你吗 [/@border] < p ></ p >
生成html 1.不带参数的宏<br> <font size="+2">Hello !</font> <p></p>   2.带参数的宏<br> <font size="+2">Hello 蒋增奎!</font> <p></p>   3.带多参数的宏,参数顺序无所谓<br> <font size="+2">Hello 蒋增奎,your address:天府大道!</font> <p></p>   4.可以指定默认值<br> <font size="+2">Hello 蒋增奎,your address:天府大道!</font> <p></p> 不传递参数,则使用默认值<br> <font size="+2">Hello 蒋增奎,your address:九眼桥!</font> <p></p>   5.宏可以嵌套内容<br> <table border=4 cellspacing=0 cellpadding=4><tr><td> 我才你吗</tr></td></table> <p></p>  
名字空间       <#macro copyright date>      <p>Copyright (C) ${date} Julia Smith. All rights reserved.      <br>Email: ${mail}</p>    </#macro>     <#assign mail = " jsmith@acme.com ">    使用import指令导入库到模板中,Freemarker会为导入的库创建新的名字空间,并可以通过import指令中指定的散列变量访问库中的变量:      <#import "/lib/my_test.ftl" as my >    <#assign mail=" fred@acme.com ">    <@my.copyright date="1999-2002"/>    ${my.mail}    ${mail}    输出结果:    <p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.      <br>Email: jsmith@acme.com </p>    jsmith@acme.com    fred@acme.com 
注意 宏的参数不一定是字符串,一定非得有初始值
    8.宏复杂传参对象    
Java   @RequestMapping ( "/macro" ) public String macro(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception{   List<User> list= new ArrayList<User>(); User user1= new User( 1 , "jzk1" , new Date(), new BigDecimal( "34.56" )); list.add(user1); User user2= new User( 1 , "jzk2" , new Date(), new BigDecimal( "34.56" )); list.add(user2); User user3= new User( 1 , "jzk3" , new Date(), new BigDecimal( "34.56" )); list.add(user3); model.addAttribute( "userList1" ,list); model.addAttribute( "tblId1" , "3" ); return "macro" ; }
macro.html <!--定义宏-->   [#macro usertTbl userList id] < table border= 1 cellspacing= 0 cellpadding= 4 style= " width : 100 % " id= "${id}" > < tr >< td > id </ td >< td > name </ td >< td > birth </ td >< td > age </ td ></ tr > [#list userList as user] < tr > < td > ${user.userId!} </ td > < td > ${user.userName!} </ td > < td > ${(user.birth?string("yyyy-MM-dd"))!} </ td > < td > ${user.age!} </ td > </ tr > [/#list] </ table > [/#macro]   <!--展示-->   6. 宏复杂参数 < br > [@usertTbl userList=userList1 id=tblId1][/@usertTbl]       输出代码   <table border=1 cellspacing=0 cellpadding=4 style="width:100%" id="3">     <tr><td>id</td><td>name</td><td>birth</td><td>age</td></tr>     <tr>         <td>1</td>         <td>jzk1</td>         <td>2020-05-03</td>         <td>34.56</td>     </tr>     <tr>         <td>1</td>         <td>jzk2</td>         <td>2020-05-03</td>         <td>34.56</td>     </tr>     <tr>         <td>1</td>         <td>jzk3</td>         <td>2020-05-03</td>         <td>34.56</td>     </tr> </table>    
说明 1.参数可以没有初始值及类型,根据传入参数而定 [#macro usertTbl userList id]   2.在引用宏的时候,参数变量就是后端的定义变量,不需要加${}符号 [@usertTbl userList=userList1 id=tblId1][/@usertTbl]   3.在宏定义里面使用变量,首先去找对应的后台使用有这个变量名,如果有的话会自动匹配,其次才找传递参数   [#macro usertTbl userList id] < table border= 1 cellspacing= 0 cellpadding= 4 style= " width : 100 % " id= "${id}" > < tr >< td > id </ td >< td > name </ td >< td > birth </ td >< td > age </ td ></ tr > [#list userList as user] 。。。   如果对应java类里有 userList变量,则能直接使用
注意   定义的参数在使用的时候一定要进行赋值,除非在创建macro的时候给参数默认值;   参数所能赋予的值不一定是字符串,也可以是其他类型,还可以是一个预运算表达式     在使用的时候,对参数赋值顺序不确定,可随意   参数是局部变量,只能在宏定义中有效 如果变量没有默认值,则要放在有默认值的变量前面,否则要出错 如: <#macro  radio    name=""  dicts xxx    val=""  >会报错 正确写法   <#macro  radio dicts xxx   name=""      val=""  >
  9.自定义函数    
自定义类   要继承 freemarker.template.TemplateMethodModelEx类,实现 exec方法 import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModelException;   import java.util.List;   /** * @class: com.jyj.controll.ToDate * @author: jiangzengkui * @company: 教育家 * @create: 2020-05-03 09:41 * @description: * @updateRemark: */ public class ToDate implements TemplateMethodModelEx {   @Override public Object exec(List params) throws TemplateModelException { String ret = " 返回值 " ;   return ret;   }   }
自定义绑定 1.单页面使用   如果在一个页面使用,可以直接在ctroller对应方法里绑定 model.addAttribute( "dictShow" , new com.jyj.controll.ToDate());   2.设置成全局变量   springmvc的xml配置       <!-- FreeMarker视图解析   在这里配置后缀名ftl和视图解析器。。--> <bean id="viewResolver"  class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">      <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"></property>   <property name="suffix" value=".html" />   <property name="contentType" value="text/html;charset=utf-8" />   <property name="exposeRequestAttributes" value="true" />   <property name="exposeSessionAttributes" value="true" />   <property name="exposeSpringMacroHelpers" value="true" />       <property name="attributesMap">       <!-- 自定义方法和宏注入 -->            <map>           <!-- 把日期类型显示成yyyy-mm-dd格式 -->             <entry key="to_date" > <bean class=" com.xbsoft.comm.freemark.ToDateMethod " /></entry>             <!-- 把日期类型显示成yyyy-mm-dd HH:mm:ss格式 -->              <entry key="to_dateTime" > <bean class=" com.xbsoft.comm.freemark.ToDateTimeMethod " /></entry>             <!-- 把数据字典的编码显示成对应中文 -->             <entry key="dict_show" > <bean class=" com.xbsoft.comm.freemark.DictMethod " /></entry>           </map>         </property> </bean>   3.springBoot2集成全局变量     import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation. Bean ; import org.springframework.context.annotation. Configuration ; import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;   import javax.annotation. PostConstruct ; import java.util.HashMap; import java.util.Map;   /** * @class: com.jyj.config.FreemarkerConfig * @author: jiangzengkui * @company: 教育家 * @create: 2020-05-03 10:52 * @description: * @updateRemark: */ @Configuration public class FreemarkerConfig { /** * 增加自定义视图变量和方法 * * @return */ @Bean public CommandLineRunner customFreemarker(FreeMarkerViewResolver resolver) { return new CommandLineRunner() { @Override public void run(String... strings) throws Exception {   Map map = resolver .getAttributesMap();   //把自定义函数压入map map.put("dictShow", new com.jyj.controll.ToDate()); } }; } }      
页面使用 直接用${声明的行数名(参数.......)}即可 ${dictShow()}
  实例    
自定义函数 import java.util.*; import com.xbsoft.comm.dict.DictManager; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModelException; /**  * 数据字典自定义函数 * @ClassName : com.xbsoft.comm.freemark.DictMethod * @author   jiangzengkui * @date 2016年9月2日 下午11:02:36 * @Description :  显示编码对应的中文值 * 调用如:${dict_show("BM044",form.service_type!)} *  */ public class DictMethod implements TemplateMethodModelEx  {              /**              * params [0]=字典名称:,如:BM - 001              * params1]=字典编码 如1              */              @Override              public Object exec( List params) throws TemplateModelException {                         String ret= "";                         String dictName= ""; //字典名称:,如:BM-001                         String dictCode= ""; //字典编码 如1                          if( params== null || params.size()<2){                                      throw new TemplateModelException( "参数个数不够");                         }                         Object obj1= params.get(0); //参数1                         Object obj2= params.get(1); //参数2                          if( "freemarker.core.DefaultToExpression$EmptyStringAndSequence".equals( obj2.getClass().getName())){                                      return ret;                         }                          if( obj2== null || obj2.toString().trim().length()==0){ //如果没有编码值,则直接返回                                      return ret;                         }                                                   if( obj1== null || obj1.toString().trim().length()==0)                                      throw new TemplateModelException( "必须传递数据字典值");                                   dictName= obj1.toString().trim();          dictCode= obj2.toString().trim();                 ret=(String)DictManager. getInstance().getDictShow( dictName, dictCode);                                                                            return  ret;             }              }
绑定   <!-- FreeMarker视图解析   在这里配置后缀名 ftl 和视图解析器。。-->   < bean id= "viewResolver"  class= "org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" >     < property name= "viewClass" value= "org.springframework.web.servlet.view.freemarker.FreeMarkerView" ></ property >   < property name= "suffix" value= ".html" />   < property name= "contentType" value= "text/html;charset=utf-8" />   < property name= "exposeRequestAttributes" value= "true" />   < property name= "exposeSessionAttributes" value= "true" />   < property name= "exposeSpringMacroHelpers" value= "true" />       < property name= "attributesMap" >       <!-- 自定义方法和宏注入 -->           < map >           <!-- 把日期类型显示成 yyyy - mm - dd 格式 -->             < entry key= "to_date" > < bean class= " com.xbsoft.comm.freemark.ToDateMethod " /></ entry >             <!-- 把日期类型显示成 yyyy - mm - dd HH:mm:ss格式 -->              < entry key= "to_dateTime" > < bean class= " com.xbsoft.comm.freemark.ToDateTimeMethod " /></ entry >             <!-- 把数据字典的编码显示成对应中文 -->             < entry key = "dict_show" > < bean class = " com.xbsoft.comm.freemark.DictMethod " /></ entry >             < entry key= "formDict" > < bean class= " com.xbsoft.comm.freemark.SRCDirective " /></ entry >             <!-- 机构课程的选择 业务通用类 -->             < entry key= "courseDict" > < bean class= " com.xbsoft.xqb.comm.OrgCourseDirective " /></ entry >              < entry key= "addressDict" > < bean class= " com.xbsoft.xqb.comm.OrgAddressDirective " /></ entry >              < entry key= "teaDict" > < bean class= " com.xbsoft.xqb.comm.OrgTeaDirective " /></ entry >               < entry key= "tgDict" > < bean class= " com.xbsoft.xqb.comm.TgDirective " /></ entry >               < entry key= "pcDict" > < bean class= " com.xbsoft.xqb.comm.PbCourseDirective " /></ entry >                         </ map >         </ property >   </ bean >
HTML  ${dict_show("BM202",car.biansu_type!"")}
注意 在html里面传递参数,直接从ctroller里的绑定变量名即可,不需要用${}等
    10.自定义标签 TemplateDirectiveModel  
TemplateDirectiveModel 这个类和TemplateMethodModelEx 作用类似,都是用于自定义标签,但其扩展性更好
  import freemarker.core.Environment; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel;   import java.io.IOException; import java.io.Writer; import java.util.Iterator; import java.util.Map;   /** * @class: com.jyj.comm.TestDirectiveModel * @author: jiangzengkui * @company: 教育家 * @create: 2020-05-03 16:33 * @description: * @updateRemark: */ public class TestDirectiveModel implements TemplateDirectiveModel { /** * * @param env 运行环境 * @param params 标签传递过来的参数 * @param loopVars * @param body * @throws TemplateException * @throws IOException */ @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { String out= "" ; // 向页面输出内容   out= " 输出内容 " ;   /** * 打印输入的标签参数测试 */ Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator(); while (it.hasNext()){ Map.Entry<String, Object> entry = it.next(); System. out .println( "key:" +entry.getKey()+ " val:" +entry.getValue()); }     // 内容输出到页面 Writer print=env.getOut(); print.write(out); } }
绑定 绑定方法和 TemplateMethodModelEx一致   @Bean public CommandLineRunner customFreemarker(FreeMarkerViewResolver resolver) { return new CommandLineRunner() { @Override public void run(String... strings) throws Exception {   Map map = resolver .getAttributesMap(); map.put( "dictShow" , new com.jyj.controll.ToDate()); map.put( "to_date" , new com.jyj.comm.ToDateMethod()); map.put( "testTag" , new com.jyj.comm.TestDirectiveModel()); } }; }
页面引用,和其他freemarker标签一致 [@标签名  参数....]   [@formDict etype="select" dictName="BM031"  name="class_week" id="${t.class_week!}"  value="${t.class_week!}" isEmpty="true"  class="input_text"  /]   注意:这里传递值需要用${}取出来,这个和自定义函数不一样
  11.运算符  
比较运算符号

 

1  =或者==:判断两个值是否相等.  2  !=:判断两个值是否不等.  3  >或者gt:判断左边值是否大于右边值  4  >=或者gte:判断左边值是否大于等于右边值  5  <或者lt:判断左边值是否小于右边值  6  <=或者lte:判断左边值是否小于等于右边值  注意 :  =和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为 FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)> 
并且或者或者   逻辑与:&&  逻辑或:||  逻辑非:!  逻辑运算符只能作用于布尔值,否则将产生错误    <#if user.name?? && user.name=="蒋增奎">  //注意判断时都要加user.name?? 属性存在的前提 [#if newsList?size==0]  //list长度等于零   <#if user.name??> 变量是否存在   </#if>    [#if form.role_code??  && form.role_code !=""] 存在并且不等于空 [/#if]
     

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

上一篇:前端body内常用标签


下一篇:mattermost的记载技巧