基础篇_开发web程序(C/S架构,SpringBoot,贷款计算器-WEB版)

文章目录

  • 一. C/S 架构
    • 1. C/S 架构
    • 2. URL 格式
  • 二. Spring Boot
    • 1. 向导生成
    • 2. 准备工作
      • 1) 修改版本
      • 2) 修改maven 设置
    • 3. 导入模块
    • 4. hello world
    • 5. 处理输入
      • 页面
      • 接收参数
      • 练习 - 加法
  • 三. 贷款计算器 - WEB 版
    • 1. 数组
      • 定义
      • 改写贷款计算器
      • 越界
      • 遍历
      • 默认值
    • 2. 二维数组
    • 3. 贷款计算器 - 增加等额本金计算
    • 4. 贷款计算器 - 异常处理
    • 5. 打包

一. C/S 架构

1. C/S 架构

之前我们开发的贷款计算器,属于单机程序,同一时刻只能有一个用户使用,为了支持多用户同时使用贷款计算器,需要改为 web 程序,也就是网络应用程序

网络应用程序,需要采用下面的软件架构方式

在这里插入图片描述

这样,多个客户端都可以通过网络连接至服务器,通过【请求】(绿色箭头)将信息传输给服务器,服务器运算后,通过【响应】(蓝色箭头)将计算结果返回给客户端,见下图

在这里插入图片描述

  • 客户端将贷款金额、年利率、贷款月数发给服务器
  • 服务器计算完毕后,将还款总额返回给客户端

这种架构方式称为 Client/Server 架构,为了能支持 C/S 架构,需要引入一个新的开发技术 Spring Boot

  • 它内置了一个软件 Tomcat,可以与客户端进行交互

    • 我们即将编写的代码,就是运行在服务器这边
  • 使用系统自带的浏览器就可以充当架构中的客户端

    • 客户端可以使用网页技术来接收用户的输入、同时用网页向用户展现服务器的结果输出
    • 网页技术暂时不作为重点内容,可视为已经提供
    • C/S 中的 C 可以有很多种,浏览器只是其中一种特例,称浏览器这种客户端的架构为 B/S 架构

2. URL 格式

浏览器客户端要与服务器交互,请求和响应都需要遵从一定的格式,发请求时需要遵从一种 URL 格式

协议://主机[:端口]/路径[?查询参数]
  • 协议常见的有 http 和 https,其中 http 对传输的内容不会加密,安全性差一些,但速度更快
  • 主机,决定了请求哪个服务器,例如:www.baidu.com,自己这台机器可以用 localhost 表示
  • 端口,因为服务器上可能同时运行多个程序,要用不同的端口加以区分,如果是 80,可以省略
  • 路径,服务器提供了很多功能,为了区分这些功能,用不同的路径表示,例如
    • 可以定义一个路径 /add 做加法
    • 另一个路径 /calculate 做还款计算
  • ? 后面的称之为查询参数,用来代表功能的输入信息,例如
    • /add 需要 ?a=100&b=200 这两个查询参数
    • /calculate 需要 ?p=2000000.0&yr=6.0&m=360 这三个查询参数
    • 可以看到参数用=分成了名称和值,多个参数之间用 & 连接
  • 可以看到 URL 就是起到一个定位和传参的作用:它决定了你将来发的这个请求到底是想访问哪台服务器,里的哪个程序,用程序中的哪个功能,并能把功能所需参数也传递过来。

二. Spring Boot

Spring Boot 不光内嵌 Tomcat,省却了搭建服务程序的成本,还提供了方便处理 C/S 开发中输入和输出的类(对服务程序来说,输入就对应着请求,输出就对应着响应),核心类库处理控制台的输入输出还行,但处理 C/S 下的请求、响应就不够看了,Spring boot 是由 VMware 公司维护的一个开源框架,让我们能快速开发独立的、生产级的应用程序。

什么是框架,它包含两方面

  1. 条条框框,必须按照框架的规则来编写代码
  2. 通用功能,框架提供了很多通用的功能,能够节省开发时间,提升开发效率
    • 对比核心类库,核心类库的提供的类功能更基本,框架提供的功能更有针对性,专注解决某方面问题

