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

02_Servlet

目录

    • 一、简介
    • 二、`Servlet`入门案例
      • 2.1、编写`Servlet`
      • 2.2、配置`Servlet`
      • 2.3、访问`Servlet`
      • 2.4、常见错误
    • 三、`Servlet`详解
      • 3.1、实现`Servlet`的三种方式
        • 3.1.1、实现`Servlet`接口
        • 3.1.2、继承`GenericServlet`类
        • 3.1.3、继承`HttpServlet`类
      • 3.2、配置`Servlet`的两种方式
        • 3.2.1、`web.xml`方式
        • 3.2.2、注解方式
      • 3.3、常见问题
      • 3.4、关于`Jrebel`
        • 3.4.1、安装
        • 3.4.2、激活
        • 3.4.3、使用之前的配置
        • 3.4.4、启动测试
    • 四、`request`和`response`
      • 4.1、请求响应流程
      • 4.2、`response`对象
        • 4.2.1、设置响应正文
        • 4.2.2、响应乱码问题处理
        • 4.2.3、重定向
      • 4.3、`request`对象
        • 4.3.1、获取请求头(了解)
        • 4.3.2、获取请求参数
        • 4.3.3、请求乱码问题处理
        • 4.3.4、域对象功能
        • 4.3.5、请求转发
      • 4.4、关于路径写法
        • 4.4.1、浏览器路径
        • 4.4.2、服务器路径
    • 五、登录案例
    • 六、`ServletContext`
      • 6.1、概述
      • 6.2、获取`ServletContext`
      • 6.3、作用
        • 6.3.1、获取项目在服务器上发布的真实路径
        • 6.3.2、获取项目的上下文路径
        • 6.3.3、域对象功能
        • 6.3.4、打开已经存在的Maven项目_getParameter和getAttribute的区别

一、简介

Server Applet(服务器小程序),是由服务器端调用和执行的、按照Servlet自身规范编写的Java类。

JavaWeb的三大组件(ServletFilterLisener)之一,是动态资源的一种。

作用:

  • 接收请求
  • 处理数据
  • 完成响应

后续我们学习Servlet也是集中在这三点。

二、Servlet入门案例

2.1、编写Servlet

  • 实现javax.servlet.Servlet
  • 重写5个主要方法
  • 在核心的service()方法中编写输出语句,打印访问结果
package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;public class TestServlet implements Servlet {public void init(ServletConfig config) throws ServletException{}public void service(ServletRequest request,ServletResponse response) throws ServletException,IOException{System.out.println("My First Servlet!");}public void destroy(){}public ServletConfig getServletConfig(){return null;	}	public String getServletInfo(){return null;}
}

2.2、配置Servlet

web.xml中配置Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><!-- 1、添加servlet节点 --><servlet><!-- Servlet的名字,和2中的名字必须一致 --><servlet-name>aServlet</servlet-name><!-- Servlet的全类名 --><servlet-class>tech.code2048.servlet.AServlet</servlet-class></servlet><!-- 2、添加servlet-mapping节点 --><servlet-mapping><!-- Servlet的名字,和1中的名字必须一致 --><servlet-name>aServlet</servlet-name><!-- Servlet的访问路径,通过该路径可以访问doServlet的Get或doPost方法 --><url-pattern>/aServlet</url-pattern></servlet-mapping>
</web-app>

url-pattern配置的内容就是浏览器地址栏输入的URL中项目名称后资源的内容

2.3、访问Servlet

Tomcat中部署该项目,访问http://localhost:8080/项目名/testServlet,控制台及浏览器有输出证明Servlet部署及访问成功。

2.4、常见错误

500错误:服务器内部出现了错误

修改TestServlet代码如下:

package tech.code2048.servlet;import javax.servlet.*;
import java.io.IOException;public class AServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("My First Servlet!");String str = null;System.out.println(str.length());}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

运行JavaWeb项目,访问TestServlet,页面显示如下:

在这里插入图片描述

三、Servlet详解

Servlet是单例的,一个类型的Servlet只有一个实例对象,那么就有可能会出现一个Servlet同时处理多个请求,Servlet不是线程安全的,不应该在Servlet中创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

  • 不要在Servlet中创建成员,创建局部变量即可;
  • 可以创建无状态成员;
  • 可以创建有状态的成员,但状态必须为只读的。

3.1、实现Servlet的三种方式

在这里插入图片描述
最后这个要自己掌握,生命周期的三种方法要背熟!

3.1.1、实现Servlet接口

在这里插入图片描述

javax.servlet.Servlet代码

public interface Servlet {void init(ServletConfig var1) throws ServletException;ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;String getServletInfo();void destroy();
}

Servlet中的大多数方法不由我们来调用,而是由Tomcat来调用,并且Servlet的对象也不由我们来创建,由Tomcat来创建!

生命周期方法

  • init()
    
    • 服务器会在Servlet第一次被访问时创建Servlet,在Servlet被创建后,服务器会马上调用Servletvoid init(ServletConfig)方法;
    • 在整个Servlet的生命周期中,该方法只被调用一次。
  • service()
    
    • 当服务器每次接收到请求时,都会去调用Servletservice()方法来处理请求;
    • 每次处理请求都会被调用
  • destroy()
    
    • 在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servletdestroy()方法;
    • 在整个Servlet的生命周期中,该方法只被调用一次。

生命周期方法方法演示

package tech.code2048.servlet;import javax.servlet.*;
import java.io.IOException;public class BServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init...");}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service...");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {System.out.println("destroy...");}
}

web.xml中配置Servlet

