【JavaEE】_Servlet API

news2024/11/7 1:45:35

目录

1. HttpServlet

1.1 init方法

1.2 destroy方法

1.3 service方法

1.4 Servlet的生命周期

1.5 代码示例

1.5.1 使用postman构造请求

1.5.2 使用ajax构造请求

2. HttpServletRequest

2.1 核心方法

2.2 代码示例1:打印请求信息

3. 前端给后端传参

3.1 通过GET的query string

3.2 通过POST,借助form表单

3.3 通过POST,使用json格式构造body

4. HttpServletResponse


[便捷起见,非必要时Servlet程序均以smart tomcat方式部署程序]

Servlet有3个重要类,分别为HttpServlet,HttpServletRequest,HttpServletResponse;

1. HttpServlet

编写Servlet程序第一步就是创建一个类继承自HttpServlet类并重写其doGet方法;

其核心方法有:

方法名称调用时机
init在HttpServlet实例化之后被调用一次
destroy在HttpServlet实例不再使用的时候调用一次
service收到HTTP请求的时候调用
doGet收到GET请求时调用(由service方法调用)
doPost收到POST请求时调用(由service方法调用)
doPut/doDelete/do Options/...收到其他请求时调用(由service方法调用)

1.1 init方法

1. 不由程序员手动调用,由tomcat自动调用

2. 当tomcat首次收到了和该类相关联的请求时,才会进行实例化

    以上一篇用Servlet的hello world程序为例:

WebServlet注解就是将/hello类和HelloServlet类绑定在一起,表示:

如果Tomcat收到了/hello这样路径的请求,就会调用HelloServlet,于是就对HelloServlet进行实例化;

实例化只进行一次,后续再收到/hello,就不必再重复实例化了,直接复用之前的HelloServlet实例即可;

3. 可以重写init方法,插入一些我们自己的初始化的逻辑:

运行以下代码:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        // 重写init方法
        System.out.println("init");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        把数据显示在服务器控制台
        System.out.println("Hello world");
//        把数据写回浏览器
        resp.getWriter().write("Hello world");
    }
}

(1)运行程序,仅启动服务器时,在控制台并未打印init:

原因:只有当请求关联到hello路径时才会打印;

(2)在浏览器中打开页面,即触发了请求,此时服务器的日志上就会调用init进行实例化:

(3)多次刷新页面,即多次发送请求:

doGet方法多次被调用,而init方法仅被调用一次;

4. 也可以通过修改web.xml配置让tomcat启动时立即实例化该servlet;

5. servlet是服务器上运行的代码,只要服务器不重新启动,init就不会再执行

1.2 destroy方法

1. 可以使用destroy方法进行一些清理工作

2. 只要服务器在运行,都有可能再使用,服务器终止时就不可再使用了;

3. 重写destroy方法:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        // 重写init方法
        System.out.println("init");
    }

    @Override
    public void destroy() {
//        重写destroy方法
        System.out.println("destroy");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        把数据显示在服务器控制台
        System.out.println("Hello world");
//        把数据写回浏览器
        resp.getWriter().write("Hello world");
    }
}

启动服务器并刷新页面后,点击停止后,可见服务器日志调用了destroy方法:

注:但此处的destroy方法是否能被执行到并不确定:

第一种情况:如果是使用smart tomcat的停止按钮终止程序,这个操作本质上是通过tomcat的8005端口来主动停止,可以触发destroy方法;

第二种情况:如果是直接杀进程,此时可能就来不及执行destroy方法;

故而并不推荐使用destroy方法;

1.3 service方法

当收到路径匹配的HTTP请求就会触发service方法

比如doGet方法就是在service方法中调用的:

父类HttpServlet有一个service方法,其内部就会调用doGet方法;

1.4 Servlet的生命周期

开始时,执行 init;

每次收到请求,执行 service;

销毁前执行 destroy;

注:一个servlet程序包含很多个servlet,某个servlet的生死,不影响整个sevlet程序;

1.5 代码示例

在java目录下再创建一个类:MethodServlet;

其内容如下:

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;

@WebServlet("/method")
public class MethodServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().write("doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
        resp.getWriter().write("doPost");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPut");
        resp.getWriter().write("doPut");
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doDelete");
        resp.getWriter().write("doDelete");
    }
}

