Spring Boot 整合视图层技术 FreeMarker

news2024/9/28 23:33:41

大家好!我是今越。简单记录一下在 Spring Boot 框架中如何整合 Freemarker 及使用。

FreeMarker 简介

FreeMarker 是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本( HTML 网页,电子邮件,配置文件,源代码等)的通用工具。它不是面向最终用户的,而是一个 Java 类库,是一款程序员可以嵌入他们所开发产品的组件。

模板编写语言为 FreeMarker Template Language,它是简单的,专用的语言,不是像 PHP 那样成熟的编程语言。那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示已经准备好的数据在模板中,你可以专注于如何展现数据,而在模板之外可以专注于要展示什么数据。

FreeMarker官网插图

这种方式通常被称为 MVC(模型 视图 控制器)模式,对于动态网页来说,是一种特别流行的模式。它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML 设计师)。设计师无需面对模板中的复杂逻辑,在没有程序员来修改或重新编译代码时,也可以修改页面的样式。而 FreeMarker 最初的设计,是被用来在 MVC 模式的 Web 开发框架中生成 HTML 页面的,它没有被绑定到 Servlet 或 HTML 或任意 Web 相关的东西上。它也可以用于非 Web 应用环境中。

FreeMarker 是免费的,基于 Apache 许可证 2.0 版本发布。

整合 Spring Boot

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

org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration 类中,可以看到自动化的配置:

@AutoConfiguration
@ConditionalOnClass({Configuration.class, FreeMarkerConfigurationFactory.class})
@EnableConfigurationProperties({FreeMarkerProperties.class})
@Import({FreeMarkerServletWebConfiguration.class, FreeMarkerReactiveWebConfiguration.class, FreeMarkerNonWebConfiguration.class})
public class FreeMarkerAutoConfiguration {}

从这里可以看出,当 classpath 下存在 Configuration 以及 FreeMarkerConfigurationFactory 时,配置才会生效,也就是说当我们引入了 Freemarker 依赖之后,配置就会生效。但是这里的自动化配置只做了模板位置检查,其他配置则是在导入的 FreeMarkerServletWebConfiguration 配置中完成的。那么我们再来看看 FreeMarkerServletWebConfiguration 类,部分源码如下:

package org.springframework.boot.autoconfigure.freemarker;

import javax.servlet.DispatcherType;
import javax.servlet.Servlet;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.servlet.ConditionalOnMissingFilterBean;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, FreeMarkerConfigurer.class})
@AutoConfigureAfter({WebMvcAutoConfiguration.class})
class FreeMarkerServletWebConfiguration extends AbstractFreeMarkerConfiguration {
    protected FreeMarkerServletWebConfiguration(FreeMarkerProperties properties) {
        super(properties);
    }

    @Bean
    @ConditionalOnMissingBean({FreeMarkerConfig.class})
    FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        this.applyProperties(configurer);
        return configurer;
    }

    @Bean
    freemarker.template.Configuration freeMarkerConfiguration(FreeMarkerConfig configurer) {
        return configurer.getConfiguration();
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"freeMarkerViewResolver"}
    )
    @ConditionalOnProperty(
        name = {"spring.freemarker.enabled"},
        matchIfMissing = true
    )
    FreeMarkerViewResolver freeMarkerViewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        this.getProperties().applyToMvcViewResolver(resolver);
        return resolver;
    }

    @Bean
    @ConditionalOnEnabledResourceChain
    @ConditionalOnMissingFilterBean({ResourceUrlEncodingFilter.class})
    FilterRegistrationBean<ResourceUrlEncodingFilter> resourceUrlEncodingFilter() {
        FilterRegistrationBean<ResourceUrlEncodingFilter> registration = new FilterRegistrationBean(new ResourceUrlEncodingFilter(), new ServletRegistrationBean[0]);
        registration.setDispatcherTypes(DispatcherType.REQUEST, new DispatcherType[]{DispatcherType.ERROR});
        return registration;
    }
}

