当前位置: 首页 > news >正文

简介Servlet

目录

一、maven中心库

二、简介Servlet

三、实现Servlet动态页面

1、创建一个maven项目

2、引入依赖 

3、创建目录结构 

 4、编写Servlet代码

5、打包 

6、部署 

7、验证程序 

四、Servlet的运行原理

五、Tomcat伪代码 

1、Tomcat初始化

a、让Tomcat先从指定的目录中找到要加载的Servlet类

b、 根据类加载结果,给这些类创建Servlet实例

c、实例创建完成之后,调用当前Servlet实例的init方法。

d、创建TCP socket,监听8080端口等待有客户端来连接

e、退出循环,依次调用调用Servlet的destroy的方法 

2、Tomcat处理请求 

3、Servlet 的 service 方法的实现 

六、Servlet关键API 

1、HttpServlet类 

2、HttpServletRequest 类

3、HttpServletResponse类


一、maven中心库

maven中心库是一个“工程管理/构建工具”,其核心功能有:

  • 管理依赖;
  • 构建/编译,这个过程会调用JDK;
  • 打包,就是可以将Java代码打包成jar文件或者war文件。

maven中心库能够将这些操作串起来。

可以不用下载安装maven,idea中内置了maven中心库。

二、简介Servlet

Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给 API, 帮助简单高效的开发一 个 web app.

动态页面就是每次用户输入的参数不同构造出的输出结果不同。例如百度的搜素页面,每次搜索的关键词不同得到的页面结果也不同。

三、实现Servlet动态页面

1、创建一个maven项目

创建一个项目,选择maven,点击next选择文件存储的路径即可。 

2、引入依赖 

进入maven库 https://mvnrepository.com下载servlet依赖,选择与自己JDK和tomcat匹配的版本。 

将对应的maven内容引入到创建的maven项目中的pom.xml中,并需要引入在depencies标签中。

   

在刚开始引入时会出现报红,但是当依赖自动下载完成之后字体就会恢复正常。

3、创建目录结构 

maven虽然已经有了一些目录:

  • src 表示源代码所在的目录。
  • main/java 表示源代码的根目录.,后续创建 .java 文件就放到这个目录中.
  • main/resources 表示项目的一些资源文件所在的目录. 此处暂时不关注.
  • test/java 表示测试代码的根目录. 此处暂时不关注。

但是还是不足以支撑写一个Servlet项目,还需要手动创建一些目录和文件。

web.xml文件内容如下:

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name>
</web-app>

 4、编写Servlet代码

在main/java目录下创建HelloServlet类,该类继承HttpServlet,然后重写了doGET方法。

@WebServlet("/hello")
public class HelloServlet  extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("hello world");resp.getWriter().write("hello world");}
}
  • doGet方法要做的工作就是根据请求计算出响应,这个方法在Tomcat收到一个HTTP GET请求的时候就会被Tomcat调用,也是一个回调函数。
  • 传入的HttpServletRequest代表的是一个HTTP请求,HttpServletResponse代表的是一个HTTP响应。
  • 在这个类上方加上 @WebServlet("/hello") 注解, 表示 Tomcat 收到的请求中, 路径为 /hello 的请求才会调用 HelloServlet 这个类的代码. (这个路径未包含 Context Path)。
  • resp.getWriter() 会获取到一个流对象, 通过这个流对象就可以写入一些数据, 写入的数据会被 构造成一个 HTTP 响应的 body 部分, Tomcat 会把整个响应转成字符串, 通过 socket 写回给浏览器.

这里就体现出如果一个类要被TomCat调用需要满足如下条件:

  • a) 创建的类需要继承自 HttpServlet
  • b) 这个类需要使用 @WebServlet 注解关联上一个 HTTP 的路径
  • c) 这个类需要实现 doXXX 方法.

5、打包 

需要先修改pom.xml,打包成一个war包,因为默认是jar包,再设置打包的文件名称。

  <!-- 打的包是一个war包,默认是jar包 --><packaging>war</packaging><build><!-- 表示打出的war包的名称--><finalName>hello</finalName></build>

然后双击package 进行打包。

 打包成功,并在target文件夹下生成了hello.war文件。

6、部署 

将上一步生成的hello.war文件拷贝到Tomcat的webapps目录下。

7、验证程序 

打开Tomcat服务器,使用127.0.0.1:8080/hello/hello在浏览器中进行访问。