<servlet><servlet-name>bServlet</servlet-name><servlet-class>tech.code2048.servlet.BServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>bServlet</servlet-name><url-pattern>/bServlet</url-pattern>
</servlet-mapping>

启动tomcat->访问BServlet->关闭tomcat

观察控制台的打印。

关于ServletConfig

  • 一个ServletConfig对象对应一段web.xml中的配置信息
  • ServletConfig是一个接口,该接口实现类的对象由Tomcat提供
  • 方法
    • getInitParameter(name) 获取servlet的初始化参数
    • getInitParameterNames()
    • getServletContext()
    • getServletName()

修改BServlet代码

package tech.code2048.servlet;import javax.servlet.*;
import java.io.IOException;public class BServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init...");System.out.println(servletConfig.getInitParameter("name"));}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service...");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {System.out.println("destroy...");}
}

修改web.xml关于BServlet的配置

<servlet><servlet-name>bServlet</servlet-name><servlet-class>tech.code2048.servlet.BServlet</servlet-class><!-- BServlet初始化参数 --><init-param><param-name>name</param-name><param-value>zhangsan</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>bServlet</servlet-name><url-pattern>/bServlet</url-pattern>
</servlet-mapping>
3.1.2、继承GenericServlet

在这里插入图片描述

GenericServlet使编写Servlet变得更容易。它提供生命周期方法initdestroy的简单实现,要编写一般的Servlet,只需重写抽象service方法即可。

代码如下:

package tech.code2048.servlet;import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;public class CServlet extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("CServlet....");}
}
web.xml`配置`CServlet
<servlet><servlet-name>cServlet</servlet-name><servlet-class>tech.code2048.servlet.CServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>cServlet</servlet-name><url-pattern>/cServlet</url-pattern>
</servlet-mapping>
3.1.3、继承HttpServlet

HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet

HttpServletservice(HttpServletRequest,HttpServletResponse)方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()doPost()方法即可。

package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;public class DServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("doGet.......");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("doPost........");}
}
web.xml`配置`DServlet
<servlet><servlet-name>dServlet</servlet-name><servlet-class>tech.code2048.servlet.DServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>dServlet</servlet-name><url-pattern>/dServlet</url-pattern>
</servlet-mapping>

3.2、配置Servlet的两种方式

3.2.1、web.xml方式

Servlet2.5及之前使用该方式

<!-- 1、添加servlet节点 -->
<servlet><!-- Servlet的名字,和2中的名字必须一致 --><servlet-name>aServlet</servlet-name><!-- Servlet的全类名 --><servlet-class>tech.code2048.servlet.AServlet</servlet-class><!-- 配置启动加载 --><load-on-startup>1</load-on-startup>
</servlet>
<!-- 2、添加servlet-mapping节点 -->
<servlet-mapping><!-- Servlet的名字,和1中的名字必须一致 --><servlet-name>aServlet</servlet-name><!-- Servlet的访问路径,通过该路径可以访问doServlet的Get或doPost方法 --><url-pattern>/aServlet</url-pattern>
</servlet-mapping>