我们来简单看下这段源码:

  • @ConditionalOnWebApplication 表示当前配置在 web 环境下才会生效。

  • ConditionalOnClass 表示当前配置在存在 Servlet 和 FreeMarkerConfigurer 时才会生效。

  • @AutoConfigureAfter 表示当前自动化配置在 WebMvcAutoConfiguration 之后完成。

  • 代码中,主要提供了 FreeMarkerConfigurer 和 FreeMarkerViewResolver。

  • FreeMarkerConfigurer 是 Freemarker 的一些基本配置,例如 templateLoaderPath、defaultEncoding 等

  • FreeMarkerViewResolver 则是视图解析器的基本配置,包含了 viewClass、suffix、allowRequestOverride、allowSessionOverride 等属性。

另外还有一点,在这个类的构造方法中,注入了 FreeMarkerProperties:

@ConfigurationProperties(
    prefix = "spring.freemarker"
)
public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties {
    public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/";
    public static final String DEFAULT_PREFIX = "";
    public static final String DEFAULT_SUFFIX = ".ftlh";
    private Map<String, String> settings = new HashMap();
    private String[] templateLoaderPath = new String[]{"classpath:/templates/"};
    private boolean preferFileSystemAccess;
}

FreeMarkerProperties 中则配置了 Freemarker 的基本信息,例如模板位置在 classpath:/templates/ ,再例如模板后缀为 .ftlh,那么这些配置我们以后都可以在 application.properties 中进行修改。

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.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/

配置文件按照顺序依次解释如下:

  1. HttpServletRequest 的属性是否可以覆盖 controller 中 model 的同名项
  2. HttpSession 的属性是否可以覆盖 controller 中 model 的同名项
  3. 是否开启缓存
  4. 模板文件编码
  5. 是否检查模板位置
  6. Content-Type 的值
  7. 是否将 HttpServletRequest 中的属性添加到 Model 中
  8. 是否将 HttpSession 中的属性添加到 Model 中
  9. 模板文件后缀
  10. 模板文件位置

示例

创建类和接口

public class User {
    private Long id;
    private String username;
    private String address;
    // setter, getter
}
@Controller
public class UserController {
    @GetMapping("/hello")
    public String hello(Model model) {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId((long) i);
            user.setUsername("jackson>>>" + i);
            user.setAddress("Hangzhou>>>" + i);
            list.add(user);
        }
        model.addAttribute("users", list);
        return "hello";
    }
}

hello.ftlh 页面中渲染数据

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<table border="1">
    <tr>
        <td>用户编号</td>
        <td>用户名称</td>
        <td>用户地址</td>
    </tr>
    <#list users as u>
        <tr>
            <td>${u.id}</td>
            <td>${u.username}</td>
            <td>${u.address}</td>
        </tr>
    </#list>
</table>
</body>
</html>

显示效果如下

FreeMarker官网插图

FreeMarker 使用细节

插值与表达式

直接输出值

1)字符串

<div>${"hello,我是直接输出的字符串"}</div>
<div>${"我的文件保存在C:\\盘"}</div>

注意:\ 需要转义

在目标字符串的引号前增加 r 标记,在 r 标记后的文本内容将会直接输出,例如

<div>${r"我的文件保存在C:\\盘"}</div>

2)数字

在 FreeMarker 中使用数值需要注意

a.数值不能省略小数点前面的 0,所以 “.5” 是错误的写法;

b.数值 8 , +8 , 8.00 都是相同的;

数字的其它用法:

将数字以钱的形式,以百分数的形式展示

<#assign price=99>
<div>${price?string.currency}</div>
<div>${price?string.percent}</div>

3)布尔

布尔类型可以直接定义,不需要引号,例如

<#assign flag=true>
<div>${flag?string("yes","no")}</div>
<!--如果 flag 为 true,则输出 yes,否则输出 no-->

4)集合

集合也可以现场定义现场输出,例如

<#list [2+2,"anson","jackson"] as x>
    <div>${x}</div>
</#list>
<#list 5..1 as x>
    <div>${x}</div>
