开发者博客 – IT技术 尽在开发者博客

开发者博客 – 科技是第一生产力


  • 首页

  • 归档

  • 搜索

冷门PHP函数汇总 概述 sys_getloadavg co

发表于 2021-11-20

概述

整理一些日常生活中基本用不到的PHP函数,也可以说在框架内基本都内置了,无需我们去自行使用的函数。量不多。后续在日常开发中如遇到更多的冷门,会更新本文章

sys_getloadavg

获取系统的负载

1
2
3
4
5
6
7
php复制代码<?php
$load = sys_getloadavg();
if ($load[0] > 80) {
header('HTTP/1.1 503 Too busy, try again later');
die('Server too busy. Please try again later.');
}
?>

compact

创建一个包含变量名和它们的值的数组

1
2
3
4
5
6
7
8
9
php复制代码<?php
$firstname = "Bill";
$lastname = "Gates";
$age = "60";

$result = compact("firstname", "lastname", "age");

print_r($result);
?>

uniqid

基于以微秒计的当前时间,生成一个唯一的 ID。

1
2
3
php复制代码<?php
echo uniqid();
?>

pack

把数据装入一个二进制字符串。

1
perl复制代码pack(format,args+)
参数 描述
format 必需。规定在包装数据时所使用的格式。
args+ 可选。规定被包装的一个或多个参数。
1
2
3
php复制代码<?php
echo pack("C3",80,72,80);
?>

exif_imagetype

判断一个图像的类型

1
2
3
4
5
6
7
php复制代码<?php

if (exif_imagetype("image.gif") != IMAGETYPE_GIF) {
echo "The picture is not a gif";
}

?>

番外

因为这两篇文章内容都太少,所以整理为一篇,列出一些大佬的博客地址,希望可以帮助到你们。
排名不分前后

  • lufficc.com/ 聪聪的个人网站
  • mengkang.net/ Mengkang’s land
  • www.cnblogs.com/wxw16/ wuxiwei
  • rango.swoole.com/ 韩天峰(Rango)的博客
  • www.ruanyifeng.com/blog/ 阮一峰的网络日志
  • oomusou.io/ 點燈坊
  • imququ.com/ Jerry Qu
  • blog.csdn.net/hejjunlin 逆流的鱼yuiop
  • www.wujunze.com/page/7/ wujunze

大佬的博客覆盖各个领域,请按需查看

致谢

这篇文章很短,感谢你看完这篇文章。如果有什么冷门的函数,可在评论区留言。有时冷门函数也会帮上大忙不是嘛?

交流

生命不息,编码不止。

微信搜索 【一文秒懂】 传播技术正能量,持续学习新知识。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

SLF4J,Logback,Log4j之间的联系和区别及Lo

发表于 2021-11-20

SLF4J,Logback,Commons Logging,Log4j之间的联系和区别

Simple Logging Facade for Java(SLF4J)简单日志门面

从名字可以看出来它用到了门面模式

门面模式,也叫外观模式,英文全称是 Facade Design Pattern

在 GoF 的《设计模式》一书中,门面模式是这样定义的:

Provide a unified interface to a set of interfaces in a subsystem.

Facade Pattern defines a higher-level interface that makes the subsystem easier to use.

门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用。

门面模式定义中的“子系统(subsystem)”也可以有多种理解方式。它既可以是一个完整的系统,也可以是更细粒度的类或者模块。

这里提到的接口指的不是Java中的Interface,我的理解是下层对外层或内层对外层提供的服务

不难理解SLF4J不是具体的日志解决方案,只是服务于各种日志框架

concrete-bindings.png

此图展示了SLF4J绑定其他日志组件的说明

从图中可以看出,SLF4J在Logback,Commons Logging,Log4j等日志框架上又封装了一层,在写代码时直接调用SLF4J的api,在实际运行时可以随时切换底层框架的,而不用改动代码。JDBC也使用了相同的模式。

Logback

这里详细介绍一下Logback

对于Spring Boot项目来说,在

image-20211120211028173.png

依赖的

image-20211120211051702.png
的

image-20211120211122429.png

中已经引入了logback,不需要在在pom里面配置了