url-pattern定义匹配规则,取值说明:

  • 精确匹配/具体的名称只有url路径是具体的名称的时候才会触发Servlet
  • 后缀匹配 *.xxx只要是以xxx结尾的就匹配触发Servlet
  • 通配符匹配 /*匹配所有请求,包含服务器的所有资源
  • 通配符匹配/匹配所有请求,包含服务器的所有资源,不包括jsp
load-on-startup
  • 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet
  • 它的值必须是一个整数,表示Servlet被加载的先后顺序;
  • 如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载;
  • 如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个Servlet,值越小,Servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
3.2.2、注解方式

Servlet3.0新增特性,推荐使用

@WebServlet常用属性:

  • nameServlet名字,可选
  • value:配置url路径,可以配置多个
  • urlPatterns:配置url路径 ,和value作用一样,不能同时和value使用
  • loadOnStartup:配置Servlet的创建的时机, 如果是0或者正数,启动程序时创建,如果是负数,则访问时创建。 数子越小优先级越高。
package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet(name = "EServlet", value = "/eServlet", loadOnStartup = 1)
public class EServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("doGet...");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("doPost...");}
}

3.3、常见问题

  1. HTTP Status 404
    

    资源找不到

    • 第一种情况:地址书写错误;
    • 第二种情况:地址没有问题,把IDEA项目中out目录删除,然后重新运行。
  2. Servlet地址配置重复,多个Servleturl-pattern使用相同的值

  3. Servlet地址配置错误,比如没有写/

3.4、关于Jrebel

我们在编写Servlet时,修改Servlet或者新增Servlet都要重启项目让项目重新发布,重启非常耗时,这样会导致效率低下,我们需要一种能够动态发布项目的技术,这就是Jrebel

3.4.1、安装

搜索插件jrebel, 安装然后重启IDEA

注意:如果使用下面的激活方式,一定要使用2022.4.1及之前版本。

3.4.2、激活
  1. 打开任何一个项目,Help -> JReBel -> Activation;
  2. 访问https://www.guidgen.com,获取GUID,然后多次单击Generate new GUID,复制生成的GUID
  3. 在激活页面Team URL输入http://jrebel.yanjiayu.cn:9001/2中的GUID,例如:http://jrebel.yanjiayu.cn:9001/5c556b5a-323f-4803-84e6-6249e7df653f,直接使用案例的Team URL也可以;
  4. 邮箱随意填;
  5. 勾选I agree....
  6. 点击Activate JRebel;
  7. Next > enable JRebel for projects;
  8. I agree
3.4.3、使用之前的配置
  1. File -> Settings -> JRebel&XRebel -> 单击Work offline;
  2. File -> Settings -> Build,Execution,Deployment -> Compiler -> Build project automatically勾上, 这一步之前我们配置IDEA的时候配置过;
  3. 展开IDEA右侧JRenel面板,勾选项目后面的第一个多选按钮。

注意:我们将来新建的项目只需要配置步骤3就可以了,不需要每次都配置步骤1和步骤2。

3.4.4、启动测试

启动

  • 不要选择之前Tomcat的启动标志,选择新增的带小火箭的启动标志。

测试

  • 在已有的Servlet中新增内容,新建Servlet都会立即生效,不需要重启Tomcat

四、requestresponse

4.1、请求响应流程

在这里插入图片描述

4.2、response对象

reponse类型为javax.servlet.http.HttpServletResponse,客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。

主要功能

  • 设置响应正文
  • 设置响应头信息
  • 发送状态码
  • 重定向
4.2.1、设置响应正文

关于设置响应正文

  • response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,常用方法:

    • PrintWriter out = response.getWriter():获取字符流—16
    • ServletOutputStream out = response.getOutputStream():获取字节流—8
  • 如果响应正文内容为字符,那么使用response.getWriter(),如果响应内容是字节,例如下载时,那么可以使用response.getOutputStream()

    注意:在一个请求中,不能同时使用这两个流,也就是说,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流。不然会抛出IllegalStateException异常。

例:在页面打印文字,字体颜色为红色。

package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet(name = "FServlet", value = "/FServlet")
public class FServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {PrintWriter out = response.getWriter();out.println("<p style='color:red;'>Hello World</p>");out.println("<p style='color:red;'>你好世界</p>");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
4.2.2、响应乱码问题处理

问题分析:

  1. 在使用response.getWriter()时默认字符编码为ISO-8859-1,不支持中文;
  2. 如果希望设置字符流的字符编码为UTF-8,可以使用response.setCharacterEncoding(“utf-8”)来设置,这样可以保证输出给客户端的字符都是使用的UTF-8编码;
  3. 客户端浏览器并不知道响应数据是什么编码的,浏览器解析之后依然出现乱码。

解决方案:

  • 使用response.setContentType("text/html;charset=utf-8")
  • 一定要在获取输出流前进行设置
  • 优势
    • 设置content-type响应头,客户端浏览器会使用content-type头来解读响应数据;
    • 这个方法还会调用response.setCharacterEncoding("utf-8")保证输出给客户端的字符都是使用UTF-8编码的。

上述案例修改

package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet(name = "FServlet", value = "/FServlet")
public class FServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置响应头response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();out.println("<p style='color:red;'>Hello World</p>");out.println("<p style='color:red;'>你好世界</p>");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
4.2.3、重定向

现象:当访问http://baidu.com时,发现地址栏变成https://www.baidu.com,这就是重定向了。

概念:重定向是服务器通知浏览器去访问另一个地址,即再发出另一个请求。

在这里插入图片描述
在这里插入图片描述

实现方式1:

  1. 设置响应码response.setStatus(302);
  2. 设置重定向的位置response.setHeader("Location", "/项目名/bServlet");

实现方式2:

  • response.sendRedirect("/项目名/bServlet");
package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet(name = "GServlet", value = "/GServlet")
public class GServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("GServlet............................");//实现方式1//response.setStatus(302);//response.setHeader("Location", "/JavaWebTest_war_exploded/bServlet");//实现方式2response.sendRedirect("/JavaWebTest_war_exploded/bServlet");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

关于重定向的总结

  • 重定向是两次请求
  • 重定向的URL可以是其他应用,不局限于当前应用,例如重定向到百度
  • 重定向的响应头为302,并且必须要有Location响应头
  • 重定向就不要再使用response.getWriter()response.getOutputStream()输出数据

4.3、request对象

requestServlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest。在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法,这说明在service()方法中可以通过request对象来获取请求数据。

主要功能(平行的关系)

  • 获取请求头
  • 获取请求参数
  • 域对象功能
  • 请求转发和请求包含
4.3.1、获取请求头(了解)
String getMethod()`:返回请求方法,例如:`GET

String getRemoteAddr():返回当前客户端的IP地址

String getRemoteHost():返回当前客户端的主机名,但这个方法的实现还是获取IP地址

String getServerName()`:返回主机名,例如:`localhost
int getServerPort()`:返回服务器端口号,例如:`8080
package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet(name = "HServlet", value = "/HServlet")
public class HServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("请求方法:" + request.getMethod());System.out.println("客户端IP:" + request.getRemoteAddr());System.out.println("客户端主机名:" + request.getRemoteHost());System.out.println("主机名:" + request.getServerName());System.out.println("服务器端口号:" + request.getServerPort());System.out.println("客户端端口号:" + request.getRemotePort());}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
4.3.2、获取请求参数

客户端传递参数方式有两种(GETPOST

  • 浏览器地址栏直接输入:一定是GET请求
  • 超链接:一定是GET请求
  • 表单:可以是GET,也可以是POST,这取决与formmethod属性值

GET请求和POST请求的区别

  • GET
    
    • 可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔,不安全
    • URL地址后附带的参数是有限制的,其数据容量通常不能超过1K
    • GET请求没有请求体
  • POST
    
    • 传送的数据量无限制
    • 传输的数据在请求体内
    • 请求参数不会显示浏览器的地址栏,相对安全
request`获取请求参数的`API
  • String getParameter(String name):通过指定名称获取参数值(必须掌握)
  • String[] getParameterValues(String name):当多个参数名称相同时,可以使用方法来获取
  • Enumeration getParameterNames():获取所有参数的名字
  • Map getParameterMap():获取所有参数封装到Map中,其中key为参数名,value为参数值,因为一个参数名称可能有多个值,所以参数值是String[],而不是String

Servlet代码如下:

package tech.code2048.servlet;import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Arrays;@WebServlet(name = "IServlet", value = "/IServlet")
public class IServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求参数String username = request.getParameter("username");System.out.println(username);//当多个参数名称相同时,可以使用方法来获取String[] hobbies = request.getParameterValues("hobby");System.out.println(Arrays.toString(hobbies));}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

Get方式提交:

http://localhost:8080/JavaWebTest_war_exploded/IServlet?username=zs&hobby=睡觉&hobby=game

Post方式提交:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/JavaWebTest_war_exploded/IServlet" method="post">用户名<input type="text" name="username" /><br/>爱好<input type="checkbox" name="hobby" value="睡觉1">睡觉1<input type="checkbox" name="hobby" value="睡觉2">睡觉2<input type="checkbox" name="hobby" value="睡觉3">睡觉3<button type="submit">提交</button></form>
</body>
</html>

在这里插入图片描述

4.3.3、请求乱码问题处理

Get请求乱码

  • Tomcat8的版本中get方式不会出现乱码了,因为服务器对url的编码格式可以进行自动转换。

POST请求乱码

  • 由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收。
  • 解决方案:使用从ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行统一的编码设置。

修改IServlet代码如下:

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Arrays;@WebServlet(name = "IServlet", value = "/IServlet")
public class IServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置请求编码request.setCharacterEncoding("utf-8");//获取请求参数String username = request.getParameter("username");System.out.println(username);//当多个参数名称相同时,可以使用方法来获取String[] hobbies = request.getParameterValues("hobby");System.out.println(Arrays.toString(hobbies));}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}
4.3.4、域对象功能
  • 域对象作用就是在多个Servlet之间传递数据
  • request可以在一个请求中共享数据,一个请求会创建一个request对象,如果在一个请求中经历了多个Servlet,那么多个Servlet就可以使用request来共享数据
  • 域方法
    • void setAttribute(String name, Object value)
    • Object getAttribute(String name)
    • 删除void removeAttribute(String name)
  • 一个请求可以通过转发、包含跨越多个Servlet,在这个请求链之上的Servlet可以通过request共享数据
    在这里插入图片描述
4.3.5、请求转发

转发的作用在服务器端,将请求发送给服务器上的其他资源,以共同完成一次请求的处理,多个ServletJSP共同来处理一个请求。

在这里插入图片描述

实现步骤:

  1. 创建调度器RequestDispatcher rd = request.getRequestDispatcher("/BServlet");
  2. 转发rd.forward(request, response);

以下代码实现转发,并通过request域传递数据

@WebServlet(name = "JServlet", value = "/JServlet")
public class JServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//在request域中存放数据request.setAttribute("name", "zs");//转发//创建调度器RequestDispatcher dispatcher = request.getRequestDispatcher("/KServlet");//转发dispatcher.forward(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}@WebServlet(name = "KServlet", value = "/KServlet")
public class KServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//从request域中获取数据String name = (String)request.getAttribute("name");System.out.println(name);//从request域中删除数据request.removeAttribute("name");//转发request.getRequestDispatcher("/LServlet").forward(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}@WebServlet(name = "LServlet", value = "/LServlet")
public class LServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//从request域中获取数据String name = (String)request.getAttribute("name");//由于KServlet删除了域对象中的内容,导致name输出为nullSystem.out.println("LServlet:" + name);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

请求转发和重定向的区别

  • 请求转发是一个请求,而重定向是两个请求
  • 请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求
  • 请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用
  • 请求转发对AServletBServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求
  • 重定向的第二个请求一定是GET

4.4、关于路径写法

在这里插入图片描述

4.4.1、浏览器路径

超链接、表单、重定向都是客户端路径(假设当前主机是http://localhost:8080,应用名称Test)

  • 绝对路径http://www.baidu.com

  • 相对路径

    • /
      

      开头的相对路径

      • 表示相对于当前主机地址(http://localhost:8080)
      • 在超链接、表单、重定向,如果以/开头,一定是/Test/...
      • 参考重定向中路径的写法
    • 不以

      /
      

      开头的相对路径

      • 表示相对当前路径

注意:强烈建议使用/开头的相对路径,后面是当前应用的名称,再是访问路径。

4.4.2、服务器路径

这里说的服务器路径,就是以/开头的相对路径

  • 表示相对于当前应用(http://localhost:8080/Test
  • 参考请求转发中路径的写法

五、登录案例

使用Servlet完成登录功能,不需要连接数据库,需求如下:

  • 输入用户名:admin,密码:admin,页面显示登录成功
  • 输入其他用户名密码,页面显示登录失败

登录页代码如下:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>登录</title></head><body><form action="http://localhost:8080/JavaWebTest/LoginServlet" method="post"><fieldset style="width: 300px;"><legend>用户登录</legend><p><label>账号</label><input type="text" name="username" placeholder="请输入用户名" /></p><p><label>密码</label><input type="password" name="password" placeholder="请输入密码" /></p><p><button type="submit">登录</button><button type="reset">重置</button></p></fieldset></form></body>
</html>

登录成功页

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>success</title>
</head>
<body><p>登录成功</p>
</body>
</html>

登录失败页

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>error</title>
</head>
<body><p>登录失败</p>
</body>
</html>

Servlet代码

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(name = "LoginServlet", value = "/LoginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取请求参数String username = request.getParameter("username");String password = request.getParameter("password");if(username.equals("admin") && password.equals("admin")) {request.getRequestDispatcher("/success.html").forward(request, response);} else {request.getRequestDispatcher("/error.html").forward(request, response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

六、ServletContext

6.1、概述

一个项目只有一个ServletContext对象,使用它可以给多个Servlet传递数据,与天地同寿,这个对象在Tomcat启动时就创建,在Tomcat关闭时才会消失。

特点:

  • 唯一性:一个应用对应一个ServletContext
  • 生命周期:只要容器不关闭或者应用不卸载,ServletContext就一直存在。

6.2、获取ServletContext

  • GenericServlet提供了getServletContext()方法;
  • HttpServletRequest提供了getServletContext()方法;
  • HttpSession提供了getServletContext()方法。

6.3、作用

6.3.1、获取项目在服务器上发布的真实路径
//获取项目在服务器上的真实路径
String realpath=servletContext.getRealPath("/");
6.3.2、获取项目的上下文路径

上下文路径指的是应用名称。

//获取项目的上下文路径 - 上下文路径(应用程序名称)
System.out.println(servletContext.getContextPath());
//另一种方式
System.out.println(request.getContextPath());

案例

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;@WebServlet(name = "MServlet", value = "/MServlet")
public class MServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取servletContextServletContext servletContext = this.getServletContext();//获取项目真实路径System.out.println(servletContext.getRealPath("/"));//获取项目上下文路径System.out.println(servletContext.getContextPath());System.out.println(request.getContextPath());}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
6.3.3、域对象功能

在这里插入图片描述

ServletContext拥有作用域,可以存储数据到全局容器中

  • 存储数据:servletContext.setAttribute("name",value);
  • 获取数据:servletContext.getAttribute("name");
  • 移除数据:servletContext.removeAttribute("name");

案例,统计网站访问人数

import javax.servlet.ServletContext;
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.PrintWriter;@WebServlet(name = "NServlet", value = "/NServlet")
public class NServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletContext sctx = this.getServletContext();Integer count = (Integer) sctx.getAttribute("count");if(count == null) {count = 1; //自动装箱} else {count++;}sctx.setAttribute("count", count);PrintWriter out = response.getWriter();out.println("<h1>" + count + "</h1>");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
6.3.4、打开已经存在的Maven项目_getParameter和getAttribute的区别

1.发给别人的项目里面只需要有下面两个东西就行了,别的东西都不要(尤其是.idea和.ml,这都是自己本地配置的东西,不需要发给别人)
在这里插入图片描述
2.关于打开项目:
打开项目,可以选择到pom.xml打开,信任项目,看看里面文件夹的颜色是否正确。

在这里插入图片描述

3.自己配置项目
(tomcat…跟之前配置方法一样)

4.getParameter和getAttribute的区别:
在这里插入图片描述

问获取请求参数getParameter和域对象什么关系?

答:没有任何关系,是完全平行的两个功能

那什么时候需要获取请求参数getParameter?什么时候才要从域对象里面获取东西?

答:如果网页、浏览器给服务器发送数据,要获取浏览器发送过来的数据,用第一个获取请求参数getParameter。

如果请求域中存放了数据,想在转发过程中想获取数据,也就是在Servlet间分享数据的时候获取数据,那么用第二个从域对象里面获取东西。

5.在同一个域当中(在同一个ServletContext中),如果同一个属性多次赋值,那么相同的key,新的值会覆盖(替换)旧的值

相关文章:

02_Servlet

目录 一、简介二、Servlet入门案例2.1、编写Servlet2.2、配置Servlet2.3、访问Servlet2.4、常见错误 三、Servlet详解3.1、实现Servlet的三种方式3.1.1、实现Servlet接口3.1.2、继承GenericServlet类3.1.3、继承HttpServlet类 3.2、配置Servlet的两种方式3.2.1、web.xml方式3.2…...

stm32之FLASH

目录 1.简介2.闪存模块组织3.基本结构3.1 FPEC3.2 程序存储器3.2.1 标准编程3.2.2 页擦除3.2.3 全擦除 3.3 选项字节3.3.1 编程3.3.2 擦除 4.器件电子签名5.实验-读取内部FLASH 1.简介 STM32F1系列的FLASH内存是一个非常重要的存储区域&#xff0c;它主要由三个部分组成&#…...

第3.4节 调用链路分析服务开发

3.4.1 什么是Code Call Graph&#xff08;CCG&#xff09; Code Call Graph&#xff08;CCG&#xff09;即业务代码中的调用关系图&#xff0c;是通过静态分析手段分析并构建出的一种描述代码间关系的图。根据精度不同&#xff0c;一般分为类级别、方法级别、控制流级别&#x…...

超详细Docker教程

前言&#xff1a;大家在在Linux上部署mysql及其他软件时&#xff0c;大家想一想自己最大的感受是什么&#xff1f; 我相信&#xff0c;除了个别天赋异禀的人以外&#xff0c;大多数人都会有相同的感受&#xff0c;那就是麻烦。核心体现在三点&#xff1a; 命令太多了&#xff…...

探索AI新领域:生成式人工智能认证(GAI认证)助力职场发展

在数字化时代的大潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术以其强大的影响力和广泛的应用前景&#xff0c;正逐步重塑我们的生活与工作方式。随着生成式AI技术的崛起&#xff0c;掌握这一前沿技能已成为职场竞争中的关键优势。那么&#xff0c;如何通过系统的学…...

sql sql复习

虽然之前学习过sql&#xff0c;但由于重在赶学习进度&#xff0c;没有学扎实&#xff0c;导致自己刷题的时候有的地方还是模模糊糊&#xff0c;现在主要是复习&#xff0c;补一补知识点。 今日靶场&#xff1a; NSSCTF 云曦历年考核题 在做题之前先回顾一下sql注入的原理&…...

初探 Skynet:轻量级分布式游戏服务器框架实战

在游戏服务器开发领域&#xff0c;高效、稳定且易于扩展的框架一直是开发者追求的目标。Skynet 作为一款轻量级、高性能的分布式游戏服务器框架&#xff0c;凭借其独特的设计理念和强大的功能&#xff0c;赢得了众多开发者的青睐 一.Skynet底层架构支持 1.Actor erlang 从语言…...

libarchive.so.19丢失

文章目录 绝对路径可以启动&#xff0c;相对路径不可以以绝对路径启动conda环境&#xff0c;运行python3.8(成功) 报错 Error while loading conda entry point: conda-libmamba-solver (libarchive.so.19: cannot open shared object file: No such file or directory) sudo a…...

vue-ganttastic甘特图label标签横向滚动固定方法

这个甘特图之前插件里&#xff0c;没有找到能固定label标签在屏幕上的办法&#xff0c;用css各种办法都没有实现&#xff0c;所以我我直接手写定位&#xff0c;用js监听滚动条滚动的距离&#xff0c;然后同步移动甘特图label标签&#xff0c;造成一种定位的错觉&#xff0c;以下…...

自动化 NuGet 包打包与上传:完整批处理脚本详解(含 SVN 支持)

在大型项目中&#xff0c;我们常常需要定期打包多个 .csproj 项目为 NuGet 包&#xff0c;并上传到私有 NuGet 服务。这篇文章分享一份实战脚本&#xff0c;支持以下自动化流程&#xff1a; 自动读取、更新 .csproj 文件中的 Version、PackageOutputPath 等节点&#xff1b; 自…...

Go语言空白导入的作用与用途

在 Go 语言中&#xff0c;导入包时前面加下划线 _ 是一种特殊的导入方式&#xff0c;称为 “空白导入” 或 “匿名导入”。 作用&#xff1a; 执行包的初始化&#xff08;init 函数&#xff09;但不直接使用包中的标识符 import _ "go.uber.org/automaxprocs" 表示你…...

实验六:按键模拟控制实现

FPGA序列检测器实验(远程实验系统) 文章目录 FPGA序列检测器实验(远程实验系统)一、数字电路基础知识1. 时钟与同步2. 按键消抖原理代码讲解:分频与消抖3. 有限状态机(FSM)设计代码讲解:状态机编码与转移4. 边沿检测与信号同步5. 模块化设计二、实验数字电路整体思想三…...

【愚公系列】《Manus极简入门》038-数字孪生设计师:“虚实映射师”

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

Linux重定向与缓冲区

目录 文件描述符的分配规则 重定向 使用 dup2 系统调用 FILE 文件描述符的分配规则 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main() {int fd open("myfile", O_RDONLY);if(fd < 0){per…...

经典还原反应解析:Wolff-Kishner机制与黄鸣龙改进法

在有机化学发展史上记载的万余种经典反应中&#xff0c;当论及以科学家命名的标志性转化反应时&#xff0c;Wolff-Kishner-黄鸣龙还原反应必然占据重要地位。在大学《有机化学》课程中&#xff0c;学习还原反应时肯定会提到Wolff-Kishner-黄鸣龙还原反应&#xff0c;这是第一个…...

DataX从Mysql导数据到Hive分区表案例

0、下载DataX并解压到对应目录 DataX安装包&#xff0c;开箱即用&#xff0c;无需配置。 https://datax-opensource.oss-cn-hangzhou.aliyuncs.com/202308/datax.tar.gz 相关参考文档 https://github.com/alibaba/DataX/blob/master/hdfswriter/doc/hdfswriter.md 1、Hive分区…...

npm 报错 gyp verb `which` failed Error: not found: python2 解决方案

一、背景 npm 安装依赖报如下错&#xff1a; gyp verb check python checking for Python executable "python2" in the PATH gyp verb which failed Error: not found: python2 一眼看过去都觉得是Python环境问题&#xff0c;其实并不是你python环境问题&#xf…...

安装npm:npm未随Node.js一起安装

文章目录 上传至linux服务器/usr/local/目录下 如果npm没有随Node.js一起安装&#xff0c;你可以尝试单独下载并安装npm。但通常情况下&#xff0c;这是不必要的&#xff0c;因为npm是Node.js的一部分。如果确实需要单独安装npm&#xff0c;你可以参考npm的官方安装指南。 npm…...

C++23 ranges::to:范围转换函数 (P1206R7)

文章目录 引言C23 Ranges 概述ranges::to 的定义与功能定义功能 使用场景范围转换为容器简化字符串解析映射转换为向量 ranges::to 的优势代码简洁性提高开发效率与C23的stl容器的范围版本构造函数配合良好 模板参数约束的思考总结 引言 在C的发展历程中&#xff0c;每一个新版…...

openfeign 拦截器实现微服务上下文打通

目录 openfeign 拦截器实现微服务上下文打通需求分析&#xff1a;代码实现&#xff1a;subject 服务&#xff1a;controllerFeign 拦截器&#xff1a;将 Feign 拦截器注册为一个Bean&#xff1a; auth 鉴权服务&#xff1a;全局配置类&#xff1a;登录拦截器&#xff1a;上下文…...

【MySQL】变更缓冲区:作用、主要配置以及如何查看

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

TCP/IP-——C++编程详解

1. TCP/IP 编程基本概念 TCP&#xff08;传输控制协议&#xff09;&#xff1a;面向连接、可靠的传输层协议&#xff0c;保证数据顺序和完整性。IP&#xff08;网际协议&#xff09;&#xff1a;负责将数据包路由到目标地址。Socket&#xff08;套接字&#xff09;&#xff1a…...

微服务如何实现服务的高可用

背景&#xff1a;微服务分层需要考虑高可用和高并发的问题 微服务如何实现服务的高可用 先说结论&#xff1a;微服务实现高可用主要通过集群冗余故障自动转移来实现的具体可以从底下几种方案来实现。 “端”到“反向代理”的高可用“反向代理”到“站点应用”的高可用“站点…...

微服务调试问题总结

本地环境调试。 启动本地微服务&#xff0c;使用公共nacos配置。利用如apifox进行本地代码调试解决调试问题。除必要的业务微服务依赖包需要下载到本地。使用mvn clean install -DskipTests进行安装启动前选择好profile环境进行启动&#xff0c;启动前记得mvn clean清理项目。…...

egpo进行train_egpo训练时,keyvalueError:“replay_sequence_length“

def execution_plan(workers: WorkerSet, config: TrainerConfigDict) -> LocalIterator[dict]: if config.get(“prioritized_replay”): prio_args { “prioritized_replay_alpha”: config[“prioritized_replay_alpha”], “prioritized_replay_beta”: config[“prior…...

Hadoop的组成

&#xff08;一&#xff09;Hadoop的组成 对普通用户来说&#xff0c; Hadoop就是一个东西&#xff0c;一个整体&#xff0c;它能给我们提供无限的磁盘用来保存文件&#xff0c;可以使用提供强大的计算能力。 在Hadoop3.X中&#xff0c;hadoop一共有三个组成部分&#…...

Android锁

引言 &#x1f512; 在 Android 应用的开发过程中&#xff0c;随着业务需求的复杂度不断提升&#xff0c;多线程并发场景层出不穷。为了保证数据一致性与线程安全&#xff0c;锁&#xff08;Lock&#xff09;成为了不可或缺的工具。本篇博客将深入剖析 Android 中常用的锁机制…...

XD08M3232接近感应单片机的接近感应模块的工作原理

XD08M3232接近感应单片机的接近感应模块基于电容式感应原理&#xff0c;通过硬件电路与软件配置实现对物体接近的检测。以下是其工作原理的详细解析&#xff1a; 一、硬件架构与核心组件 1. 核心电路组成 接近感应模块由三大关键部分构成&#xff1a; 两个轨到轨运算放大器&…...

编程日志5.6

串的习题 1.2236. 判断根结点是否等于子结点之和 - 力扣(LeetCode) /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * Tr…...

量子计算实用化突破:从云端平台到国际竞合,开启算力革命新纪元

在硅谷某生物医药实验室&#xff0c;研究员艾米丽正盯着量子计算模拟界面露出微笑 —— 搭载中电信 "天衍" 量子计算云平台的 880 比特超导量子处理器&#xff0c;用 17 分钟完成了传统超算需 3 个月才能跑完的新型抗生素分子键合模拟。这个场景标志着量子计算正从 &…...

Made with Unity | 拓展“双点”宇宙版图

双点工作室&#xff08;Two Point Studios&#xff09;团队成立于2016年&#xff0c;其创立初衷是打造一个完美的游戏IP&#xff1a;构建一个既能持续吸引玩家&#xff0c;又具备足够扩展空间&#xff0c;同时经得起时间考验的虚拟世界。2018年&#xff0c;团队以《双点医院&am…...

3D 数据可视化系统是什么?具体应用在哪方面?

目录 一、3D 数据可视化系统的定义与内涵 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;核心要素 二、3D 数据可视化系统的优势 三、3D 数据可视化系统的应用领域 &#xff08;一&#xff09;城市规划与管理 &#xff08;二&#xff09;工业制造 &am…...

2025-5-14渗透测试:利用Printer Bug ,NTLMv2 Hash Relay(中继攻击),CVE-2019-1040漏洞复现

python3 printerbug.py test.com/test192.168.186.131 192.168.186.134 sudo python2 MultiRelay.py -t 192.168.186.132 -u ALLPrinter Bug 原理 PrinterBug&#xff08;CVE-2018-0886&#xff09;是Windows打印系统服务&#xff08;Spooler&#xff09;的一个设计缺陷&…...

OracleLinux7.9-ssh问题

有套rac环境&#xff0c;db1主机无法ssh db1和db1-priv&#xff0c;可以ssh登录 db2和db2-priv [rootdb1 ~]# ssh db1 ^C [rootdb1 ~]# ssh db2 Last login: Wed May 14 18:25:19 2025 from db2 [rootdb2 ~]# ssh db2 Last login: Wed May 14 18:25:35 2025 from db1 [rootdb2…...

《AI大模型应知应会100篇》第64篇:构建你的第一个大模型 Chatbot

第64篇&#xff1a;构建你的第一个大模型 Chatbot 手把手教你从零开始搭建一个基于大模型的聊天机器人 摘要 你是否想过&#xff0c;自己也能构建一个像 ChatGPT 一样能对话、能思考的聊天机器人&#xff08;Chatbot&#xff09;&#xff1f;别担心&#xff0c;这并不需要你是…...

鸿蒙OSUniApp 实现精美的用户登录和注册页面#三方框架 #Uniapp

UniApp 实现精美的用户登录和注册页面 前言 在开发鸿蒙APP时&#xff0c;登录注册页面作为用户与应用交互的第一道门槛&#xff0c;其体验与质量往往决定了用户的第一印象。去年我接手了一个电商小程序项目&#xff0c;产品经理特别强调要做一个既美观又实用的登录注册页面。…...

c#中equal方法与gethashcode方法之间有何关联?

文章目录 前言一、对hash运算的深入思考二、equal与gethashcode的关联三、 equal与gethashcode不同步的后果四、 规范的重写gethashcode 前言 大家有没有遇到过&#xff0c;当你重写了c#对象的equal方法之后&#xff0c;编译器会提示你对相应的gethashcode进行重写&#xff0c…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案

本地搭建服务并提供互联网连接时&#xff0c;较为传统的方法是使用公网IP地址。因此&#xff0c;如何查询本地自己是不是公网IP&#xff0c;是必须要掌握的一种技巧。当面对确实无公网IP时&#xff0c;则可以通过内网穿透方案&#xff0c;如nat123网络映射工具&#xff0c;将本…...

【轻松学 C:编程小白的大冒险】— 16 函数的定义与调用

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【轻松学 C&#xff1a;编程小白的大冒险…...

【Tools】CPU 分析

CPU 分析 Windows SDK 本指南提供了可用于调查影响评估指标的中央处理单元 (CPU) 相关问题的详细技术。 特定于评估的分析指南中的各个指标或问题部分确定了需要调查的常见问题。 本指南提供了可用于调查这些问题的技术和工具。 本指南中的技术使用 Windows Performance Too…...

进阶2_1:QT5多线程与定时器共生死

1、在widget.ui中使用 LCD Number控件 注意&#xff1a;若 LCD 控件不是多线程&#xff0c;LCD控件则会瞬间自增到最大的数值&#xff0c;如上图&#xff0c;说明两者都是多线程处理 2、实现方式 1、创建 LCD 控件并修改为 LCD1 2、创建任务类 mytask. h&#xff0c;对任务类…...

ECharts:数据可视化的强大引擎

在当今这个信息爆炸的时代&#xff0c;如何有效地展示和理解复杂的数据成为了每一个开发者和技术爱好者面临的挑战。Apache ECharts 作为一款基于 JavaScript 的开源可视化库&#xff0c;以其强大的功能、丰富的图表类型以及高度的可定制性&#xff0c;迅速成为了数据可视化领域…...

记录 QT 在liunx 下 QFileDialog 类调用问题 ()Linux下QFileDialog没反应)

1. 2025.05.14 踩坑记录 因为QT 在 liunx 文件系统不同导致的 Windows &#xff1a; QString filePath QFileDialog::getOpenFileName(nullptr, "选择文件", ".", "文本文件 (*.txt);所有文件 (*.*)"); 没问题 liunx 下 打不开&#xff…...

通用软件项目技术报告 - 导读III

现在,我们正式进入报告的第六个主要领域:6. 领域六:与第三方服务/API 集成 (含 LLM API)。 连接: 在现代软件开发中,很少有应用程序是完全孤立的。我们经常需要与各种外部的第三方服务或 API 进行集成,以利用它们提供的特定功能(如支付处理、地图服务、社交媒体登录、云…...

Kali Linux 桌面环境安装与配置指南

一、为什么选择 Kali Linux&#xff1f; Kali Linux 由 Offensive Security 维护&#xff0c;集成了数百种安全测试工具&#xff08;如 Metasploit、Nmap 和 Burp Suite&#xff09;&#xff0c;非常适合安全研究。但需要注意的是&#xff0c;Kali 默认以 root 用户运行&#…...

FFmpeg视频编码的完整操作指南

步骤如下&#xff1a; 安装和准备FFmpeg&#xff1a;确保包含所需编码器&#xff08;如libx264&#xff09;。基本命令行编码&#xff1a;使用ffmpeg命令进行转码&#xff0c;设置视频编码器、CRF、预设等。API编码流程&#xff08;针对开发者&#xff09;&#xff1a; a. 注册…...

【网络协议】TCP、HTTP、MQTT 和 WebSocket 对比

从协议本质、工作原理、特点、应用场景等方面详细对比 TCP、HTTP、MQTT 和 WebSocket。 1. TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09; 本质 协议类型&#xff1a;传输层协议&#xff08;OSI模型第4层&#xff09;。核心功能&#x…...

Leetcode数组day1

704 二分查找 注意点&#xff0c;左闭右闭 class Solution { public:int search(vector<int>& nums, int target) {//整数类型的动态数组的引用。int left0;int right nums.size()-1;while (left < right){int middle (rightleft)/2;if (nums[middle]>targ…...

leetcode2934. 最大化数组末位元素的最少操作次数-medium

1 题目&#xff1a;最大化数组末位元素的最少操作次数 官方标定难度&#xff1a;中 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;这两个数组的长度都是 n 。 你可以执行一系列 操作&#xff08;可能不执行&#xff09;。 在每次操作中&#xff0c;你可以选…...

常见相机焦段的分类及其应用

相机焦段是指镜头的焦距范围&#xff0c;决定了拍摄时的视角、画面范围和透视效果。不同焦段适合不同的拍摄场景和主题&#xff0c;以下是常见焦段的分类及其应用&#xff1a; 一、焦段的核心概念 焦距&#xff1a;镜头光学中心到成像传感器的距离&#xff08;单位&#xff1a…...