</#list>
<#list 1..5 as x>
    <div>${x}</div>
</#list>

其中,x 代表集合中的每一个元素。

也可以定义 Map 集合,Map 集合用一个 {} 来描述,例如

<#assign userinfo={"name":"jackson","address":"hanghzou西湖"}>
<#list userinfo?keys as key>
    <div>${key}--${userinfo[key]}</div>
</#list>
<hr/>
<#list userinfo?values as value>
    <div>${value}</div>
</#list>
<hr/>
<div>${userinfo.name}</div>
<div>${userinfo['address']}</div>

上面两个循环分别表示遍历 Map 中的 key 和 value。

输出变量

@Controller
public class UserController {
    @GetMapping("/hello")
    public String hello(Model model) {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId((long) i);
            user.setUsername("jackson>>>" + i);
            user.setAddress("Hangzhou>>>" + i);
            list.add(user);
        }
        model.addAttribute("users", list);
        Map<String, Object> info = new HashMap<>();
        info.put("name", "向往的今越");
        info.put("age", 18);
        info.put("address", "市中心");
        model.addAttribute("info", info);
        model.addAttribute("name", "shengsheng");
        model.addAttribute("birthday", new Date());
        return "hello";
    }
}

1)普通变量

普通变量的展示,例如

<div>${name}</div>

2)集合

直接遍历:

<div>
    <table border="1">
        <#list users as u>
            <tr>
                <td>${u.id}</td>
                <td>${u.username}</td>
                <td>${u.address}</td>
            </tr>
        </#list>
    </table>
</div>

输出集合中索引为 3 的元素:

<div>${users[3].address}</div>

输出子集合:

<div>
    <table border="1">
        <#list users[3..5] as u>
            <tr>
                <td>${u.id}</td>
                <td>${u.username}</td>
                <td>${u.address}</td>
                <td>${u_index}</td>
                <td>${u_has_next?string("yes","no")}</td>
            </tr>
        </#list>
    </table>
</div>

遍历时,可以通过 变量名_index 获取遍历的下标,变量名_has_next 判断是否有后继元素。

3)Map

直接获取 Map 中的值有不同的写法,例如

<div>${info.name}</div>
<div>${info['age']}</div>
<div>${info['address']}</div>

获取 Map 中的所有 key,并根据 key 获取 value

<div>
    <#list info?keys as key>
        <div>${key}--${info[key]}</div>
    </#list>
</div>

获取 Map 中的所有 value

<div>
    <#list info?values as value>
        <div>${value }</div>
    </#list>
</div>

字符串操作

字符串的拼接有两种方式

<div>${"hello ${name}"}</div>
<div>${"hello " + name}</div>

也可以从字符串中截取子串

<div>${name[0]}${name[1]}</div>
<div>${name[1..3]}</div>

集合操作

集合相加

<div>
    <#list [1,2,3] + [4,5,6] as x>
        ${x},
    </#list>
</div>

Map 相加

<div>
    <#list (info+{"weather":"sunny"})?keys as key>
        ${key},
    </#list>
</div>

算术运算

+*/% 运算都是支持的。

<div>
    <#assign age=99>
    <div>${age*99/99+99-1}</div>
</div>

比较运算

比较运算和 Thymeleaf 比较类似:

  • = 或者 == 判断两个值是否相等

  • != 判断两个值是否不等

  • > 或者 gt 判断左边值是否大于右边值

  • >= 或者 gte 判断左边值是否大于等于右边值

  • < 或者 lt 判断左边值是否小于右边值

  • <= 或者 lte 判断左边值是否小于等于右边值

<div>
    <#assign age=99>
    <#if age=99>age=99</#if><br/>
    <#if age gt 99>age gt 99</#if><br/>
    <#if (age > 99)>age > 99</#if><br/>
    <#if age gte 99>age gte 99</#if><br/>
    <#if age lt 99>age lt 99</#if><br/>
    <#if age lte 99>age lte 99</#if><br/>
    <#if age!=99>age!=99</#if><br/>
    <#if age==99>age==99</#if><br/>
