【SpringBoot】FreeMarker视图渲染

news2024/10/1 1:30:34

目录

一、FreeMarker 简介

1.1 什么是FreeMarker?

1.2 Freemarker模板组成部分

1.3 为什么要使用FreeMarker

二、Springboot集成FreeMarker

2.1 配置

2.2 数据类型

2.2.1 字符串

2.2.2 数值

2.2.3 布尔值

2.2.4 日期

2.3 常见指令  

2.3.2 assign

2.3.3 include

...

三、常见指令实现增删改查(综合案例)⭐

3.1 后端

3.2 前端

3.3 效果展示

3.3.1 新增功能

3.3.2 修改功能

3.3.3 查询功能

3.3.4 删除功能


一、FreeMarker 简介

1.1 什么是FreeMarker?

       FreeMarker是一款 模板引擎 ,它允许开发人员使用模板和数据来生成输出文本,如HTML网页、电子邮件、配置文件和源代码等。它是一个Java类库,可以被嵌入到开发人员所创建的产品中。开发人员可以使用FreeMarker来动态生成和渲染视图,以便将数据呈现给最终用户

官方手册icon-default.png?t=N7T8https://freemarker.apache.org/

下面是一些关键点:

  1. 模板引擎: FreeMarker是一种模板引擎,允许开发者定义模板文件,其中包含要动态填充的占位符或表达式。这些模板文件可以包含HTML、XML、文本等。

  2. 动态内容生成: FreeMarker的主要用途是根据模板和数据生成最终的输出内容。模板中的占位符将被实际的数据替代,从而生成动态的、个性化的输出。

  3. 嵌入式组件: FreeMarker是一个Java类库,可以轻松地集成到Java应用程序中。这使得开发人员可以在他们的Java应用中使用FreeMarker来处理视图层的动态内容生成。

  4. 面向程序员: FreeMarker通常被程序员用于构建动态的用户界面或生成其他类型的文本输出。它不直接面向最终用户,而是提供给开发人员一个工具,使他们能够以更灵活和动态的方式生成内容。

1.2 Freemarker模板组成部分

FreeMarker模板文件主要由如下4个部分组成:

  • 文本:直接输出的部分

  • 注释:使用 <#-- ... --> 格式做注释,里面内容不会输出

  • 插值:即 ${...} 或 #{...} 格式的部分,类似于占位符,将使用数据模型中的部分替代输出

  • FTL指令:即FreeMarker指令,全称是:FreeMarker Template Language,和HTML标记类似,但名字前加#予以区分,不会输出

1.3 为什么要使用FreeMarker

FreeMarker在Spring Boot中被广泛使用的原因与其特性和与Spring Boot的集成有关。

  1. 轻量级: FreeMarker相对轻量,不引入过多的依赖,易于集成和使用。

  2. 与Spring框架整合良好: FreeMarker与Spring框架集成良好,通过Spring Boot的自动配置,可以很容易地配置FreeMarker作为模板引擎。

  3. Spring Boot 默认支持: Spring Boot对多个模板引擎提供了自动配置支持,包括FreeMarker。因此,Spring Boot项目中使用FreeMarker非常方便,只需在依赖中引入相应的starter即可。

  4. 开箱即用: FreeMarker可以作为Spring Boot的一部分,无需额外的配置。这使得开发者能够快速启动项目并使用FreeMarker构建视图。

  5. 简化模板文件的构建: FreeMarker的模板语法相对简洁,可以更容易地与后端Java代码交互。在Spring Boot项目中,Java对象的数据可以直接在FreeMarker模板中使用。

       FreeMarker的诞生是为了取代JSP。虽然JSP功能强大,可以写Java代码实现复杂的逻辑处理,但是页面会有大量业务逻辑,不利于维护和阅读,更不利于前后台分工,容易破坏MVC结构,所以舍弃JSP,选择使用FreeMarker是大势所趋。

二、Springboot集成FreeMarker

2.1 配置

1、配置pom.xml,引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

 

2、添加application.yml配置:

  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/**

3、新建模板文件(.ftl)

在resources/templates目录新建一个.ftl文件

第一创建是没有这个文件类型的选项的,所以我们要定义个.ftl格式的文件:

settings --> Editor --> File and Code Templates 

该内容模板于html差不多的,最后在创建文件的时候就有个一个.ftl格式的文件选项

index.ftl:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Freemarker</title>
</head>
<body>
<h1>Hello FreeMarker!!!</h1>
</body>
</html>

Controller:

package com.ycxw.boot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author 云村小威
 * @create 2023-12-13 18:57
 */