官方文档中对于logbook自动配置的说明

Let us begin by discussing the initialization steps that logback follows to try to configure itself:

  1. Logback tries to find a file called logback-test.xml in the classpath.
  2. If no such file is found, logback tries to find a file called logback.groovy in the classpath.
  3. If no such file is found, it checks for the file logback.xml in the classpath..
  4. If no such file is found, service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of com.qos.logback.classic.spi.Configurator interface by looking up the file META-INF\services\ch.qos.logback.classic.spi.Configurator in the class path. Its contents should specify the fully qualified class name of the desired Configurator implementation.
  5. If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.

大概意思就是logback首先在classpath中寻找logback-test.xml,没找到就找logback.groovy,还没找到就找logback.xml,还没找到就用JDK的service-provider在META-INF\services\ch.qos.logback.classic.spi.Configurator中寻找com.qos.logback.classic.spi.Configurator的实现类,要是还没有就用自己的BasicConfigurator进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xml复制代码<configuration>
​
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
   <!-- encoders are assigned the type
        ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
   <encoder>
     <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
   </encoder>
 </appender>
​
 <root level="debug">
   <appender-ref ref="STDOUT" />
 </root>
</configuration>

这个就和BasicConfigurator配出来的效果一样

接下来说一下Logback的配置文件

Logback配置文件

configuration下包含3种元素appender, root,logger

appender和logger都可以包含0或多个,root只能有一个

basicSyntax.png

对于logger

包含name一个必填参数和level,additivity 两个可选参数

level可选 TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF,设置为INHERITED, NULL将会强制继承层次更高的level

logger下包含0或多个appender-ref,<appender-ref ref="STDOUT" /> 包含一个参数ref通过那么指定appender

root与logger相似,root是最高层次的,他只有一个name属性,可以使用TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF,root下也可以包含0或多个appender-ref

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
xml复制代码<configuration>
​
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
   <!-- encoders are assigned the type
        ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
   <encoder>
     <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
   </encoder>
 </appender>
​
 <logger name="chapters.configuration" level="INFO"/>
​
 <!-- Strictly speaking, the level attribute is not necessary since -->
 <!-- the level of the root level is set to DEBUG by default.       -->
 <root level="DEBUG">          
   <appender-ref ref="STDOUT" />
 </root>  
 
</configuration>

appender结构

appenderSyntax.png

class参数指定appender实现类的全限定类名

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
xml复制代码<configuration>
​
 <appender name="FILE" class="ch.qos.logback.core.FileAppender">
   <file>myApp.log</file>
​
   <encoder>
     <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
   </encoder>
 </appender>
​
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
   <encoder>
     <pattern>%msg%n</pattern>
   </encoder>
 </appender>
​
 <root level="debug">
   <appender-ref ref="FILE" />
   <appender-ref ref="STDOUT" />
 </root>
</configuration>

不想写了大概就这样

官方文档logback.qos.ch/manual/conf…

看到了几篇博客发现现在log4j2貌似性能更好一点
juejin.cn/post/694575…
juejin.cn/post/684490…
决定再写一篇关于log4j的

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

数据中有emoji,导致插入不了数据库 前言 问题原因 解决

发表于 2021-11-20

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

前言

前两天负责的系统,因为需要获取用户的昵称并进行入库,但是有个别用户的昵称中存在emoji表情,导致入库时报错。

报错内容:

java.sql.SQLException: Incorrect string value: ‘\xF0\x9F\x92\x94‘ for column

问题原因

Q:为什么我们设置表的的字符类型为utf8却不能存放emoji呢?

A:因为我们UTF-8编码可能是2或3或4个字节,但mysql中的utf8是3个字节,存放一个emoji是需要4个字节的,自然不够。

Mysql数据库在5.5.3之后开始支持utf8mb4字符集,所以mysql版本是5.5.3+的都可以设置让数据库存储Emoji表情

所以如果你的应用有移动端的,最好一开始设计数据库的时候就使用utf8mb4字符集

解决方案:

方案一: 过滤字符串中的emoji

方案二: 转译emoji后入库。获取时反转译成emoji使用