直接在浏览器输入地址访问,只能发送GET请求,其他请求类型可以通过ajax或postman进行构造。

1.5.1 使用postman构造请求

基于一次浏览器地址访问后(即已构造一个GET请求),使用postman依次构造:GET,POST,PUT,DELETE请求并发送,再查看服务器日志:

1.5.2 使用ajax构造请求

1. 在IDEA中创建.html文件:

tomcat要求:.html文件设置在webapp目录下,与WEB-INF同级

可以使用vscode进行编写:

用vscode打开即可;

2. 编写代码:

<!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.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        $.ajax({
            type:'get',
            url:'method',
            // 此处url为相对路径,此时基准路径为当前html所在的路径:127.0.0.1:8080/hello_servlet
            success:function(body, status){
                console.log(body);
            }
        })
    </script>
</body>
</html>

在浏览器输入地址:

按f12进入chrome的console标签页:

同样在服务器日志也可见:

3. 依次修改请求类型为post,put,delete,再运行,即可得到不同的结果:

注:使用ajax构造HTTP请求的注意点:

(1)html文件的位置:webapp下,与WEB-INF同级;

(2)在html文件中使用ajax构造HTTP请求时的url可以写为相对路径,该相对路径的基准路径就是当前html文件的路径,在此例中为:127.0.0.1:8080/hello_servlet;

也可以写为绝对路径:(浏览器要求:以 / 开头的为绝对路径

        $.ajax({
            type:'get',
            url:'/hello_servlet/method',
            success:function(body, status){
                console.log(body);
            }
        })

(3)注意@WebServlet注解的路径必须 / 开头,此处的含义不是绝对路径,而是servlet的要求;

2. HttpServletRequest

HttpServletRequest表示一个HTTP请求,这个对象是tomcat自动构造的,

tomcat其实会自动监听端口,接受连接,读取请求,解析请求,构造请求对象等一系列工作;

2.1 核心方法

方法描述
String getProtocal()返回请求协议的名称和版本

String getMethod()

返回请求的HTTP方法的名称,如GET、POST或PUT
String getQequestURI()从协议名称直到HTTP请求的第一行的查询字符串中,返回该请求的URL的一部分
String getContexPath()返回指示请求上下文的请求URI部分
String getQueryString()返回包含在路径后的请求URL中的查询字符串(?后的参数)
Enumeration getParameterNames()返回一个String对象的枚举,包含在该请求中包含的参数的名称
String getParameter(String name)以字符串形式返回请求参数的值,或者如果参数不存在则返回null
String[] getParameterValues(String name)返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回null
Enumeration getHeaderNames()返回一个枚举,包含在该请求中包含的所有头名
String getHeader(String name)以字符串形式返回指定的请求头的值
String getCharacter Encoding()返回请求主题中使用的字符编码的名称
String getContentType()返回请求主题的MIME类型,如果不知道类型则返回null
int getContentLength()以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回-1
InputStream getInputStream()用于读取请求的body内容,返回一个InputStream对象

 注:(1)query string是键值对结构,此处可以通过getParameter方法来根据key获取到value

(2)InputStream就是输入流对象,进行read操作即可把body数据读取出来;

2.2 代码示例1:打印请求信息

基于hello_servlet项目,创建一个ShowRequestServlet.java文件,其内容如下:

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.Enumeration;

@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置响应的content-type,即表明body里的数据格式是何种类型
        resp.setContentType("text/html");
        // 创建一个StringBuilder,把这些api的结果拼起来统一写回响应中
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getMethod());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getRequestURI());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getContextPath());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getQueryString());
        stringBuilder.append("<br>");
        stringBuilder.append("<br>");
        stringBuilder.append("<br>");

        // 获取到header中的所有键值对
        Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            stringBuilder.append(headerName+" : "+req.getHeader(headerName));
            stringBuilder.append("<br>");
        }

        resp.getWriter().write(stringBuilder.toString());
    }
}

运行后根据url打开页面:

注:(1)此处实现html页面的换行操作不能使用\n,而使用<br>标签,同时设置响应的content-type为text/html,告诉浏览器,响应的body里的数据格式是何种类型;

(2)按照没有添加query string时,默认响应为null,比如增加query string 为a=10&b=20,响应的query string便为a=10&b=20;

3. 前端给后端传参

3.1 通过GET的query string

 (1)前端:test.html:

<!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="studentId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>

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

(2)后端:GetParameterServlet.java:

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;

@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 预期浏览器会发一个形如 /getParameter?studentId=001&classId=2001;
        // 借助req的getParameter方法就能拿到query string 中的键值对内容了
        // getParameter得到的是一个String类型的值
        String studentId = req.getParameter("studentId");
        String classId = req.getParameter("classId");
        resp.setContentType("text/html");
        resp.getWriter().write("studentId = "+studentId +" classId = "+classId);
    }
}

 运行程序后,根据url打开浏览器页面如下:

注:(1)输入在url后的查询字符串键值对会被Tomcat处理成形如Map这样的结构,后续就可以随时通过key来获取到value了;

(2)如果key在query string中不存在,则返回值为空;

3.2 通过POST,借助form表单

form表单也是键值对形式组织数据的,只是这部分内容在body中;

对于前端是form表单这样格式的数据,后端还是使用paraMeter来获取;

(1)前端:test.html:

<!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="studentId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>

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

 (2)后端:PostParameterSrvlet.java:

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;

@WebServlet("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentId = req.getParameter("studentId");
        String classId = req.getParameter("classId");
        resp.setContentType("text/html");
        resp.getWriter().write("studentId = "+studentId+" classId = "+classId);
    }
}

运行程序后根据url打开浏览器页面:

提交后,页面如下:

 注:(1)使用query string和使用form表单的后端代码格式基本相同,都是通过getParameter根据key获取value,只是使用form表单构造的键值对不在query string中,而是在body中;

(2)getParameter方法不仅能获取到请求中query string中的键值对,还可以获取到form表单构造的body中的键值对;

(3)以form表单形式构造并发送的请求一定会触发页面跳转;

(4).html及请求、浏览器页面的对应关系图:

(5)前端后端交互的过程:

图1:

图2:

3.3 通过POST,使用json格式构造body

json也是键值对结构的数据格式,可以把body按照该形式组织;

在前端,可以通过ajax方式构造该内容,也可以使用postman;

(1)postman构造请求:

 (2)后端:PostParameter2Sevlet.java

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.InputStream;

@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 通过这个方法处理 body 为 json 格式的数据
        // 直接把 req 对象中的 body 完整地读取出来

        // 获取请求的body长度并构造数组
        int length = req.getContentLength();
        byte[] buffer = new byte[length];

        InputStream inputStream = req.getInputStream();
        inputStream.read(buffer);

        //把这个字节数组构造成 String, 打印出来
        String body = new String(buffer, 0, length,"utf8");
        System.out.println("body = "+body);
        resp.setContentType("text/html");
        resp.getWriter().write(body);
    }
}

使用fiddler可以查看到构造的json请求:

当请求到达tomcat后,tomcat就会将其解析为req对象;

在servlet代码中,req.getInputStrea,,读取body内容,又把body的内容构造成一个响应结果返回给浏览器(此例中为postman),在post页面中就有响应结果:

注:(1)使用form表单构造请求传参与json格式请求传参的代码执行流程是类似的,只是传输数据的格式不同,

form表单的格式形如:

json格式形如:

但是当前通过json传递数据,服务器只是将整个body都读出来,没有按照键值对的方式处理,还不能根据key获取到value,可以使用第三方库来解析json的body,如jackson,gson,fastjson,由于spring mvc内置了jackson这个库,故而天然就支持处理jackson的数据。

故而,以引入jackson库为例:

通过maven引入第三方库:

基于jackson库,修改代码使得获取到请求body内部的键值对:

 class Student{
    public int studentId;
    public int classId;
}
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// 使用jackson的核心对象:
  ObjectMapper objectMapper = new ObjectMapper();

// readValue就是把一个json格式的字符串转为java对象:
  Student student = objectMapper.readValue(req.getInputStream(), Student.class);

    }
}

注意:(1)objectMapper对象的readValue方法的作用:

① 将json格式的字符串读取出来;

② 根据第二个参数类对象创建Student实例,第二个参数是一个类对象

③ 解析json格式的字符串,处理成map键值对结构;

④ 遍历所有键值对,看键的名字和Student实例的哪个属性名匹配,就把对应的value设置到该属性中;

⑤ 返回该Student实例;

(2)readValue方法用于将json字符串转成java对象,writeValue方法用于把一个java对象转成json格式字符串

