AWS
AWS基本教程场景是:在把22端口关闭了,无法再连上服务器的情况 解决办法:关闭服务器,点击操作->实例设置->编辑用户数据 1234567#!/bin/bash# 允许 SSH 端口iptables -P INPUT ACCEPTiptables -P OUTPUT ACCEPTiptables -P FORWARD ACCEPTiptables -Fiptables -A INPUT -p tcp --dport 22 -j ACCEPT 再启动服务器 AWS升级配置1.先停止实例,不是终止实例 2.修改实例类型 重启公网IP可能会改变 服务器局域网互通需要把局域网 想要互通的服务器,加入一个公共的的默认安全组 选择default安全组 要看服务器部署在哪里 JavaSDK上传图片到S3123456789101112131415161718192021222324252627282930313233343536@RestController@Slf4j@Api(tags = "上传接口")public class UploadController { @Value("${S3.accessKey}") String accessKey; @Value("${S3.secretKey}") String secretKey; @Value("${S3.endPoint}") String endPoint; @Value("${S3.bucketName}") String bucketName; @PostMapping("/upload") @ApiOperation("上传") @NotNeedAuth public Response<String> upload(@RequestParam("file") MultipartFile file) { String originalFilename = file.getOriginalFilename(); if (!Constant.PHOTO_LIST.contains(originalFilename.substring(originalFilename.lastIndexOf(".") + 1))) { return Response.fail(CodeConstant.CODE_095); } String newImageName = ThreadLocalRandom.current().nextInt(10000) + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase(); String fileName = "lxdt/dt/" + Constant.DIRECTORY_TIME_FORMAT.format(LocalDateTime.now(Constant.TIME_ZONE)) + newImageName; try { S3Util.uploadFileByFile(accessKey, secretKey, endPoint, bucketName, fileName, file); } catch (Exception e) { log.error("上传失败", e); return Response.error(""); } return Response.successData(fileName); }} 12345678910111213141516public class S3Util { /** * 图片上传 */ public static void uploadFileByFile(String accessKey, String secretKey, String endPoint, String bucketName, String folderName, MultipartFile file) throws IOException { ClientConfiguration clientConfig = new ClientConfiguration(); clientConfig.setProtocol(Protocol.HTTPS); AmazonS3 amazonS3 = AmazonS3Client.builder().withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, Region.getRegion(Regions.AP_SOUTHEAST_1).getName())) .withClientConfiguration(clientConfig).withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey))) .disableChunkedEncoding().withPathStyleAccessEnabled(true).withForceGlobalBucketAccessEnabled(true).enablePathStyleAccess().build(); ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentType(file.getContentType()); objectMetadata.setContentLength(file.getSize()); amazonS3.putObject(new PutObjectRequest(bucketName, folderName, file.getInputStream(), objectMetadata).withCannedAcl(CannedAccessControlList.PublicRead)); }} S3桶策略公开访问桶策略 123456789101112{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-bucket-name/*" } ]} 印象中有遇到这种情况: 第一次操作桶的时候,桶里面的文件是能正常共享出来的 很久之后没有操作了,再上传一个新文件,上传的这个文件就不能共享了 第二次出现这样情况的时候,我文件的url搞错了,是可以正常共享的 PicGO+S3创建存储桶红框里不要勾选 创建文件夹,设置公开 开启静态托管 新建IAM用户访问创建IAM页面 创建使用者 创建使用者详情 创建使用者权限,点击下一步,然后就能看到key和密钥了 PicGO配置PicGO软件许要下再S3插件,然后再配置文件里粘贴这个 1234567"aws-s3": { "accessKeyID": "AKIA2Q6ZSIPP7MKZOFHR", "secretAccessKey": "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", "bucketName": "mmzcg.com", "uploadPath": "blog/{year}/{fullName}", "acl": "public-read"} 参考S3教程 PicGoS3教程 CloudFront加速Vercel1.找到vercel自动分配的域名 2.aws 创建分配 3.选择源 不要选择源,输入vercel分配的域名 4.选择全部https,其它可以默认 5.选择证书 备用域名:比如vercel默认分配的是xxx.vercel.app你想加速的域名是 abc.blog,备用域名就填abc.blog 自定义SSL证书:用aws自带的证书申请工具 点击保存,回到CloudFront首页 6.cname 看上次修改时间这一列,如果显示的时间,就表示刚才的配置已经生效了,如果显示在部署中…就等一会 CloudFront这一列会分配一个域名,在域名解析那里Cname指向这个域名就可以了 AWS S3和Hexo1.安装插件 12# 装置npm install hexo-deployer-aws-s3 --save-dev 2.改_config.yml 12345678deploy:# - type: 'git'# repo: [email protected]:aaaaaaanthony/aaaaaaanthony.github.io.git# branch: master type: 'aws-s3' # 写死 region: ap-east-1 # 区域名 bucket: mmzcg.com # 桶名 如果要部署多个地方,每个仓库的type前面要加一个- 如果只有一个,就只用type开头就行 3.执行环境变量 123export AWS_ACCESS_KEY_ID=AKIA2Q6ZSIPP7MKZOFHRexport AWS_SECRET_ACCESS_KEY=ZifJfUmVVGMq37hd8Itozp4fws5O97dVlwgMgtCYsource /etc/profile 4.部署 1234hexo cleanhexo algolihexo d -g 发现报错,The bucket does not allow ACLs,还需要在存储中开启 ACLs 接下来要关闭「阻止共有访问操作」 部署成功后,开启静态网站托管功能 RDS创建RDS选择mysql社区版本 AWS的RDS开启慢查询日志到cloudwatch中 快照导出到S3 参考文档 接下来的页面是需要的设置 导出标识符,就是导出任务的名字 导出的数据,这里测试就简单点,导出全部表,要是选部分表,文档里有导出规则 S3 目标, 选一个存储桶 接下来的两个是难点,IAM角色,和加密 先看加密,先创建ARN,找到配置的选项卡 点击下面的链接 在客户管理的秘钥,创建一个秘钥, 客户管理的密钥和AWS托管的密钥是有区别的,要选对 创建完之后,再回到 密钥列表的页面,点密钥ID,进入到详情页 复制ARN刚刚才导出的页面,角色权限什么的,各种尝试下就可以了 front清空缓存API12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849import boto3import datetimedef create_invalidation(distribution_id, paths): # 创建一个CloudFront客户端并提供凭证 client = boto3.client('cloudfront',aws_access_key_id='AKIA2UC26S7767GSGKJQ',aws_secret_access_key='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') # 创建一个唯一的无效请求ID caller_reference = str(datetime.datetime.now()) # 格式化路径 items = paths if isinstance(paths, list) else [paths] # 构建无效请求 invalidation_batch = { 'Paths': { 'Quantity': len(items), 'Items': items }, 'CallerReference': caller_reference } # 创建无效请求 response = client.create_invalidation( DistributionId=distribution_id, InvalidationBatch=invalidation_batch ) return response# distribution_id 列表,包含ID、说明和类型distribution_info = [ ["EX123AFBG", "生产环境", "生产", "baidu.com"],]# 要使失效的路径paths_to_invalidate = ['/*']# 循环遍历每个distribution_idfor info in distribution_info: distribution_id = info[0] print(f"Creating invalidation for Distribution ID: {distribution_id}, Description: {info[1]}, Type: {info[2]}") response = create_invalidation(distribution_id, paths_to_invalidate) print(response) print("================")print("刷新完成")
CSS
CSS选择器基础选择器 选择器名字 示例 标签选择器 p{color: green;} 类选择器 .red {color: red;} ID选择器 #red {color: red;} 通配符选择器 * {color: red;} 复合选择器逗号 就是选择多个 大于号 就是选择儿子 空格 就是选择孩子 123456789101112131415161718192021222324252627282930<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>复合选择器,后代选择器和子代选择器</title> <style> /* 后代选择器 */ ol div { color: green; } /* 子代选择器:只能找儿子 */ ol > div { color: red; } </style> </head> <body> <ol> <li>我是ol的儿子</li> <li> <div>我是ol的孙子 子类选择器找不到我</div> </li> <div>我是ol的儿子</div> </ol> </body></html> 1234567891011121314151617181920212223242526272829<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>复合选择器</title> <style> div, p { color: yellow; } div, p, ul > li { color: red; } </style> </head> <body> <div>熊大</div> <p>熊二</p> <span>光头强</span> <ul class="pig"> <li>小猪佩奇</li> <li>猪爸爸</li> <li>猪妈妈</li> </ul> </body></html> 伪类选择器 :link 未被访问的连接 :visited 已经访问的连接 :hover 鼠标放在上面的连接 :active 鼠标按下没有谈起的连接 focus伪类选择器获取焦点的表单选择器 字体属性 文本属性 盒子模型边框还有个表格边框合并的属性:border-collapse:两条边合并成一条边 内边距 内边距也会影响盒子的实际大小 padding 值得顺序是 上 右 下 左 没有指定width,加了padding就不会改变盒子宽度 外边距margin的语法跟padding用法一样 外边距应用-盒子居中让盒子居中的前提条件是: 盒子必须指定了宽度 盒子左右的外边距都设置为auto 嵌套外边距塌陷 解决方法1: 给父元素定义上边框,坏处就是撑大了盒子border-top: 1px solid transparent; 解决方法2:指定一个上内边距,坏处就是撑大了盒子padding: 1px; 解决方法三:为父元素添加 overflowoverflow: hidden; 在浮动,固定,绝对定位的盒子就不会有塌陷问题 元素显示模式块元素 div ,h1 p ul ol li 一个占一行 高度,宽度,外边距,内边距都可以控制 宽度默认是容器的100% 是一个容器及盒子,里面可以放行内或者块元素 <p>和<h1> 等用于存放文字的标签里面不能放<div> 行内元素 span a strong b em i 一行可以用多个 宽高,设置无效,背景颜色设置有效 默认宽度就是它本身内容的宽度 行内元素只能放文本或者其他行内元素 特殊情况链接里面不能再放连接,<a>里面可以放块级元素 <input> <img>是行内款,一行可以给多个,也能设置宽高 元素显示模式的转换
HTML
1234567891011121314<!-- 声明文档类型,表示这是一个 HTML5 文档 --><!-- 这个不是标签,这是文档类型的声明标签 --><!DOCTYPE html><!-- 定义 HTML 文档的根元素,并设置文档的语言为英语 --><html lang="en"><head> <!-- 指定文档的字符编码为 UTF-8,支持大多数语言的字符 --> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body></body></html> 标题标签12345678<body> <h1>111111111111</h1> <h2>111111111111</h2> <h3>111111111111</h3> <h4>111111111111</h4> <h5>111111111111</h5> <h6>111111111111</h6></body> 段落标签1234<body> <p>我们一进里面一片漆黑,然后老师给我们每一个人都发了一个眼镜,我们戴上眼镜,后面前有一张大白纸,后面有一个投影仪,放了一个电影,名叫“雪怪大冒险”。</p> <p>有几位老师去帮我们买汉堡去了,我们先到那里先吃一些零食,我们吃饱后,我们一起去玩游戏,第一个游戏的名字叫做动物园里有什么。第二个游戏的名字叫做学校里面有什么</p></body> 段落格式的特点 段落内容会自动换行,无需手动添加 <br> 标签。 段落段落之间会有空隙 换行标签123<body>13213123<br/>3123123</body> 文本格式化标签12345678<body> 1<strong>加粗</strong>3 1<b>加粗</b>3 1<em>倾斜</em>3 1<del>删除线</del>3 1<ins>下划线</ins>3</body> div1234<body><div>div单独占一行</div>3213123<div>div单独占一行</div></body> span所有的span占一行 1234<body><span>div单独占一行</span>3213123<span>div单独占一行</span></body> 图像标签123<body>这是百度的图片:<img src="./demo.png"/></body> 通常只需调整宽度或高度中的一个,另一个会自动计算以保持比例不变。 超链接target属性有_self为默认值,当前页面_blank 新的页面打开 外连接就要加http,内连接就是路径地址 123<body><a href="http://baidu.com">这是超裂解</a></body> 锚点123456789101112131415161718192021<body>目录:<a href="#1">1</a><a href="#2">2</a><hr><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><h2 id="1">这是锚点1</h2><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><h2 id="2">这是锚点2</h2></body> 表格标签123456789101112<body><table border="1" align="center"> <tr> <th>姓名</th> <th>性别</th> </tr> <tr> <td>anthony</td> <td>南</td> </tr></table></body> 列表标签1234567891011121314151617181920212223242526<body><!-- 无序列表 --><ul> <li>无序列表1</li> <li>无序列表2</li> <li>无序列表3</li> <li>无序列表4</li></ul><!-- 有序列表 --><ol> <li>1</li> <li>2</li> <li>4</li> <li>3</li></ol><!-- 自定义 --><dl> <dt>这是自定义列表</dt> <dd>1</dd> <dd>2</dd> <dd>4</dd> <dd>3</dd></dl></body> 表单标签12345678910111213141516171819<form action="url地址" method="提交方式" name="表单名称"> <!-- 点击lable 就能把光标古交到输入框里面--> <label for="usernameId">用户名</label> <input type="text" name="username" value="anthony" id="usernameId"> <br> 密码 :<input type="password" name="pwd"> <br> 性别 : 男<input type="radio" name="sex" value="男" checked> 女<input type="radio" value="女" name="sex"><br> 爱好: 吃饭<input type="checkbox" name="hobby" value="1"> 睡觉<input type="checkbox" name="hobby" value="2"> 玩<input type="checkbox" name="hobby" value="3"><br> <label for="selectId">选项:</label> <select id="selectId"> <option value="1" >一</option> <option value="2" selected>二</option> <option value="3">三</option> </select><br> 文本域元素:<textarea>23123</textarea></form> input12345678910111213141516171819<body> <form> 用户名:<input type="text" name="myName" value="anthony"><br /> 密码:<input type="password" name="myPassword" value="123456"><br /> 测试重置:<input type="text" name="myTest"><br /> 性别: <input type="radio" name="myGender" value="male" checked> 男 <input type="radio" name="myGender" value="female"> 女 <br /> 爱好: <input type="checkbox" name="myHobby" value="basketball" checked> 篮球 <input type="checkbox" name="myHobby" value="football"> 足球 <input type="checkbox" name="myHobby" value="pingpong"> 乒乓球 <br /> <input type="submit" value="提交"> <input type="reset" value="重置"> </form></body> select1234567891011<body> <form> 地区: <select name="myArea"> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="guangzhou" selected>广州</option> <option value="shenzhen">深圳</option> </select> </form></body> 综合练习123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>综合案例-注册</title></head><body> <h4>青春不常在,赶紧谈恋爱</h4> <table border="1" cellspacing="0" cellpadding="0" width="500px"> <tr> <td>性别:</td> <td> <input type="radio" name="myGender" id="man"><label for="man">男<img src="./assert/male.svg" alt="male" width="12px"></label> <input type="radio" name="myGender" id="woman"><label for="woman">女<img src="./assert/female.svg" alt="female" width="12px"></label> </td> </tr> <tr> <td>生日:</td> <td> <select name="myBirthday"> <option value="1990" selected>请选择年</option> <option value="1991">1991</option> <option value="1992">1992</option> <option value="1993">1993</option> <option value="1994">1994</option> <option value="1995">1995</option> </select> <select name="myBirthday"> <option value="1" selected>请选择月</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> </select> <select name="myBirthday"> <option value="1" selected>请选择日</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> </select> </td> </tr> <tr> <td>所在地区:</td> <td> <input type="text" name="myLocation" placeholder="请输入所在地区"> </td> </tr> <tr> <td>婚姻状态:</td> <td> <input type="radio" name="myMarriage" id="married"><label for="married">已婚</label> <input type="radio" name="myMarriage" id="unmarried"><label for="unmarried">未婚</label> <input type="radio" name="myMarriage" id="divorced"><label for="divorced">离异</label> </td> </tr> <tr> <td>学历:</td> <td> <input type="text" name="myEducation" placeholder="请输入学历"> </td> </tr> <tr> <td>爱好:</td> <td> <input type="checkbox" name="myHobby"><label for="basketball">篮球</label> <input type="checkbox" name="myHobby"><label for="football">足球</label> <input type="checkbox" name="myHobby"><label for="pingpong">乒乓球</label> </td> </tr> <tr> <td>自我介绍:</td> <td> <textarea name="myIntro" cols="30" rows="10" placeholder="请输入自我介绍"></textarea> </td> </tr> <tr> <td></td> <td> <input type="submit" name="myCode" value="免费注册"> </td> </tr> <tr> <td></td> <td> <input type="checkbox" checked><label for="myAgreement">我同意《用户协议》</label> </td> </tr> <tr> <td></td> <td> <a href="https://www.baidu.com">我是会员,立即登录</a> </td> </tr> <tr> <td></td> <td> <h5>我承诺</h5> <ul> <li>1. 我是成年人</li> <li>2. 我是成年人</li> <li>3. 我是成年人</li> <li>4. 我是成年人</li> </ul> </td> </tr> </table></body></html> 动态修改html标题 123456789101112131415161718192021222324252627<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>欢迎来到我的网页</title></head><body><h1>试着切换标签页吧!</h1><script> // 记录原始标题 var originalTitle = document.title; // 定义当页面可见性发生变化时的事件处理函数 document.addEventListener('visibilitychange', function() { if (document.hidden) { // 如果页面不可见,修改标题 document.title = "我等着你回来"; } else { // 如果页面可见,恢复原始标题 document.title = originalTitle; } });</script></body></html>
博客修改记录
至今 2025-05-09 把_posts_目录下的something/index.md(博客更新的时间)和interview/index.md(面试经历)改成文章 2025-05-05 Hexo 升级到7.3Butterfly 升级到 5.3.5 2024-04-05 图片放在华为云上,固定图片域名 2023-08-13 又买了一个域名, runtimes.cc (运行时)Dynaot买的域名, 指定 Cloudflar 的NameServer图片放在本地 2022-12-04 终于把文章内链搞定了Aws CloudFront 加速 Vercel网站 2022-11-26 迁移完成,迁移过程中,笔记有丢失的 2022-11-19 把笔记初步迁移到博客上来
面试记录
至今 2023-08-01 yb mysql 主从复制异常怎么办 ThreadLocal 没有答上来 强应用,弱引用 mybatis源码,myabtis怎么通过接口调用到sql的 RabbitMQ 和 RocketMQ的区别 Redis的数据结构有哪些 重构代码用了哪些设计模式 Spring Cloud的常用组件 violate关键字 实现多数据源 Spring事务传播
Mac Apple芯片安装Win11
Mac Apple芯片安装Win11 M1/M2 Pro VMware Fusion虚拟机安装Win11教程(超详细)_m1装win11_七维大脑的博客-CSDN博客 M用户使用VM虚拟机安装win11连不上网,怎么解决_mac_xwz的博客-CSDN博客 记得要下载ARM版本的 这里设置的密码,后面不会再用了,可以设置个简单点的就行 内存设置4GB,硬盘设置成80GB 这里要快速按回车,不然就提示EFI Network,如果是这个提示,重新启动虚拟机就行,之后就是正常安装Window系统的步骤,然后就会遇到连接到网络的问题 Shift + F10打开命令行,输入OOBE\BYPASSNRO 然后系统就行回重启,然后又回到设置Windown的设置开始,这是正常的,然后就一直都是配置,正常配置就好,选择没有连接,就可以创建本地账号 安装完成之后,是没有网络的,需要安装vm-tools 正常安装软件的步骤就可以了 固定IP配置完了,最好是重启下vmware和虚拟机,和禁用开启 win10上的vmare8网卡 1.vmare配置 2.电脑配置,虚拟机配置
ESM
导入和导出Es Module和CommonJs的导入导出不一样 1234567891011121314// b.js// 一个模块只能有一个默认输出,export default 命令只能使用一次;export default function sayHello() { console.log('Hello!');}export default function sayHello2() { console.log('Hello!');}// a.js , 运行报错import sayHello from './b.js';sayHello(); 如何导出多个变量呢 12345678910111213// b.jsexport function sayHello() { console.log('Hello!');}export function sayHello2() { console.log('Hello!');}// a.jsimport {sayHello} from './b.js';sayHello(); 什么时候花括号呢? 12345678910111213141516// b.js// 对于import命令后面不用加大括号,因为只有唯一对应export default命令。export default function sayHello() { console.log('Hello!');}export function sayHello2() { console.log('Hello2!');}// a.js// 导入default的变量不用花括号import sayHello, {sayHello2} from './b.js';sayHello();sayHello2(); Promise基本代码结构 12345678910111213141516171819202122232425const myPromise = new Promise((resolve, reject) => { // 异步操作 (如读取文件、获取数据) let success = true; // 这是模拟的异步操作结果 if (success) { resolve("操作成功!"); // 成功时调用 resolve } else { reject("操作失败!"); // 失败时调用 reject }});// 使用 .then() 处理成功的情况,使用 .catch() 处理失败的情况myPromise.then((result) => { console.log(result); // 输出:操作成功! }) .catch((error) => { console.log(error); // 如果失败,则输出错误信息 });// 也可以写成这样myPromise .then( () => { console.log("操作成功!"); }, // 成功时执行 () => { console.log("操作失败!"); } // 失败时执行 );
Flarum
Flarum 部署 Ubuntu 24.04 安装 PHP、MariaDB、Nginx、Composer 安装的目录是在/home/ubuntu/flarum/ 安装Flarum✅ 安装PHP12345678910111213141516171819sudo apt update && sudo apt upgrade -ysudo apt install -y \ nginx \ php \ php-cli \ php-mbstring \ unzip \ curl \ php-gd \ php-mysql \ php-xml \ php-curl \ php-zip \ php-bcmath \ php-fpm# 验证版本php -v ✅ 安装 Composer12345678cd ~curl -sS https://getcomposer.org/installer | phpsudo mv composer.phar /usr/local/bin/composer# 验证版本composer -V ✅ 安装 Flarum123cd ~mkdir flarumcomposer create-project flarum/flarum flarum ✅ 安装MariaDB123456789101112131415161718192021222324252627282930313233# 安装数据库sudo apt install mariadb-server -ysudo systemctl enable mariadbsudo systemctl start mariadb# 初始化,设置密码sudo mysql_secure_installation# 登录sudo mysql -u root -p# 设置密码ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyRootPass123!' ;# 设置远程访问CREATE USER 'root'@'%' IDENTIFIED BY 'MyRootPass123!';# 设置权限GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;# 创建数据库CREATE DATABASE flarum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;# 刷新权限FLUSH PRIVILEGES;# 退出EXIT;# 开启远程访问sudo vim /etc/mysql/mariadb.conf.d/50-server.cnfbind-address = 127.0.0.1 -> bind-address = 0.0.0.0sudo systemctl restart mariadb ✅ 配置Nginx12345678910111213141516171819202122232425262728293031server { listen 80; server_name _; # ← 如果没有域名,可以写你的公网 IP root /home/ubuntu/flarum/public; index index.php index.html; # URL 重写规则 location / { try_files $uri $uri/ /index.php?$query_string; } # PHP 解析设置 location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # 禁止访问隐藏文件 location ~ /\.ht { deny all; } # 缓存静态资源 location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|ttf|svg|eot)$ { expires 6M; access_log off; add_header Cache-Control "public"; }} ✅ 修改文件全新到这一步,使用IP访问,会404,执行以下命令授权 1234sudo chown -R www-data:www-data /home/ubuntu/flarumsudo chmod -R 775 /home/ubuntu/flarum/storagesudo chmod -R 775 /home/ubuntu/flarum/public/assetssudo chmod +x /home/ubuntu ✅ 配置域名Cloudflare开启了正常CDN,还需要修改php的配置文件修改flarum目录下的config.php 1234567vim ~/flarum/config.php'url' => 'http://<原来的IP>',修改成'url' => 'https://forum.example.com', php flarum cache:clear 配置📤配置邮箱驱动:smtp 主机:smtp.gmail.com 顿口:587 加密协议:tls 用户名:发送验证码的邮箱 密码:Gmail应用程序的专用密码
JavaScript
JavaScript12345678910111213141516171819202122232425262728293031323334353637383940414243<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>setTimeout</title> </head> <body> <input type="text" id="displayBox" name="displayBox" value="0"> <div id="content"></div> <button type="button" onclick="countSecond()">开始计数</button> <!--例子4--> <button type="button" onclick="clearTimeout(stop)">停止计数</button> <script> // 例子1 setTimeout("alert('对不起, 要你久候')", 3000) // 例子2 setTimeout("changeState()", 1000); function changeState() { let content = document.getElementById('content'); content.innerHTML = "<div style='color:red'>我是三秒后显示的内容!</div>"; } // 例子3 x = 0 function countSecond() { x = x+1 document.getElementById("displayBox").value=x stop = setTimeout("countSecond()", 1000) } // 例子5 setTimeout(demo5, 3000,"1232") function demo5(msg) { alert(msg) } </script> </body></html> 函数JSJS声明普通函数 1234567// 声明函数-没有参数-没有返回值function showMessage() { console.log( 'Hello everyone!' );}// 调用函数showMessage(); 1234567// 声明有参数的函数function showMessage2(param1,param2){ console.log(param1, param2);}// 调用函数showMessage2("anthony",23) 12345678// 声明有默认值的函数function showMessage2(param1,param2=24){ console.log(param1, param2);}// 调用函数showMessage2("anthony",23)showMessage2("anthony") 1234567// 声明有返回值的函数function haveReturn(param1,param2){ return param1 + param2;}// 调用函数console.log(haveReturn(1,2))12345678910111213/** * 计算两个数字的和 * @param num1 - 第一个加数 * @param num2 - 第二个加数 * @returns 返回两个数字的和 */function add(num1: number, num2: number): number { return num1 + num2;}// 调用示例const result = add(5, 3);console.log(result); // 输出: 8 函数表达式 1234567891011let let1 = function sayHi(){ return 10086;}// 打印 [Function: sayHi]// 不像别的语言 调用let1的作用==let1(), js里调用函数就需要()console.info(let1)let let2 = let1console.info(let1());console.info(let2()); 回调 1234567891011121314151617181920212223242526272829function ask(question, yes, no) { if (question) { yes(); } else { no(); }}function showQuestion() { return 1 === 1;}function showOk() { console.info("同意");}function showCancel() { console.info("不同意");}// 用法:函数 showOk 和 showCancel 被作为参数传入到 askask(showQuestion(), showOk, showCancel);// 也可以写成ask(1 === 1, function () { console.info("同意"); }, function () { console.info("不同意"); }) 普通函数和函数表达式的区别 123456789101112sayHi("John"); // Hello, Johnfunction sayHi(name) { alert( `Hello, ${name}` );}----------------------------------------------------sayHi2("John"); // 报错,函数还没有创建!let sayHi2 = function(name) { // (*) no magic any more alert( `Hello, ${name}` );}; 箭头函数,功能是更简化函数表达式 定义 1234567891011121314151617let demo1 = function () { console.info("常用的函数表达式")};let demo2 =()=>console.info("单行的箭头函数")let demo3 =()=>{ console.info("单行的箭头函数第一行") console.info("单行的箭头函数第二行")}let demo4 = (name, age) => console.info("带参数的箭头表达式", name, age);demo1();demo2();demo3();demo4("Anthony", 24); 重新上面的例子 123456789let ask = (question, yes, no) => { question ? yes() : no();}// 也可以写成ask(() => 1 === 1, () => console.info("同意"), () => console.info("不同意")); 对象创建对象 123456789101112131415161718192021let user = { // 一个对象 name: "John", // 键 "name",值 "John" age: 30, // 键 "age",值 30 "likes birds": true // 多词属性名必须加引号};// 访问属性console.info(user.age)// 删除属性delete user.age;console.info(user.age)// 访问多词属性console.info(user["likes birds"])// 也可以访问普通属性console.info(user["name"])// 给对象添加属性,这样不行user.address="Dubai"user["sex"]="男"console.info(user.address)console.info(user.sex) 引用 1234567891011121314151617181920let user = { // 一个对象 name: "John", // 键 "name",值 "John" age: 30, // 键 "age",值 30};let user1 = userconsole.info(user1.name)user.name="anthony"console.info(user1.name)// 比较两个对象console.info(user === user1)// 浅拷贝,克隆对象,克隆user 给 user2let user2={}Object.assign(user2, user);console.info(user2.name)user.name="Nick"console.info(user2.name) 方法 12345678910111213141516171819202122232425262728293031let user = { // 一个对象 name: "John", // 键 "name",值 "John" age: 30, // 键 "age",值 30 // 给对象添加方法的第三种写法 sayHi3: function () { console.info(this.name) }, sayHi4: function () { let demo = ()=>{ console.info("箭头函数不能访问this"); } demo(); },};// 给对象添加方法的第一种写法user.sayHi = function () { console.info(this.name)};// 给对象添加方法的第二种写法function sayHi2() { console.info(this.name)}user.sayHi2 = sayHi2;// 调用对象方法user.sayHi()user.sayHi2()user.sayHi3()user.sayHi4() 数组 12345678910111213141516// 数组let arr = [];// 添加新元素arr[0] = "A"arr[1] = "B"arr[2] = "C"console.info("获取指定元素",arr[0])console.info("打印元素个数",arr.length)console.info("打印全部元素",arr)// 数组作为队列(push/pop),也可以做为栈(shift和unshift)arr.push("哈哈哈,存入输入")console.info("打印全部元素",arr)// 取出数据arr.pop()console.info("打印全部元素",arr) map 123456789101112131415// maplet map = new Map();map.set("k1","v1")map.set("k2","v2")map.set("k3","v3")// 访问数据console.info(map)console.info(map.get("k1"))console.info(map["k1"]) // 这样不行// 遍历for (const key of map.keys()) { console.info(map.get(key))}