SpringBoot+FreeMaker

news2024/10/6 20:26:01

目录

  • 1.FreeMarker说明
  • 2.SpringBoot+FreeMarker快速搭建
    • Pom文件
    • application.properties文件
    • Controller文件
    • 目录结构
  • 3.FreeMarker数据类型
    • 3.1.布尔类型
    • 3.2.数值类型
    • 3.3.字符串类型
    • 3.4.日期类型
    • 3.5.空值类型
    • 3.6.sequence类型
    • 3.7.hash类型
  • 4.FreeMarker指令
    • assign自定义变量指令
    • if/elseif/else逻辑判断指令
    • list遍历指令
    • macro自定义指令(宏)
    • nested占位指令
    • import导入指令
    • include包含指令

1.FreeMarker说明

FreeMarker中文文档:http://freemarker.foofun.cn/index.html
学习视频:https://www.bilibili.com/video/BV1vq4y1p718

2.SpringBoot+FreeMarker快速搭建

参考文章:
(1)https://blog.csdn.net/xhf852963/article/details/116233053
(2)https://www.cnblogs.com/dw3306/p/9602139.html
(3)https://www.cnblogs.com/rainbowbridge/p/11410286.html
(4)https://blog.csdn.net/qq_46921028/article/details/130493378

Pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.asta</groupId>
    <artifactId>freemaker-hello</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 添加freemarker的maven依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

application.properties文件

server.port=8080
#HttpServletRequest 的属性是否可以覆盖controller中model 的同名项
spring.freemarker.allow-request-override=false
#H ttp Session 的属性是否可以覆盖 controller model 的同名项
spring.freemarker.allow-session-override=false
#是否开启缓存
spring.freemarker.cache=false
#模板文件编码
spring.freemarker.charset=UTF-8
#是否检查模板位置
spring.freemarker.check-template-location=true
#Content-Type的值
spring.freemarker.content-type=text/html
#是否将HttpServletRequest中的属性添加到Model中
spring.freemarker.expose-request-attributes=false
#是否将HttpSession中的属性添加到Model
spring.freemarker.expose-session-attributes=false
#模板文件后缀
spring.freemarker.suffix=.ftl
#模板文件位置
spring.freemarker.template-loader-path=classpath:/templates/

Controller文件

package com.asta.controller;
import com.asta.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.*;
/**
 * @Author:cs.cao
 * @Date:2024/4/14 15:42
 */
@Controller
@RequestMapping("/freemarker")
public class HelloController {

    @RequestMapping("/type")
    public ModelAndView hello() {
        String[] stars = new String[]{"周杰伦", "林俊杰", "陈奕迅", "五月天"};
        List<String> cities = Arrays.asList("北京", "上海", "南京", "杭州");
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "zhangsan", 22));
        userList.add(new User(2, "lisi", 23));
        userList.add(new User(3, "wangwu", 18));
        Map<String, Object> cityMap = new HashMap<>();
        cityMap.put("BJ", "北京");
        cityMap.put("SH", "上海");
        cityMap.put("HZ", "杭州");

        ModelAndView mv = new ModelAndView();
        // boolean类型
        mv.addObject("flag", true);
        // 数值类型
        mv.addObject("age", 18);
        mv.addObject("salary", 100000);
        mv.addObject("avg", 0.545);
        // 字符串类型
        mv.addObject("name", "cs.cao");
        // 日期类型
        mv.addObject("now", new Date());
        // 空值类型
        mv.addObject("nullValue", null);
        // sequence类型
        mv.addObject("stars", stars);
        mv.addObject("cities", cities);
        mv.addObject("userList", userList);
        // hash类型
        mv.addObject("cityMap", cityMap);
        mv.setViewName("hello");
        return mv;
    }
}

目录结构

在这里插入图片描述

3.FreeMarker数据类型

FreeMarker模板中的数据类型有如下几种:

  • 布尔型:等价于java中的Boolean类型,不同的是不能直接输出,可转换为字符串再输出。
  • 日期型:等价于java中的Date类型,不同的是不能直接输出,需要转换成字符串再输出。
  • 数值型:等价于java中的int,float,double等数值类型。有三种显示形式:数值型(默认)、货币型、百分比型。
  • 字符型:等价于java中的字符串,有很多内置函数
  • sequence类型:等价于java中的数组,list,set等集合类型。
  • hash类型:等价于java中的Map类型。