绿色代表第一级目录,叫做Context Path,就是刚才拷贝到webapps目录下的war包文件名称。 

紫色代表第二级目录,叫做Servlet Path,是刚才创建的HelloServlet上面的@WebServlet("/hello")注解名称。

如果对代码进行了如下修改:

 resp.getWriter().write("hello world"+System.currentTimeMillis());

就需要再将5、6、7 再重复一遍,新修改的代码再次访问时才会生效。

这就引入了idea中的是smart Tomcat插件方便我们进行操作。

安装SmartTomcat插件:

 下载完成后进行apply应用。

然后点击运行 

 

出现如下信息表示成功: 然后再次在浏览器中访问即可:

 

每次刷新,时间戳也会发生改变。 

四、Servlet的运行原理

Servlet是属于上层建筑,下面的传输层、网络层、数据链路层和物理层属于经济基础。

Servlet是Tomcat提供的API,但是Tomcar其实也只是一个应用程序,是运行在用户态的普通进程,然后用户写代码(根据请求计算响应),通过Servlet和Tomcat进行交互,然后Tomcat进一步和浏览器之间进行网络传输。

                    

具体的过程也可以参考下图:

接收请求:用户会在浏览器输入一个URL,然后浏览器就出构造出相应的HTTP请求,这个HTTP请求会经过网络协议栈逐层封装成二进制的比特流,最后经过物理层的硬件设备转换成光信号或者电信号传输出去,然后这些信号再经过互联网的一系列网络设备到达服务器主机,服务器主机经过逐层分用还原得到HTTP请求交给Tomcat进行处理,然后利用HTTP请求的格式进行解析。根据 请求中的 Context Path 确定一个 webapp, 再通过 Servlet Path 确定一个具体的 类. 再根据当前请 求的方法 (GET/POST/...), 决定调用这个类的 doGet 或者 doPost 等方法. 此时我们的代码中的 doGet / doPost 方法的第一个参数 HttpServletRequest 就包含了这个 HTTP 请求的详细信息。

返回响应:doGet / doPost 执行完毕后, Tomcat 就会自动把 HttpServletResponse 这个我们刚设置 好的对象转换成一个符合 HTTP 协议的字符串, 通过 Socket 把这个响应发送出去.

此时响应数据在服务器的主机上通过网络协议栈层层 封装, 最终又得到一个二进制的 bit , 通过 物理层硬件设备转换成光信号/电信号传输出去. 这些承载信息的光信号/电信号通过互联网上的一系列网络设备, 最终到达浏览器主机,收到这些光信号/电信号, 又会通过网络协议栈逐层进行 分用, 层层解析, 最终还原成 HTTP 响应, 并交给浏览器处理. 浏览器也通过 Socket 读到这个响应(一个字符串), 按照 HTTP 响应的格式来解析这个响应. 并且把 body 中的数据按照一定的格式显示在浏览器的界面上.

五、Tomcat伪代码 

通过 "伪代码" 的形式描述了 Tomcat 初始化/处理请求 两部分核心逻辑.

1、Tomcat初始化

a、让Tomcat先从指定的目录中找到要加载的Servlet类

在前面部署的时候将Servlet代码编译成.class文件,然后打包成war包,并且拷贝到webapps文件夹里面,Tomcat就会从webapps里找到.class文件对应的Servlet类,然后根据需要加载 

b、 根据类加载结果,给这些类创建Servlet实例

// 这里要做的的是实例化出所有的 Servlet 对象出来;for (Class<Servlet> cls : allServletClasses) {// 这里是利用 java 中的反射特性做的// 实际上还得涉及一个类的加载问题,因为我们的类字节码文件,是按照约定的// 方式(全部在 WEB-INF/classes 文件夹下)存放的,所以 tomcat 内部是// 实现了一个自定义的类加载器(ClassLoader)用来负责这部分工作。Servlet ins = cls.newInstance();instanceList.add(ins);}

c、实例创建完成之后,调用当前Servlet实例的init方法。

 // 调用每个 Servlet 对象的 init() 方法,这个方法在对象的生命中只会被调用这一次;for (Servlet ins : instanceList) {ins.init();}

d、创建TCP socket,监听8080端口等待有客户端来连接

