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

【JAVA】Servlet开发

目录

HttpServlet

HttpServletRequest

 HttpServletResponse

错误页面

设置网页自动刷新时间

构造重定向相应

js发起http请求 

服务器端对js发起的http请求进行处理

前端获取后端数据,添加到当前页面的末尾,代码示例: 

 前后端交互:引入数据库(存储数据)

1)引入数据库依赖

​编辑

​编辑2)建库建表

3)编写数据库代码

整体代码 

利用Cookie和Session实现登录逻辑

1.登录页面(html)

2.通过一个Servlet处理上述的登录请求

3.网站主页,通过另一个servlet生成的动态页面


掌握如下三个类,就可以完成Servlet的大部分开发了

  1. HttpServlet
  2. HttpServletRequest
  3. HttpServletResponse

URI:唯一资源标识符

URL:唯一资源定位/地址符

HttpServlet

HttpServlet继承这个类,重写里面的方法,目的就是为了把咱们子集定义的代码,“插入到”tomcat中,HttpServlet的常用方法如下:

方法名称
调用时机
init
HttpServlet 实例化之后被调用一次,初始化
destory
HttpServlet 实例不再使用的时候调用一次,释放资源
service
收到 HTTP 请求的时候调用
doGet
收到 GET 请求的时候调用 ( service 方法调用 )
doPost
收到 POST 请求的时候调用 ( service 方法调用 )
doPut/doDelete/doOptions/...
收到其他请求的时候调用 ( service 方法调用 )
我们实际开发的时候主要重写 doXXX 方法 , 很少会重写 init / destory / service
init还是比较有用的;service一般会doGet/doPost替代;destory一般用不上,说了不算,算了不说,因为一个Servlet不用了,说明Tomcat要关闭了,而Tomcat关闭有两种方式:
  1. 直接干掉Tomcat进程,完全来不及调用destory的;
  2. 通过8005管理端口,给Tomcat发送一个“停机”指令,这个时候是能够执行destory的。

init / destory / service 这三个方法都不需要手动调用,会被tomcat在合适的时机,自动调用,咱们写好代码,让别人来帮忙调用,这种方式就叫做 “框架” ,也就是一个程序的主体部分,都已经被其他大佬们写完了,有些细节内容,允许咱们插入咱们自己写的自定义的逻辑.

HttpServletRequest

Tomcat 通过 Socket API 读取 HTTP 请求 ( 字符串 ), 并且按照 HTTP 协议的格式把字符串解析成
HttpServletRequest 对象 .
核心方法
方法
描述
String getProtocol()
返回请求协议的名称和版本。
String getMethod()
返回请求的 HTTP 方法的名称,例如, GET POST PUT
String getRequestURI()
从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该
请求的 URL 的一部分。
String getContextPath()
返回指示请求上下文的请求 URI 部分。
String getQueryString()
返回包含在路径后的请求 URL 中的查询字符串。
InputStream
getInputStream()
用于读取请求的 body 内容 . 返回一个 InputStream 对象 .
Enumeration
getParameterNames()
返回一个 String 对象的枚举,包含在该请求中包含的参数的名
称。
String getParameter(String
name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回
null
String[]
getParameterValues(String
name)
返回一个字符串对象的数组,包含所有给定的请求参数的值,
如果参数不存在则返回 null
Enumeration
getHeaderNames()
返回一个枚举,包含在该请求中包含的所有的头名。
String getHeader(String
name)
以字符串形式返回指定的请求头的值。
String
getCharacterEncoding()
返回请求主体中使用的字符编码的名称。
String getContentType()
返回请求主体的 MIME 类型,如果不知道类型则返回 null
int getContentLength()
以字节为单位返回请求主体的长度,并提供输入流,或者如果
长度未知则返回 -1

上述的方法都是get系列方法(都是读方法),没有set系列(没有写方法),当前拿到的HttpServletRequest,这些数据的内容已经确定下来了,程序员是不应该修改的.

前端将数据交给后端

除了query string之外,还可以通过http请求的body来传递参数(POST)。

(1)直接通过form表单

        (body的格式就是query string的格式)

        Content-Type:application/x-www-form-urlencoded

(2)直接使用json

        (body的格式就是json)

        Content-Type:application/json

这三种方式本质上是等价的,都是把键值对数据交给服务器,前两种方法servlet天然支持的,json这种方法需要引入第三方库。

在java中,json的第三方库是非常多的,这里我们使用jackson(jackson是spring官方推荐的库,也被spring集成起来了)

步骤如下:

1)下载导入jackson到项目中,通过maven

