Node.js入门指南(二)

news2024/9/21 14:32:27

目录

http模块

创建http服务端

浏览器查看 HTTP 报文

获取 HTTP 请求报文

设置响应报文

网页资源的基本加载过程

静态资源服务


hello,大家好!上一篇文章我们对Node.js进行了初步的了解,并介绍了Node.js的Buffer、fs模块以及path模块。这一篇文章主要介绍Node.js的http模块。

http模块

创建http服务端

首先需要导入http模块,接着创建服务对象,调用http中的createsServer方法,该方法会传入两个形参,request以及response。request会接受请求报文的封装对象,能够通过该对象获取到请求头,请求行以及请求体。response会传入对响应报文的封装对象,它能够设置响应头,响应行以及响应体。当我们在浏览器发送http请求时,该回调函数就会执行。

// 导入http模块
const http=require('http');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //设置响应体
    response.end('Hello http server');
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

server.listen用于设置监听的端口号,当我们成功运行js文件时,我们就可以通过本地的9000端口访问到我们设置的响应体了。以下有一些注意事项:

1️⃣命令行 ctrl + c 停止服务。

2️⃣当服务启动后,更新代码必须重启服务才能生效。

3️⃣响应内容中文乱码的解决办法 response.setHeader('content-type','text/html;charset=utf-8');

4️⃣当端口号被占用时,可以关闭当前正在运行监听端口的服务,或者修改其他端口号。

5️⃣HTTP 协议默认端口是 80 。HTTPS 协议的默认端口是 443, HTTP 服务开发常用端口有 3000,8080,8090,9000 等。

6️⃣如果端口被其他程序占用,可以使用 资源监视器 找到占用端口的程序,然后使用任务管理器 关闭对应的程序。

浏览器查看 HTTP 报文

学会使用浏览器来查看我们的http报文是非常重要的,对于后续我们的调试会起到很大的作用。当我们向服务端发送get请求时,我们如何查询对应的请求头请求行以及请求体呢?我们还是以上面的代码为例向9000端口发送请求。

点击Network,然后发送请求之后会有显示,点击127.0.0.1,然后在点击Headers部分,点击Response Heasers,然后再点击Raw就可以清晰地看到相应的响应头和响应行。

然后点击Response,可以看到相应的响应体信息。

由于我们再向该端口号发送一个post请求,并携带对应的参数,来查看相应的请求头,请求行和请求体。对应大代码如下:

<form action="http://127.0.0.1:9000" method="post">
  <input type="text" name="username">
  <input type="text" name="password">
  <input type="submit" value="提交">
</form>

同样步骤,我们点击Request Headers进行查看请求行和请求头。由于我们携带了相应的数据,因此会多出一个Payload的部分,我们点击它就是我们的请求体。

Payload的部分除了可以查看我们请求体的内容,还可以查看我们url中查询字符串的内容,这里就不做演示,感兴趣的小伙伴可以自行实践。

获取 HTTP 请求报文

我们可以通过使用  request 对象来获取请求方法,请求的url,获取协议的版本号以及获取http的请求头等信息。注意:获取请求的url,不会包括协议,域名端口号等信息,只会包含url中的路径以及查询的字符串。
// 导入http模块
const http=require('http');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //获取请求方法
    console.log(request.method);
    //获取请求的url,只会包括url中的路径与查询字符串
    console.log(request.url);
    //获取协议的版本号
    console.log(request.httpVersion);
    //获取http的请求头
    console.log(request.headers);
    //设置响应体
    response.end('Hello http server');
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

我们还可以获取请求体中的内容,我们通过给request对象绑定data事件以及end事件来实现请求体的获取,当我们发送get请求时,它的请求体会是空的。因此我们使用上面的表单发起post请求,只有我们会在控制台看到输出相应的请求体信息。username=N-A&password=123456。该方式了解即可后续还会提供更加简便的方式。

// 导入http模块
const http=require('http');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //声明一个变量
    let body='';
    //绑定data事件
    request.on('data',chunk=>{
        body+=chunk;
    })
    //绑定end事件
    request.on('end',()=>{
        console.log(body);//username=N-A&password=123456
        //响应
        response.end('Hello http server');
    })

});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