1. 向导生成

  • 如果使用 Idea 最终版,可以通过它的向导创建 Spring Boot 项目。
  • 如果只有 Idea 社区版也没有关系,可以用 官网 Spring Boot 向导 网页版的向导来生成 Spring Boot 项目
    • 如果官网向导打不开,可以替换为 Aliyun Spring Boot 向导

在这里插入图片描述

  • 他一开始让你去选择项目的构建方式,这个先不用管啥意思,用默认 maven 就可以
  • 开发语言没啥说的,默认的Java就行
  • Spring boot 版本这一块你随便选一个啊,因为他选完了以后我们最终还得改,我们为了配合 java 17,最后得改成 2.7.0 这个版本
  • 接下来就是填写一些项目的基本信息,这个 group 就填写公司域名的那个倒置,它会影响代码中 package 包名。比如说我这是黑马的,那就写 com.itheima。
  • artifact 这里,一般就填写功能名称,比如说你是做的是一个商城系统,你就写一个mall,那如果你是一个管理系统你就写某某 management,总之根据程序功能来定,我这儿就随便起个名字吧,叫 module2
  • 高级选项里,是让你去选打包方式啊,Java的版本啊等等,阿里云的java版本也是比较低,它最高才支持15,这个也不用关心,最后再统一修改
  • 组件依赖这儿呢,我们一定要选一个叫web,你先敲一下web,他会提示出来一些候选项,选第1个,这是啥意思呢?Springboot中支持很多功能组件,其中做 web 程序开发,需要用到这个 web 组件

主要关注图中红框的几处位置就可以,都设置完了,点击获取代码,它就会根据刚才的选择生成一个压缩包并下载。

2. 准备工作

骨架代码生成好之后,还有两个准备工作要做一下

1) 修改版本

刚才也说了,如果是官网生成的骨架,版本不用改,springboot 就用 2.7.0 Java 就用 17,但 aliyun 生成的骨架版本较低,需要修改一下,怎么改呢

  1. 解压缩
  2. 找到 pom.xml,把其中的
    • java 改为 17
    • boot 改为 2.7.0

2) 修改maven 设置

maven 到底是干嘛的呢,以后咱们进行 java 开发,会用到很多第三方的压缩 jar 包,例如今天学的 spring boot,spring boot 中的 web 组件等等,都是以这种 jar 包形式提供的,这些 jar 包需要下载到本地才能使用吧,如果让我们人工下载管理的话,显然太过麻烦,maven 就是这么一个工具,能帮我们下载、管理这些第三方的 jar 包。

  1. idea 已经集成了maven 工具,但是由于maven默认会连接国外地址进行下载,不仅下载很慢还容易出错,因此需要用配置将 jar 包下载地址改为国内的

  2. 找到 idea 带的 maven 配置文件

    D:\ideaIC-2022.1.win\plugins\maven\lib\maven3\conf\settings.xml

在内部加入如下的配置

<mirrors>  
	<mirror>
        <id>central</id>
        <mirrorOf>central</mirrorOf>
        <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    
    <!-- ... -->
</mirrors>  

3. 导入模块

准备工作做好了之后,就可以把刚才的骨架代码加入到当前项目中了。

  • 先到下载目录,把刚刚修改好的 module2 目录,复制到当前项目目录下

  • 切换回 idea 可以看到已经有了,不过 idea 还没有把这个文件夹识别为模块,这时找到 module2 下的 pom.xml 文件,右键点击它,选择【添加为 maven 项目】,就可以了。

    • 第一次操作时会慢一些,这是 idea 正在通过 maven 来下载 jar 包
    • 下载完毕,如果右侧还有报错,没关系,这是 idea 没有刷新过来,关掉项目重新打开一般就能解决

4. hello world

骨架代码中,有一个 XxxApplication 类,它其中的 main 方法是程序的入口,但与控制台版的 Hello world 不同,要通过 C/S 的方式处理输入和输出,需要学习一点新的知识

@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public String hi() {
        return "hello world";
    }
}

这段代码描述的是一个称为控制器的类,用来处理输入、输出。

  • 不是所有的类都能成为控制器类,@Controller 是java中的语法,叫做注解,这个注解是 Spring 给我们提供的,由它标注的类才能作为控制器。

方法上还有分别跟输入、输出相关的两个注解

  • @RequestMapping(“/hello”) 对应着 URL 中的路径部分,例如请求 URL 中携带了 /hello,那么将来就会执行 hi 这个方法
  • @ResponseBody 是用来处理 hi 方法的返回结果,将方法执行结果作为响应内容(即输出)