@Controller
public class IndexController {

    @RequestMapping("/")
    public String home(){
        return "index";
    }
}

一个基本的数据显示就成功了

2.2 数据类型

2.2.1 字符串

        在文本中确定字符串值的方法是看双引号,比如: "some text",或单引号,比如: 'some text'。这两种形式是等同的。 如果文本自身包含用于字符引用的引号 ( "')或反斜杠时, 应该在它们的前面再加一个反斜杠;这就是转义。 转义允许直接在文本中输入任何字符, 也包括换行。

${"It's \"quoted\" and this is a backslash: \\"}

字符串类型处理:

方法含义
?substring(start,end)截取字符串(左闭右开)
?uncap_first首字母小写输出
?cap_first首字母大写输出
?lower_case字母转小写输出
?upper_case字母转大写输出
?length获取字符串长度
?starts_with("xx")?string是否以指定字符开头(boolean类型)
?ends_with("xx")?string是否以指定字符结尾(boolean类型)
?index_of("xx")获取指定字符的索引
?trim去除字符串前后空格
?replace("xx","xx")替换指定字符串

字符串空值情况处理:

FreeMarker 的变量必须赋值,否则就会抛出异常。而对于 FreeMarker 来说,null 值和不存在的变量是完全一样的,因为 FreeMarker 无法理解 null 值。

<#-- 如果值不存在,直接输出会报错 -->
<#--${str}-->
<#-- 使用!,当值不存在时,默认显示空字符串 -->
${str!}<br>
<#-- 使用!"xx",当值不存在时,默认显示指定字符串 -->
${str!"这是一个默认值"}<br>
<#-- 使用??,判断字符串是否为空;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串 -->
${(str??)?string}<br>

注意事项:

使用??或?starts_with("xx"),判断字符串是否为空或指定字符开头;返回布尔类型。如果想要输出,需要将布尔类型转换成字符串在后面添加 ?c or ?string

例如:

${"嗨害嗨"?starts_with("我")}
${str??}

不进行转换则会报错

2.2.2 数值

输入不带引号的数字就可以直接指定一个数字, 必须使用点作为小数的分隔符而不能是其他的分组分隔符。

${0.45}<br>
${18}<br>
<#-- 将数值转换成字符串输出 -->
${1000?c} <br>
<#-- 将数值转换成货币类型的字符串输出 -->
${1000?string.currency} <br>
<#-- 将数值转换成百分比类型的字符串输出 -->
${0.45?string.percent} <br>
<#-- 将浮点型数值保留指定小数位输出 (##表示保留两位小数) -->
${0.45723123?string["0.##"]} <br>

2.2.3 布尔值

直接写 true 或者 false 就表示一个布尔值了,不需使用引号。

在freemarker中布尔类型不能直接输出;如果输出要先转成字符串

${flag?c}<br>
${flag?string}<br>
${flag?string("yes","no")}<br>

 

2.2.4 日期

日期变量可以存储和日期/时间相关的数据。

在freemarker中日期类型不能直接输出;如果输出要先转成日期型或字符串

日期格式输出:

输出方式说明
?date年月日
?time时分秒
?datetime年月日时分秒
?string("自定义格式")指定格式
<#-- 输出日期格式 -->
${createDate?date} <br>
<#-- 输出时间格式 -->
${createDate?time} <br>
<#-- 输出日期时间格式 -->
${createDate?datetime} <br>
<#-- 输出格式化日期格式 -->
${createDate?string("yyyy年MM月dd日 HH时mm分ss秒")} <br>

注意事项:

在.ftl文件中不能直接创建时间需要通过后端传入时间进行显示(替换掉createDate)

2.3 常见指令  

2.3.2 assign

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

案例演示:

<#-- 创建一个str的变量 -->
<#assign str="hello">
<#-- 输出str -->
${str} <br>
<#-- 一次创建多个变量 -->
<#assign num=1 names=["嗨","害","嗨"] >
${num} and ${names?join(",")}

 

2.3.3 include

可以使用它在你的模板中插入另外一个 FreeMarker 模板文件 (由 path 参数指定)

该标签主要用于引入其他资源,简化数据

首先创建一个公共页面定义一个变量存储本地访问路径

 在index.ftl中进行引入调用src数值

<#-- 引入公共页面 -->
<#include "common.ftl">
<a href="${src}/xxx"></a>

...

还有如:if/elseif/else、list指令在下面的综合案例中进行演示👇

三、常见指令实现增删改查(综合案例)⭐

3.1 后端

BookMapper.xml

    <select id="list" resultMap="BaseResultMap" resultType="com.ycxw.boot.entity.Book">
        select
        <include refid="Base_Column_List"/>
        from t_book
        where 1=1
        <if test="bookname !=null and bookname !=''">
            and bookname like CONCAT('%',#{bookname},'%')
        </if>
    </select>

在此添加了模糊查询的方法,其他的增删改都是自动生成。

BookMapper.java

package com.ycxw.boot.mapper;

import com.ycxw.boot.entity.Book;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
* @author 云村小威
* @description 针对表【t_book(书本信息表)】的数据库操作Mapper
* @createDate 2023-12-12 14:50:45
* @Entity com.ycxw.boot.entity.Book
*/
@Repository
public interface BookMapper {

    List<Book> list(@Param("bookname")String bookname);

    ...其他方法
}

BookService.java

package com.ycxw.boot.service;

import com.ycxw.boot.entity.Book;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @author 云村小威
 * @create 2023-12-12 15:11
 */
public interface BookService {
    List<Book> list(@Param("bookname")String bookname);

    int insert(Book record);

    int deleteByPrimaryKey(Long id);

    int updateByPrimaryKey(Book record);
}

BookServiceImpl.java

package com.ycxw.boot.service.impl;

import com.ycxw.boot.entity.Book;
import com.ycxw.boot.mapper.BookMapper;
import com.ycxw.boot.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 云村小威
 * @create 2023-12-12 15:12
 */
@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookMapper bookMapper;

    @Override
    public List<Book> list(String bookname) {
        return bookMapper.list(bookname);
    }

    @Override
    public int insert(Book record) {
        return bookMapper.insert(record);
    }

    @Override
    public int deleteByPrimaryKey(Long id) {
        return bookMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKey(Book record) {
        return bookMapper.updateByPrimaryKey(record);
    }
}

IndexController.java

package com.ycxw.boot.controller;

import com.ycxw.boot.entity.Book;
import com.ycxw.boot.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author 云村小威
 * @create 2023-12-13 18:57
 */
@Controller
public class IndexController {
    @Autowired
    private BookService bookService;

    /**
     * 查询所有
     *
     * @param model
     * @return
     */
    @RequestMapping("/")
    public String home(Model model) {
        List<Book> list = bookService.list(null);
        model.addAttribute("book", list);
        return "index";
    }

    /**
     * 新增
     *
     * @param book
     * @return
     */
    @PostMapping("/add")
    public String add(@RequestBody Book book) {
        bookService.insert(book);
        return "redirect:/";
    }

    /**
     * 删除
     *
     * @param book
     * @return
     */
    @RequestMapping("/del")
    public String del(Book book) {
        bookService.deleteByPrimaryKey(book.getId().longValue());
        return "redirect:/";
    }

    /**
     * 修改
     *
     * @param book
     * @return
     */
    @PutMapping("/edit")
    public String edit(@RequestBody Book book) {
        bookService.updateByPrimaryKey(book);
        return "redirect:/";
    }

    /**
     * 模糊查询
     *
     * @param bookname
     * @param model
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.POST)
    public String search(@RequestParam("bookname") String bookname, Model model) {
        // 在这里使用 bookname 进行相关的处理
        List<Book> list = bookService.list(bookname);
        model.addAttribute("book", list);
        return "index"; // 返回搜索结果页面
    }


}

3.2 前端

common.ftl (公共资源)

<#--引入当前项目的运行路径-->
<#assign src="${springMacroRequestContext.contextPath}">
<#--引入样式与脚本-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<!-- 引入Bootstrap的JavaScript文件(需要在jQuery之后引入) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js"></script>

index.ftl(自定义引擎模版)

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>FreeMarker</title>
    <#--引入公共模块-->
    <#include "common.ftl">
</head>
<body>
<div class="container mt-5" id="body">
    <div class="row justify-content-center">
        <div class="col-3">
            <input type="text" class="form-control" id="input" placeholder="请输入书籍名称"
                   style="width: 300px"/>
        </div>
        <div class="col-2">
            <button type="submit" class="btn btn-dark mb-3" onclick="query()">搜索</button>
            <button type="button" class="btn btn-outline-dark mb-3" data-bs-toggle="modal"
                    data-bs-target="#exampleModal">
                新增书籍
            </button>
        </div>

    </div>
    <div class="row">
        <table class="table table-hover" style="width: 65%;margin: auto">
            <thead class="table-dark">
            <tr>
                <th>序号</th>
                <th>书籍名称</th>
                <th>价格</th>
                <th>类型</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <#if book??>
                <#list book as b>
                    <tr>
                        <td>${b.id}</td>
                        <td>${b.bookname}</td>
                        <td>${b.price}</td>
                        <td>${b.booktype}</td>
                        <td>
                            <a href="${src}/del?id=${b.id}">删除</a>
                            <a href="javascript:void(0);"
                               onclick="editModal('${b.id}', '${b.bookname}', '${b.booktype}', ${b.price})"
                               data-bs-toggle="modal" data-bs-target="#editModal">修改</a>
                        </td>
                    </tr>
                </#list>
            </#if>
            </tbody>
        </table>
    </div>
</div>
<!-- 新增弹窗 -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">新增书籍</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <!-- 表单 -->
                <form>
                    <div class="mb-3">
                        <label for="title" class="form-label">书籍名称</label>
                        <input type="text" class="form-control" id="name" placeholder="请输入标题">
                    </div>
                    <div class="mb-3">
                        <label for="author" class="form-label">类型</label>
                        <select class="form-select" id="bookType" aria-label="Default select example">
                            <option selected>请选择书籍类型</option>
                            <option value="动作">动作</option>
                            <option value="冒险">冒险</option>
                            <option value="文学">文学</option>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="price" class="form-label">价格</label>
                        <input type="number" class="form-control" id="price" placeholder="请输入价格">
                    </div>
                    <button type="button" class="btn btn-outline-dark" data-bs-dismiss="modal" aria-label="Close">取消
                    </button>
                    <button type="button" class="btn btn-dark" onclick="add()">提交</button>
                </form>
            </div>
        </div>
    </div>
</div>
<!-- 修改弹窗 -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">修改书籍</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <!-- 表单 -->
                <form>
                    <div class="mb-3">
                        <label for="id" class="form-label">书籍编号</label>
                        <input type="text" class="form-control" id="id" disabled>
                    </div>
                    <div class="mb-3">
                        <label for="title" class="form-label">书籍名称</label>
                        <input type="text" class="form-control" id="name_edit" placeholder="请输入标题">
                    </div>
                    <div class="mb-3">
                        <label for="author" class="form-label">类型</label>
                        <select class="form-select" id="type_edit" aria-label="Default select example">
                            <option selected>请选择书籍类型</option>
                            <option value="动作">动作</option>
                            <option value="冒险">冒险</option>
                            <option value="文学">文学</option>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="price" class="form-label">价格</label>
                        <input type="number" class="form-control" id="price_edit" placeholder="请输入价格">
                    </div>
                    <button type="button" class="btn btn-outline-dark" data-bs-dismiss="modal" aria-label="Close">取消
                    </button>
                    <button type="button" class="btn btn-dark" onclick="edit()">确认修改</button>
                </form>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    /*模糊查询*/
    function query() {
        //获取输入值
        var name = $("#input").val();
        // 发送AJAX请求
        $.ajax({
            url: "${src}/search",
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: {"bookname": name},
            success: function (data) {
                //更新整个页面元素
                $("#body").html(data);
            }
        });
    }

    /*新增方法*/
    function add() {
        // 获取表单数据
        var name = $("#name").val();
        var type = $("#bookType").val();
        var price = $("#price").val();
        // 创建一个对象来存储表单数据
        var book = {
            bookname: name,
            booktype: type,
            price: price
        };
        // 发送AJAX请求
        $.ajax({
            url: "${src}/add",
            type: "POST",
            contentType: "application/json",
            data: JSON.stringify(book),
            success: function (res) {
                console.log(res);
                // 请求成功处理逻辑
                alert("书籍添加成功!");
                // 关闭弹窗
                var modal = $("#exampleModal");
                modal.modal("hide");
                // 刷新页面
                location.reload();
            }
        });
    }

    /* 修改方法(回显数据) */
    function editModal(id, name, type, price) {
        // 将数据设置到弹窗表单中
        $("#id").val(id);
        $("#name_edit").val(name);
        $("#type_edit").val(type);
        $("#price_edit").val(price);

        // 显示修改弹窗
        $("#editModal").modal("show");
    }

    /*修改方法*/
    function edit() {
        // 获取表单数据
        var id = $("#id").val();
        var name = $("#name_edit").val();
        var type = $("#type_edit").val();
        var price = $("#price_edit").val();
        // 创建一个对象来存储表单数据
        var book = {
            id: id,
            bookname: name,
            booktype: type,
            price: price
        };
        // 发送AJAX请求
        $.ajax({
            url: "${src}/edit",
            type: "PUT",
            contentType: "application/json",
            data: JSON.stringify(book),
            success: function (res) {
                console.log(res);
                // 请求成功处理逻辑
                alert("书籍修改成功!");
                // 关闭弹窗
                var modal = $("#editModal");
                modal.modal("hide");
                // 刷新页面
                location.reload();
            }
        });
    }
</script>
</html>

3.3 效果展示

3.3.1 新增功能

3.3.2 修改功能

3.3.3 查询功能

3.3.4 删除功能

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

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

相关文章

国产仿日立高速离心瓶250ml/500ml/1000ml日立通用离心杯

国产仿日立高速离心瓶250ml/500ml/1000ml日立离心机通用离心杯 250ml高速离心瓶 货号&#xff1a;ZY1136229 材质&#xff1a;PPCO 外径&#xff1a;61 mm 高度&#xff1a;130mm 500ml高速离心瓶 货号&#xff1a;ZY1136219 材质&#xff1a;PPCO 外径&#xff1a;73m…

大模型应用_FastGPT

1 功能 整体功能&#xff0c;想解决什么问题 官方说明&#xff1a;FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01;个人体会…

【map】【动态规划】LeetCode2713:矩阵中严格递增的单元格数

本文涉及的基础知识点 二分查找算法合集 题目 给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat&#xff0c;你可以选择任一单元格作为 起始单元格 。 从起始单元格出发&#xff0c;你可以移动到 同一行或同一列 中的任何其他单元格&#xff0c;但前提是目标单元格的值 …

UML-认识6种箭头(画类图无烦恼)

文章目录 一、背景二、箭头详解2.1 泛化&#xff08;Generalization&#xff09;2.2 实现&#xff08;Realize&#xff09;2.3 依赖&#xff08;Dependency&#xff09;2.4 关联&#xff08;Association&#xff09;2.5 聚合&#xff08;Aggregation&#xff09;2.6 组合&#…

npm安装,idea中启动vue失败

node 设置配置之后&#xff0c;要查询时&#xff0c;会从.npmrc中读取路径 .npmrc自己创建的&#xff08;默认情况下.npmrc会创建在C盘中&#xff09; 我创建的在D:\studay-and-working\node16.14\node_modules\npm中 指定.npmrc文件&#xff0c;因为默认会访问C盘的.npmrc文件…

现代雷达车载应用——第2章 汽车雷达系统原理 2.4节 雷达波形和信号处理

经典著作&#xff0c;值得一读&#xff0c;英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.4 雷达波形和信号处理 对于连续波雷达来说&#xff0c;波形决定了其基本信号处理流程以及一些关键功能。本节将以FMCW波形为例&#xff0c;讨论信号…

# 和 $ 的区别①

# 和 $ 都是为了获取变量的值 # 和 $ 区别 : 使用 # 查询 id 为 1 的内容 如果看不懂代码,就去看<<Mybatis 的操作(结合上文)续集>>,我这里为了简练一点就不多解释了 Select("select * from userInfo where id #{id}")UserInfo selectOne(Integer id…

2023版本QT学习记录 -1- 手写登录注册界面(信号与槽)

登录界面图片 登录界面设计 分别创建如下图的&#xff0c;一个文本框&#xff0c;两个输入框&#xff0c;两个按键 注册界面图片 注册界面设计 分别创建如下图的&#xff0c;一个文本框&#xff0c;两个输入框&#xff0c;两个按键 设计子框&#xff08;也就是注册页面&…

机器视觉系统选型-线光源分类及应用场景

标准线光源 从线性LED的发光面照射漫射光 玻璃划痕检测印刷字符检测手机屏幕检测PCB板检测 高亮线光源 从线性LED的发光面照射高亮度漫射光高速流水线检测表面印刷检测表面缺陷检测 集光型线光源 从线性LED的发光面照射直射光划痕缺陷检测印刷字符检测布料检测 同轴线光源 与相…

做数据分析为何要学统计学(2)——如何估计总体概率分布

我们可以通过手头掌握的样本来估计总体的概率分布。这个过程由以下步骤组成。 第一步&#xff0c;我们采用Seaborn软件的histplot函数建立核密度图&#xff08;一种概率密度图&#xff09;。 import numpy as np #输入样本数据 xnp.array([2.12906357, 0.72736725, 1.0515282…

Simple Water Caustic Pattern In Unity ShaderGpaph

shadertoy上有各种神奇的效果&#xff0c;以我的见识根本想象不到这些是怎么弄出来的。 不过不会做至少可以先会用。 这篇文章抓取一个shadertoy的示例以制作一个测试效果。 参考这篇shadertoy&#xff0c;使用自定义节点装填hlsl的noise代码 Shader - Shadertoy BETA 首先使…

使用FluentAvalonia组件库快速完成Avalonia前端开发

前言 工欲善其事必先利其器,前面我们花了几篇文章介绍了Avalonia框架以及如何在Avalonia框架下面使用PrismAvalonia完成MVV模式的开发。今天我们将介绍一款重磅级的Avalonia前端组件库,里面封装了我们开发中常用的组件,这样就不用我们自己再写组件了。专注业务功能开发,提…

tesseract-ocr安装使用

描述&#xff1a; 在centos上安装 tesseract 并在springboot项目中使用 步骤一&#xff1a;安装 确认使用的版本tesseract和test4j版本需要匹配&#xff0c;这里选择最新版 tesseract5.3.3 &#xff0c;test4j 5.9.0 版本匹配可查看 Releases nguyenq/tess4j GitHub 或…

「Leetcode」滑动窗口—长度最小的子数组

&#x1f4bb;文章目录 &#x1f4c4;题目✏️题目解析 & 思路&#x1f4d3;总结 &#x1f4c4;题目 209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, …,…

deepstream-python安装

​ 安装deepstream-docker 在这边文章中deepstream-docker详细介绍了如何在Ubuntu下安装deepstream-docker&#xff0c;安装完成之后&#xff0c;为了快速入门deepstream&#xff0c;我们可以安装deepstream-python库&#xff0c;通过阅读相应的例子来快速搭建一个应用。 安…

【Hive】

一、Hive是什么 Hive是一款建立在Hadoop之上的开源数据仓库系统&#xff0c;将Hadoop文件中的结构化、半结构化数据文件映射成一张数据库表&#xff0c;同时提供了一种类SQL语言&#xff08;HQL&#xff09;&#xff0c;用于访问和分析存在Hadoop中的大型数据集。Hive的核心是将…

第一届古剑山ctf-pwn全部题解

1. choice 附件&#xff1a; https://github.com/chounana/ctf/blob/main/2023%E7%AC%AC%E4%B8%80%E5%B1%8A%E5%8F%A4%E5%89%91%E5%B1%B1pwn/choice.zip 漏洞代码&#xff1a; 漏洞成因&#xff1a; byte_804A04C输入的长度可以覆盖nbytes的值&#xff0c;导致后面输入时存…

数据管理与持久化:深度解析Docker数据卷

Docker 数据卷在容器化应用中扮演着关键角色&#xff0c;它们提供了一种灵活且可持久化的方式来处理应用数据。本文将深入讨论 Docker 数据卷的基本概念、使用方法以及一系列高级应用场景&#xff0c;通过更为丰富和实际的示例代码&#xff0c;帮助大家全面掌握数据卷的使用和管…

Impala4.x源码阅读笔记(二)——Impala如何高效读取Iceberg表

前言 本文为笔者个人阅读Apache Impala源码时的笔记&#xff0c;仅代表我个人对代码的理解&#xff0c;个人水平有限&#xff0c;文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解&#xff0c;欢迎指正。 Iceberg表是一种用于存储大规模结构化数据的…

市场全局复盘 20231213

昨日回顾&#xff1a; SELECT TOP 10000 CODE,成交额排名,净流入排名,代码,名称,DDE大单金额,涨幅 ,主力净额,DDE大单净量,CONVERT(DATETIME, 最后封板, 120) AS 最后封板 FROM dbo.全部&#xff21;股20231213_ALL WHERE 连板天 > 1AND DDE大单净量 > 0AND DDE散户数量…