对于我们得到的请求路径以及请求的查询字符串是非常重要的,我们可以通过获取相应的请求路径以及查询的字符串向浏览器返回不同的内容。因此我们可以导入url模块来进行获取。这时候可能会有小伙伴有疑问,刚才我们不是可以直接通过request.url来得到请求的路径以及查询的字符串吗?

确实是可以,但是它返回出来的形式并不利于我们更直观更方便地进行获取。因此我们采用导入url模块来获取请求的路径以及查询的参数。

// 导入http模块
const http=require('http');
//导入url模块
const url=require('url');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //解析request.url
    let res=url.parse(request.url);
    let pathname=res.pathname;
    //查询路径
    console.log(pathname);// /serach
    //设置响应体
    response.end('Hello http server');
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

当服务启动之后假设我向9000端口发送:http://127.0.0.1:9000/serach?name=N-A的请求,控制台打印出的res为

Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: '?name=N-A',
  query: 'name=N-A',
  pathname: '/serach',
  path: '/serach?name=N-A',
  href: '/serach?name=N-A'
}

此时我们可以直接获取res的hostname属性来得到对应的路径:/search。那如何得到查询的参数呢?我们可以看到我们的参数存在query的属性里面,如果直接获取得出来的结果也不是我们想要的,因此这时候就需要用到parse方法的第二个参数了,将其设置为true,查询字符串将会以对象的形式进行展示如下。第一个数组不需要管。

Url {
  query: [Object: null prototype] { name: 'N-A' },
}

因此我们通过对应以及键名来进行查询。

// 导入http模块
const http=require('http');
//导入url模块
const url=require('url');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //解析request.url
    let res=url.parse(request.url,true);
    //查询字符串
    let keyword=res.query.name;
    console.log(keyword);//N-A

    //设置响应体
    response.end('Hello http server');
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

除了上面介绍的那一种方法,我们还可以采用实例化的方式去创建一个对象,再通过对象里面的属性来获取url里面的相关内容了。这种方式较为简便。

// 导入http模块
const http=require('http');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //实例化URL对象
    // let url=new URL('/search?name?N-A','http://127.0.0.1:9000');
   let url=new URL(request.url,'http://127.0.0.1');
   //输出路径
   console.log(url.pathname);// /search
   //查询字符串
   console.log(url.searchParams.get('name'));//N-A
    //设置响应体
    response.end('Hello http server');
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

设置响应报文

我们可以通过相应的方法来设置响应报文的信息,包括:响应状态码(response.statusCode)、响应状态描述(response.statusMessage) 、响应头信息(response.setHeader)以及响应体(response.write以及 response.end)。

设置响应头可以使用数组来实现设置多个同名的响应头。response.write和 response.end都可以用来设置响应体,区别在与前者可以多次设置,而后者只能设置一次。当使用response.write来设置响应体是,一般就不再使用response.end进行设置响应体,直接为空即可。在回调函数中必须要response.end。