这些注解就是框架提供的条条框框

5. 处理输入

这节课来学习控制器如何处理输入

客户端这边当然可以以查询参数的方式将数据传递给服务器,但这样对于使用者不太友好,因此会用到网页技术,以更友好的方式处理数据。

网页里就可以用下面文本框接收用户的输入,作为查询参数,对用户隐藏了复杂性,提高了用户体验,我现在想做的效果很简单

在这里插入图片描述

就是在文本块中输入一个名字 xxx,点击 say hello, 由服务器返回 hello, xxx

页面

页面要放在 static 目录下,页面也需要通过 URL 来访问,格式为 http://localhost:8080/页面名称

双击 hello.html 网页,就看到了它的源代码,这段代码里包含了两种语言,html 语言 和 javascript 语言(简称js),不过这些代码绝大部分也不需要理解,并非我们的重点,我只会讲作用,不会讲语法

  • 其中文本框对应的代码是这一行,<input type="text" name="name" id="n">,可以接收用户键入的文字

  • var n = document.querySelector("#n").value; 是页面中用的 js 语言,=右边的代码作用是获取用户在文本框输入的值,var n 是定义了一个变量,用来代表=号后的值。但是输入的值目前还在浏览器这边,并没有通过网络传输给服务器

  • 接下来按格式拼接好 URL,"http://localhost:8080/hello?name=" + n

    • 这是 js 中一种拼接字符串的方法

    • fetch 处的代码才是真正根据 URL 发送请求,并把服务器返回的内容显示出来,但这部分暂不需要了解

运行,发现总是返回 hello world,这是因为hello控制器这边还未对查询参数做出任何处理,下面就来解决这个问题

接收参数

hi 如何接收请求中的查询参数呢,一种方式就是提供同名的方法参数

@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    String hi(String name) { // ⬅️ 这里的方法参数要和查询参数【名称】一致
        return "Hello, " + name;
    }
}

练习 - 加法

加法例子,这回要提供两个参数,两个参数用 int 接收即可,其实请求中的参数类型原始是 String,Spring 会把 String 转换为 int

@Controller
public class AddController {

    @RequestMapping("/add")
    @ResponseBody
    int add(int a, int b) {
        return a + b;
    }
}

页面上的 URL 拼接有两种方法

`http://localhost:8080/add?a=${a}&b=${b}`

"http://localhost:8080/add?a=" + a + "&b=" + b

其中 a 和 b 来自于页面的两个数字框

在这里插入图片描述

三. 贷款计算器 - WEB 版

需求1,计算还款总额,这个其实很简单

@Controller
public class CalController {
    @RequestMapping("/cal")
    @ResponseBody
    String[] cal(double p, int m, double yr) {
        double mr = yr / 12 / 100.0;
        double pow = Math.pow(1 + mr, m);
        double payment = p * mr * pow / (pow - 1);
        return NumberFormat.getCurrencyInstance().format(payment * m);
    }
}

需求2,计算还款总额,以及利息总额

  • 如何用方法返回多个值呢,需要用到数组

1. 数组

定义

方法只能返回一个结果,现在要返回两个值,可以使用数组。数组可以容纳多个值。

定义字符串数组、给数组的两个元素赋值

String[] a = new String[2];
a[0] = "hello";
a[1] = "world";

定义并赋值(一步完成)

String[] a = new String[]{"hello", "world"};

后者可以简化为

String[] a = {"hello", "world"};
  • 最后这种,虽然看着简单,但它的限制较多,用的少

改写贷款计算器

前端页面要求

  • 数组索引为0的元素,代表还款总额

  • 数组索引为1的元素,代表利息总额

因此代码改写如下

@Controller
public class CalController {

    @RequestMapping("/cal")
    @ResponseBody
    String[] cal(double p, int m, double yr) {
        double mr = yr / 12 / 100.0;
        double pow = Math.pow(1 + mr, m);
        double payment = p * mr * pow / (pow - 1);
		// [0]还款总额   [1]总利息
        return new String[]{
                NumberFormat.getCurrencyInstance().format(payment * m),
                NumberFormat.getCurrencyInstance().format(payment * m - p)
        };
    }
}

越界

