Freemarker快速入门(SpringBoot版)

news2025/1/12 20:47:05

文章目录

  • Freemarker快速入门
    • 1、Freemarker概述
    • 2、Freemarker初体验
    • 3、数据类型
      • 3.0 常见操作符
      • 3.1 数值类型
      • 3.2 字符串类型
      • 3.3 布尔类型
      • 3.4 日期类型
      • 3.5 序列类型
      • 3.6 哈希类型
    • 4、运算符
      • 4.1 算术运算符
      • 4.2 逻辑运算符
      • 4.3 比较运算符
      • 4.4 空值运算符
    • 5、常用指令
      • 5.1 assign 自定义变量指令
      • 5.2 if elseif else 逻辑判断指令
      • 5.3 list 遍历指令
      • 5.4 macro 自定义指令
      • 5.5 nested 占位指令
      • 5.6 import 导入指令
      • 5.7 include 包含指令

Freemarker快速入门

在这里插入图片描述

1、Freemarker概述

  • Freemarker是什么

    Freemarker是一个强大的 Java 模板引擎,它允许开发人员将展示层与应用逻辑分离。通过提供一种灵活高效的方式,在运行时生成动态内容。Freemarker模板使用类似HTML的语法,但包含可以在运行时填充数据的占位符和控制结构。这使得创建动态网页、电子邮件和其他文本文档非常简单。

    Freemarker支持条件语句、循环、宏等各种功能,并且可以与不同的数据模型和框架集成。它在Java Web开发中被广泛应用于生成HTML视图、电子邮件模板和其他文本输出。

    个人理解:Freemarker是类似于JSP的模板引擎,只要我们理解了什么是模板引擎就知道Freemarker大概是一个什么东西了

    PS:如果你学习过 JSP 或者 Thmeleaf,我相信你对模板引擎不会陌生,关于 JSP 和 Thmeleaf 的详细介绍可以参考这两篇文章:JSP速通、Thmeleaf快速入门(Spring整合版)

  • 什么是模板引擎

    模板引擎是一种用于生成动态内容的工具或框架。它将应用程序的逻辑和数据与视图分离,允许开发人员使用预定义的模板来定义页面、电子邮件、报表等的结构和布局。通过在模板中使用占位符、条件语句、循环等控制结构,模板引擎可以动态地将数据填充到模板中,生成最终的输出结果。这样的方法可以提高开发效率,减少代码重复,并使前后端工作更加分离。模板引擎通常支持多种语法和标记,可以集成到不同的编程语言和框架中,以满足各种应用场景的需求。

    个人理解:模板引擎就是一类特殊的HTML页面,它将数据和页面骨架(HTML)、样式(CSS)与数据进行了分离,数据是需要我们动态填充(模板引擎这个概念很类似与前端的组件,模板引擎是一种后端的页面渲染技术)

  • 模板引擎的作用是什么

    个人理解:模板引擎的主要作用是将逻辑和数据进行分离,提高复用性,相当于是给我们一个模板,我们只需要往这个模板中填充数据即可

    • 分离视图和业务逻辑:模板引擎使开发人员能够将视图(如网页、电子邮件等)的结构和布局与应用程序的业务逻辑分开。这样,设计师和前端开发人员可以专注于界面设计,而后端开发人员可以专注于业务逻辑的实现。
    • 提高开发效率:使用模板引擎可以减少编写重复代码的工作量。开发人员只需定义一次模板,并根据需要填充不同的数据即可生成多个相似但内容不同的输出结果。这样可以节省时间并提高开发效率。
    • 支持可维护性和扩展性:通过将视图和业务逻辑分离,模板引擎使代码更易于维护和修改。开发人员可以更轻松地修改UI布局或样式,而无需修改底层的业务逻辑。此外,模板引擎还提供了灵活的控制结构和标记,使开发人员可以根据需要进行定制和扩展。
    • 支持多平台和多语言:模板引擎通常支持多种编程语言和框架,可以适用于不同的开发环境和应用场景。这使得开发人员能够在不同的项目中重用他们的模板知识和经验。
  • 常见的模板引擎有哪些

    模板引擎说明
    JSPJsp 为 Servlet 专用,不能单独进行使用
    Thymeleaf新技术,功能较为强大,但是执行的效率比较低
    FreeMarker性能好,强大的模板语言、轻量
    VelocityVelocity从2010年更新完 2.0 版本后,7年没有更新。Spring Boot 官方在 1.4 版本后对此也不在支持
  • Freemarker的组成

    • 模板:模板是FreeMarker的核心组件,它定义了要生成的输出内容的结构和格式。模板使用FreeMarker的模板语法编写,可以包含变量、表达式、标签和指令等。

      模板的组成:

      • 文本:文本会照着原样来输出。
      • 插值:这部分的输出会被计算的值来替换。插值由 ${ and } 所分隔(或者 #{ and },这种风格已经不建议再使用了;点击查看更多)。
      • FTL 标签:FTL标签和HTML标签很相似,但是它们却是给FreeMarker的指示, 而且不会打印在输出内容中。
      • 注释:注释和HTML的注释也很相似,但它们是由 <#---->来分隔的。注释会被FreeMarker直接忽略, 更不会在输出内容中显示。
    • 模板解析器:模板解析器负责将模板文件解析为抽象语法树(AST),以便进行后续的处理和渲染。模板解析器将模板语法解析为相应的AST节点,表示模板的结构和内容。

    • 数据模型:数据模型是FreeMarker所使用的数据源,它包含了要在模板中展示的数据。数据模型可以是任意的Java对象,例如POJO、Map、List等。在模板中可以通过表达式访问数据模型的属性和方法。

    • 标签和指令:FreeMarker提供了一些内置的标签和指令,用于控制模板的渲染和逻辑处理。标签和指令可以包含条件判断、循环控制、变量赋值等逻辑,以及数据展示和格式化等操作。

    • 模板渲染引擎:模板渲染引擎是FreeMarker的核心引擎,负责将模板和数据结合起来进行渲染。模板渲染引擎根据AST节点和数据模型,生成最终的输出内容。

    除了上述组件之外,FreeMarker还提供了一些辅助类和工具,用于扩展和定制模板引擎的功能。例如,提供了各种自定义标签和函数的扩展点,以及模板缓存和预编译等性能优化功能。

2、Freemarker初体验

由于平常大部分都是基于SpringBoot框架进行开发的,这里我就不基于Spring学习Freemarker了,直接基于SpringBoot演示Freemarker的使用

创建SpringBoot项目
添加依赖
编写模板
编写配置文件
编写Controller
测试
  • Step1:创建SpringBoot项目

    image-20231017223637599

  • Step2:添加依赖

            <!--Freemarker-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
    
            <!--Web环境-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
  • Step3:编写模板

    src/main/resources/templates目录下创建 index.ftl 文件

    根据 Spring Boot 约定,模板文件默认是放在 src/main/resources/templates 目录下,如果你想要自定义模板文件的位置,可以通过template-loader-path配置属性进行设置。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Freemarker</title>
        </head>
        <body>
            Hello ${title}!
        </body>
    </html>
    
  • Step4:编写配置文件

    spring:
      freemarker:
        suffix: .ftl # 模板文件的后缀名,默认为 .ftl
    #    content-type: text/html # 响应的文档类型,默认为 text/html
    #    charset: UTF-8 # 页面的编码,默认为 UTF-8
        cache: false # 是否启用页面缓存,默认为 true。如果设置为 false,则每次请求都会重新解析模板文件
    #    template-loader-path: classpath:/templates/ # 模板文件的路径,默认为 classpath:/templates/。可以根据实际情况进行配置
    

    注意:suffix虽然有默认值 .ftl,但是仍然需要手动配置,否则无法成功响应模板

  • Step5:编写Controller

    package com.ghp.freemarker.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * @author ghp
     * @title
     * @description
     */
    @Controller
    @RequestMapping("/page")
    public class PageController {
    
        @GetMapping("/index1")
        public String toIndex1(){
            return "index1";
        }
    
        @GetMapping("/index2")
        public ModelAndView toIndex2 () {
            ModelAndView modelAndView = new ModelAndView("index2");
            modelAndView.addObject("title", "Freemarker");
            return modelAndView;
        }
    }
    

    注意:不要使用@RestController注解表示响应模板视图的 Controller 类,因为使用@RestController注解会将 Controller 类标识为一个 RESTful API 控制器,它主要用于返回数据或处理 API 请求,并不会返回视图页面

  • Step5:测试

    现在可以在浏览器上分别访问 http://localhost:8080/page/index1 和 http://localhost:8080/page/index2

    image-20231017223447188

3、数据类型

Freemarker是一个模板引擎,它主要用于生成动态的文本输出。它并没有特定的数据类型,而是使用 Java 对象作为模板的数据模型,所以这里的数据类型本质还是 Java 中的数据类型,本节主要讲解 Freemarker 中如何操作不同的数据类型

3.0 常见操作符

操作符描述
?c格式化对象
?string将对象转成字符串
?string.currency将对象转成货币类型的字符串
?string.percent将对象转成百分比类型的字符串
?string["0.#"]将数字转成字符串,并四舍五入保留一位小数
?time将日期按照“时:分:秒”输出
?date将日期按照“年-月-日”输出
?datetime将日期按照“年-月-日 时:分:秒”输出
?html对字字符串进行转移输出
?esc对字字符串进行转移输出
?reverse反转结果
?sort排序
?index获取当前遍历元素的索引
?sort_by按照某一个字段进行排序

3.1 数值类型

  • 设置值
  • 获取值

3.2 字符串类型

  • 设置值
  • 获取值

3.3 布尔类型

  • 设置值
  • 获取值

3.4 日期类型

  • 设置值
  • 获取值

3.5 序列类型

  • 设置值
  • 获取值

3.6 哈希类型

  • 设置值
  • 获取值

这里就统一编写吧,不一个一个的CV了,太浪费时间了,直接来一个整的

    /**
     * 演示 Freemarker 中不同的数据类型的相关操作
     *
     * @return
     */
    @GetMapping("/data_type")
    public ModelAndView toDataType() {
        // 响应的模板
        ModelAndView modelAndView = new ModelAndView("data_type");
        // 响应数值类型的数据
        modelAndView.addObject("number", 666);
        // 响应字符串类型的数据
        modelAndView.addObject("string", "Freemarker");
        // 响应布尔类型的数据
        modelAndView.addObject("boolean", true);
        // 响应日期类型的数据
        modelAndView.addObject("date", new Date());
        // 响应序列类型的数据(数组、List、Set)
        modelAndView.addObject("sequence", Arrays.asList("张三", "李四", "王五"));
        // 响应哈希类型的数据
        modelAndView.addObject("hash", new HashMap<String, String>(3) {{
            put("a", "A");
            put("b", "B");
            put("c", "C");
        }});

        // 还可以直接使用 addAllObjects 一次性全部添加
        modelAndView.addAllObjects(new HashMap<String, Object>(6) {{
            put("number2", 3.1415926);
            put("string2", "Freemarker");
            put("boolean2", false);
            put("date2", new Date());
            put("sequence2", new String[]{"张三", "李四", "王五"});
            put("hash2", new HashMap<String, String>(3) {{
                put("a", "A");
                put("b", "B");
                put("c", "C");
            }});
            User user1 = new User(1L, "张三", 19);
            User user2 = new User(2L, "李四", 20);
            User user3 = new User(3L, "李四", 21);
            ArrayList<User> userList = new ArrayList<>(3);
            Collections.addAll(userList, user1, user2, user3);
            put("userList", userList);

            Map<String, User> userMap = new HashMap<>(3);
            userMap.put("key1", user1);
            userMap.put("key2", user2);
            userMap.put("key3", user3);
            put("userMap", userMap);
        }});
        return modelAndView;
    }

image-20231018225602446

4、运算符

4.1 算术运算符

<!--
    算术运算
        +、-、*、/、%
-->
<#assign a1 = 8 a2 = 2 >
${a1} + ${a2} = ${a1 + a2} <br/>
${a1} - ${a2} = ${a1 - a2} <br/>
${a1} * ${a2} = ${a1 * a2} <br/>
${a1} / ${a2} = ${a1 / a2} <br/>
${a1} % ${a2} = ${a1 % a2} <br/>
<!--字符串运算-->
${"hello" + "," + "freemarker"}

4.2 逻辑运算符

<#--
    逻辑运算符
     &&、||、!
-->

4.3 比较运算符

<#--
    比较运算符
        > (gt): 大于号,推荐使用 gt
        < (lt): 小于号,推荐使用 lt
        >= (gte): 大于等于, 推荐是用 gte
        <= (lte): 小于等于,推荐使用 lte
        == : 等于
        != : 不等于
-->

4.4 空值运算符

<#--
    空值运算符
     1. ??:判断是否为空,返回布尔类型
        如果不为空返回 false, 如果为空返回 true,不能直接输出
       ${(name??)?string}
     2. !: 设置默认值,如果为空,则设置默认值
         1. 设置默认为空字符串:
         ${name!}
         2. 设置指定默认值
         ${name!'zhangsan'}
-->

5、常用指令

5.1 assign 自定义变量指令

使用 assign 指令你可以创建一个新的变量, 或者替换一个已经存在的变量。

<#--
    assign 自定义变量指令
        语法:
            <#assign 变量名=>
            <#assign 变量名= 变量名=> (定义多个变量)
-->
<#assign str="hello">
${str} <br> 
<#assign num=1 names=["zhangsan","lisi","wangwu"] >
${num} -- ${names?join(",")}

5.2 if elseif else 逻辑判断指令

可以使用 if , elseif 和 else 指令来条件判断是否满足某些条件。

<h5> 2. if, else, elseif 逻辑判断指令</h5>
<#assign score = 60>
<#if score lt 60 >
    <h6>你个小渣渣!</h6>
    <#elseif score == 80>
        <h6>分不在高,及格就行!</h6>
    <#elseif score gt 60 && score lt 80 >
        <h6>革命尚未成功,同志仍需努力!</h6>
    <#else >
        <h6>哎哟不错哦!</h6>
</#if>
<#--判断数据是否存在-->
<#assign list="">
<#if list??>
    数据存在
    <#else >
        数据不存在
</#if>
<br>
<#if list2??>
    数据存在
<#else >
    数据不存在
</#if>

5.3 list 遍历指令

可以使用 list 指令来对序列进行遍历。

<h5>3. list指令</h5>
<#assign users = ["张三","李四","王五"]>
<#list users as user>
    ${user} |
</#list>
<br>
<#--判断数据不为空,再执行遍历 (如果序列不存在,直接遍历会报错)-->
<#if users2??>
    <#list users2 as user>
        ${user}
    </#list>
</#if>
<br>
<#-- 当序列没有数据项时,使用默认信息 -->
<#assign users3 = []>
<#list users3 as user>
    ${user} |
    <#else >
        用户数据不存在!
</#list>

5.4 macro 自定义指令

可以使用 macro 指令来自定义一些自定义指令。

<#--
    macro 自定义指令 (宏)
        1. 基本使用
            格式:
                <#macro 指令名>
                    指令内容
                </#macro>
            使用:
                <@指令名></@指令名>
        2. 有参数的自定义指令
            格式:
                 <#macro 指令名 参数名1 参数名2>
                    指令内容
                </#macro>
            使用:
                <@指令名 参数名1=参数值1 参数名2=参数值2></@指令名>
        注:
            1. 指令可以被多次使用。
            2. 自定义指令中可以包含字符串,也可包含内置指令
-->
<#-- 定义基本的自定义指令 -->
<#macro address>
    © 1999–2015 The FreeMarker Project. All rights reserved. 
</#macro> 
<#-- 使用指令 -->
<@address></@address> <br> 
<@address></@address> <hr> 
<#-- 定义有参数的自定义指令 -->
<#macro queryUserByName uname>
    通过用户名查询用户信息 - ${uname} 
</#macro> 
<#-- 使用指令,并传递参数 -->
<@queryUserByName uname="admin"></@queryUserByName> <br> 
<#-- 定义有多个参数的自定义指令 -->
<#macro queryUserByParams uname uage>
    通过多个餐宿查询用户信息 - ${uname} - ${uage} </#macro> 
<#-- 使用指令,并传递多个参数 -->
<@queryUserByParams uname="admin" uage=18></@queryUserByParams> <br> 
<hr>
<#-- 自定义指令中包含内置指令 -->
<#macro cfb>
    <#list 1..9 as i>
        <#list 1..i as j>
           ${j}*${i}=${j*i}&nbsp;
        </#list>
        <br>
    </#list> 
</#macro> 
<@cfb></@cfb> 
<@cfb></@cfb> 
<#-- 动态数据 -->
<#macro cfb2 num>
    <#list 1..num as i>
        <#list 1..i as j>
           ${j}*${i}=${j*i}&nbsp;
        </#list>
        <br>
    </#list> 
</#macro> 
<@cfb2 num=5></@cfb2>

5.5 nested 占位指令

nested 指令执行自定义指令开始和结束标签中间的模板片段。嵌套的片段可以包含模板中任意合法的内容。

<#--
    nested 占位指令
        nested 相当于占位符,一般结合macro指令一起使用。
        可以将自定义指令中的内容通过nested指令占位,当使用自定义指令时,会将占位内容显示。
-->
<#macro test>
    这是一段文本!
    <#nested>
    <#nested> 
</#macro> 
<@test><h4>这是文本后面的内容!</h4></@test>

5.6 import 导入指令

import 指令可以引入一个库。也就是说,它创建一个新的命名空间, 然后在那个命名空间中执行给定路径的模

板。可以使用引入的空间中的指令。

1)创建commons.ftl文件