1
2
3
4
arduino复制代码//转译emoji
URLEncoder.encode(含有emoji的数据, "UTF-8");
//反转译成emoji<br/>
URLDecoder.decode(经过转义的数据, "UTF-8");

另外再推荐一款emoji转义工具

注意点:emoji转译后可以入库。但当用户就是输入的内容本身就是【转译后的内容】

此时从库中反转译时就变成了emoji。这就造成跟用户输入不一致的情况

方案三: 修改数据库配置,实现可存储emoji

目前网上给的解决方案普遍都是:修改该字段或者该张表的编码方式为utf8mb4

但仅这么处理是并不起作用。

还需要执行SET NAMES utf8mb4; 将整个库的 character_set_client、character_set_connection、character_set_results等值修改为utf8mb4才会起作用

修改已经建立表的字符集alter table TABLE_NAME convert to character set utf8mb4 collate utf8mb4_bin;

注意点:新建数据库时可以进行初始化设置,但是已有的线上生产库进行此操作有风险,因此建议使用相关类库转义后进行存储和显示

使用下列SQL语句可以查看MySQL中character_set相关变量:
SHOW VARIABLES LIKE '%char%';

——The End——

如果对您有用,或者您希望持续关注,可以在微信公众号中搜索【码路无涯】

感谢大家看到最后,文章持续更新!欢迎大家指出我的文章的不足之处,也欢迎大家关注、收藏+分享

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Mysql 温故知新系列「联表查询」

发表于 2021-11-20

「这是我参与11月更文挑战的第 20 天,活动详情查看:2021最后一次更文挑战」

在 mysql 的查询操作中,我们一般都是在一张表上做数据查询,但有的时候,又需要我们联合上多张表来做数据获取

image.png

举个例子,我们需要获取 a 表中的数据,但是需要限定 a 表中的外键字段 b_id 对应的关联记录中的状态为指定值。这个需求可以拆分为 2 个操作

  1. 先查询 b 中的记录数据,根据 status=1 过滤,拿到符合要求的 id
  2. 在 a 表中查询数据,使用 where 过滤,限定他的外键 b_id 必须在上一个操作的结果集中

像上述的操作可以合并为 1 条 sql,即我们可以吧第一步 sql 的结果,作为一个临时表,然后供第二步的 sql 使用