// 利用我们之前学过的知识,启动一个 HTTP 服务器// 并用线程池的方式分别处理每一个 RequestServerSocket serverSocket = new ServerSocket(8080);// 实际上 tomcat 不是用的固定线程池,这里只是为了说明情况ExecuteService pool = Executors.newFixedThreadPool(100);while (true) {Socket socket = ServerSocket.accept();// 每个请求都是用一个线程独立支持,这里体现了我们 Servlet 是运行在多线程环境下的pool.execute(new Runnable() {doHttpRequest(socket); });}

e、退出循环,依次调用调用Servlet的destroy的方法 

 // 调用每个 Servlet 对象的 destroy() 方法,这个方法在对象的生命中只会被调用这一次;for (Servlet ins : instanceList) {ins.destroy();}

2、Tomcat处理请求 

class Tomcat {void doHttpRequest(Socket socket) {// 参照我们之前学习的 HTTP 服务器类似的原理,进行 HTTP 协议的请求解析,和响应构建HttpServletRequest req = HttpServletRequest.parse(socket);HttpServletRequest resp = HttpServletRequest.build(socket);// 判断 URL 对应的文件是否可以直接在我们的根路径上找到对应的文件,如果找到,就是静态
内容// 直接使用我们学习过的 IO 进行内容输出if (file.exists()) {// 返回静态内容return;}// 走到这里的逻辑都是动态内容了// 根据我们在配置中说的,按照 URL -> servlet-name -> Servlet 对象的链条// 最终找到要处理本次请求的 Servlet 对象Servlet ins = findInstance(req.getURL());// 调用 Servlet 对象的 service 方法// 这里就会最终调用到我们自己写的 HttpServlet 的子类里的方法了try {ins.service(req, resp); } catch (Exception e) {// 返回 500 页面,表示服务器内部错误}}
}
  • Tomcat Socket 中读到的 HTTP 请求是一个字符串, 然后会按照 HTTP 协议的格式解析成一个HttpServletRequest 对象.
  • Tomcat 会根据 URL 中的 path 判定这个请求是请求一个静态资源还是动态资源. 如果是静态资源, 直接找到对应的文件把文件的内容通过 Socket 返回. 如果是动态资源, 才会执行到 Servlet 的相关 逻辑.
  • Tomcat 会根据 URL 中的 Context Path Servlet Path 确定要调用哪个 Servlet 实例的 service 方法.
  • 通过 service 方法, 就会进一步调用到我们之前写的 doGet 或者 doPost。

3、Servlet service 方法的实现 

class Servlet {public void service(HttpServletRequest req, HttpServletResponse resp) {String method = req.getMethod();if (method.equals("GET")) {doGet(req, resp);} else if (method.equals("POST")) {doPost(req, resp);} else if (method.equals("PUT")) {doPut(req, resp);} else if (method.equals("DELETE")) {doDelete(req, resp);} ......}
}

根据Servlet对象来调用service方法,在service方法的内部又会进一步地调用doGet等方法。

通过上述整套流程中,可以看出Servlet的生命周期主要有三个阶段:

init:初始化阶段,对象创建好之后就会执行init方法,用户可以重写这个方法来初始化逻辑。

service:在处理请求阶段来调用,每次请求都会调用service。

destroy:退出主循环,tomcat结束之前都会调用来释放资源。 

六、Servlet关键API 

当前主要使用HttpServlet类、HttpServletRequest类和HttpServletResponse类。

1、HttpServlet类 

在写代码创建的类都继承自HttpServlet类,这个类有以下常用方法:

创建一个MethodServlet类继承Servlet类,并且重写doPost方法。

@WebServlet("/method")
public class MethodServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");//将字符集指定为utf-8,避免乱码resp.getWriter().write("POST响应");}
}

但是对于POST请求在浏览器中通过URL无法直接访问,就还需要通过form表单或者ajax来进行实现。

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script>$.ajax({type: 'post',url: 'method',success: function(body){console.log(body);}});
</script>
</body>
</html>

这个html在目录文件的位置:

通过127.0.0.1:8080/test/test.html在浏览器访问,通过控制台可以看到如下结果:

2、HttpServletRequest 类

HttpServletRequest类对应的是一个Http请求,当 Tomcat 通过 Socket API 读取 HTTP 请求, 并且按照 HTTP 协议的格式把字符串解析成 HttpServletRequest 对象。其常用方法:

上述的方法都只是进行读操作。 

打印HTTP请求信息