3.1.布尔类型

	<#--
	    boolean类型,需要转为字符串:
	    ${flag?c}
	    ${flag?string}
	    ${flag?string("yes","no")}
	-->
	<h3>boolean类型:</h3>
	${flag?c}<br/>
	${flag?string}<br/>
	${flag?string("yes","no")}<br/>

3.2.数值类型

	<#--
        数值类型,直接输出或转成字符串
        1.转字符串
            普通字符串:${num?c}
            货币型字符串:${num?string.currency}
            百分比型字符串:${num?string.percent}
        2.保留浮点型数值指定小数位数(#表示一个小数位)
            ${num?string["0.##"]}
    -->
    <h3>数值类型:</h3>
    ${age}<br/>
    ${salary}<br/>
    ${salary?c}<br/>
    ${salary?string.currency}<br/>
    ${avg?string.percent}<br/>
    ${avg?string["0.##"]}<br/>

3.3.字符串类型

	<#--
        字符串类型:
        1.截取字符串(左闭右开)${text?substring(start,end)}
        2.首字母小写输出:${text?uncap_first}
        3.首字母大写输出:${text?cap_first}
        4.字母转小写输出:${text?lower_case}
        5.字母转大写输出:${text?upper_case}
        6.获取字符串长度:${text?length}
        7.是否以指定字符开头(boolean类型)${text?starts_with("xx")?string}
        8.是否以指定字符结尾(boolean类型)${text?ends_with("xx")?string}
        9.获取指定字符的索引:${text?index_of("xx")}
        10.去除字符串前后空格:${text?trim}
        11.替换指定字符串:${text?replace("xx","xxx")}
    -->
    <h3>字符串类型:</h3>
    ${name?substring(1,4)}<br/>
    ${name?uncap_first}<br/>
    ${name?cap_first}<br/>
    ${name?lower_case}<br/>
    ${name?upper_case}<br/>
    ${name?length}<br/>
    ${name?starts_with("c")?string}<br/>
    ${name?ends_with("o")?string}<br/>
    ${name?index_of("cao")}<br/>
    ${name?trim}<br/>
    ${name?replace(".","-")}<br/>

3.4.日期类型

	<#--
        日期类型,需要先转成日期型或字符串:
        1.年月日:${now?date}
        2.时分秒:${now?time}
        3.年月日时分秒:${now?datetime}
        4.指定格式:${now?string("自定义格式")}
    -->
    <h3>日期类型:</h3>
    ${now?date}<br/>
    ${now?time}<br/>
    ${now?datetime}<br/>
    ${now?string("yyyy年MM月dd日 HH:mm:ss")}<br/>

3.5.空值类型

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

	<#--
        空值类型:
        Freemarker的变量必须赋值,否则就会抛出异常。对于FreeMarker来说,null值和不存在的变量是完全一样的,因为FreeMarker无法理解null值。
        FreeMarker提供两个运算符来避免空值:
        1.!:指定缺失变量的默认值
            ${value!}:如果value值为空,则默认值为空字符串。
            $(value!"默认值"):如果value值为空,则默认值为字符串"默认值"2.??:判断变量是否存在
            如果变量存在返回true,否则返回false。
            ${(value??)?string}
    -->
    <h3>空值类型:</h3>
    ${nullValue!}<br/>
    ${nullValue!"空"}<br/>
    ${(nullValue??)?string}<br/>

3.6.sequence类型

	<#--
        sequence类型:序列类型(数组、List、Set)
        1.通过list执行输出序列:<#list 序列名 as 元素名>${名称}</#list>
        2.获取序列的长度:${序列名?size}
        3.获取序列元素的下标:${序列名?index}
        4.获取第一个元素:${序列名?first}
        5.获取最后一个元素:${序列名?last}
        6.倒序输出:序列名?reverse
        7.升序输出:序列名?sort
        9.降序输出:序列名?sort?reverse
        10.指定字段名排序:序列名?sort_by("字段名")
            注:一般是JavaBean集合,对应的字段名需要提供get方法。
    -->
    <h3>sequence序列类型:</h3>
    <#list stars as star>
        下标:${star?index}--名字:${star}<br/>
    </#list>
    数组的长度:${stars?size}<br/>
    第一个元素:${stars?first}<br/>
    最后一个元素:${stars?last}<br/>
    <#list cities?reverse as city>
        下标:${city?index}--城市:${city}<br/>
    </#list>
    <#list cities?sort as city>
        下标:${city?index}--城市:${city}<br/>
    </#list>
    <#list cities?sort?reverse as city>
        下标:${city?index}--城市:${city}<br/>
    </#list>
    <#list userList?sort_by("age") as user>
        序号:${user.index}--名称:${user.name}--年龄:${user.age}<br/>
    </#list>

3.7.hash类型

	<#--
        hash类型(Map)1.key遍历输出:
            <#list hash?keys as key>
                ${key} -- ${hash[key]}
            </#list>
        2.value遍历输出:
            <#list hash?values as value>
                ${value}
            </#list>
    -->
    <h3>hash类型:</h3>
    <#list cityMap?keys as key>
        key:${key}--城市:${cityMap[key]}<br/>
    </#list>
    <#list cityMap?values as value>
        城市:${value}<br/>
    </#list>

4.FreeMarker指令

assign自定义变量指令

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

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

if/elseif/else逻辑判断指令

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

	<#--
        if/elseif/else逻辑判断指令:
        语法:
        <#if condition>
            ...
        <#elseif condition2>
            ...
        <#elseif condition3>
            ...
        <#else>
            ...
        </#if>
        注意:
        1.condition、condition2等:将被计算成布尔值的表达式
        2.elseif和else指令是可选的。
    -->
    <h3>if/elseif/else逻辑判断指令:</h3>
    <#assign score=80>
    <#if score < 60 >
        加油
    <#elseif score = 60  >
        及格万岁
    <#elseif score gt 60 && score lt 80 >
        小伙子还不错
    <#else>
        厉害
    </#if>
    <br/>
    <#assign list="">
    <#if list?? >
        数据存在
    <#else>
        数据不存在
    </#if>
    <br/>

list遍历指令

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

	<#--
        list遍历指令:
        格式1:
            <#list sequence as item>
                ...
            </#list>
        格式2:
            <#list sequence as item>
                ...
            <#else>
                当没有选项时执行else指令
            </#list>
        注:
        1.else部分是可选的
        2.sequence:想要迭代的项,可以是序列或集合的表达式
        3.item:循环变量的名称
        4.当没有迭代项时,才使用else指令,可以输出一些特殊的内容而不只是空在那里。
    -->
    <#assign nameList=[]>
    <#--判断数据部位空,再执行遍历(如果序列不存在时直接遍历会报错)-->
    <#if nameList??>
        <#list nameList?sort?reverse as name>
            下标:${name?index}--名称:${name}<br/>
        <#else>
            哈哈空的
        </#list>
    </#if>
    <br/>

macro自定义指令(宏)

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

	<#--
        macro自定义指令()1.基本使用
        格式:
            <#macro 指令名>
                指令内容
            </#macro>
        使用:
            <@指令名></@指令名>
        2.有参数的自定义指令
        格式:
            <#macro 指令名 参数名1 参数名2>
                指令内容
            </#macro>
        使用:
            <@指令名 参数名1=参数值1 参数名2=参数值2></@指令名>
        注:
        1.指令可以被多次使用
        2.自定义指令中可以包含字符串,也可以包含内置指令
    -->
    <h3>macro自定义指令:</h3>
    <#--自定义指令-->
    <#macro address>
        @1995-2024 The FreeMarker Project.
    </#macro>
    <#--使用指令-->
    <@address></@address><br/>
    <@address></@address><br/>

    <#--自定义指令(含参数)-->
    <#macro queryUserByParams uname uage>
        通过多个餐宿查询用户信息 - ${uname} - ${uage}
    </#macro>
    <@queryUserByParams uname="zhangsan" uage="18"></@queryUserByParams><br/>

    <#--自定义指令(其中包含内置指令)-->
    <#macro cfg>
        <#list 1..9 as i>
            <#list 1..i as j>
                ${i}*${j}=${i*j}&nbsp;
            </#list>
            <br/>
        </#list>
        <br/>
    </#macro>
    <@cfg></@cfg><br/>

nested占位指令

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

<#--
        nested占位指令:
            nested相当于占位符,一般结合macro指令一起使用。
            可以将自定义指令中的内容通过nested指令占位,当使用自定义指令时会将占位内容显示。
    -->
    <h3>nested占位指令:</h3>
    <#macro testNested>
        测试nested:
        <#nested>
        <#nested>
    </#macro>
    <#--使用指令-->
    <@testNested><p>占位的内容</p></@testNested><br/>

import导入指令

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

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

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

	<#--
        import导入指令:
        导入命名空间:<#import "ftl文件" as 命名空间>
        使用命名空间中的指令:<@命名空间.指令></@命名空间.指令>
    -->
    <h3>import导入指令:</h3>
    <#import "commons.ftl" as common>
    <@common.cfg></@common.cfg><br/>

include包含指令

可以使用include指令在你的模板中插入另一个FreeMarker模板文件。被包含模板的输出格式是在include标签出现的位置插入的。被包含的文件和包含它的模板共享变量,就像是被复制粘贴进去的一样。

	<#--
        include包含指令:
        用来引入其他页面文件(如txt、ftl、html等)
    -->
    <h3>include包含指令:</h3>
    <#include "test.txt">
    <#include "test.ftl">
    <#include "test.html">

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

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

相关文章

[大模型]DeepSeek-7B-chat FastApi 部署调用

DeepSeek-7B-chat FastApi 部署调用 DeepSpeek 介绍 由70亿个参数组成的高级语言模型 DeepSeek LLM。它是在一个包含2万亿个英文和中文代币的庞大数据集上从零开始训练的。为了促进研究&#xff0c;DeepSeek 已经为研究社区开放了DeepSeek LLM 7B/67B Base 和 DeepSeek LLM 7…

软考129-上午题-【软件工程】-McCabe度量法+白盒测试真题

一、真题 真题1&#xff1a; 简单路径&#xff1a; 简单路径是指在一个图中&#xff0c;从一个顶点出发&#xff0c;经过一系列不同的顶点&#xff0c;最终到达另一个顶点&#xff0c;且在整个过程中&#xff0c;除了起点和终点外&#xff0c;每个顶点只被访问一次的路径。在简…

Linux 目录结构与基础查看命令

介绍 目录结构如下 /bin&#xff1a;存放着用户最经常使用的二进制可执行命令&#xff0c;如cp、ls、cat等。这些命令是系统管理员和普通用户进行日常操作所必需的。 /boot&#xff1a;存放启动系统使用的一些核心文件&#xff0c;如引导加载器&#xff08;bootstrap loader…

商业银行业务与管理

商业银行业务与管理 资产负债表恒等式中国商业银行的资产负债表商业银行的业务种类银行运行管理的案例银行管理的基本准则流动性管理资产和负债管理资本充足管理 资产负债表恒等式 &#xff08;一般&#xff09;资产负债所有者权益 一个公司的资产是由负债和所有者权益所构成…

飞驰云联入选金融信创生态实验室「金融信创优秀解决方案」

近日&#xff0c;由中国人民银行领导、中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布了第三期金融信创优秀解决方案&#xff0c;Ftrans飞驰云联“文件数据传输解决方案”成功入选&#xff01; 本次金融信创优秀解决方案遴选经方案征集、方案初审、专家评审等多环…

【MATLAB源码-第188期】基于matlab的64QAM系统相位偏移估计EOS算法仿真,对比补偿前后的星座图误码率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 引言 M-QAM调制技术的重要性 现代通信系统追求的是更高的数据传输速率和更有效的频谱利用率。M-QAM调制技术&#xff0c;作为一种高效的调制方案&#xff0c;能够通过在相同的带宽条件下传输更多的数据位来满足这一需求…

《自动机理论、语言和计算导论》阅读笔记:p172-p224

《自动机理论、语言和计算导论》学习第 8 天&#xff0c;p172-p224总结&#xff0c;总计 53 页。 一、技术总结 1.Context-Free Grammar(CFG) 2.parse tree (1)定义 p183&#xff0c;But perhaps more importantly, the tree, known as a “parse tree”, when used in a …

【Java】新手一步一步安装 Java 语言开发环境

文章目录 一、Windows 10 系统 安装 JDK8二、 Mac 系统 安装 JDK8三、IDEA安装 一、Windows 10 系统 安装 JDK8 &#xff08;1&#xff09;打开 JDK下载网站&#xff0c;根据系统配置选择版本&#xff0c;这里选择windows 64位的版本&#xff0c;点击下载&#xff08;这里需要…

考试酷基本功修炼课学习历程_FPGA成长篇

本文为明德扬原创文章&#xff0c;转载请注明出处&#xff01;作者&#xff1a;明德扬学员&#xff1a;考试酷账号&#xff1a;11167760 我是硬件工程师&#xff0c;日常工作中主要跟数字电路、模拟电路、嵌入式系统打交道&#xff0c;当然也会涉及到FPGA&#xff0c;但是苦于…

学习笔记之——3DGS-SLAM系列代码解读

最近对一系列基于3D Gaussian Splatting&#xff08;3DGS&#xff09;SLAM的工作的源码进行了测试与解读。为此写下本博客mark一下所有的源码解读以及对应的代码配置与测试记录~ 其中工作1~5的原理解读见博客&#xff1a; 学习笔记之——3D Gaussian Splatting及其在SLAM与自动…

mac电脑软件 Magnet v2.14.0免激活中文版

Magnet是一款窗口管理工具&#xff0c;适用于Mac操作系统。它可以帮助用户轻松地管理和组织多个应用程序的窗口&#xff0c;提高工作效率。 Magnet支持多种窗口布局和组合方式&#xff0c;可以将窗口分为左右、上下、四分之一等不同的比例和位置&#xff0c;用户可以根据实际需…

Vue入门:天不生Vue,前端万古如长夜 - Vue从入门到放弃

&#x1f44b; Vue环境搭建 首先&#xff0c;搭一个打代码的环境 1.安装node.js 在使用VS Code之前&#xff0c;需要安装Vue的开发环境。 安装Vue的最简单方法是使用npm包管理器&#xff0c;先安装Node.js和npm。 node官网 ​​ 2.配置环境变量 在nodejs安装目录下新建…

强大的压缩和解压缩工具 Keka for Mac

Keka for Mac是一款功能强大的压缩和解压缩工具&#xff0c;专为Mac用户设计。它支持多种压缩格式&#xff0c;包括7z、Zip、Tar、Gzip和Bzip2等&#xff0c;无论是发送电子邮件、备份文件还是节省磁盘空间&#xff0c;Keka都能轻松满足用户需求。 这款软件的操作简单直观&…

Android ParcelFileDescriptor实现进程间通信

需求 一个通信通道&#xff0c;实现跨进程的的Socket网络通信。 具体的通信通道的图如下。 需求分析 我们需要一个进程一直做通信通道的事情&#xff0c;业务进程把数据通过进程间通信交给通信进程。通信进程通过Socket通道将数据发给网络另外一端的通信进程。接收端的通信进…

【Web】DASCTF X GFCTF 2022十月挑战赛题解

目录 EasyPOP hade_waibo EasyLove BlogSystem EasyPOP 先读hint.php sorry.__destruct -> secret_code::secret() exp: $anew sorry(); $bnew secret_code(); $a->password"suibian"; $a->name"jay"; echo serialize($a); 真暗号啊&…

【SQL】数据库SQL语句

1、主键 主键值唯一&#xff0c;不可修改&#xff0c;不能为空&#xff0c;删除不能重用 2、数据类型&#xff08;常用&#xff09; char int float date timestamp 3、select select * from data; select xx,xxx from data;//取部分行 select * from data limit 100; //限…

聊聊jvm中内存模型的坑

jvm线程的内存模型 看图&#xff0c;简单来说线程中操作的变量是副本。在并发情况下&#xff0c;如果数据发生变更&#xff0c;副本的数据就变为脏数据。这个时候就会有并发问题。 参考&#xff1a;https://www.cnblogs.com/yeyang/p/12580682.html 怎么解决并发问题 解决的…

蓝桥杯嵌入式第十五届省赛真题题目

蓝桥杯昨天也考完了&#xff0c;大家可以看看题目 客观题题目 程序题题目

Spring AI 应用 - 智能记者

参考实现&#xff1a; https://github.com/mshumer/ai-journalist 上面是通过 Claude 配合 SERP 搜索 API&#xff0c;使用 Python 语言实现的&#xff0c;本文通过 GitHub Copilot 辅助改为了基于 Spring AI 的 Java 版本&#xff0c;本文使用的 OpenAI。 AIJournalist 实现…

Python大数据分析——一元与多元线性回归模型

Python大数据分析——一元与多元线性回归模型 相关分析概念示例 一元线性回归模型概念理论分析函数示例 多元线性回归模型概念理论分析示例 线性回归模型的假设检验模型的F检验理论分析示例 模型的T检验理论分析示例 相关分析 概念 a 正相关&#xff1b;b 负相关&#xff1b;c…