数组呢,有一个需要大家注意的地方就是。这个数组一旦它的长度确定了,就不能改了。并且啊,不能越过他的这个大小限制,比如说对于下面的数组

String[] a = {"hello", "world"};

我想访问他的索引2的元素行不行?

  • 不行,这个时候会报一个错误,他叫做。ArrayIndexOutOfBoundsException 数组索引越界异常,大家一定要避免
  • 可以通过数组的一个 length 变量来得知此数组的大小是多少。

遍历

即逐一获取数组中的每个元素进行操作

for(int i = 0; i < a.length; i++) {
    System.out.println(a[i]); // 获取数组中第 i 个元素
}

默认值

整数数组,new int[5],创建了五个元素的数组,并未给元素赋初始值,这时元素默认值是 0

类似的

  • String[] 的元素默认值是 null
  • double[] 的元素默认值是 0.0
  • boolean[] 的元素默认值是 false

2. 二维数组

比如我想表示一张表格

在这里插入图片描述

可以用二维数组来表示,就是数组里面再套一个数组

例如上面的表格可以表示为:外层数组长度3,内层数组长度5,内层长度可以不指定

String[][] a2 = new String[3][5];

a2[0] = new String[]{"1", "¥33,667.22", "¥33,167.22", "¥500.00", "¥66,832.78"};
a2[1] = new String[]{"2", "¥33,667.22", "¥33,333.06", "¥334.16", "¥33,499.72"};
a2[2] = new String[]{"3", "¥33,667.22", "¥33,499.72", "¥167.50", "¥0.00"};

如何动态生成这张表格呢

回忆一下以前的代码

double mr = yr / 100.0 / 12.0;
double pow = Math.pow((1 + mr), m);
double payment = p * mr * pow / (pow - 1); 			// 月供
for (int i = 0; i < m; i++) {
    double payInterest = p * mr;      				// 月利息=剩余本金*月利率
    double payPrincipal = payment - payInterest;    // 月本金=月供-月利息
    p -= payPrincipal;                              // 更新剩余本金    
}

只需要把月供、月利息、月本金、剩余本金等作为 row,多个 row 作为二维数组即可。得到最终用二维数组改写的代码

@Controller
public class CalController {
	// ...

    @RequestMapping("/details")
    @ResponseBody
    String[][] details(double p, int m, double yr, int type) {
        String[][] a2 = new String[m][]; // 二维数组        
        double mr = yr / 12 / 100.0;
        double pow = Math.pow(1 + mr, m);
        double payment = p * mr * pow / (pow - 1);              // 月供
        for (int i = 0; i < m; i++) {
            double payInterest = p * mr;                        // 偿还利息
            double payPrincipal = payment - payInterest;        // 偿还本金
            p -= payPrincipal;                                  // 剩余本金
            String[] row = new String[]{                       // 一行的数据
                    (i + 1) + "",
                    NumberFormat.getCurrencyInstance().format(payment),
                    NumberFormat.getCurrencyInstance().format(payPrincipal),
                    NumberFormat.getCurrencyInstance().format(payInterest),
                    NumberFormat.getCurrencyInstance().format(p)
            };
            a2[i] = row; // 将每一行放入二维数组
        }
        return a2;
    }
}

3. 贷款计算器 - 增加等额本金计算

增加按等额本金计算的功能

  • 每月偿还的本金是固定的,即 p a y P r i n c i p a l = p / m payPrincipal = p / m payPrincipal=p/m,其中 p p p 是初始本金
  • 每月偿还的利息还是 p a y I n t e r e s t = p ′ ∗ m r payInterest = p' * mr payInterest=pmr,其中 p ′ p' p 是剩余本金,随月份越还越少

页面新增了还款类型,等额本息的类型为 0,等额本金的类型为1

在这里插入图片描述

  • 选择本息会附带查询参数 type=0
  • 选择本金会附带查询参数 type=1

改写后代码如下

@Controller
public class CalController {
    
    @RequestMapping("/cal")
    @ResponseBody
    String[] cal(double p, int m, double yr, int type) {
        if (type == 0) { // 等额本息
            return cal0(p, m, yr);
        } else {    // 等额本金
            return cal1(p, m, yr);
        }
    }