@WebServlet("/show")
public class ShowRequestServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");StringBuilder respondBody = new StringBuilder();respondBody.append(req.getProtocol());respondBody.append("<br>");respondBody.append(req.getMethod());respondBody.append("<br>");respondBody.append(req.getRequestURI());respondBody.append("<br>");respondBody.append(req.getContextPath());respondBody.append("<br>");respondBody.append(req.getQueryString());respondBody.append("<br>");Enumeration<String> headerNames = req.getHeaderNames();while(headerNames.hasMoreElements()){String headerName = headerNames.nextElement();respondBody.append(headerName+" ");respondBody.append(req.getHeaders(headerName));respondBody.append("<br>");}resp.getWriter().write(respondBody.toString());}
}

 在浏览器通过url访问:

获取POST请求的参数 :

首先POST请求body的格式有:x-www-form-urlencoded,这种格式需要利用form表单来进行构造。

@WebServlet("/postParameter")
public class PostGetParameterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String userName = req.getParameter("userName");String pwd = req.getParameter("pwd");resp.getWriter().write("userName:"+userName+" pwd:"+pwd);}
}
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><form action="postParameter" method="post"><input type="text" name="userName"><input type="password" name="pwd"><input type="submit" value="提交"></form><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</body>
</html>

运行效果:

  

点击提交按钮之后: 

POST请求body格式还有json格式,但是这种格式需要引入第三方库Jackson,需要在maven中心库中找到然后引入到pom.xml之中,然后前端代码中需要在JS构造出body格式为json的请求。 

<body><input type="text" id="userName"><input type="text" id="password"><input type="button" value="提交" id="submit"><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"> </script><script>let userNameInput = document.querySelector('#userName');let passwordInput = document.querySelector('#password');let button = document.querySelector('#submit');button.onclick = function(){$.ajax({type:'post',url:'postJason',contentType:'application/json',data:JSON.stringify({userName:userNameInput.value,password:passwordInput.value}),success:function(body){console.log(body);}});}</script>
</body>

 后端代码使用Jackson,将请求从body中读取出来,并且解析为Java对象。

class User{public String userName;public String password;
}
@WebServlet("/postJason")
public class PostJasonServlet extends HttpServlet {//创建一个Jason对象private ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");User user = objectMapper.readValue(req.getInputStream(),User.class);resp.getWriter().write("userName:"+user.userName+" password:"+user.password);}
}

 运行效果:

提交之后可以在控制台上看到:

3、HttpServletResponse类

Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到 HttpServletResponse 对象中. 然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过 Socket 写回给浏览器.

其常见方法如下:

可以写一个自动刷新的页面: 

@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setHeader("Refresh","1");resp.getWriter().write("time"+System.currentTimeMillis());}
}

 运行效果:

相关文章:

简介Servlet

目录 一、maven中心库 二、简介Servlet 三、实现Servlet动态页面 1、创建一个maven项目 2、引入依赖 3、创建目录结构 4、编写Servlet代码 5、打包 6、部署 7、验证程序 四、Servlet的运行原理 五、Tomcat伪代码 1、Tomcat初始化 a、让Tomcat先从指定的目录…...

Learning C++ No.7

引言&#xff1a; 北京时间&#xff1a;20223/2/9/22:20&#xff0c;距离大一下学期开学还有2天&#xff0c;昨天收到好消息&#xff0c;开学不要考试了&#xff0c;我并不是害怕考试&#xff0c;考试在我心里&#xff0c;地位不高&#xff0c;可能只有当我挂了&#xff0c;才能…...

【MyBatis】第八篇:一级,二级缓存

其实缓存字面的意思就是将一些内容缓存下来&#xff0c;等下次使用的时候可以直接调用&#xff0c;通过数据库得到数据&#xff0c;有时候会使用相同的数据&#xff0c;所以mybatis自然也支持缓存。 而mybatis按照缓存的效果可以分两大类&#xff1a;一级缓存和二级缓存。 一…...

【大唐杯备考】——5G基站开通与调测(学习笔记)

&#x1f4d6; 前言&#xff1a;本期介绍5G基站开通与调测。 目录&#x1f552; 1. 概述&#x1f552; 2. 5G基站开通与调测基础&#x1f558; 2.1 3.5GHz单模100MHz配置&#xff08;S111&#xff09;&#x1f558; 2.2 3.5GHz单模100MHz配置&#xff08;S111111&#xff09;&a…...