<#macro cfb>
    <#list 1..9 as i>
        <#list 1..i as j>
           ${j}*${i}=${j*i}&nbsp;
        </#list>
        <br>
    </#list> 
</#macro>

在其他ftl页面中通过import导入commons.ftl的命名空间,使用该命名空间中的指令

2)创建test.ftl文件

<#-- 导入命名空间 -->
<#import "commons.ftl" as common> 
<#-- 使用命名空间中的指令 -->
<@common.cfb></@common.cfb>

3)创建Controller

package org.example.controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author ghp
 * @description Freemarker常用指令
 * @date 2022/12/20 14:05
 */
@WebServlet("/f04")
public class FreeMarker04 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


//        请求转发到指定的页面,
        req.getRequestDispatcher("template/test.ftl").forward(req, resp);

    }
}

5.7 include 包含指令

可以使用 include 指令在你的模板中插入另外一个 FreeMarker 模板文件 。 被包含模板的输出格式是在 include

标签出现的位置插入的。 被包含的文件和包含它的模板共享变量,就像是被复制粘贴进去的一样。

<#--包含指令(引入其他页面文件) include-->
<#--html文件-->
<#include "test.html"> 
<#--freemarker文件-->
<#include "test.ftl"> 
<#--text文件-->
<#include "test.txt">