    @RequestMapping("/details")
    @ResponseBody
    String[][] details(double p, int m, double yr, int type) {
        if (type == 0) {
            return details0(p, m, yr);
        } else {
            return details1(p, m, yr);
        }

    }

    static String[] cal0(double p, int m, double yr) {
        double mr = yr / 12 / 100.0;
        double pow = Math.pow(1 + mr, m);
        double payment = p * mr * pow / (pow - 1);
        return new String[]{
                NumberFormat.getCurrencyInstance().format(payment * m),
                NumberFormat.getCurrencyInstance().format(payment * m - p)
        };
    }

    static String[] cal1(double p, int m, double yr) {
        double payPrincipal = p / m;        // 偿还本金
        double backup = p;                  // 备份本金
        double mr = yr / 12 / 100.0;
        double payInterestTotal = 0.0;      // 总利息
        for (int i = 0; i < m; i++) {
            double payInterest = p * mr;    // 偿还利息
            p -= payPrincipal;              // 剩余本金
            payInterestTotal += payInterest;
        }
        // [0]还款总额   [1]总利息
        return new String[]{
                NumberFormat.getCurrencyInstance().format(backup + payInterestTotal),
                NumberFormat.getCurrencyInstance().format(payInterestTotal)
        };
    }
    
    static String[][] details0(double p, int m, double yr) {
        String[][] a2 = new String[m][];
        double mr = yr / 12 / 100.0;
        double pow = Math.pow(1 + mr, m);
        double payment = p * mr * pow / (pow - 1);              // 月供
        for (int i = 0; i < m; i++) {
            double payInterest = p * mr;                        // 偿还利息
            double payPrincipal = payment - payInterest;        // 偿还本金
            p -= payPrincipal;                                  // 剩余本金
            String[] row = new String[]{                       // 一行的数据
                    (i + 1) + "",
                    NumberFormat.getCurrencyInstance().format(payment),
                    NumberFormat.getCurrencyInstance().format(payPrincipal),
                    NumberFormat.getCurrencyInstance().format(payInterest),
                    NumberFormat.getCurrencyInstance().format(p)
            };
            a2[i] = row;
        }
        return a2;
    }

    static String[][] details1(double p, int m, double yr) {
        // 等额本金
        double payPrincipal = p / m;                        // 偿还本金
        double mr = yr / 12 / 100.0;
        String[][] a2 = new String[m][];
        for (int i = 0; i < m; i++) {
            double payInterest = p * mr;                    // 偿还利息
            p -= payPrincipal;                              // 剩余本金
            double payment = payPrincipal + payInterest;    // 月供
            String[] row = new String[]{
                    (i + 1) + "",
                    NumberFormat.getCurrencyInstance().format(payment),
                    NumberFormat.getCurrencyInstance().format(payPrincipal),
                    NumberFormat.getCurrencyInstance().format(payInterest),
                    NumberFormat.getCurrencyInstance().format(p)
            };
            a2[i] = row;
        }
        return a2;
    }
}

4. 贷款计算器 - 异常处理

对输入的数据做合法检查

  • 贷款金额必须大于0
  • 贷款月份范围必须在 1 ~ 360 之间
  • 年利率范围必须在 1 ~ 36 之间
  • 还款类型只能有 0 和 1 两种类型,其它应该显示【不支持的还款类型】

改写后的代码

@Controller
public class CalController {
    
    @RequestMapping("/cal")
    @ResponseBody
    String[] cal(double p, int m, double yr, int type) {
        check(p, m, yr, type); // 检查通过,才会向下运行
        if (type == 0) { // 等额本息
            return cal0(p, m, yr);
        } else {    // 等额本金
            return cal1(p, m, yr);
        }
    }

    @RequestMapping("/details")
    @ResponseBody
    String[][] details(double p, int m, double yr, int type) {
        check(p, m, yr, type); // 检查通过,才会向下运行
        if (type == 0) {
            return details0(p, m, yr);
        } else {
            return details1(p, m, yr);
        }

    }
    
    // 检查方法
    static void check(double p, int m, double yr, int type) {
        if (p <= 0) {
            throw new IllegalArgumentException("贷款金额必须>0");
        }
        if (m < 1 || m > 360) {
            throw new IllegalArgumentException("贷款月份必须在 1~360 之间");
        }
        if (yr < 1.0 || yr > 36.0) {
            throw new IllegalArgumentException("年利率必须在 1~36 之间");
        }
        if (type != 0 && type != 1) {
            throw new IllegalArgumentException("不支持的还款类型");
        }
    }