// 导入http模块
const http=require('http');
// 创建服务对象
const server=http.createServer((request,response)=>{
    //设置响应状态码
    response.statusCode=203;
    //设置响应状态的描述
    response.statusMessage='N-A';
    //设置响应头
    response.setHeader('content-type','text/html;charset=utf-8');
    //设置多个同名的响应头
    response.setHeader('text',['a','b','c']);
    //设置响应体,write可以重复设置
    response.write('N-A');
    response.write('N-A');
    response.write('N-A');

    //设置响应体,end只能设置一次
    response.end();
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

网页资源的基本加载过程

假设我们在浏览器搜索CSDN,然后向会向CSDN的服务端发送请求,但是这时候需要注意的是,浏览器并不是只发送一次请求。网页资源的加载都是循序渐进的,首先获取 HTML 的内容, 然后解析 HTML 在发送其他资源的请求,如 CSS,Javascript,图片等。 

静态资源服务

静态资源是指 内容长时间不发生改变的资源 ,例如图片,视频,CSS 文件,JS文件,HTML文件,字体文件等。而动态资源是指 内容经常更新的资源 ,例如百度首页,网易首页,京东搜索列表页面等。现在我们来试着搭建一个静态资源服务,主要实现以下的功能:

可以通过以下的方式来进行实现:

// 导入http模块
const http=require('http');
const fs=require('fs');
// 创建服务对象
const server=http.createServer((request,response)=>{
   //获取请求url对象
   let {pathname}=new URL(request.url,'http://127.0.0.1');
   if(pathname==='/index.html'){
    //读取文件内容
    let html=fs.readFileSync(__dirname+'/page/index.html');
    response.end(html);
   }else if(pathname==='/css/app.css'){
    //读取文件内容
    let css=fs.readFileSync(__dirname+'/page/css/app.css');
    response.end(css);
   }else if(pathname==='/images/logo.png'){
     //读取文件内容
     let img=fs.readFileSync(__dirname+'/page/images/logo.png');
     response.end(img);
   }else{
    response.statusCode=404;
    response.end('<h1>404 Not Found</h1>')
   }
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})

当访问相应的文件路径时,我们就可以再浏览器看到对应文件中的内容。但是这种方式并不简便,当有很多的不同的文件时需要编写很长的代码。因此可以提取公共的路径部分进行修改如下:

// 导入http模块
const http=require('http');
const fs=require('fs');
// 创建服务对象
const server=http.createServer((request,response)=>{
   //获取请求url对象
   let {pathname}=new URL(request.url,'http://127.0.0.1');
   //拼接文件路径
   let filePath=__dirname+'/page'+pathname;
   //读取文件
   fs.readFile(filePath,(err,data)=>{
    if(err){
        response.statusCode=500;
        response.end('文件读取失败');
        return;
    }
    //响应内容
    response.end(data);
   })
});
// 监听端口
server.listen(9000,()=>{
    console.log("服务已经启动.....")
})
HTTP 服务在哪个文件夹中寻找静态资源,那个文件夹就是静态资源目录 ,也称之为网站根目录。以上面的静态资源服务为例,path就是网站的根目录。它还可以单独地和__firname赋值给一个变量,该变量再去与pathname进行拼接,结果是一样的,只是后续如果想要修改根目录的话更为方便。
   //声明一个变量
   let root=__dirname+'/page'
   //拼接文件路径
   let filePath=root+pathname;

再补充一些关于网页中URL的内容,网页中的 URL 主要分为两大类:相对路径与绝对路径。绝对路径可靠性强,而且相对容易理解,在项目中运用较多。相对路径在发送请求时,需要与当前页面 URL 路径进行 计算 ,得到完整 URL 后,再发送请求,学习阶段用的较多。

绝对路径的形式:

形式特点
http://atguigu.com/w
eb
直接向目标资源发送请求,容易理解。网站的外链会用到此形式
//atguigu.com/web
与页面 URL 的协议拼接形成完整 URL 再发送请求。大型网站用的比较多
/web
与页面 URL 的协议、主机名、端口拼接形成完整 URL 再发送请求。中小型网站
相对路径的形式: 例如当前网页 url http://www.atguigu.com/course/h5.html 
形式最终的 URL
./css/app.csshttp://www.atguigu.com/course/css/app.css
js/app.jshttp://www.atguigu.com/course/js/app.js
../img/logo.pnghttp://www.atguigu.com/img/logo.png
../../mp4/show.mp4http://www.atguigu.com/mp4/show.mp4
在前面我们已经有涉及到,设置响应头的信息时,其中有一部分是 text/html,表示请求的资源文件为html类型的文件,除了html类型,还有很多的其他类型也有相应的格式。浏览器会帮助我们识别对应的文件类型,但是如果我们设置文件的相应信息会更加地规范。这一个步骤叫做 mime 类型的设置。 HTTP 服务可以设置响应头 Content-Type 来表明响应体的 MIME 类型,浏览器会根据该类型决定如何处理 资源。它常见的类型有:
html: 'text/html',
css: 'text/css',
js: 'text/javascript',
png: 'image/png',
jpg: 'image/jpeg',
gif: 'image/gif',
mp4: 'video/mp4',
mp3: 'audio/mpeg',
json: 'application/json'

对上面我们编写的静态资源服务设置mime类型,如下:

// 导入http模块
const http = require('http');
const fs = require('fs');
const path=require('path')
let mimes = {
    html: 'text/html',
    css: 'text/css',
    js: 'text/javascript',
    png: 'image/png',
    jpg: 'image/jpeg',
    gif: 'image/gif',
    mp4: 'video/mp4',
    mp3: 'audio/mpeg',
    json: 'application/json'
}
// 创建服务对象
const server = http.createServer((request, response) => {
    //获取请求url对象
    let { pathname } = new URL(request.url, 'http://127.0.0.1');
    //声明一个变量
    let root = __dirname + '/page'
    //拼接文件路径
    let filePath = root + pathname;
    //读取文件
    fs.readFile(filePath, (err, data) => {
        if (err) {
            response.statusCode = 500;
            response.end('文件读取失败');
            return;
        }
        //获取文件后缀名
        let ext = path.extname(filePath).slice(1);
        //获取对应的类型
        let type = mimes[ext];
        if (type) {
            response.setHeader('content-type', type);
        } else {
            response.setHeader('content-type', 'application/octet-stream')
        }
        //响应内容
        response.end(data);
    })
});
// 监听端口
server.listen(9000, () => {
    console.log("服务已经启动.....")
})

css文件以及js中的文件若存在中文,使用浏览器打开会出现乱码的情况,因此可以设charset=utf-8。修改如下:

   if (type) {
            response.setHeader('content-type', type+';chaeset=utf-8');
        } else {
            response.setHeader('content-type', 'application/octet-stream')
        }
对于未知的资源类型,可以选择 application/octet-stream 类型,浏览器在遇到该类型的响应时,会对响应体内容进行独立存储,也就是我们常见的下载效果。
我们还需要对响应错误进行一定的处理,我们前面都只是给你指定为500的错误,我们可以根据不同的状态 err.code来设置相应的错误编码以及错误信息,详细完整的错误可看官网。我们对以上的代码进行修改:
// 导入http模块
const http = require('http');
const fs = require('fs');
const path=require('path')
let mimes = {
    html: 'text/html',
    css: 'text/css',
    js: 'text/javascript',
    png: 'image/png',
    jpg: 'image/jpeg',
    gif: 'image/gif',
    mp4: 'video/mp4',
    mp3: 'audio/mpeg',
    json: 'application/json'
}
// 创建服务对象
const server = http.createServer((request, response) => {
    if(request.method !=='GET'){
        response.statusCode=405;
        response.end('<h1>405 Method Not Allowed</h1>');
    }
    //获取请求url对象
    let { pathname } = new URL(request.url, 'http://127.0.0.1');
    //声明一个变量
    let root = __dirname + '/page'
    //拼接文件路径
    let filePath = root + pathname;
    //读取文件
    fs.readFile(filePath, (err, data) => {
        if (err) {
          switch(err.code){
            case 'ENOENT':
                response.statusCode=404;
                response.end('<h1>404 Not Found</h1>');
            case 'EPERM':
                response.statusCode=403;
                response.end('<h1>403 Forbidden</h1>');
            default:
                response.statusCode=500;
                response.end('<h1>Internal Server Error</h1>');
          }
            return;
        }
        //获取文件后缀名
        let ext = path.extname(filePath).slice(1);
        //获取对应的类型
        let type = mimes[ext];
        if (type) {
            response.setHeader('content-type', type+';chaeset=utf-8');
        } else {
            response.setHeader('content-type', 'application/octet-stream')
        }
        //响应内容
        response.end(data);
    })
});
// 监听端口
server.listen(9000, () => {
    console.log("服务已经启动.....")
})

最后我们来介绍一下get请求以及post请求的应用场景以及区别:

GET 请求的情况POST 请求的情况:
在地址栏直接输入 url 访问
form 标签中的 method post (不区分大小写)
点击 a 链接AJAX post 请求
link 标签引入 css
script 标签引入 js
img 标签引入图片
form 标签中的 method get (不区分大小写)
ajax 中的 get 请求
它们之间的区别主要有以下几点:
1️⃣GET 主要用来获取数据, POST 主要用来提交数据。但是也可以反过来,这并不是绝对的。
2️⃣GET 带参数请求是将参数缀到 URL 之后,在地址栏中输入 url 访问网站就是 GET 请求,POST 带参数请求是将参数放到请求体中。
3️⃣POST 请求相对 GET 安全一些,因为在浏览器中参数会暴露在地址栏。
4️⃣GET 请求大小有限制,一般为 2K ,而 POST 请求则没有大小限制。

好啦!本文就先到这里了!感谢阅读。后续持续更新,拜拜!! 

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

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

相关文章

51单片机应用从零开始(八)·循环语句(for循环、while 语句、do‐while 语句)

51单片机应用从零开始&#xff08;七&#xff09;循环语句&#xff08;if语句&#xff0c;swtich语句&#xff09;-CSDN博客 目录 1. 用for 语句控制蜂鸣器鸣笛次数 2. 用while 语句控制 LED 3. 用 do‐while 语句控制 P0 口 8 位 LED 流水点亮 1. 用for 语句控制蜂鸣器鸣笛…

6.3.WebRTC中的SDP类的结构

在上节课中呢&#xff0c;我向你介绍了sdp协议&#xff0c; 那这节课呢&#xff0c;我们再来看看web rtc中。是如何存储sdp的&#xff1f;也就是sdp的类结构&#xff0c;那在此之前呢&#xff1f;我们先对sdp的内容啊&#xff0c;做一下分类。因为在上节课中呢&#xff0c;虽然…

jetpack的简单使用

Jetpack ViewModel&#xff1a; 什么是ViewModel&#xff1f; ViewModel 是 Android 架构组件的一部分&#xff0c;用于帮助开发者管理 UI 数据的持久性和生命周期感知。ViewModel 的主要目的是将 UI 数据与界面控制逻辑分离&#xff0c;以便更好地管理数据的生命周期&#…

佳易王早点点餐快餐店点单软件会员管理系统教程

佳易王早点点餐快餐店点单软件会员管理系统教程 软件特色&#xff1a; 1、功能实用&#xff0c;操作简单&#xff0c;不会电脑也会操作&#xff0c;软件免安装&#xff0c;已内置数据库。软件在关闭的时候&#xff0c;可以设置会员数据备份到U盘&#xff0c;数据本机备份一份&…

基于SSM安全生产培训管理平台设计与实现 毕业设计源码26918

赠送源码-毕业设计&#xff1a;SSM 安全生产培训平台https://www.bilibili.com/video/BV1gH4y1z7c6/?vd_source72970c26ba7734ebd1a34aa537ef5301 目录 摘 要 Abstract 第1章 前 言 1.1 研究背景 1.2 研究现状 1.3 系统开发目标 第2章 系统开发环境 2.1 JAVA简介…

uniapp 使用Highcharts,多色曲线,多色阴影,百分比,网格等处理,accessibility.js提示错误处理

示例图 1.安装Highcharts npm install highcharts --save npm install highcharts-vue2.demo代码 <template><view class"charts-main"><view id"charts" style"width: 90%;height: 460rpx;"></view></view>&l…

OpenHarmony之NAPI框架介绍

张志成 诚迈科技高级技术专家 NAPI是什么 NAPI的概念源自Nodejs&#xff0c;为了实现javascript脚本与C库之间的相互调用&#xff0c;Nodejs对V8引擎的api做了一层封装&#xff0c;称为NAPI。可以在Nodejs官网&#xff08;https://nodejs.org/dist/latest-v20.x/docs/api/n-api…

SSM家具个性定制管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 家具个性定制管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用…

STM32电容触摸按键检测

STM32电容触摸按键检测 电容触摸按键简介检测原理 CubeMX配置代码展示&讲解TPAD.cTPAD.h 本期内容我们将学习电容触摸按键的检测原理。以及代码实现思路 电容触摸按键 简介 电容触摸按键依赖的是电容的充放电相对于机械按键更加耐用&#xff0c;不容易受外界环境干扰在我们…

mybatis注解方式动态标签时有特殊符号,出现元素内容必须由格式正确的字符数据或标记组成

原始代码demo Select("SELECT COUNT(1) FROM AAAA WHERE name #{nage} AND age< 4") public Integer sumXxxxx(String nage, String age);现需求改为nage可以为空&#xff0c;因此使用了动态拼接 Select("<script> SELECT COUNT(1) FROM AAAA WHERE …

ruoyi-plus使用Statistic统计组件升级element-plus

原本使用的就是gitee上lionli的ruoyi-plus版本的代码。但是在使用过程中作首页数据看板时想使用elementui的Statistic统计组件。结果在浏览器控制台报错找不到组件el-statistic 于是查看elementui的历史版本&#xff0c;发现是在新版中才有这个组件&#xff0c;旧版本是没这个组…

常见树种(贵州省):012茶、花椒、八角、肉桂、杜仲、厚朴、枸杞、忍冬

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、茶 灌…

读像火箭科学家一样思考笔记07_探月思维

1. 挑战“不可能”的科学与企业 1.1. 互联网 1.1.1. 和电网一样具有革命性&#xff0c;一旦你插上电源&#xff0c;就能让自己的生活充满活力 1.1.2. 互联网的接入可以帮助人们摆脱贫困&#xff0c;拯救生命 1.1.3. 互联网还可以提供与天气相关的信息 1.2. 用廉价、可靠的…

实例讲解:在3dMax中如何使用python脚本?

如果你是Python或Maxscript的新手&#xff0c;你现在可以跟着这篇文章开始做一些代码了&#xff0c;本文将让我们从非常基本的东西开始学习。 如何在3dmax中获取选定的节点并打印出它们的名称&#xff1f;所有场景对象如何&#xff1f;我们直接看代码&#xff1a; import MaxP…

常见树种(贵州省):014槭树、梧桐、鹅掌楸、檫木、梓木、油桐、泡桐、川楝、麻楝

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、色木槭…

Windows如何截取屏幕图片以及动态图

在制作PPT或是其他演示文稿或是说明文档的时候&#xff0c; 常常需要截取网页或是屏幕的截图&#xff0c;在Windows中有多种方式可以实现截取屏幕。 Windows 截取屏幕图片的方式 在Windows 中截取屏幕中某个区块的方式有&#xff1a; 方式1. 最原始的方式&#xff1a; 点击 …

旋转的数组

分享今天看到的一个题目&#xff0c;不同思路解法 题目 思路1&#xff1a;时间复杂度0(N*k&#xff09; void rotate(int *a,int N,int k)//N为数组元素个数 { while(k--) { int tema[N-1]; for(int rightN-2;right>0;right--) { a[right1]a[right]; } a[0]tem; …

飞翔的小鸟——Java

一、创建文件、包、类、插入图片文件 二、app包 1、Gameapp类&#xff08;运行游戏&#xff09; package app;import main.GameFrame;public class Gameapp {public static void main(String[] args) {//游戏的入口new GameFrame();} } 三、main包 1、Barrier&#xff08…

【华为OD题库-037】跳房子2-java

题目 跳房子&#xff0c;也叫跳飞机&#xff0c;是一种世界性的儿童游戏游戏。参与者需要分多个回合按顺序跳到第1格直到房子的最后一格&#xff0c;然后获得一次选房子的机会&#xff0c;直到所有房子被选完&#xff0c;房子最多的人获胜。 跳房子的过程中&#xff0c;如果有踩…

React中如何解决点击<Tree>节点前面三角区域不触发onClick事件

React中如何解决点击节点前面三角区域不触发onClick事件&#xff0c;如何区别‘左边’和‘右边’区域点击逻辑呢&#xff1f;&#xff08;Tree引用开源组件TDesign&#xff09; 只需要在onClick里面加限制一下就行&#xff1a; <TreeexpandMutexactivabletransitiondata{t…