1
2
3
sql复制代码select *from a 
where
b_id in (select id from b where status =`1)

像上面的这种操作,准确的描述,应该叫表的嵌套查询。他将上一步查询得到的结果集,作为一个条件,供下一个表使用,但这种操作,限定返回的结果只有 a 的字段,不涉及到 b 的字段


现在,我们在返回 a 表的字段的时候,同时需要部分 b 表的数据,就需要联合表a,表b然后根据给定的条件,过滤得到结果集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sql复制代码SELECT
a.*, b.*
FROM
tableA a,
(
SELECT
*
FROM
tableB
WHERE
STATUS = 0
) b
WHERE
a.b_id = b.id

像这种操作,其实就是 mysql 的内连接查询(inner join)

sql 的模式为:

在 select 和 from 之间,添加我们需要连接查询的表,在后面使用 where 条件来限定我们需求的结果,必备的条件就是多个表之间的连接判断,如上述的判断就是 a.b_id = b.id


以上一篇文章 # Mysql 温故知新系列「group by | having」 中提到的分组案例,我们拿到了重复的条码,但需要分析一下这些重复条码的记录都分布在哪些产线上

先统计重复的条码,获取到条码后,去匹配有哪些记录使用了这些条码,再对过滤得到的结果按照产线进行分组统计,整个逻辑非常清楚

现在我表演个仙术:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
sql复制代码SELECT
sparator_line,
count(sparator_line) count
FROM
rfid_info
WHERE
id IN (
SELECT
id
FROM
rfid_info r,
(
SELECT
product_time,
COUNT(product_time) count
FROM
rfid_info
GROUP BY
product_time
HAVING
count > 1
) t
WHERE
r.product_time = t.product_time
)
GROUP BY
sparator_line
order by count desc

sql 看着有点长,其实就是上述分析思路的多次嵌套查询,联表查询


本文主要讲的日常 sql 中的稍微复杂一点点的联表查询,下一章安排 mysql 的 join 关键字,讲讲他的左连接,右连接,内连接,外连接等具体的细节

原创文章,未经允许,禁止转载

– by 安逸的咸鱼

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

电商系统设计之购物车 前言 业务 逻辑 复杂度 统计 致谢

发表于 2021-11-20

本章适合初级工程师及中级工程师细看,大佬请随意

前言

  • 问 [不存价格字段不行吗?直接查询商品表获取价格]
  • 答 [如果价格更新,应提示用户,商品的浮动信息。可以选择直接更新购物车,或者单独建立一个表,来记录更新的价格和信息,类似京东]
  • 问 [联表查询可以从商品表中知道商品是否上架]
  • 答 [商品不存在了如何联,只会将逻辑整复杂,未来包括降价提醒,无货提醒,下架提醒,购物车该如何查询就成了一个问题]

上一篇文章在对于购物车业务及数据表设计中,有位童鞋在评论区与我讨论许久,特此独立一篇文章来详解下我的想法及我为什么这么做,以下为在业务层面、逻辑层面、未来功能的可扩展性、编码的复杂度、数据统计层面来解释下我的设计。
业务
==

image.png

业务上来看,无论是多表查还是单表存都是合理的,列出以下在购物车上的相关部分业务

  • 库存不足提醒 (提高付款概率)
  • 降价提醒 (提高付款概率)
  • 商品下架提醒
  • 有关商品的商品优惠券或其他活动 (提高付款概率)
    以技术角度说明

降价提醒

多表的降价提醒需要第三张表支撑 <商品修改记录表>

多表

image.png

这时购物车内的商品与商品表存在关联,检测降价的系统就需要在商家修改价格时将检测结果后查询加入本商品的购物车,顺便去查询商家修改前价格,算出差价,发送到队列或者其他的手段,用户接收到降价通知,刺激消费。这时你发现,这貌似没有什么地方有问题,如果这时候需要增加一个业务,按照用户加入购物车的时间,提示他在加入购物车后这段时间降价多少?这时是否需要在来个加入购物车的记录表,这样不断的多级关联,看似没有问题,实际将业务耦合,一次sql要关联N个表,如果这时增加sku和spu那就更不用说了。在未来量级上升后是支撑不住的,并且也不方便扩展。

单表

image.png

[我的设计并不是最好的,仅此参考] , 在考虑到未来业务不断增加的问题,我是将价格与标题和商品的SKU加入到购物车表内,在商户修改时无需关心其他表,直接检索与修改商品相关的购物车,拿出价格,计算差价,提示用户。如果计算加入购物车这段实际降价多少,这其实与上述操作一样,对于单表的设计上,这2种需求实为一种解决方案。在查询上也是一条sql语句的实现。

当然,我们还是需要关联上,不知道未来的某一天就用的上了呢?
有很多场景,都要将标题呀,内容呀直接存储,类似与收藏的店铺和商品,无论卖家怎么做,用户购物车,订单不能动,这是基准。

商品下架

商品下架,用户的购物车实际是不能动的,某猫的做法是使其变灰,让用户自行删除。
商家分很多种,商品的标题,图片或者分类修改了,都属于下架,这时的多表关联查询就彻彻底底的失效了。
其实商品的下架应该直接通知购物车下架 (变灰),并非关联查询是否下架。如果你非要这样做,那你依旧需要做一些表去记录。

我并不是说不需要做记录。而是记录的表实际是不参与业务查询的。

逻辑

逻辑这里特指代码的架构编写。以php为例,可以参考我之前的文章 segmentfault.com/a/119000001…
在逻辑方面,要考虑方面比较多,类似sql的性能,代码的性能,服务器的性能等。尽量避免多表查询吧。

可复用性

百度百科的定义是

可复用性(Reuseability)复用又叫重用,是重复使用的意思。目前,一般软件的复用率并不高,尤其在国内。复用的好处可以得到 较高的生产效率以及随之而来的成本降低、较高的软件质量(错误可以更快的被纠正)以及 恰当的使用复用可以改善系统的可维护性。

在购物车的设计上,重用主要提现在商品信息的存储方式上,避免多次去联表查询,在业务量大后的份表分库提现会更明显。

可扩展性

百度百科的定义是:

设计良好的代码允许更多的功能在必要时可以被插入到适当的位置中。这样做的目的的是为了应对未来可能需要进行的修改,而造成代码被过度工程化地开发。

正常购物车、商品、优惠券都是独立的系统及功能,不要看做商品在购物车内。现实和逻辑并非是一脉相承的。就假设在实际生活中,物品仅仅是放在购物车中,如果不结账,依旧不属于自己。为了方便扩展更多业务,尽量在设计之初,功能与功能之间不要“粘”在一起。

可维护性

百度百科的定义是:

系统的可维护性是衡量一个系统的可修复(恢复)性和可改进性的难易程度。所谓可修复性是指在系统发生故障后能够排除(或抑制)故障予以修复,并返回到原来正常运行状态的可能性。而可改进性则是系统具有接受对现有功能的改进,增加新功能的可能性。

购物车的设计之初也是考虑未来商品的业务功能各种变更。不如简单点,直接将其属性存到购物车。

复杂度

初期的设计,决定未来开发及重构的复杂度。功能与功能,系统与系统之间尽量避免直接关联。

统计

后期的数据统计、计算也会受到前期设计的影响。

致谢

感谢你们看到这里,下一篇我会讲一下关于电商系统的商品设计的部分。有什么问题可以评论区提问。谢谢

交流

生命不息,编码不止。

微信搜索 【一文秒懂】 传播技术正能量,持续学习新知识。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

SpringMVC接收请求参数 参数是拼接在地址栏中的

发表于 2021-11-20

通过控制器中方法的形参接收请求参数

1.基本类型参数

2.实体收参,定义一个实体,在后端控制器的参数列表中使用实体接收参数

3.数组收参

4.集合收参

5.路径参数

6.中文乱码

参数是拼接在地址栏中的

1.基本类型参数

请求参数和方法的形参 同名即可

SpringMVC默认可以识别的日期字符串格式为:YYYY|MM|dd HH:mm:ss

通过@DateTimeFormal可以修改默认日志格式

image.png

2.实体收参

请求参数和实体的属性 同名即可

image.png

3.数组收参

简单类型的数组

image.png

4.集合收参(了解)

image.png
image.png

5.路径参数

@PathVariable(“id”) 将路径上的变量名为id的值传递给Integer id

image.png

6.中文乱码

file放在resource下的SpringMVC配置文件中
image.png

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Springboot系列(一) 零基础入门springboo

发表于 2021-11-20

👨‍🎓作者:bug菌

✏️博客:CSDN、掘金、infoQ、51CTO等

🎉简介:CSDN博客专家,C站历届博客之星Top50,掘金/InfoQ/51CTO等社区优质创作者,全网合计8w粉+,对一切技术感兴趣,重心偏Java方向;硬核公众号「 猿圈奇妙屋」,欢迎小伙伴们的加入,一起秃头,一起变强。

..

✍️温馨提醒:本文字数:1999字, 阅读完需:约 5 分钟

嗨,家人们,我是bug菌呀,我又来啦。今天我们来聊点什么咧,OK,接着为大家更[《springboot零基础入门教学》](https://link.juejin.cn/?target=https%3A%2F%2Fblog.csdn.net%2Fweixin_43970743%2Fcategory_11599389.html)系列文章吧。希望能帮助更多的初学者们快速入门!

小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章点亮👍吧,您的点赞三连(收藏⭐+关注👨‍🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻‍♀️,创作不停💕,加油☘️

一、前言

  • springboot是什么?
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。


该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。用我的话来理解,就是spring boot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架(不知道这样比喻是否合适)。
  • 使用spring boot有什么好处?
  1. 快速创建独立运行的Spring项目以及与主流框架集成
  2. 嵌入的Tomcat,无需打包成WAR包
  3. starters自动依赖与版本控制
  4. 大量自动配置,简化开发,也可修改默认值
  5. 无需配置xml,无代码生成,开箱即用
...

简言之就是整个Spring技术栈的整合,来简化Spring应用开发,约定大于配置,去繁从简,just run 就能创建一个独立的,产品级别的应用。

说了那么多,手痒痒的很,马上来一发试试!

二、正文

方式一:

**maven构建项目,**去spring官网拿现成的demo

  1. start.spring.io/
  2. 选择构建工具Maven Project、java、Spring Boot版本以及一些工程基本信息,java版本选择1.8,可参考下图所示:选择完后直接点击EXplore;

)3、直接点击下载即可;

4、然后解压出来,bug菌用的是idea编辑器,点击open打开你刚才下载的demo。你们也可使用自己习惯的编辑器,这里就不多赘述了。

5、瞅瞅!如果加载不出来的,可以右边选择maven->刷新一下

6、下面我们在ide中打开工程,这里使用的ide是idea,这样一个springboot项目就成型了,但是缺点东西,有些依赖没有配置,那就手动给它加上吧!工程的目录结构为:

方式二:

1、你们也可以徒手搭建一个springboot demo;比如就使用idea,非常方便,选择spring initialization创建SpringBoot项目即可。如下图

2、要注意的就是选择好你环境配置的jdk版本;然后一路next;最后打开;跟第一种官网下载的一样;如下是目录结构;

3、好啦;我们就得到了一个直接可执行的 Web 应用,接着怎么运行呢?这肯定直接是运行不了的,还差点火候;

1、pom加上如下依赖;

1
2
3
4
5
6
xml复制代码<dependencies>    
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

2、配置文件配置运行端口号

1
ini复制代码server.port=8080

3、选择DemoApplication文件然后直接右键选择 run application 就可以直接启动一个使用了嵌入式 tomcat 服务请求的 Web 应用;

4、如上打印即表示运行成功啦;

只不过,我们还没有提供任何服务 Web 请求的 Controller,所以,访问任何路径都会返回一个 SpringBoot 默认提供的错误页面(一般称其为 whitelabel error page),我们可以在当前项目下新建一个服务根路径 Web 请求的 Controller 实现:

1
2
3
4
5
6
7
8
9
less复制代码@RestController
@RequestMapping("/test")
public class TestController {

@GetMapping( "/hello")
public String index() {
return "Hello World!";
}
}

5、访问http://localhost:8080/test/hello

6、能看到正常打印了“Hello World!”。证明springboot项目雏形已成。接着想怎么玩就怎么玩啦。

OK,以上就是这期所有的内容啦,如果有任何问题欢迎评论区批评指正,咱们下期见。

三、热门推荐

  • springboot系列(一):如何创建springboot项目及启动
  • springboot系列(二):yaml、properties两配置文件介绍及使用
  • springboot系列(三):多环境切换,实例演示
  • springboot系列(四):stater入门
  • springboot系列(五):史上最最最全springboot常用注解
  • springboot系列(六):mysql配置及数据库查询
  • springboot系列(七):如何通过mybatis-plus实现接口增删改查
  • springboot系列(八):mybatis-plus之条件构造器使用手册
  • springboot系列(九):mybatis-plus之如何自定义sql
  • springboot系列(十):mybatis之xml映射文件>、<=等特殊符号写法
  • springboot系列(十一):实现多数据源配置,开箱即用
  • springboot系列(十二):如何实现邮件发送提醒,你一定得会(准备篇)
  • springboot系列(十三):如何实现发送普通邮件?你一定得会
  • springboot系列(十四):如何实现发送图片、doc文档等附件邮件?你一定得会
  • springboot系列(十五):如何实现静态邮件模板发送?你一定得会
  • springboot系列(十六):如何实现发送邮件提醒,附完整源码
  • springboot系列(十七):集成在线接口文档Swagger2
  • springboot系列(十八):如何Windows安装redis?你玩过么
  • springboot系列(十九):如何集成redis?不会我教你
  • springboot系列(二十):如何通过redis实现手机号验证码功能
  • … …

四、文末🔥

如果还想要学习更多,小伙伴们可关注bug菌专门为大家创建的专栏《springboot零基础入门教学》,从无到有,从零到一!希望能帮助到更多小伙伴们。

我是bug菌,一名想走👣出大山改变命运的程序猿。接下来的路还很长,都等待着我们去突破、去挑战。来吧,小伙伴们,我们一起加油!未来皆可期,fighting!

感谢认真读完我博客的铁子萌,在这里呢送给大家一句话,不管你是在职还是在读,绝对终身受用。

时刻警醒自己:

抱怨没有用,一切靠自己;

想要过更好的生活,那就要逼着自己变的更强,生活加油!!!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

换钱的最少货币数

发表于 2021-11-20

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

换钱的最少货币数

问题描述

322. 零钱兑换

给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。如果无解,请返回-1.

示例:

输入:coins = [1, 2, 5],amount = 11

输出:3

说明:11 = 5 + 5 + 1

分析问题

由于题目是求最优解问题,所以我们最直观的感觉就是这题是否可以使用动态规划来求解。

我们都知道,对于求解动态规划相关的问题,最重要的就是求出状态转移方程。下面我们来看一下如何求解,首先我们定义F(S) 为组成金额 S 所需的最少货币数量。

假设目前我们已经知道了F(S),和最后一枚货币的面值是C,我们就可以得出:

F(S)=F(S-C)+1
由于最后一枚货币的面值是未知的,所以我们需要枚举每个货币的面额值 C0, C1,…..,Cn-1,并选择其中的最小值。即

F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),….,F(S-Cn-1)} + 1

S-Ci >=0
当S=0时,F(S)=0
当n=0时,即货币的种类为0时,F(S)无解,即F(S)=-1
所以,F(S)的状态转移方程为

F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),….,F(S-Cn-1)} + 1
其中 Cj 代表的是第 j 枚货币的面值,即我们枚举最后一枚货币面额是Cj,那么F(S)需要从S-Cj这个金额对应的状态 F(S-Cj) 转移过来,再加上枚举的这枚货币数量1的贡献。由于题目是求货币的数量最少,所以 F(S)为前面能转移过来的状态的最小值。

假设 coins= [1, 2, 5],amount = 11,即F(11) = min( F(10), F(9), F(6) ) + 1。

image-20211118171456070

下面我们来看一下代码的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
ini复制代码import sys
class Solution:
def coinChange(self, coins,amount):
dp = [sys.maxsize] * (amount + 1)

#S为0时,需要的货币数为0
#S<0时,直接忽略dp[S]
dp[0] = 0
for coin in coins:
#忽略S<0的。
for x in range(coin, amount + 1):
dp[x] = min(dp[x], dp[x - coin] + 1)
return dp[amount] if dp[amount] != sys.maxsize else -1

该算法的时间复杂度是O(Sn),其中S是金额数,n是不同面额的个数。空间复杂度是O(S)。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

【k8s 系列】k8s 学习四,k8s 基本架构

发表于 2021-11-20

「这是我参与11月更文挑战的第 19 天,活动详情查看:2021最后一次更文挑战」

k8s 中支持的 node 数 和 pod 数

k8s 也是逐步发展过来的,来看看以前和现在支持的 node 数 和 pod 数对比

node 即 节点 , 早期的 k8s 版本能够支持 100 台节点,现在 k8s 可以支持到 2000 台了

pod 数,早期的版本可以支持 1000 个,现在的 k8s 可以支持到 150000 个了

k8s 应用部署架构

对于应用部署架构,分为 无中心节点架构 和 有中心节点架构

  • 什么是无中心节点架构?

就是集群当中所有的主机之间都互为伙伴关系 , 例如 GlusterFS 分布式存储

  • 什么是有中心节点架构?

例如 HDFS 就是一个有中心节点架构 , 他有 NameNode (整个集群的管理者)和 DataNode (集群中存储数据的)

现在要学的 K8S 也是一个有中心节点的架构

通过上图我们可以看出, K8S 有一个 master 节点, 2 个 worker 节点

worker 节点分别能够和 master 节点进行通信

k8s 集群架构节点角色以及功能

master node

  • 是集群的主控节点,能够对集群进行管理和调度,接受集群外部的用户去做集群相关的操作
  • 组成
    • API Server
    • Scheduler
    • Cluster State Store
    • Controller Mananger Server

worker node

  • 是集群的工作节点,主要是运行用户业务应用的容器
  • 组成
    • kubelet
    • kubeproxy
    • Container Runtime

从上图中我们可以知道 ,

master 节点中的 四个模块,其余 3 个模块都会和 api server 进行通信

由 apiserver 与 多个 woroker 节点进行通信

多个 worker 节点中,都会有容器,网络,以及 kubelet

那么接下来咱们就开始看看如何部署 K8S 集群环境了,接下来分别从 K8S 的集群部署工具, K8S 的部署方法,以及如何验证 K8S 的集群可用性 来分享

今天就到这里,学习所得,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

若依系统分页工具学习-PageHelper篇八

发表于 2021-11-20

这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

在《若依系统分页工具学习-PageHelper篇七》中,我们已经知晓了Dialect至MySqlDialect的类继承结果,如下:

Dialect -> AbstractDialect -> AbstractHelperDialect -> MySqlDialect

并且已经知道了方法beforePage方法定义与Dialect,实现在AbstractHelperDialect中,判断SQL语句是否需要分页。

其中涉及到一个Page对象,beforePage中涉及到了Page对象是如何获取的呢?今天我们来看一下。

Page的获取

我们来看Page对象是如何在beforePage获取的:

1
java复制代码Page page = getLocalPage();

我们再来看getLocalPage方法:

1
2
3
4
5
6
7
8
java复制代码    /**
* 获取分页参数
* @param <T>
* @return
*/
public <T> Page<T> getLocalPage() {
return PageHelper.getLocalPage();
}

恩,继续深入查看:

1
2
3
4
5
6
7
java复制代码    /**
* 获取 Page 参数
* @return
*/
public static <T> Page<T> getLocalPage() {
return LOCAL_PAGE.get();
}

这里的LOCAL_PAGE是如何定义的呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码/**
* 基础分页方法
* @author liuzh
*/
public abstract class PageMethod {
protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();

/**
* 设置 Page 参数
* @param page
*/
protected static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}
}

这里的LOCAL_PAGE是不是有些熟悉呢?

在文章《若依系统分页工具学习-PageHelper篇二》中,通过Controller中的方法startPage的调用层次中,调用了PageMethod中的startPage方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
java复制代码 public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page<E> page = new Page<E>(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
//当已经执行过orderBy的时候
Page<E> oldPage = getLocalPage();
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
setLocalPage(page);
return page;
}

/**
* 设置 Page 参数
*
* @param page
*/
protected static void setLocalPage(Page page) {
LOCAL_PAGE.set(page);
}

如此便通过一个线程内部变量ThreadLocal<Page>传过来了参数。

恩,这种传参方式没有深入理解的功力干不出来啊!反正我是不敢用~~

我们接着看beforePage方法中判断逻辑:

1
2
3
4
5
6
7
8
java复制代码@Override
public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
Page page = getLocalPage();
if (page.isOrderByOnly() || page.getPageSize() > 0) {
return true;
}
return false;
}

如果分页参数的orderByOnly为true或者有pageSize大于0,则执行分页。

我们返回去看pageQuery方法中的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码    /**
* 分页查询
*/
public static <E> List<E> pageQuery(Dialect dialect, Executor executor, MappedStatement ms, Object parameter,
RowBounds rowBounds, ResultHandler resultHandler,
BoundSql boundSql, CacheKey cacheKey) throws SQLException {
//判断是否需要进行分页查询
if (dialect.beforePage(ms, parameter, rowBounds)) {
//生成分页的缓存 key
CacheKey pageKey = cacheKey;
//处理参数对象
parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);
....

这里缓存我们暂时不说。

看下一句调用的dialect方法:processParameterObject,注释为:“处理参数对象”,这个方法又在哪个类结构层次中呢?

最后发现它和beforePage一样,位于类AbstractHelperDialect中。

为了尽快查看SQL修改的具体位置我们暂时不对这个processParameterObject方法深入了解。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

1…262263264…956

开发者博客

9558 日志
1953 标签
RSS
© 2025 开发者博客
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%