</div>

提示:带 < 或者 > 的符号,也都有别名,建议使用别名。

逻辑运算

逻辑运算符有三个:

  • 逻辑与 &&
  • 逻辑或 ||
  • 逻辑非 !
<div>
    <#assign age=99>
    <#if age=99 && 1==1>age=99 && 1==1</#if>
    <#if age=99 || 1==0>age=99 || 1==0</#if>
    <#if !(age gt 99)>!(age gt 99)</#if>
</div>

注意:逻辑运算符只能作用于布尔值,否则将产生错误。

空值处理

为了处理缺失变量,Freemarker 提供了两个运算符:

  • !:指定缺失变量的默认值

  • ??:判断某个变量是否存在

如果某个变量不存在,则设置其为 jackson,例如

<div>${aaa!"jackson"}</div>

如果某个变量不存在,则设置其为空字符串,例如

<div>${aaa!}</div>

! 后面的东西如果省略了,默认就是空字符串。

判断某个变量是否存在,例如

<div><#if aaa??>aaa</#if></div>

内建函数

内建函数可参考官网文档:http://freemarker.foofun.cn/ref_builtins.html

<div>
    <#--cap_first 使字符串第一个字母大写-->
    <div>${"hello"?cap_first}</div>
    <#--lower_case 将字符串转换成小写-->
    <div>${"HELLO"?lower_case}</div>
    <#--upper_case 将字符串转换成大写-->
    <div>${"hello"?upper_case}</div>
    <#--trim 去掉字符串前后的空白字符-->
    <div>${" hello "?trim}</div>
    <#--size 获取序列中元素的个数-->
    <div>${users?size}</div>
    <#--int 取得数字的整数部分,结果带符号-->
    <div>${-3.14?int}</div>
    <#--日期格式化-->
    <div>${birthday?string("yyyy-MM-dd")}</div>
</div>

常用指令

if/else

分支控制指令,作用类似于 Java 语言中的 if

<div>
    <#assign age=23>
    <#if (age>60)>老年人
    <#elseif (age>40)>中年人
    <#elseif (age>20)>青年人
    <#else> 少年人
    </#if>
</div>

比较符号中用了 (),因此不用转义。

switch

分支指令,类似于 Java 中的 switch

<div>
    <#assign age=99>
    <#switch age>
        <#case 23>23<#break>
        <#case 24>24<#break>
        <#default>9999
    </#switch>
</div>

<#break> 是提前退出,也可以用在 <#list> 中。

noparse

如果想在页面展示一些 Freemarker 语法而不被渲染,则可以使用 noparse 标签,如下:

<#noparse>
  <div>hhh</div>
<#noparse>

include

include 包含外部页面进来。

<#include "./test.ftlh">

macro

macro 用来定义一个宏。例如定义一个名为 book 的宏,并引用它:

<#macro book>
    三国演义
</#macro>
<@book/>

最终页面中会输出宏中所定义的内容。

在定义宏的时候,也可以传入参数,那么引用时,也需要传入参数:

<#macro book bs>
    <table border="1">
        <#list bs as b>
            <tr>
                <td>${b}</td>
            </tr>
        </#list>
    </table>
</#macro>
<@book ["三国演义","水浒传"]/>

bs 就是需要传入的参数。可以通过传入多个参数,多个参数跟在 bs 后面即可,中间用空格隔开。

还可以使用 <#nested> 引入用户自定义指令的标签体,像下面这样:

<#macro book bs>
    <table border="1">
        <#list bs as b>
            <tr>
                <td>${b}</td>
            </tr>
        </#list>
    </table>
    <#nested>
</#macro>
<@book ["三国演义","水浒传"]>
    <h1>hello javaboy!</h1>
</@book>

在宏定义的时候,<#nested> 相当于是一个占位符,在调用的时候,<@book> 标签中的内容会出现在 <#nested> 位置。

前面的案例中,宏都是定义在当前页面中,宏也可以定义在一个专门的页面中。新建 mymarcro.ftlh 页面,内容如下:

<#macro book bs title>
    <table>
        <#list bs as b>
            <tr>
                <td>${b}</td>
            </tr>
        </#list>
    </table>
    <#nested>
</#macro>

此时,需要先通过 <#import> 标签导入宏,然后才能调用,如下:

<#import "./mymacro.ftlh" as com>
<@com.book bs=["三国演义", "水浒传"] title="hhh">
    <h1>hello jackson!</h1>
</@com.book>

唯有热爱可抵岁月漫长。我是今越,欢迎大家点赞、收藏和评论,感谢支持!

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

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

相关文章

Python3 实例(二) | 菜鸟教程(二十)

目录 一、Python 将列表中的头尾两个元素对调 &#xff08;一&#xff09;定义一个列表&#xff0c;并将列表中的头尾两个元素对调。 &#xff08;二&#xff09;实例1 &#xff08;三&#xff09;实例2 &#xff08;四&#xff09;实例3 二、Python 将列表中的指定位置的…

新一代版本依赖管理Vesion Catalog的探索与实践

前言 前段时间使用新版本的Android Studio创建了个项目想测试点东西&#xff0c;项目创建后发现整个Gradle的依赖管理发生了巨大的变化。 先说一下我使用的Android Studio的版本如下。 创建项目后主要变化如下&#xff1a; 原本的.gradle变成了.gradle.kts&#xff0c;也就是…

商业综合体智能管理系统

自主研发的商业综合体智能管理系统和智能硬件&#xff0c;并针对行业不同需求&#xff0c;推出了不同行业的创新解決方案和服务。该系统能够提高商业综合体的管理效率和安全性&#xff0c;为商业综合体的经营和服务增加更多的价值。全自动智能完成无需人工干预&#xff0c;从而…

【企业架构框架】SOGAF架构类型/模式

模式概述 Salesforce 运营、治理和架构框架 (SOGAF) 将新窗口企业架构框架中的 MIT-CISR Salesforce 实施和程序。在此框架内&#xff0c;有四种通用架构类型&#xff1a; 单一系统核心模型模板多系统 每个特定的架构类型对应一个支持 SOGAF 运营模型。架构类型的选择还应包括…

前端搭建名言生成器(内含源码)

目录 前言 名言生成器 页面搭建 功能实现 前言 今天呢我们来给大家展示的&#xff0c;就是一个非常非常简单的名言生成器&#xff0c; 那么它的功能的非常简单&#xff0c;就是我们通过点击按钮&#xff0c;然后可以生成名人名言&#xff0c;然后我们也可以点击按钮将它分享到…

C++图形开发(1):graphics图形库简介与安装

文章目录 1.引入2.安装&#xff08;1&#xff09;在官网下载安装包&#xff08;2&#xff09;安装 3.检验 1.引入 为了帮助大家实现真正的、更有意思的C开发&#xff0c;本人决定开一个C图形开发的专栏&#xff0c;来制作更多的有意思的游戏、程序。 首先我们要了解的&#x…

MySQL 分库分表实战之ShardingSpare(分库分表+读写分离)

文章目录 概要一、安装二、配置2.1、 通用配置2.2、 分片配置2.3、读写分离 三、演练3.1、读写分离3.2、分库分表3.3、分库分表读写分离 4、总结 概要 市面上MySQL分库分表中间件还是很多的&#xff0c;主要分为两大类&#xff1a;应用层依赖类中间件&#xff08;比如sharding…

电气自动化入门——总览

目录 学习路线 电气设备组成部分 设备驱动类设备元件 常用电机类型 电机控制器类型​编辑 气缸类设备驱动 设备控制与数据采集监控部分 小型PLC 中大型PLC 数据采集与监控 HMI——人机交互界面 IPC——工控机 设备检测反馈元件——传感器 学习路线 电气设备组成部分 …

第 352 场LeetCode周赛