    // ...
}

需要在 application.properties 文件中加入

server.error.include-message=always

这样才能在页面上显示错误详情

5. 打包

Web 程序打包与之前控制台打包操作不一样,参考下图

在这里插入图片描述

使用 package 打包

打包成功后,会在 module2 模块下 target 目录下找到这个打好的 jar 包,运行 jar 包的方法是一样的,进入 jar 包所在目录,用终端程序执行

java -jar module2-0.0.1-SNAPSHOT.jar

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PaddleSeg学习4——paddle模型使用TensorRT推理(c++)

paddle模型使用TensorRT推理 1 模型末端添加softmax和argmax算子2 paddle模型转onnx模型3 onnx模型转TensorRT模型3.1 安装TensorRT-8.5.3.13.2 使用 trtexec 将onnx模型编译优化导出为engine模型 4 TensorRT模型推理测试5 完整代码6 测试结果 1 模型末端添加softmax和argmax算…

SpringBoot 源码解析4:refresh 方法解析

SpringBoot 源码解析4&#xff1a;refresh 方法解析 1. refresh 方法解析2. 准备刷新 AbstractApplicationContext#prepareRefresh3. 获取bean工厂 AbstractApplicationContext#obtainFreshBeanFactory4. 准备bean工厂 AbstractApplicationContext#prepareBeanFactory5. Servle…

Dell 机架式服务器 - 高级定制