redhat7 忘记root密码,重置办法

来自https://www.tracymc.cn/archives/802 亲测可用&#xff0c;太感谢了&#xff0c;在此记录一下&#xff0c;原文有图 1.启动的时候,在有启动项界面,相应启动项内核名称上按“e”; 2.进入后,找到linux16开头的地方,按“end”键或者controle到最后,输入rd.break,再按ctrlx进…...

QML- 对象属性

QML- 对象属性一、概述二、id 属性三、Property 属性1. 定义属性1. 自定义属性定义中的有效类型2. 为属性属性赋值1. 初始化时的值赋值2. 命令式赋值3. 静态值和绑定表达式值4. 类型安全5. 特殊属性类型1. 对象列表属性2. 分组属性6. 属性别名1. 属性别名的注意事项2. 属性别名…...

将.js文件转成vue标签结构的样式

例如&#xff1a;下图所示&#xff1a; 依次识别获取.js文件中的tag和props&#xff0c;可以理解为字符串拼接&#xff0c;将整个vue的标签结构看作是一个字符串。 话不多说&#xff0c;先放上完整代码&#xff0c;思路看代码备注。&#xff08;自己实现的时候&#xff0c;可以…...

前端知识点复盘

组件和jsx <body><div id"root"></div><script type"text/babel">const root ReactDOM.createRoot(document.getElementById("root"))class App extends React.Component {render() {return (<div> <h1>s…...

前端JavaScript获取图片文件的真实格式

常见方式判断图片格式 当我们进行前端开发&#xff0c;需要处理图片上传功能&#xff0c;针对图片格式做判断时&#xff0c;常规的方法都是使用文件后缀名来判断&#xff0c;如下代码所示&#xff1a; input.addEventListener(change, (e) > {const file e.target.files[…...

今天面了一个来华为要求月薪25K,明显感觉他背了很多面试题...

最近有朋友去华为面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…...

11 Advanced CNN

文章目录GoogLeNetInception Module1x1 Conv计算效果代码实现总结ResNet (残差网络)问题引入梯度消失与传统神经网络的比较代码实现课程来源&#xff1a; 链接对于前篇中所提到问题&#xff0c;设计出的是一种类似于LeNet5的线性结构&#xff0c;而对于大多数问题&#xff0c;简…...

亿级高并发电商项目---万达商城项目搭建(二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…...

UML术语标准和分类

一、UML术语标准 1&#xff0e;中文UML术语标准 中国软件行业协会&#xff08;CSIA&#xff09;与日本UML建模推进协会&#xff08;UMTP&#xff09;共同在中国推动的UML专家认证&#xff0c;两个协会共同颁发认证证书、两国互认&#xff0c;CSIA与UMTP共同推出了UML中文术语…...

LeetCode 刷题系列 -- 151. 反转字符串中的单词

给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。注意&#xff1a;输入字符串 s中可能会存在前导空格、尾随空格或…...

二十二、Gtk4-ListView

GTK 4添加了新的列表对象GtkListView、GtkGridView和GtkColumnView。这个新特性在Gtk API参考—列表小构件概述中有描述。 GTK 4还有其他实现列表的方法。它们是GtkListBox和GtkTreeView&#xff0c;它们是从GTK 3接管的。在Gtk开发博客中有一篇关于Matthias Clasen所写的列表…...

ASP.NET Core3.1实战教程---基于Jquery单文件上传

这个必须记录一下费劲啊&#xff01;废了我2天的时间&#xff0c;昔日的net快速已经没落....就文件上传都这么费劲。 先说下要求&#xff08;在线apk文件上传实现手机端整包更新&#xff09;&#xff1a; 1、为了简化需求文件上传和数据提交分开执行 2、选完文件后按钮变成上…...

10 卷积神经网络CNN(基础篇)

文章目录全连接CNN过程卷积过程下采样过程全连接层卷积原理单通道卷积多通道卷积改进多通道总结以及课程代码卷积改进PaddingStride下采样过程大池化层&#xff08;Max Pooling&#xff09;简单卷积神经网络的实现课程代码本篇课程来源&#xff1a; 链接部分文本来源参考&#…...

Windows下LuaBridge2.8的环境配置及简单应用

Windows下LuaBridge2.8的环境配置及简单应用 LuaBridge2.8下载链接&#xff1a; https://github.com/vinniefalco/LuaBridge/tags 关于Lua的环境配置可参考以下链接&#xff08;这里不做简述&#xff09;&#xff1a; https://ufgnix0802.blog.csdn.net/article/details/125341…...

每天10个前端小知识 【Day 10】

前端面试基础知识题 1. es5 中的类和es6中的class有什么区别&#xff1f; 在es5中主要是通过构造函数方式和原型方式来定义一个类&#xff0c;在es6中我们可以通过class来定义类。 class类必须new调用&#xff0c;不能直接执行。 class类执行的话会报错&#xff0c;而es5中…...

【LeetCode】1223. 掷骰子模拟

1223. 掷骰子模拟 题目描述 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数。 不过我们在使用它时有个约束&#xff0c;就是使得投掷骰子时&#xff0c;连续 掷出数字 i 的次数不能超过 rollMax[i]&#xff08;i 从 1 开始编号&#xff09;。 现在&#xff0c;…...

SPSS数据分析软件的安装与介绍(附网盘链接)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…...

2022年38女神节大促美妆、珠宝、母婴、保健电商数据回顾

近期&#xff0c;我们陆续接收到了品牌商家朋友们对于2022年女神节大促期间部分品类的数据需求&#xff0c;希望能对今年的大促活动有一个更宏观的认知、更精准的预测&#xff0c;从而拿到更好的数据效果。 为此&#xff0c;在距离大促开启一个月的备货阶段&#xff0c;鲸参谋决…...

Java笔记-线程同步

目录线程的同步---以三个窗口售票100张为例方式一&#xff1a;同步代码块方式二&#xff1a;同步方法使用同步机制的作用&#xff1a;线程的同步—以三个窗口售票100张为例 &#xff08;1&#xff09;问题&#xff1a;卖票的过程出现重票和错票 &#xff08;2&#xff09;原因…...

通过python 调用OpenAI api_key提交问题解答

通过python 调用OpenAI api_key提交问题解答✨可以通过网页版的jupyter notebook调用&#xff0c;也可以通过spyder窗口等IDE窗口. &#x1f33c;通过python 调用OpenAI api_key接口&#xff0c;可以避免国内网页不能访问的问题。前提是需要自己已经注册了OpenAI帐号&#xff…...

图表控件LightningChart .NET再破世界纪录,支持实时可视化 1 万亿个数据点

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…...

什么是响应性?

响应性&#xff1a; 这个术语在今天的各种编程讨论中经常出现&#xff0c;但人们说它的时候究竟是想表达什么意思呢&#xff1f;本质上&#xff0c;响应性是一种可以使我们声明式地处理变化的编程范式。一个经常被拿来当作典型例子的用例即是 Excel 表格&#xff1a; 这里单元…...

黑马】后台管理176-183

一、新建订单管理的分支二、创建一个订单管理的vue文件进行组件页面的路由配置import Order from ../components/order/Order.vue{path:/orders,component:Order},注意上面的components不要忘记少加一个s&#xff01;三&#xff0c;获取后台数据面包屑导航粘贴过来文本输入框&a…...

Typescript - 类型守卫(typeof / in / instanceof / 自定义类型保护的类型谓词)通俗易懂详细教程

前言 类型守卫用于获取变量类型信息&#xff0c;通常使用在条件块语句中。类型守卫是返回布尔值的常规函数&#xff0c;接受一个类型并告诉 TypeScript 是否可以缩小到更具体的类型。类型守卫具有唯一的属性&#xff0c;可以确保测试的值返回的是布尔值类型。 TypeScript 使用了…...

6.8 左特征向量

特征值很复杂&#xff0c;除了普通的特征向量外&#xff0c;还有左特征向量和广义特征向量。先说说比较容易的左特征向量吧。它是这样定义的&#xff0c;AAA是一个矩阵&#xff0c;λ\lambdaλ是它的一个特征值&#xff0c;下面的向量yyy就是矩阵关于特征值的左特征向量left ei…...

10个自动化测试框架,测试工程师用起来

软件行业正迈向自主、快速、高效的未来。为了跟上这个高速前进的生态系统的步伐&#xff0c;必须加快应用程序的交付时间&#xff0c;但不能以牺牲质量为代价。快速实现质量是必要的&#xff0c;因此质量保证得到了很多关注。为了满足卓越的质量和更快的上市时间的需求&#xf…...