Maven Repository: Search/Browse/Explore (mvnrepository.com)

(2)使用jackson

一个类两个方法

ObjectMapper

  • 把json字符串,映射成java的一个对象(read方法)
  • 把一个java对象,映射成json字符串(write方法)
Request request = objectMapper.readValue(req.getInputStream(),Request.class);

1.核心工作就是把json字符串,映射成java 对象,参数就是json字符串(json字符串是在http的body中的,就需要通过HttpServletRequest中的getInputStream来获取到)

此处把这个流对象直接传给readValue,readValue内部就会读取InputStream中的所有数据(http请求的body,也就是json字符串),进一步尝试解析

2.按照json的格式,进行解析,把json字符串,解析成map(键值对)

3.把map转换成对象,在方法的第二个参数

如下示例:

import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.ObjectInputValidation;class Request()
{public String username;public String password;
}
class Response{public boolean ok;
}@WebServlet("/json")
public class JsonParameterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ObjectMapper objectMapper = new ObjectMapper();Request request = objectMapper.readValue(req.getInputStream(),Request.class);System.out.println("username="+request.username);System.out.println("password="+request.password);Response response=new Response();response.ok=true;//把响应对象转成json字符串String respJson=objectMapper.writeValueAsString(response);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}
}

 HttpServletResponse

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

核心方法

方法
描述
void setStatus(int sc)
为该响应设置状态码
void setHeader(String name, String value)
设置一个带有给定的名称和值的 header. 如果 name 已经存在 , 则覆盖旧的值
void addHeader(String
name, String value)
添加一个带有给定的名称和值的 header. 如果 name 已经存在 , 不覆盖旧的值, 并列添加新的键值对
void setContentType(String type)
设置被发送到客户端的响应的内容类型。
void setCharacterEncoding(String
charset)
设置被发送到客户端的响应的字符编码( MIME 字符集)例如,UTF-8
void sendRedirect(String location)
使用指定的重定向位置 URL 发送临时重定向响应到客户端
PrintWriter getWriter()
用于往 body 中写入文本格式数据
OutputStream getOutputStream()
用于往 body 中写入二进制格式数据

错误页面

resp.sendError(404,"这个页面是一个错误页面")

设置网页自动刷新时间

resp.setHeader("refresh","1");

构造重定向相应

resp.setStatus(302);
resp.setHeader("Location","https://www.baidu.com");

header需要有一个Location属性,描述要跳转到哪里 ,除了这种写法外,还有如下另一种方法:

resp.sendRedirect("https://www.baidu.com");

使用ajax,需要先引入JQeury第三方库

jquery (v3.7.1) - jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。它提供的 API 易于使用且兼容众多浏览器,这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。 | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务icon-default.png?t=N7T8https://www.bootcdn.cn/jquery/

链接如上,选择如下链接

在script标签引入jquery

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

js发起http请求 

        // 把用户填写的内容,发送给服务器,让服务器来保存// $ 是jquery提供的全局变量,ajax是$的一个方法// ajax的参数是一个js对象,可以有很多属性let body={"from":from,"to":to,"message":message}//上述body是一个js对象,还需要转换成json字符串let jsonString = JSON.stringify(body)$.ajax({type:'post',url:'message',contentType:'application/json; charset=utf8',data:jsonString,//这里的body与上面的body不是同一个,是响应报文的正文success:function(body){// 这个回调就是收到响应之后要执行的代码了}});

此处success回调函数,不是立即执行的,而是在浏览器收到服务器返回的成功这样的响应的时候,才会执行function ,这个函数的第一个参数,是响应数据的body中的内容。

服务器端对js发起的http请求进行处理