参考资料

  • 什么是 FreeMarker? - FreeMarker 中文官方参考手册 (foofun.cn)
  • Freemarker笔记.md · liyonghui/Freemarker_readme - Gitee.com
  • Spring Boot 整合 Freemarker 模板引擎 - spring 中文网 (springdoc.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1108778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python argparse解析参数

用法比较简单&#xff0c;直接看代码 import argparseargparser argparse.ArgumentParser(descriptionthis is a hello argparser program) argparser.add_argument(--arg1, -a, typestr, helparg1 has value) argparser.add_argument(--arg2, typestr, default"value2&q…

Web攻防02-MySQL注入概述MySQL架构注入获取数据

文章目录 SQL注入概述&#xff1a;sql注入的原理&#xff1a;sql注入攻击&#xff1a; MYSQL-Web组成架构MYSQL5.0以上版本&#xff1a;自带的数据库information_schema MYSQL注入流程MYSQL注入查询数据过程查询数据流程靶场案例 MYSQL-SQL跨库注入查询跨库注入&#xff1a;影响…

xray的使用

不需要扫描 点击 双击xray 1.打开 2.使用 主打扫描 3.被动扫描 网站 与 Burp 联动 - xray 安全评估工具文档 双击 xray cmd xray_windows_amd64.exe webscan --listen 127.0.0.1:7777 --html-output text.html 1.bp 2.这道这个 3.配置 xray 改为* 4.代理

Hadoop3教程(二十二):Yarn的基础架构与工作流程

文章目录 &#xff08;126&#xff09;基础架构&#xff08;127&#xff09;YARN的工作机制&#xff08;128&#xff09;作业全流程参考文献 &#xff08;126&#xff09;基础架构 之前基本介绍完了Hadoop的几个核心组件&#xff0c;接下来可以思考下&#xff0c;在MR程序运行…

计算未来:微软眼中的人工智能

计算未来 :人工智能及其社会角色&#xff08;The Future Computed. Artificial Intelligence and its role in society &#xff09;这本书于2018年09月由北京大学出版社出版。 书籍的作者是&#xff1a;沈向洋&#xff08;微软全球执行副总裁&#xff09;,&#xff08;美&…

C++标准模板(STL)- 类型支持 (数值极限,quiet_NaN,signaling_NaN,denorm_min)

数值极限 提供查询所有基础数值类型的性质的接口 定义于头文件 <limits> template< class T > class numeric_limits; numeric_limits 类模板提供查询各种算术类型属性的标准化方式&#xff08;例如 int 类型的最大可能值是 std::numeric_limits<int>::ma…

AST实战|比较大的混淆文件(超过10M)怎么还原

关注它&#xff0c;不迷路。 本文章中所有内容仅供学习交流&#xff0c;不可用于任何商业用途和非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请联系作者立即删除&#xff01; 1. 需求 目前&#xff0c;我接触到的混淆js文件大小刷新了新记录&…

在 Visual Studio Code (VS Code) 中设置

在 Visual Studio Code (VS Code) 中设置代理服务器的详细教程如下&#xff1a; 打开 Visual Studio Code。 在顶部菜单栏中&#xff0c;点击 "File"&#xff08;文件&#xff09; > "Preferences"&#xff08;首选项&#xff09; > "Settings…

成为吃鸡战场绝对王者,掌握顶级作战干货!

在绝地求生的战场上&#xff0c;只有强者才能生存&#xff01;作为吃鸡行家&#xff0c;吃鸡将在这里为您带来与众不同的游戏技巧和干货&#xff0c;助您成为绝对的战场王者&#xff01; 首先&#xff0c;让我们来介绍几个实用的吃鸡作图工具。我们推荐了几款实用的绘图软件和工…

springboot项目东方通TongWeb改造以及部署

SpringBoot东方通TongWeb改造以及部署 文章目录 SpringBoot东方通TongWeb改造以及部署1、替换springboot中的tomcat为 (东方通)tongweb&#xff0c;打包1.1 排除springboot中内置的tomcat依赖&#xff0c;设置打包方式为war包1.2 修改配置文件的配置1.2.1查看端口是否被占用1.2…

轮转数组[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个整数数组nums&#xff0c;将数组中的元素向右轮转k个位置&#xff0c;其中k是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,…

VMware安装银河麒麟高级服务器操作系统V10

目标 VMware安装银河麒麟高级服务器操作系统V10背景介绍环境准备安装步骤配置VM虚拟机系统安装 VMware安装银河麒麟高级服务器操作系统V10 背景介绍 近期&#xff0c;随着国产信创的持续发热和大众关注度的上升&#xff0c;我们公司决定与时俱进&#xff0c;针对国产技术趋势…

【使用OpenCV进行目标分割与计数的代码实例详解】

文章目录 概要实例一&#xff1a;硬币分割计数实例二&#xff1a;玉米粒分割计数 概要 在当今数字图像处理领域&#xff0c;图像分割技术是一项至关重要的任务。图像分割旨在将图像中的不同目标或区域准确地分开&#xff0c;为计算机视觉、图像识别和机器学习等领域提供了坚实…

javascript/python 笔记: folium feature group自动切换

1 python部分 python部分只能是静态的结果 1.1 导入库 import folium import math 1.2 数据 cell_lst表示基站位置&#xff0c;location_lst表示 用户实际位置&#xff08;均为伪数据&#xff09; cell_lst[[1.341505, 103.682498],[1.342751, 103.679604],[1.341505, 10…

【微信小程序】自定义组件布局会议OA其他页面(附源码)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…

如何为 Elasticsearch 创建自定义连接器

了解如何为 Elasticsearch 创建自定义连接器以简化数据摄取过程。 作者&#xff1a;JEDR BLASZYK Elasticsearch 拥有一个摄取工具库&#xff0c;可以从多个来源获取数据。 但是&#xff0c;有时你的数据源可能与 Elastic 现有的提取工具不兼容。 在这种情况下&#xff0c;你可…

推荐 3 个国外的自由职业者/兼职网站,大家有空可以去淘淘金

推荐 3 个国外的自由职业者/兼职网站&#xff0c;大家有空可以去淘淘金 1. Upwork 这个是全球最大的外包网站之一,很多知名公司都会在这里找外包员工 upwork.com 2. fiverr.com 这个平台也是侧重于技能变现&#xff0c;除了专业的职业技能&#xff0c;还有很多稀奇古怪的…

SpringCloud之Ribbon负载均衡解读

目录 基本介绍 概述 LoadBalanced理解 简单源码解读 1&#xff09;LoadBalancerIntercepor 2&#xff09;LoadBalancerClient 3&#xff09;负载均衡策略IRule 4&#xff09;总结 负载均衡策略 负载均衡策略 自定义负载均衡策略 基本介绍 概述 Ribbon是Netflix发布…

Nginx集群负载均衡配置完整流程

今天&#xff0c;良哥带你来做一个nginx集群的负载均衡配置的完整流程。 一、准备工作 本次搭建的操作系统环境是win11&#xff0c;linux可配置类同。 1&#xff09;首先&#xff0c;下载nginx。 下载地址为&#xff1a;http://nginx.org/en/download.html 良哥下载的是&am…

浅谈余压监控系统在住宅小区的应用方案

【摘要】&#xff1a; 本文分析了火灾发生时人员伤亡的主要原因——烟雾&#xff0c;并针对该原因提供切实可靠的系统应用解决方案&#xff0c;并通过具体案例&#xff0c;从设计依据、产品选型、系统组网、现场安装等方式介绍余压监控系统&#xff0c;希望可以在火灾发生时较大…