A 最长奇偶子数组 枚举满足条件的左端点能延续的最长右端点 class Solution { public:int longestAlternatingSubarray(vector<int> &nums, int threshold) {int res 0;int n nums.size();for (int i 0; i < n;) {if (nums[i] % 2 0 && nums[i] <…

Spring Boot 中的 Spring Cloud Hystrix:原理和使用

Spring Boot 中的 Spring Cloud Hystrix&#xff1a;原理和使用 什么是 Spring Cloud Hystrix&#xff1f; Spring Cloud Hystrix 是一个用于处理分布式系统中故障的库。它实现了熔断器模式&#xff0c;可以防止由于故障服务的连锁反应而导致整个系统崩溃。Spring Cloud Hyst…

RabbitMq应用延时消息

一.建立绑定关系 package com.lx.mq.bind;import com.lx.constant.MonitorEventConst; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annota…

innovus: 如何让两个generate clock balance skew group?

如题&#xff0c;在sdc约束中两个generate clock被设置到同一个clock group中&#xff0c;工具虽然会生成对应的两个skew group&#xff0c;但是阅读ccoot_spec发现工具并没有让两个skew group进行balance&#xff0c;这时就需要手动设置balance skew group。 方法如下: 在读…

回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测

回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测 目录 回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 基于鲸鱼算法优化深度置信网络(WOA-DBN)的数据回归预测&…

微软AI太会了,示爱威胁PUA!

微软在以ChatGPT为基础的最新搜索引擎New Bing在公测仅一周后就引发了人们的担忧和恐惧。用户反馈&#xff0c;New Bing不仅会表现出类似示爱、PUA和威胁人类等人类特有的行为&#xff0c;还可能超越人类意志和价值观&#xff0c;并违反“阿西莫夫的机器人三定律”。这引起了人…

ODERBY的运行原理

定义表: CREATE TABLE t (id int(11) NOT NULL,city varchar(16) NOT NULL,name varchar(16) NOT NULL,age int(11) NOT NULL,addr varchar(128) DEFAULT NULL,PRIMARY KEY (id),KEY city (city) ) ENGINEInnoDB; SQL语句: select city,name,age from t where city杭州 orde…

【第二章 flutter学习之Dart介绍】

文章目录 前言一、Dart环境搭建安装 Dart Sdkvscode安装dart 前言 Dart是谷歌开发的计算机编程语言&#xff0c;诞生于2011&#xff0c;可以被用于web、服务器、移动应用、物联网应用的开发。要学习flutter必须会Dart 一、Dart环境搭建 安装 Dart Sdk 官网&#xff1a;https…

Kubernetes(k8s)容器编排Service

目录 1 Service概述1.1 为什么要有Service1.2 Service实现原理 2 Service 的类型3 Service示例3.1 准备工作3.1.1 创建deployment3.1.2 启动deployment3.1.3 访问测试 3.2 ClusterlP类型3.2.1 编辑资源清单3.2.2 应用Service3.2.3 访问测试3.2.4 删除Pod3.2.5 访问测试 3.3 Nod…

Python学习——类与对象

一、编程的两大思想 &#xff08;1&#xff09;面向过程 事物比较简单&#xff0c;用简单的线性思维即可解决 &#xff08;2&#xff09;面向对象 事物比较复杂&#xff0c;用简单的线性思维无法解决 &#xff08;3&#xff09;两者之间的关系 在面对复杂的问题时&#xff0c;宏…

gcc编译过程详解

以一个简单的C代码为例&#xff0c;详细讲解gcc整个编译过程。 1、预处理 主要处理#开头的东西&#xff0c;例如头文件处理、条件编译处理、将宏定义进行替换&#xff0c;还可以去掉注释、添加行号等。预处理的命令如下&#xff1a; gcc -E hello.c -o hello.i #-E表示预处理…

全志V3S嵌入式驱动开发(解决kernel 5.2.y wifi驱动问题)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 wifi模块&#xff0c;之前测试的时候&#xff0c;开发板上用的是esp 8089&#xff0c;当时内核时4.14.y&#xff0c;测试结果也是通过的。印象不是…