import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;class Message{
//    确保java代码中类的属性名字和json中的属性名字保持一致,才能够自动填充public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();private List<Message> messageList = new ArrayList<>();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//使用jackson读取前端发来的数据,把这个数据保存到服务器这边Message message = objectMapper.readValue(req.getInputStream(),Message.class);System.out.println("请求中收到的message:"+ message);//保存数据最简单的是直接内存中存储,使用集合类//但是这样做一旦重启服务器,一切数据都没有了,一般存储到数据库中messageList.add(message);//返回一个响应resp.setStatus(200);resp.getWriter().write("ok");}
}

这里启动服务器后,不能直接访问/message,需要访问.html路径

当浏览器要向服务器获取资源, 服务器方使用List类型的数组存储历史数据,转成的json字符串就是一个json数组,jackson自动遍历List里的每个元素,把每个元素分别转成json字符串。

    @Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setStatus(200);resp.setContentType("application/json;charset=utf-8");String respJson = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respJson);}

上述代码setStatus和setContentType必须在getWriter前面,否则不会生效 

    $.ajax{

        type:'get',

        url:'message',

        success:function(body){

            //处理服务器返回的响应数据。(json格式的数组)

        }

    }

//当响应中,header带有ContentType:"application/json",JQuery就会自动把json字符串解析成js对象了,如果没有带ContentType:"application/json"就需要通过js代码JSON.parse方法手动把json字符串转成js对象

前端获取后端数据,添加到当前页面的末尾,代码示例: 

    $.ajax{type:'get',url:'message',success:function(body){//处理服务器返回的响应数据。(json格式的数组)//由于响应中已经有ContentType:"application/json"了,就不需要使用parse方法手动转换了//body = JSON.parse(body);//拿到 container这个元素let containerDiv = document.querySelector('.container');//处理服务器返回的响应数据。(json格式的数组了)for(let i=0;i<body.length;i++){//body是一个数组,此时的message也就是js对象了//这个message对象里有三个属性:from、to、messagelet message = body[i];//根据message对象构建html片段,把这个片段给显示到网页上//createElement 方法就能构造一个html标签//此时就得到了<div></div>let div = document.createElement('div');//还需要给这个div设置一个属性div.className = 'row';//设置内容div.innerHTML = message.from + " 对 " + message.to + " 说:" +message.message;//将这个div添加到containerDiv末尾containerDiv.appendChild(div);}}

 前后端交互:引入数据库(存储数据)

1)引入数据库依赖

Maven仓库链接

Maven Repository: Search/Browse/Explore (mvnrepository.com)

搜索MySQL,选择如下:

这里选择5.1.47版本

复制如下代码

复制到pom.xml里


2)建库建表

create database if not exists message_wall charset utf8;
use message_wall;
-- 删表的目的是为了防止之前数据库里有一样的表
drop table if exists message;
use message_wall;
create table message(`from` varchar(1024),`to` varchar(1024),message varchar(1024));

3)编写数据库代码

// 1. 创建数据源
private DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3307/message_wall?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("root");
// 2. 建立连接
Connection connection = dataSource.getConnection();// 3. 构造 SQL
String sql = "insert into message values(?, ?, ?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, message.from);
statement.setString(2, message.to);
statement.setString(3, message.message);// 3. 执行 SQL
statement.executeUpdate();// 4. 回收资源
statement.close();
connection.close();

整体代码 