(3)在上文代码中,将Student类内的属性设置为public修饰,这在Java中并不常见。但是如果要把一个类作为jackson返回的对象,就需要让jackson能够看到类中的属性,可以采取的方法有:

① 把属性设置为public;② 给该属性提供public修饰的getter与setter方法;

4. 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中写入二进制格式数据

(1)一个HTTP响应中报头的key是可以存在多个重复的

(2)可以通过setCharacterEncoding指定响应的编码格式:

浏览器默认不知道程序员的页面编码方式,会采取猜测的方式使用字符集进行解析,比如在getParameterServlet.java中将写回浏览器的响应格式写为:

resp.setContentType("text/html");
resp.getWriter().write("学生id: "+studentId +" 班级id: "+classId);

 此时根据路径打开浏览器页面,就会出现乱码: 

为了避免这种情况,我们需要在写回响应前,显式指定响应的编码格式字符集:

        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().write("学生id: "+studentId +" 班级id: "+classId);

刷新浏览器页面,有: 

(3)也可以把字符集和ContentType一起设置:

        resp.setContentType("text/html; charset=utf8");
        resp.getWriter().write("学生id: "+studentId +" 班级id: "+classId);

(4)void sendRedirect用于构造重定向响应,3xxx的状态码就会跳转到另外一个页面:

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;

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://www.sogou.com");
    }
}

运行代码后,根据路径打开浏览器页面,即可跳转至搜狗主页:

前后端交互逻辑如下:

 

实现重定向,尤其是返回错误页面有多种方式:

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

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

相关文章

新手如何用Airtest实现在图片范围内随机点击?

1. 前言 前几天有个新手同学在Airtest官群里问了这样一个问题&#xff1a; 我是新手&#xff0c;在图片范围内随机点击 &#xff0c;用Airtest怎么实现&#xff1f;代码&#xff1f; 那我们就以这个问题为例&#xff0c;浅浅聊一下&#xff0c;怎么把需求转化成我们的Airtest代…

Linux——shell外壳程序

shell外壳程序 1. 什么是shell外壳程序 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心 “ &#xff0c;但我们一般用户&#xff0c;不能直接使用核心。 而是通过核心的“外壳”程序&#xff0c;也就是所谓的shell。 shell是所有外壳程序的统称 平时程序员…

毅速3D打印丨哪些产品最适合应用3D打印随形水路模具

3D打印技术随形水路模具无论是从生产效率、生产成本&#xff0c;还是从产品质量出发考虑&#xff0c;在各个领域有着重要的应用&#xff0c;毅速3D打印根据统计了目前应用比较多的产品领域主要有以下几类&#xff1a; 1、医疗美妆类产品。如化妆品包装瓶、脸部按摩仪等透明产品…

行情分析——加密货币市场大盘走势(10.20)

大饼昨日迅猛上涨&#xff0c;并在今日依然上涨&#xff0c;目前处在蓝色上涨趋势线&#xff0c;上涨趋势依然在。中长线可以考虑过几天止损或者继续持有。目前MACD日线呈现绿色实心5天&#xff0c;预计明后天可能会绿色空心&#xff0c;注意后续空头的到来&#xff0c;注意多单…

UART通信——笔记

UART通信特点 异步、全双工、串行。 只使用一对线就可以实现数据的通信&#xff0c;节约成本。 数据一位一位发送&#xff0c;数据传输较慢。 只能一对一通信。 如何实现通信的&#xff1f; UART&#xff1a; 发送数据的TX接受数据的RX参考GND UART是异步通信&#xff0c;…

SpringCloud 微服务全栈体系(一)

第一章 认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 一、单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff…

MySQL数据库简单安装