Dell 机架式服务器 - 高级定制 1. Dell Technologies2.1. Servers & Storage (服务器及存储) -> Servers2.2. Rack Servers (机架式服务器)2.3. Shop2.4. PowerEdge Rack Servers (PowerEdge 机架式服务器)2.5. PowerEdge R760 Rack Server (PowerEdge R760 机架式服务器…

边缘计算:连接实时数据的力量与未来发展之路

边缘计算是一种分布式计算范式&#xff0c;它旨在将数据处理、存储和应用服务带到数据源的近端&#xff0c;即网络的“边缘”。在边缘计算模型中&#xff0c;算力和存储资源距离末端用户或数据源更近&#xff0c;这减少了数据在网络中传输的距离&#xff0c;从而降低延迟&#…

BikeDNA(四)初始化参考数据

BikeDNA&#xff08;四&#xff09;初始化参考数据 这本笔记本&#xff1a; 加载定义研究区域的多边形&#xff0c;然后为研究区域创建网格叠加。加载参考数据。处理参考数据以创建分析所需的网络结构和属性。 先决条件和条件 输入/输出 config.yml 必须提前设置。 此笔记本…

uniapp 查找不到uview-ui文件怎么办?

用官方的方式总是报&#xff1a;文件查找失败&#xff1a;uview-ui at main.js 解决方案&#xff1a; 1.先安装uview-ui npm install uview-ui 下载成功是这样的&#xff1a; 而不是这样的&#xff1a; 这样的原因是你的项目里没有package.json包&#xff0c;先执行 npm …

Ps:操控变形

Ps菜单&#xff1a;编辑/操控变形 Edit/Puppet Warp 操控变形 Puppet Warp命令能够借助网格随意扭曲特定图像区域&#xff0c;同时可保持其他区域不变。 其应用范围小至精细的图像修饰&#xff08;如发型设计&#xff09;&#xff0c;大至总体的变换&#xff08;如重新定位手臂…

Ftrans飞驰云联荣获“CSA 2023安全创新奖”

2023年12月21日&#xff0c;第七届云安全联盟大中华区大会在深圳成功举办。会上&#xff0c;CSA大中华区发布了多个研究成果并进行 CSA 2023年度颁奖仪式&#xff0c;Ftrans飞驰云联以其突出的技术创新能力和广泛的市场应用前景&#xff0c;荣获备受瞩目的“CSA 2023安全创新奖…

watchdog,一个无敌的 Python 库

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个无敌的 Python 库 - watchdog。 Github地址&#xff1a;https://github.com/gorakhargosh/watchdog 在软件开发和系统管理领域&#xff0c;经常需要监控文件和目录的变化&#xff0c;以便在文…

JDBC PrepareStatement 的使用(附各种场景 demo)

在 Java 中&#xff0c;与关系型数据库进行交互是非常常见的任务之一。JDBC&#xff08;Java Database Connectivity&#xff09;是 Java 平台的一个标准 API&#xff0c;用于连接和操作各种关系型数据库。其中&#xff0c;PreparedStatement 是 JDBC 中的一个重要接口&#xf…

abaqus重新打开之后自定义的工具栏状态恢复默认的解决办法

在自定义工具栏之后&#xff0c;点击&#xff1a; File——Save Display Options——勾选Current&#xff0c;点击OK。 中文版&#xff1a;文件-保存显示选项-目录选择当前目录&#xff0c;点击确定。 重新打开abaqus之后发现工具栏是自己定义的。 另&#xff1a; 1. 视口注…

brpc: a little source code

之前在https://www.yuque.com/treblez/qksu6c/nqe8ip59cwegl6rk?singleDoc# 《olap/clickhouse-编译器优化与向量化》中我谈过brpc的汇编控制bthread。本文就来看一下brpc作为一个高性能的rpc实现&#xff0c;除了自定义线程栈之外&#xff0c;代码还有什么优秀之处。 因为时间…

# C++系列-第3章循环结构-28-累加

在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 累加 奥运奖牌计数 题目描述 2008 2008 2008 年北京奥运会&#xff0c;A 国的运动员参与了 n n n 天的决赛项目 ( 1 ≤ n ≤ 100 ) (1 \le n \le 100) (1≤n≤100)。现在要统计一下 A 国所获得的…

uniapp小程序超出一行显示...并展示更多按钮

注意:全部标签需要浮动在父盒子右边哦 循环获取所有需要展示数据标签的高度 this.goods this.goods.map(item > ({...item,showBtn: false}));this.$nextTick(() > {uni.createSelectorQuery().in(this).selectAll(".cart-info").boundingClientRect((data)…

亚马逊云科技 WAF 部署小指南(五):在客户端集成 Amazon WAF SDK 抵御 DDoS 攻击...

方案介绍 在 WAF 部署小指南&#xff08;一&#xff09;中&#xff0c;我们了解了 Amazon WAF 的原理&#xff0c;并通过创建 WEB ACL 和托管规则防护常见的攻击。也了解了通过创建自定义规则在 HTTP 请求到达应用之前判断是阻断还是允许该请求。在 Amazon WAF 自定义规则中&am…

【ACL 2023】 The Art of Prompting Event Detection based on Type Specific Prompts

【ACL 2023】 The Art of Prompting: Event Detection based on Type Specific Prompts 论文&#xff1a;https://aclanthology.org/2023.acl-short.111/ 代码&#xff1a;https://github.com/VT-NLP/Event_APEX Abstract 我们比较了各种形式的提示来表示事件类型&#xff0…

STM32CubeMX配置STM32G071UART+DMA收发数据(HAL库开发)

时钟配置HSI主频配置64M 配置好串口&#xff0c;选择异步模式 配置DMA TX,RX,选择循环模式。 NVIC中勾选使能中断 勾选生成独立的.c和h文件 配置好需要的开发环境并获取代码 串口重定向勾选Use Micro LIB main.c文件修改 增加头文件和串口重定向 #include <string.h&g…

thinkphp6报错Driver [Think] not supported.

thinkphp6报错Driver [Think] not supported. 问题解决方法测试 问题 直接使用 View::fetch();渲染模板报错 解决方法 这个报错是由于有安装视图驱动造成的 运行如下命令安装即可 composer require topthink/think-view官方文档中是这么写的 视图功能由\think\View类配合视…

Python集合(set)

目录 集合创建集合访问集合向集合中添加和删除元素集合的 交集&#xff0c;并集&#xff0c;差集运算**交集****并集****差集** 集合方法 集合 集合是无序和无索引的集合。在 Python 中&#xff0c;集合用花括号编写。 创建集合 创建集合&#xff1a; thisset {"a"…

若依在表格中如何将字典的键值转为中文

文章目录 一、需求&#xff1a;二、问题解决步骤1、给需要转换的列绑定formatter属性2、获取字典项3、编写formatter属性绑定的方法 一、需求&#xff1a; 后端有时候返回的是字典的键值&#xff0c;在前端展示时需要转成中文值 后端返回的是dictValue&#xff0c;现在要转换…