MessageServlet.java

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;class Message {public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();// 引入数据库, 此时 messageList 就不再需要了.// private List<Message> messageList = new ArrayList<>();private DataSource dataSource = new MysqlDataSource();@Overridepublic void init() throws ServletException {// 1. 创建数据源((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3307/message_wall?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("root");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 读取前端发来的数据, 把这个数据保存到服务器这边.Message message = objectMapper.readValue(req.getInputStream(), Message.class);System.out.println("请求中收到的 message: " + message);// 最简单的办法, 直接在内存中保存. 可以使用一个集合类, 把所有收到的 message 都存到内存中.// 很明显, 保存到内存, 并非是一个非常合理的办法. 后续一旦重启服务器, 数据丢失了.// 相比之下, 把这个数据持久化存储到数据库中, 更科学的.// messageList.add(message);// 插入数据库try {save(message);} catch (SQLException e) {throw new RuntimeException(e);}// 返回一个响应resp.setStatus(200);resp.getWriter().write("ok");// resp.setContentType("application/json");// resp.getWriter().write("{ ok: true }");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 通过这个方法来处理当前获取消息列表的 get 请求. 不需要解析参数, 直接返回数据即可.resp.setStatus(200);resp.setContentType("application/json; charset=utf8");// 从数据库查询List<Message> messageList = null;try {messageList = load();} catch (SQLException e) {throw new RuntimeException(e);}String respJson = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respJson);}private void save(Message message) throws SQLException {// 通过这个方法把 message 插入到数据库中// 1. 建立连接Connection connection = dataSource.getConnection();// 2. 构造 SQLString sql = "insert into message values(?, ?, ?)";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1, message.from);statement.setString(2, message.to);statement.setString(3, message.message);// 3. 执行 SQLstatement.executeUpdate();// 4. 回收资源statement.close();connection.close();}private List<Message> load() throws SQLException {// 通过这个方法从数据库读取到 message.// 1. 建立连接Connection connection = dataSource.getConnection();// 2. 构造 SQLString sql = "select * from message";PreparedStatement statement = connection.prepareStatement(sql);// 3. 执行 sqlResultSet resultSet = statement.executeQuery();// 4. 遍历结果集合List<Message> messageList = new ArrayList<>();while (resultSet.next()) {Message message = new Message();message.from = resultSet.getString("from");message.to = resultSet.getString("to");message.message = resultSet.getString("message");messageList.add(message);}// 5. 回收资源resultSet.close();statement.close();connection.close();// 6. 返回 messageListreturn messageList;}
}

 message_wall.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>表白墙</title><style>/* * 通配符选择器, 是选中页面所有元素 */* {/* 消除浏览器的默认样式. */margin: 0;padding: 0;box-sizing: border-box;}.container {width: 600px;margin: 20px auto;}h1 {text-align: center;}p {text-align: center;color: #666;margin: 20px 0;}.row {/* 开启弹性布局 */display: flex;height: 40px;/* 水平方向居中 */justify-content: center;/* 垂直方向居中 */align-items: center;}.row span {width: 80px;}.row input {width: 200px;height: 30px;}.row button {width: 280px;height: 30px;color: white;background-color: orange;/* 去掉边框 */border: none;border-radius: 5px;}/* 点击的时候有个反馈 */.row button:active {background-color: grey;}</style><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<div class="container"><h1>表白墙</h1><p>输入内容后点击提交, 信息会显示到下方表格中</p><div class="row"><span>谁: </span><input type="text"></div><div class="row"><span>对谁: </span><input type="text"></div><div class="row"><span>说: </span><input type="text"></div><div class="row"><button id="submit">提交</button></div><!-- <div class="row">xxx 对 xx 说 xxxx</div> -->
</div><script>// 实现提交操作. 点击提交按钮, 就能够把用户输入的内容提交到页面上显示.// 点击的时候, 获取到三个输入框中的文本内容// 创建一个新的 div.row 把内容构造到这个 div 中即可.let containerDiv = document.querySelector('.container');let inputs = document.querySelectorAll('input');let button = document.querySelector('#submit');button.onclick = function() {// 1. 获取到三个输入框的内容let from = inputs[0].value;let to = inputs[1].value;let msg = inputs[2].value;if (from == '' || to == '' || msg == '') {return;}// 2. 构造新 divlet rowDiv = document.createElement('div');rowDiv.className = 'row message';rowDiv.innerHTML = from + ' 对 ' + to + ' 说: ' + msg;containerDiv.appendChild(rowDiv);// 3. 清空之前的输入框内容for (let input of inputs) {input.value = '';}// 4. 把用户填写的内容, 发送给服务器. 让服务器来保存.//    $ 是 jquery 提供的全局变量. ajax 就是 $ 的一个方法.//    ajax 的参数是一个 js 对象, 可以有很多属性let requestBody = {"from": from,   // from 变量里的值, 就是第一个输入框的内容, "张三""to": to,       // to 变量的值, 就是第二个输入框的内容, "李四""message": msg  // msg 变量的值, 就是第三个输入框的内容, "我喜欢你很久了"};// 上述 body 是一个 js 对象, 还需要转成 json 字符串.let jsonString = JSON.stringify(requestBody);$.ajax({type: 'post',url: 'message',contentType: 'application/json; charset=utf8',data: jsonString,success: function(responseBody) {// 这个回调就是收到响应之后要执行的代码了.// 前端使用 console.log 打印日志到控制台. (chrome 开发者工具的控制台)console.log("responseBody: " + responseBody);}});}// 直接在 script 里面写的 js 代码, 就是在页面加载时被执行到的.// 发起一个 get 请求, 从服务器获取到数据// get 请求不需要 body, 也就不需要上述 data 和 contentType 属性了.$.ajax({type: 'get',url: 'message',success: function(body) {// 由于响应中已经有 Content-Type: application/json 了, 就不需要使用 parse 方法手动转换了.// body = JSON.parse(body);// 拿到 container 这个元素let containerDiv = document.querySelector('.container');// 处理服务器返回的响应数据. (json 格式的数组了)for (let i = 0; i < body.length; i++) {// body 是一个数组, 此时 message 也就是 js 对象了.// 这个 message 对象里, 有三个属性, from, to, messagelet message = body[i];// 根据 message 对象构建 html 片段, 把这个片段给显示到网页上.// createElement 方法就能构造出一个 html 标签.// 此时就得到了 <div></div>let div = document.createElement('div');// 还需要往里面设置一个 属性 , class="row" (设置这个属性, 是为了让 css 能够给这个元素设置一些样式)// 此时就得到了 <div class="row"></div>div.className = 'row';// 给这个 div 里设置内容// 此时就得到了 <div class="row">张三 对 李四 说: 我喜欢你很久了</div>div.innerHTML = message.from + " 对 " + message.to + " 说: " + message.message;// 把 div 添加到 containerDiv 的末尾containerDiv.appendChild(div);}}});
</script>
</body>
</html>

利用Cookie和Session实现登录逻辑

Cookie是客户端存储数据的机制

Session是服务器存储数据的机制(不算持久化存储)

1.登录页面(html)

2.通过一个Servlet处理上述的登录请求

通过这个Servlet读取用户名和密码,并且验证是否登录成功。

如果登陆成功,就会给当前用户,创建一个会话 ,并且把得到的sessionid,通过cooki返回给客户端,客户端就把cookie保存起来了。

3.网站主页,通过另一个servlet生成的动态页面

在这个页面中,就会把刚才这里的用户数据给显示到页面上。

getSession(true)

这个方法,就是根据请求的cookie中的sessionid,查询服务器的hash表,找到对应的session对象。如果cookie中没有sessionid(首次登录的时候,就是没有的)或者sessionid没有查找到对应的session对象,就可以创建出一个session对象出来。

参数为true,允许不存在时自动创建;false不能创建,直接返回null

//可以给会话中保存一些自定义的数据,通过Attribute的方式来保存
HttpSession session = req.getSession(true);
//此处Atrribute也是键值对,这里的内容存储什么都可以
session.setAttribute("username",username);
session.setAttribute("loginTime",System.currentTimeMillis());
//此处相当于登录成功,让页面跳转网站首页
resp.sendRedirect("index");

此处的getSession会创建新会话

1)生成sessionid和HttpSession对象