MySQL介绍 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;目前属于 Oracle 旗下公司。MySQL 最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面MySQL是最好的 RDBMS (Relational Database Management System&#xff0c;关系数据库管…

大河弯弯:CSS 文档流与三大元素显示模式

文章目录 参考环境文档流概念三大显示模式 内联元素概念常见的内联元素宽高由内容决定 块级元素概念常见的块级元素宽度受容器影响&#xff0c;高度受内容影响 内联块级元素概念常见的内联块级元素折中方案 设置元素的显示模式display 属性内联元素与块级元素的切换为什么要通过…

大托,如何站上天心南部的价值高地?

作者 | 魏启扬 陈宇航 来源 | 洞见新研社 陈飞 摄 “商贾云集于四方&#xff0c;市井数盈于万户”&#xff0c;长沙南城古往今来生生不息的热辣与烟火&#xff0c;每隔一段时间&#xff0c;都会有璀璨的迸发。 才在“加长版”黄金周释放了“不夜南城”的魅力&#xff0c;第…

YOLO目标检测——红细胞数据集【(含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;红细胞的自动检测和计数数据集说明&#xff1a;YOLO目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富。使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(json)和yolo(txt)三种格式标签&am…

C++类和对象(四) (构造函数 析构函数)

1 类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生…

SolidWorks2021 安装教程(亲测可用)

1.安装教程&#xff1a;&#xff08;断网进行&#xff0c;否则安装了后还是无法用&#xff09; 1.运行sw2021_network_serials_licensing 2. 注册表编辑器确定 3.成功添加到注册表中 4.复制SolidWorks_Flexnet_Server文件夹 5.运行SolidWorks_Flexnet_Server下的lserver_insta…

一个适合练手的接口测试实战项目——慕慕生鲜

前言 最近很多粉丝找小月要接口测试项目练练手&#xff0c;看看实力&#xff01;今天&#xff0c;它来了 慕慕生鲜&#xff0c;完整版&#xff0c;文末有福利&#xff01; 干货来咯&#xff0c;收藏好&#xff01; 1. 接口测试需求分析 常见接口文档提供的两种方式 ①wor…

代码随想录算法训练营第23期day26|39. 组合总和、40.组合总和II、131.分割回文串

目录 一、&#xff08;leetcode 39&#xff09;组合总和 二、&#xff08;leetcode 40&#xff09;组合总和II 三、&#xff08;leetcode 131&#xff09;分割回文串 一、&#xff08;leetcode 39&#xff09;组合总和 力扣题目链接 状态&#xff1a;基本回溯AC&#xff0c…

Docker(2)

Docker网络 原生网络 [rootserver1 harbor]# docker network ls默认使用桥接模式&#xff0c;桥接到docker0上 [rootserver1 ~]# docker run -d --name demo nginx [rootserver1 ~]# yum install -y bridge-utils [rootserver1 ~]# brctl showhost模式&#xff0c;容器和宿…

【vue3】Transition过渡组件

Transition 自带的内部组件xxx-enter-from 开始进入过渡 0%xxx-enter-active 过渡过程xxx-enter-to 过渡完成 100%xxx-leave-from 开始退出 0%xxx-leave-active 退出过程xxx-leave-to 退出完成 100% xxx是组件属性name的值&#xff0c;自定义的。我使用的是fade-box <templa…

JavaSE编程题目练习(三)

博客昵称&#xff1a;架构师Cool 最喜欢的座右铭&#xff1a;一以贯之的努力&#xff0c;不得懈怠的人生。 作者简介&#xff1a;一名Coder&#xff0c;欢迎关注小弟&#xff01; 博主小留言&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟Cool&#xff0…

基于 Qt UDP通信局域网通信

前言 该例程经过实际验证可以正常使用,只简单的使用UDP中的单播模式(一对一), 所用测试系统在同一局域网,其中: QT版本:5.12 PC端UDP模式:单播 UDP通信目标:基于STM32F4+LWIP协议的以太网接口 调试助手: 虚拟串口+串口助手+UDP和TCP调试助手[编程人员必备]一、UDP通…

RIP,EIGRP,OSPF区别

1. 动态路由协议的作用是什么&#xff1f; 2. 路由协议都有哪些种类&#xff1f; 3. 如何判断路由协议的优劣&#xff1f; -- RIP&#xff0c;EIGRP&#xff0c;OSPF - 动态路由协议 -- 路由协议 - 路由器上的软件 -- 帮助路由器彼此之间同步路由表 -- 相互的传递…

MC 我的世界 模拟城市模拟大都市 模组下载及整合包导入详解

如何导入整合包 如果是从curseforge下载的整合包不需要解压的&#xff0c;直接按照下方步骤整就行了&#xff0c;把启动器和整合包复制到没有中文的路径下 双击启动exe文件&#xff0c;如果弹窗要更新啥的点确定即可&#xff0c;启动好了先登录账户&#xff0c;有正式版的登录…