2)把上述sessionid和HttpSession对象保存到内存hash表中

3)把sessionid设置到响应报文的header中的 Set-Cookie字段

浏览器拿到响应,就会把这个Set-Cookie的内容保存到浏览器的Cookie中 。

相关文章:

【JAVA】Servlet开发

目录 HttpServlet HttpServletRequest HttpServletResponse 错误页面 设置网页自动刷新时间 构造重定向相应 js发起http请求 服务器端对js发起的http请求进行处理 前端获取后端数据&#xff0c;添加到当前页面的末尾&#xff0c;代码示例&#xff1a; 前后端交互&…...

k8s helm 删除 tiller

kuberneter 上面装了 helm 想卸载还并不是那么简单, 参考 stackoverflow 回复 kubectl get -n kube-system secrets,sa,clusterrolebinding -o name|grep tiller|xargs kubectl -n kube-system delete kubectl get all -n kube-system -l apphelm -o name|xargs kubectl dele…...

Python入门(小白友好)

知识图谱 搭建环境 安装Python:Download Python | Python.org 安装PyCharm:Download PyCharm: The Python IDE for data science and web development by JetBrains 注意:专业版本是收费的,新手小白使用社区版(community)即可 创建第一个项目: 一些PyCharm的设置(也适用…...

【数据结构与算法】:非递归实现快速排序、归并排序

&#x1f525;个人主页&#xff1a; Quitecoder &#x1f525;专栏&#xff1a;数据结构与算法 上篇文章我们详细讲解了递归版本的快速排序&#xff0c;本篇我们来探究非递归实现快速排序和归并排序 目录 1.非递归实现快速排序1.1 提取单趟排序1.2 用栈实现的具体思路1.3 代码…...

2024-3-18-C++day6作业

1>思维导图 2>试编程 要求: 封装一个动物的基类&#xff0c;类中有私有成员&#xff1a;姓名&#xff0c;颜色&#xff0c;指针成员年纪 再封装一个狗这样类&#xff0c;共有继承于动物类&#xff0c;自己拓展的私有成员有&#xff1a;指针成员&#xff1a;腿的个数&a…...

【OceanBase诊断调优】—— 敏捷诊断工具obdiag一键分析OB集群日志设计与实践

最近总结一些诊断OCeanBase的一些经验&#xff0c;出一个【OceanBase诊断调优】专题&#xff0c;也欢迎大家贡献自己的诊断OceanBase的方法。 1. 前言 obdiag定位为OceanBase敏捷诊断工具。1.2版本的obdiag支持诊断信息的一键收集&#xff0c;光有收集信息的能力&#xff0c;…...

python 调用redis创建查询key

部署redis apiVersion: apps/v1 # 描述api版本&#xff0c;默认都用这个 kind: Deployment # 资源类型&#xff0c;可以配置为pod&#xff0c;deployment&#xff0c;service&#xff0c;statefulset等等 metadata: # deployment相关的元数据&#xff0c;用于描述deployment的…...

归并排序思路

归并排序是一种经典的分治算法&#xff0c;其基本思路可以简述为以下几步&#xff1a; 分解&#xff1a;将待排序的数组递归地分解成较小的子数组&#xff0c;直到每个子数组只包含一个元素为止。这里采用分治的思想&#xff0c;将问题不断地划分为规模更小的子问题。 合并&am…...

【蓝桥杯选拔赛真题65】python输出三个字符 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python输出3个字符 一、题目要求 1、编程实现 2、输入输出...

K8S日志收集方案-EFK部署

EFK架构工作流程 部署说明 ECK (Elastic Cloud on Kubernetes)&#xff1a;2.7 Kubernetes&#xff1a;1.23.0 文件准备 crds.yaml 下载地址&#xff1a;https://download.elastic.co/downloads/eck/2.7.0/crds.yaml operator.yaml 下载地址&#xff1a;https://download.e…...

js基础语法大全(时间戳,uuid,字符串转json)

目录 一、获取时间戳二、获取uuid三、字符串转json格式 一、获取时间戳 var times Math.round(new Date().getTime()/1000).toString(); //获取 10位 时间戳 console.log(times);二、获取uuid function guid() {return xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx.replace(/[xy]…...

uView LoadingIcon 加载动画

此组件为一个小动画&#xff0c;目前用在uView的loadMore加载更多等组件的正在加载状态场景。 #平台差异说明 App&#xff08;vue&#xff09;App&#xff08;nvue&#xff09;H5小程序√√√√ #基本使用 通过mode设定动画的类型&#xff0c;circle为圆圈的形状&#xff0…...

Elasticsearch使用Kibana进行基础操作

一、Restful接口 Elasticsearch通过RESTful接口提供与其进行交互的方式。在ES中&#xff0c;提供了功能丰富的RESTful API的操作&#xff0c;包括CRUD、创建索引、删除索引等操作。你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上&#xff0c;你甚至可以使用 curl …...

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展应用教程

原文链接&#xff1a;“SRP模型”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI 指数的生态质量评价及拓展应用教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247597452&idx5&snf723d9e5858a269d00e15dbe2c7d3dc0&chksmfa823c6…...

【Windows 常用工具系列 15 -- VMWARE ubuntu 安装教程】

文章目录 安装教程镜像下载 工具安装 安装教程 安装教程参考链接&#xff1a;https://blog.csdn.net/Python_0011/article/details/131619864 https://linux.cn/article-15472-1.html 激活码 VMware 激活码连接&#xff1a;https://www.haozhuangji.com/xtjc/180037874.html…...

SpringSecurity(SpringBoot2.X版本实现)

资料来源于 SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权 侵权删 目录 介绍 快速开始 认证 认证流程 登录校验流程 SpringSecurity完整流程 认证流程详解 代码实现 准备工作 mysql mybatis-plus redis 统一返回类 核心代码 密码加密存…...

仿牛客项目Day8:社区核心功能2

显示评论 数据库 entity_type代表评论的目标类型&#xff0c;评论帖子和评论评论 entity_id代表评论的目标id&#xff0c;具体是哪个帖子/评论 targer_id代表评论指向哪个人 entity public class Comment {private int id;private int userId;private int entityType;priv…...

Vmware虚拟机配置虚拟网卡

背景 今天同事咨询了我一个关于虚拟机的问题&#xff0c;关于内网用Vmware安装的虚拟机&#xff0c;无法通过本机访问虚拟上的Jenkins的服务。   验证多次后发现有如下几方面问题。 Jenkins程序包和JDK版本不兼容&#xff08;JDK1.8对应Jenkins不要超过2.3.57&#xff09;虚…...

双向链表代码(带哨兵位循环/不带哨兵位不循环

以下代码全为本人所写&#xff0c;如有错误&#xff0c;很正常&#xff0c;还请指出&#xff0c; 目录 带哨兵位循环 test.c DLList.c DLList.h 不带哨兵位不循环 test.c DLList.c DLList.h 带哨兵位循环 test.c #define _CRT_SECURE_NO_WARNINGS#include"DLlist.h&…...

C语言自学笔记13----C语言指针与函数

C 语言指针与函数 在C语言编程中&#xff0c;也可以将地址作为参数传递给函数。 要在函数定义中接受这些地址&#xff0c;我们可以使用指针。这是因为指针用于存储地址。让我们举个实例&#xff1a; 示例&#xff1a;通过引用致电 #include <stdio.h> void swap(int n1, …...

每日五道java面试题之mybatis篇(一)

目录&#xff1a; 第一题. MyBatis是什么&#xff1f;第二题. ORM是什么?第三题. 为什么说Mybatis是半自动ORM映射工具&#xff1f;它与全自动的区别在哪里&#xff1f;第四题. 传统JDBC开发存在的问题第五题. JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的…...

一文解读ISO26262安全标准:概念阶段

一文解读ISO26262安全标准&#xff1a;概念阶段 1 相关项定义2 安全生命周期启动3 危害分析和风险评估 HaRa4 功能安全概念 由上一篇文章知道&#xff0c;安全生命周期包含概念阶段、产品开发阶段、生产发布后续阶段。本文详细解读概念阶段要进行的安全活动。 本部分规定了车辆…...

微信小程序调用百度智能云API(菜品识别)

一、注册后生成应用列表创建应用 二、找到当前所需使用的api菜品识别文档 三、点链接看实例代码 这里需要使用到如下几个参数&#xff08;如下&#xff09;&#xff0c;其他的参数可以不管 client_id &#xff1a; 就是创建应用后的API Keyclient_secret&#xff1a; 就是创建…...

idea项目mapper.xml中的SQL语句黄色下划线去除

问题描述 当我们使用idea开发java项目时&#xff0c;经常会与数据库打交道&#xff0c;一般在使用mybatis的时候需要写一大堆的mapper.xml以及SQL语句&#xff0c;每当写完SQL语句的时候总是有黄色下划线&#xff0c;看着很不舒服。 解决方案&#xff1a; 修改idea的配置 Edi…...

es 聚合操作(二)

书接上文&#xff0c;示例数据在上一篇&#xff0c;这里就不展示了 一、Pipeline Aggregation 支持对聚合分析的结果&#xff0c;再次进行聚合分析。 Pipeline 的分析结果会输出到原结果中&#xff0c;根据位置的不同&#xff0c;分为两类&#xff1a; Sibling - 结果和现有…...

【vue.js】文档解读【day 5】| ref模板引用

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 模板引用前言访问模板引用模板引用与v-if、v-show的结合v-for中的模板引用函数模板引用 模板引用 前言 …...

算法简单小技巧

主页&#xff1a;xiaocr_blog 1.最小公倍数和最大公约数 #include<iostream> using namespace std; int main(){int a,b;cin>>a>>b;int r a%b;while (r!0){a b;b r;r a%b;}cout<<b<<endl;return 0 ; } #include<iostream> using nam…...

前端入职配置新电脑!!!

前端岗位入职第一天到底应该做些什么呢&#xff1f;又该怎样高效的认识、融入团队&#xff1f;并快速进入工作状态呢&#xff1f;这篇文章就来分享一下&#xff0c;希望对即将走向或初入前端职场的你&#xff0c;能够有所帮助。内含大量链接&#xff0c;欢迎点赞收藏&#xff0…...

Java面试题总结15之简述你对RPC,RMI的理解

RPC&#xff1a;在本地调用远程的函数&#xff0c;远程过程调用&#xff0c;可以跨语言实现&#xff0c;httpClient RMI&#xff1a;远程方法调用&#xff0c;Java中用于实现RPC的一种机制&#xff0c;RPC的Java版本是J2EE的网络调用机制&#xff0c;跨JVM调用对象的方法&…...

内网穿透利器 n2n 搭建指南

1. n2n 简介 上文实验分析了 FRP 和 Zerotier 的利弊&#xff0c;本文再介绍另一种内网穿透方案&#xff0c;n2n。 n2n 是 C/S 架构的内网穿透服务&#xff0c;不同于 FRP 的 反向代理&#xff0c;它的原理是类似 Zerotier 的先打孔&#xff0c;打孔失败再尝试转发。关于打孔本…...

做网站的问题/互动营销的案例及分析

oracle 导入excel数据? 通过plsql实现 1.准备工作 Excel中的字段名称&#xff0c;必须和表结构字段一 一对应 下面以tdoctor_apply表为例&#xff0c;进行演示 表结构 Excel表数据字段名称 说明&#xff1a;为保密&#xff0c;表中的数据进行了隐藏&#xff1b;另外&#xff…...

wordpress没有上级目录的写权限/东莞网站营销推广

目录1、Jsoup是什么2、Jsoup解析URL返回结果3、Jsoup解析HTML片段1、Jsoup是什么 Jsoup是java的HTML解析器&#xff0c;可以解析请求URL的返回结果&#xff0c;可以解析HTML的片段内容&#xff0c;其实主要用来解析HTML内容的。 pom.xml文件引入&#xff1a; <!-- https:…...

锤子网站cms版本/如何做好推广引流

npm 在执行install的时候&#xff0c;会根据三方库中的package.json里面的bin配置&#xff0c;在node_modules下面的.bin目录生成一个可执行文件例如 生产的可执行文件其实是一个替身文件&#xff0c;那么这个替身文件真正指向的就是package.json里面的bin配置里面的那个文件。…...

网站建设华企云商/百度广告点击一次多少钱

(松勤软件测试讯)在软件测试面试过程中&#xff0c;可能会遇到「如果让你测试一个完全不熟悉的系统&#xff0c;你会怎么办&#xff1f;」的面试问题&#xff0c;面试官与应聘者对话如下&#xff1a;面试官诡异的微笑&#xff1a;“如果让你测试一个你完全不熟悉的系统&#xf…...

做网站的步骤的文本/网络推广企划

本文讲的是CSS 遮罩的过渡效果&#xff0c;一份关于如何使用 CSS 遮罩来创建一些有趣的视觉滑动过渡的教程。这份教程具有高度试验性&#xff01; 查看演示 下载源码 今天我们想向你展示怎样创建一个有趣简单并且吸引眼球的过渡效果&#xff0c;采用的是 CSS 遮罩 。 与剪裁一样…...

现在去环球中心会变黄码吗/江苏网站seo营销模板

这题就是深搜加剪枝&#xff0c;有一个很明显的剪枝&#xff0c;因为题目中给出了一个deadline&#xff0c;所以我们一定要用这个deadline来进行剪枝。 题目的意思是求到达每个点的时间总和&#xff0c;当时把题看错了&#xff0c;卡了好久。 剪枝一&#xff1a;走到这个点的时…...