Java Web——动态Web开发核心-Servlet

1. 官方文档

官方文档地址:Overview (Servlet 4.0 API Documentation - Apache Tomcat 9.0.83)

servlet 与 Tomcat 的关系:Tomcat 支持 Servlet

Tomcat 是一个开源的 Java 服务器,它主要用来提供 Web 服务,包括 HTTP 请求和响应的处理。Servlet 是 Java 的一种技术,用于创建动态 Web 应用程序。

Tomcat 支持 Servlet,这意味着你可以在 Tomcat 服务器上运行 Servlet 程序。Tomcat 为 Servlet 提供了一个运行环境,使得你可以使用 Servlet 技术来开发并部署 Web 应用程序。

简单来说,如果你想使用 Servlet 技术来开发 Web 应用程序,你需要一个支持 Servlet 的服务器,而 Tomcat 就是一个很好的选择。


2. Servlet概述

Servlet 是 Java 的一种技术,就是用Java编写的,本质就是Java类,用于创建动态 Web 应用程序。它是

一个运行在服务器端的 Java 小程序,可以响应客户端的请求,处理数据,并返回响应结果。Servlet 由

Sun Microsystems 公司提供一套规范,定义了动态资源如何在 Web 服务器上运行。

从代码层面上讲,Servlet 是一个接口,这意味着它定义了一组方法,这些方法可以由 Web 服务器调用。

在 Tomcat 中,Servlet 运行在一个称为“容器”的环境中。Tomcat 为 Servlet 提供了一个运行环境,这

个容器负责加载和运行 Servlet。Tomcat 会将来自客户端的 HTTP 请求转发给 Servlet 处理,并将

Servlet 的响应返回给客户端。

因此,Servlet 和 Tomcat 是相互依存的。如果你想使用 Servlet 技术来开发 Web 应用程序,你需要一个

支持 Servlet 的服务器,而 Tomcat 就是一个很好的选择。


简单总结就是:

Servlet是一种用于接收、处理客户端请求、响应给浏览器的动态资源的Java类。它必须满足特定的接口规范,并需要被部署在支持Servlet的Web服务器或应用服务器上才能正常运行。


3. Servlet基本使用

需求:

开发一个 HelloServlet

当浏览器 访问 http://localhost:8080/web 应用名/helloServlet 时,后台输出 "Hi HelloServelt"

具体步骤:

  1. 用IDEA创建一个项目,配置好Tomcat服务器


  1. 添加servlet-api.jar(在tomcat/lib下) 到工程, 因为servlet.jar 不是jdk自带的, 要引入

这里用两种方法:一个是自己导入实体Tomcatlib文件夹下的servlet的jar包

二是在pom文件配置联网下载Servlet的jar包


  1. 创建HelloServlet.java类,并实现Servlet接口
package com.example;

import javax.servlet.*;

//创建一个Servlet类,要实现Servlet接口
//实现接口的5个方法,但常用的是3个

public class HelloServlet implements Servlet {

    /*
    * 该方法常用
    * init初始化方法,在服务器启动时调用该方法
    * 该方法只执行一次
    * */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init方法被调用~");
    }

    /*
    * getServletConfig方法
    * 返回ServletConfig 也就是返回ServLet的配置
    * */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /*
    * 该方法使用的非常多
    * service方法,在服务器接收到请求时(含get/post方法)调用该方法
    * 该方法每次请求都会被调用
    * 该方法会把http请求转为Java对象,进行一系列操作
    * 处理请求之后会把Java对象转为http响应,返回给客户端
    * */
    @Override
    public void service(ServletRequest req, ServletResponse res) {
    	System.out.println("Hello Servlet!");
    }
    
    /*
    * getServletInfo方法
    * 返回Servlet的描述信息*/
    @Override
    public String getServletInfo() {
        return null;
    }

    /*
     * 该方法常用
     * destroy销毁方法,
     * 在服务器关闭时调用该方法
     * 该方法只执行一次
     * */
    @Override
    public void destroy() {

    }
}
  • init(ServletConfig config): 这个方法在Servlet创建后立即被调用,一般用于初始化Servlet。它只会被调用一次。你可以在这里进行一些只需要在Servlet创建时执行一次的代码,例如加载一些配置信息。
  • getServletConfig(): 这个方法返回一个ServletConfig对象,该对象包含了Servlet的配置信息。通常,你会在init(ServletConfig config)方法中获取这些配置信息,并在需要的时候使用。
  • service(ServletRequest req, ServletResponse res): 这个方法是最重要的,它处理所有的HTTP请求。当服务器收到一个新的HTTP请求时,就会调用这个方法。这个方法会接收一个ServletRequest对象和一个ServletResponse对象作为参数。ServletRequest对象包含了客户端发送的请求信息,而ServletResponse对象则用于向客户端发送响应。
  • getServletInfo( ): 这个方法返回一个字符串,用于描述Servlet的信息。这个字符串可以包含任何你希望提供的信息,例如版本信息、版权信息等。
  • destroy( ): 这个方法在服务器关闭时被调用,用于清理资源。它只会被调用一次。在这个方法中,你可以执行一些在服务器关闭时需要执行的代码,例如关闭数据库连接或者释放其他资源。

记住,虽然这五个方法都是可选的,但init()、service()和destroy()是最常用的


  1. 在web.xml文件下配置HelloServlet的映射

为什么要怎么做,不进行这步,刚才写的Servlet是没办法调用实现功能的。

因为Servlet容器不知道如何将客户端的请求分发到该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_4_0.xsd"
         version="4.0">

    <!--servlet-name 是servlet的名称,HelloServlet是servlet的类名-->
    <!--servlet-class 是servlet的全路径-->
    <!--servlet-mapping 是servlet的映射路径-->
    <!--url-patter 是servlet的访问路径-->
    <!--这样就可以访问/hello-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.example.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>
  • <servlet-name>:这是servlet的名称,通常用于标识servlet。在这里,servlet的名称是HelloServlet。
  • <servlet-class>:这是servlet的全路径,也就是servlet类的完整类名。在这里,servlet的类名是com.example.HelloServlet。
  • <servlet-mapping>:这个元素用于将servlet映射到URL模式。这意味着当应用程序接收到与该URL模式匹配的请求时,会调用相应的servlet。
  • <servlet-name>:在<servlet-mapping>元素中,我们需要指定与<servlet>元素中相同的servlet名称。这样,服务器就知道哪个URL模式应该与哪个servlet关联。
  • <url-pattern>:这是URL模式,指定了可以通过哪些URL访问该servlet。在这里,URL模式是/hello,这意味着可以通过在浏览器中输入http://localhost:8080/appName/hello(其中appName是应用程序的名称)来访问该servlet。

  1. 运行启动Tomcat服务器

在浏览器输入对应的地址并回车

IDEA控制台显示刚才在Servlet方法中的输出信息

如果此时多次刷新该页面,控制台会多次输出 “Hello Servlet”


3.1. 浏览器调用Servlet的流程

第一次HTTP请求:(也就是在浏览器地址栏输入回车对应的地址)

  1. Tomcat接收到HTTP请求后,会根据请求的URL路径在web.xml中进行匹配,找到对应的URL Pattern。

先在web.xml文件上找url-pattern是否有对应的,也就是“/hello”。如果有就会得到对应的servlet-name:HelloServlet。

同时,Tomcat维护了一个很大的HashMap<id,servlet>,查询HashMap中有没有这个servlet实例。根据servlet-name:HelloServlet去查询对应的id。

查询有这个servlet-name:HelloServlet的话,就会根据相应的servlet-class找到该类的全路径,找这个类在这个项目的哪里。

最后使用反射技术,将servlet实例化 -> init( )

并放到Tomcat维护的HashMap<id,Servlet>中去

  1. Tomcat会调用Servlet类的service()方法来处理HTTP请求。

在service()方法中,可以根据请求的类型(GET、POST等)和URL路径来确定 具体要执行的方法。

  1. 执行完service()方法后,Tomcat会返回响应给客户端。
  2. Tomcat会根据需要销毁或重新实例化Servlet类,以供下一次请求使用。

第二次及以后的相同HTTP请求,Tomcat会执行以下步骤:

  1. Tomcat接收到HTTP请求后,会根据请求的URL路径在web.xml中进行匹配,找到对应的Servlet类或URL Pattern。
  2. Tomcat会根据匹配结果直接调用已经实例化的Servlet类的service()方法来处理HTTP请求。
  3. 在service()方法中,可以根据请求的类型(GET、POST等)和URL路径来确定具体要执行的方法。
  4. 执行完service()方法后,Tomcat会返回响应给客户端。

对于第二次及以后的相同HTTP请求,Tomcat会有以下的不同:

  • Tomcat会直接根据之前已经实例化的Servlet类来处理请求,而不需要再次实例化。
  • Tomcat会直接调用已经初始化的Servlet类的service()方法来处理请求,而不需要再次调用init()方法进行初始化。

3.2. Servlet生命周期

  1. Servlet生命周期概述

Servlet的生命周期是指从创建Servlet对象到销毁Servlet对象的过程。这个过程包括三个阶段:初始化(init)、服务(service)和销毁(destroy)。

  1. 初始化阶段(init):当Servlet第一次被加载到内存时,Servlet容器会调用Servlet的init()方法进行初始化。init()方法在Servlet的整个生命周期中只会被调用一次。
  2. 服务阶段(service):当客户端发送请求时,Servlet容器会调用service()方法来处理客户端的请求。service()方法可以处理GET、POST等不同类型的请求。
  3. 销毁阶段(destroy):当Servlet不再需要时,Servlet容器会调用destroy()方法来销毁Servlet对象。在销毁阶段,Servlet对象将不再可用。

总之,Servlet的生命周期是指从创建Servlet对象到销毁Servlet对象的过程,包括初始化、服务和销毁三个阶段。


  1. Servlet容器

Servlet容器是一个运行环境,它负责创建Servlet对象,并调用Servlet的生命周期方法。Servlet容器负责管理Servlet的生命周期,包括初始化、服务和销毁阶段。

在Servlet的生命周期中,Servlet容器会调用Servlet的init()方法进行初始化,然后根据客户端的请求调用service()方法来处理请求。当Servlet不再需要时,Servlet容器会调用destroy()方法来销毁Servlet对象。


  1. Servlet主要的生命周期执行特点

生命周期

对应方法

执行时机

执行次数

构造对象

构造器

第一次请求或者容器启动

1

初始化

init()

构造完毕后

1

处理服务

service(HttpServletRequest req,HttpServletResponse resp)

每次请求

多次

销毁

destory()

容器关闭

1

简单讲,Servlet的生命周期就是从创建Servlet对象开始,经过初始化、处理服务,最后到销毁Servlet对象的过程。在这个过程中,开发人员可以关注和实现业务逻辑,而Servlet容器会负责调用相应的生命周期方法。


3.3. Get/Post请求的分发处理

当我们在开发Web应用程序时,通常需要处理两种主要的HTTP请求方法:Get和Post。

在Servlet开发中,我们通常会为这两种请求方法编写不同的处理逻辑。这是通过在Servlet中重写doGet和doPost方法来完成的。这两个方法是Java Servlet API定义的一部分,用于处理HTTP请求。

  • doGet方法:当请求是通过GET方法发送时,Servlet容器会调用doGet方法。GET请求通常用于获取或查询资源,而不是发送数据。由于GET请求通常在URL中包含数据,因此这些数据可以在浏览器的地址栏中看到。因此,GET请求通常不适合发送敏感或大量数据。
  • doPost方法:当请求是通过POST方法发送时,Servlet容器会调用doPost方法。POST请求通常用于发送数据,而不是获取资源。与GET请求不同,POST请求中的数据不会显示在URL中,因此更适合发送敏感或大量数据。

代码演示:

  1. 准备一个前端静态的注册页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <h1>用户注册</h1>
    <form action="http://localhost:8080/_1_25_1_war_exploded/hello" method="post">
        <input type="text" name="username" placeholder="请输入用户名">
        <input type="submit" value="注册">
    </form>
</body>
</html>


  1. 后端Servlet写上相应的处理

后端的Servlet就用刚刚的HelloServlet,方便,web.xml也不用配置

注意:前端页面提交的数据是请求对象,但在service方法中的ServletRequest中并没有对应的方法去获取这个请求对象,怎么办,查看ServletRequest的子类是否有

但是ServletRequest类的实现类中的HttpServletRequest含有这个方法

显示下面这个界面是在IDEA中同时按下Ctrl+Alt再鼠标指向ServletRequest

该操作可以查看该接口的子接口和实现子类

所以就有了如下代码:

  1. 启动服务器,地址栏输入相关地址,并输入数据点击注册

  1. 结合上面Servlet中service写的方法,查看结果

控制台输出了这些

原因如下:

同理,如果前端中method的方法写成get,控制台也会有相应的输出


4. Servlet继承结构

下面两个是抽象类,上面仨是接口,具体源码可以自己在IDEA中Ctrl+鼠标键详情查看

这里稍微“简单”介绍一下:

Servlet接口

源码及功能解释

  • 通过idea查看: 此处略

接口及方法说明

  • Servlet 规范接口,所有的Servlet必须实现
    • public void init(ServletConfig config) throws ServletException;
      • 初始化方法,容器在构造servlet对象后,自动调用的方法,容器负责实例化一个ServletConfig对象,并在调用该方法时传入
      • ServletConfig对象可以为Servlet 提供初始化参数
    • public ServletConfig getServletConfig();
      • 获取ServletConfig对象的方法,后续可以通过该对象获取Servlet初始化参数
    • public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
      • 处理请求并做出响应的服务方法,每次请求产生时由容器调用
      • 容器创建一个ServletRequest对象和ServletResponse对象,容器在调用service方法时,传入这两个对象
    • public String getServletInfo();
      • 获取ServletInfo信息的方法
    • public void destroy();
      • Servlet实例在销毁之前调用的方法

GenericServlet 抽象类

源码

  • 通过idea查看: 此处略

源码解释

  • GenericServlet 抽象类是对Servlet接口一些固定功能的粗糙实现,以及对service方法的再次抽象声明,并定义了一些其他相关功能方法
    • private transient ServletConfig config;
      • 初始化配置对象作为属性
    • public GenericServlet() { }
      • 构造器,为了满足继承而准备
    • public void destroy() { }
      • 销毁方法的平庸实现
    • public String getInitParameter(String name)
      • 获取初始参数的快捷方法
    • public Enumeration getInitParameterNames()
      • 返回所有初始化参数名的方法
    • public ServletConfig getServletConfig()
      • 获取初始Servlet初始配置对象ServletConfig的方法
    • public ServletContext getServletContext()
      • 获取上下文对象ServletContext的方法
    • public String getServletInfo()
      • 获取Servlet信息的平庸实现
    • public void init(ServletConfig config) throws ServletException()
      • 初始化方法的实现,并在此调用了init的重载方法
    • public void init() throws ServletException
      • 重载init方法,为了让我们自己定义初始化功能的方法
    • public void log(String msg)
    • public void log(String message, Throwable t)
      • 打印日志的方法及重载
    • public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
      • 服务方法再次声明
    • public String getServletName()
      • 获取ServletName的方法

HttpServlet 抽象类

源码

  • 通过idea查看: 此处略

解释

  • abstract class HttpServlet extends GenericServlet  HttpServlet抽象类,除了基本的实现以外,增加了更多的基础功能
    • private static final String METHOD_DELETE = "DELETE";
    • private static final String METHOD_HEAD = "HEAD";
    • private static final String METHOD_GET = "GET";
    • private static final String METHOD_OPTIONS = "OPTIONS";
    • private static final String METHOD_POST = "POST";
    • private static final String METHOD_PUT = "PUT";
    • private static final String METHOD_TRACE = "TRACE";
      • 上述属性用于定义常见请求方式名常量值
    • public HttpServlet() {}
      • 构造器,用于处理继承
    • public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
      • 对服务方法的实现
      • 在该方法中,将请求和响应对象转换成对应HTTP协议的HttpServletRequest HttpServletResponse对象
      • 调用重载的service方法
    • public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
      • 重载的service方法,被重写的service方法所调用
      • 在该方法中,通过请求方式判断,调用具体的do***方法完成请求的处理
    • protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    • protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
      • 对应不同请求方式的处理方法
      • 除了doOptions和doTrace方法,其他的do*** 方法都在故意响应错误信息

5. 继承HttpServlet开发Servlet

5.1. HttpServlet介绍

实际开发中,在Servlet的继承体系下,很少直接实现Servlet接口去写代码,更多的是使用HttpServlet

自己写一个自定义的Servlet接口去继承HttpServlet抽象类


5.2. 使用相关代码测试

HelloServlet

快捷生成doget、dopost的方法

右键选择生成或则Alt+insert键

找到重写方法

在选择对应的doget、dopost方法即可

对应的web.xml文件配置

register.html

注意,这里是post方法

启动服务器,并输入相关地址


5.3. HttpServletRequest

  1. HttpServletRequest概念

HttpServletRequest是Java Servlet API中的一个核心接口,它代表了来自客户端的HTTP请求。这个接口提供了许多方法,用于获取请求的各种属性和参数,如请求的URI、请求方法、请求头信息、请求参数等。

当一个HTTP请求到达Servlet容器(如Tomcat)时,容器会将请求报文转换成一个HttpServletRequest对象,并将这个对象作为参数传递给Servlet的service方法。这样,Servlet就可以通过HttpServletRequest对象获取到所有关于该请求的信息,从而进行处理。


  1. HttpServletRequest常见API
  • 获取请求行信息相关(方式,请求的url,协议及版本)

API

功能解释

StringBuffer getRequestURL();

获取客户端请求的url

String getRequestURI();

获取客户端请求项目中的具体资源

int getServerPort();

获取客户端发送请求时的端口

int getLocalPort();

获取本应用在所在容器的端口

int getRemotePort();

获取客户端程序的端口

String getScheme();

获取请求协议

String getProtocol();

获取请求协议及版本号

String getMethod();

获取请求方式

  • 获得请求头信息相关

API

功能解释

String getHeader(String headerName);

根据头名称获取请求头

Enumeration getHeaderNames();

获取所有的请求头名字

String getContentType();

获取content-type请求头

  • 获得请求参数相关

API

功能解释

String getParameter(String parameterName);

根据请求参数名获取请求单个参数值

String[] getParameterValues(String parameterName);

根据请求参数名获取请求多个参数值数组

Enumeration getParameterNames();

获取所有请求参数名

Map<String, String[]> getParameterMap();

获取所有请求参数的键值对集合

BufferedReader getReader() throws IOException;

获取读取请求体的字符输入流

ServletInputStream getInputStream() throws IOException;

获取读取请求体的字节输入流

int getContentLength();

获得请求体长度的字节数

  • 其他API

API

功能解释

String getServletPath();

获取请求的Servlet的映射路径

ServletContext getServletContext();

获取ServletContext对象

Cookie[] getCookies();

获取请求中的所有cookie

HttpSession getSession();

获取Session对象

void setCharacterEncoding(String encoding) ;

设置请求体字符集


5.4. HttpServletResponse

  1. HttpServletResponse概念

HttpServletResponse是Java Servlet API中的另一个核心接口,它代表了服务器对客户端的响应。这个接口提供了一些方法,用于设置响应头信息、输出响应内容、设置响应状态等。

当Servlet的service方法处理完请求后,它可以通过HttpServletResponse对象将响应内容写入到响应报文中,并将响应报文发送给客户端。通过HttpServletResponse对象,Servlet可以设置响应的状态码、响应头信息、响应内容等。


  1. HttpServletResponse常见API
  • 设置响应行相关

API

功能解释

void setStatus(int  code);

设置响应状态码

  • 设置响应头相关

API

功能解释

void setHeader(String headerName, String headerValue);

设置/修改响应头键值对

void setContentType(String contentType);

设置content-type响应头及响应字符集(设置MIME类型)

  • 设置响应体相关

API

功能解释

PrintWriter getWriter() throws IOException;

获得向响应体放入信息的字符输出流

ServletOutputStream getOutputStream() throws IOException;

获得向响应体放入信息的字节输出流

void setContentLength(int length);

设置响应体的字节长度,其实就是在设置content-length响应头

  • 其他API

API

功能解释

void sendError(int code, String message) throws IOException;

向客户端响应错误信息的方法,需要指定响应码和响应信息

void addCookie(Cookie cookie);

向响应体中增加cookie

void setCharacterEncoding(String encoding);

设置响应体字符集

MIME类型

  • MIME类型,可以理解为文档类型,用户表示传递的数据是属于什么类型的文档
  • 浏览器可以根据MIME类型决定该用什么样的方式解析接收到的响应体数据
  • 可以这样理解: 前后端交互数据时,告诉对方发给对方的是 html/css/js/图片/声音/视频/... ...
  • tomcat/conf/web.xml中配置了常见文件的拓展名和MIMIE类型的对应关系
  • 常见的MIME类型举例如下

文件拓展名

MIME类型

.html

text/html

.css

text/css

.js

application/javascript

.png /.jpeg/.jpg/... ...

image/jpeg

.mp3/.mpe/.mpeg/ ... ...

audio/mpeg

.mp4

video/mp4

.m1v/.m1v/.m2v/.mpe/... ...

video/mpeg


6. Servlet注意事项

  1. Servlet 是一个特殊的 Java 类,用于在 Web 服务器或应用服务器上提供动态内容。它们不能独立运行,需要在一个 Servlet 容器(或称为 Servlet 引擎)中运行。

Servlet 容器提供了一个环境,让 Servlet 能够与 HTTP 请求和响应进行交互,并提供了诸如生命周期管理、安全性和并发处理等重要功能。

Servlet 实现了一个叫做 javax.servlet.Servlet 的接口,这个接口定义了一些方法,比如 init(), service(), doGet(), doPost(), 和 destroy()。这些方法使得 Servlet 能够处理 HTTP 请求,生成响应,以及在 Servlet 的生命周期中进行必要的操作。

为了运行 Servlet,你需要一个 Servlet 容器,比如 Tomcat 或者 Jetty。这些容器会加载 Servlet 类,管理它们的生命周期,并提供一个环境让它们能够与 HTTP 请求和响应进行交互。


  1. 对于每次请求,服务器通常只会创建一个Servlet实例,这个实例会一直存在直到Web应用程序被重新部署或服务器关闭。每个请求会得到一个新的对象实例来处理,但实例变量在每次请求后会被重置。当Web应用程序被重新部署或服务器重启时,所有的Servlet实例都会被销毁并重新创建,以确保正确运行。


  1. 在Servlet的生命周期中,init方法是只被调用一次的。这是因为Servlet的实例在服务器启动时就被创建,然后一直存在,直到Web应用程序被重新部署或服务器关闭。在Servlet的生命周期内,init方法只会在Servlet实例创建时被调用一次,用于初始化Servlet。
  2. 对于每次用户发出的请求,Servlet引擎都会调用一次Servlet的service方法。这个service方法会接收两个参数:HttpServletRequest请求对象和HttpServletResponse响应对象。这两个对象是Servlet引擎为每个请求创建的新的对象。
  3. 对于每次用户请求,Servlet引擎都会为每个请求创建一个新的HttpServletRequest对象和一个新的HttpServletResponse对象。这两个对象包含了请求和响应的所有信息。这些对象会被传递给service方法,service方法会根据请求的方式(如GET、POST等)来调用doXXX方法(如doGet、doPost等)来处理请求。

7. ServletConfig和ServletContext

7.1. ServletConfig的使用

ServletConfig是Java Servlet API中的一个接口,它提供了Servlet的初始化配置参数。每个Servlet实例都有一个自己独立且唯一的ServletConfig对象。

当Web应用程序被部署并启动时,Servlet容器会实例化每个Servlet,并为每个Servlet实例创建一个ServletConfig对象。这个ServletConfig对象包含了在Web应用程序的部署描述符(web.xml文件)中为该Servlet指定的初始化参数。

这些初始化参数可以在Servlet的初始化方法(init())中被访问和利用。在Servlet的生命周期中,ServletConfig对象作为属性被传递给Servlet的init方法。这样,Servlet就可以在初始化时获取到它所需要的配置信息,从而进行相应的初始化操作。

举个简单的例子就是:

ServletConfig可以类比为一家餐厅的菜单。当顾客进入餐厅时,他们会看到菜单,并根据菜单选择他们想吃的菜品。菜单提供了关于菜品的信息,如菜名、价格、食材等。同样地,ServletConfig提供了关于Servlet的信息,如Servlet的名称、初始化参数等。

在Web应用程序中,Servlet扮演着处理请求的角色,就像餐厅中的服务员一样。当一个请求到达Servlet时,Servlet会根据ServletConfig中的信息来处理请求。就像服务员根据菜单上的信息为顾客提供服务一样。


ServletConfig 类能干什么

  • 获取 Servlet 程序的 servlet-name 的值:通过调用 getServletName() 方法,可以获取 Servlet 的名称。这个名称是在 web 应用程序的部署描述符(web.xml 文件)中定义的。
  • 获取初始化参数 init-param:ServletConfig 接口提供了 getInitParameter 方法,用于获取在 web.xml 文件中为 Servlet 定义的初始化参数。这些参数可以在 Servlet 的生命周期中使用。
  • 获取 ServletContext:通过调用 getServletContext 方法,可以获取与当前 Servlet 关联的 ServletContext 对象。ServletContext 是整个 web 应用程序共享的上下文,它包含了与该应用程序相关的数据和属性。


ServletConfig是一个接口,定义了如下API:

package jakarta.servlet;
import java.util.Enumeration;
public interface ServletConfig {
    String getServletName();
    ServletContext getServletContext();
    String getInitParameter(String var1);
    Enumeration<String> getInitParameterNames();
}

方法名

作用

getServletName()

获取<servlet-name>HelloServlet</servlet-name>定义的Servlet名称

getServletContext()

获取ServletContext对象

getInitParameter()

获取配置Servlet时设置的『初始化参数』,根据名字获取值

getInitParameterNames()

获取所有初始化参数名组成的Enumeration对象


ServletConfig怎么用,测试代码如下

  • 定义Servlet
public class ServletA extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletConfig servletConfig = this.getServletConfig();
        // 根据参数名获取单个参数
        String value = servletConfig.getInitParameter("param1");
        System.out.println("param1:"+value);
        // 获取所有参数名
        Enumeration<String> parameterNames = servletConfig.getInitParameterNames();
        // 迭代并获取参数名
        while (parameterNames.hasMoreElements()) {
            String paramaterName = parameterNames.nextElement();
            System.out.println(paramaterName+":"+servletConfig.getInitParameter(paramaterName));
        }
    }
}



public class ServletB extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletConfig servletConfig = this.getServletConfig();
        // 根据参数名获取单个参数
        String value = servletConfig.getInitParameter("param1");
        System.out.println("param1:"+value);
        // 获取所有参数名
        Enumeration<String> parameterNames = servletConfig.getInitParameterNames();
        // 迭代并获取参数名
        while (parameterNames.hasMoreElements()) {
            String paramaterName = parameterNames.nextElement();
            System.out.println(paramaterName+":"+servletConfig.getInitParameter(paramaterName));
        }
    }
}

  • 配置Servlet
  <servlet>
       <servlet-name>ServletA</servlet-name>
       <servlet-class>com.atguigu.servlet.ServletA</servlet-class>
       <!--配置ServletA的初始参数-->
       <init-param>
           <param-name>param1</param-name>
           <param-value>value1</param-value>
       </init-param>
       <init-param>
           <param-name>param2</param-name>
           <param-value>value2</param-value>
       </init-param>
   </servlet>

    <servlet>
        <servlet-name>ServletB</servlet-name>
        <servlet-class>com.atguigu.servlet.ServletB</servlet-class>
        <!--配置ServletB的初始参数-->
        <init-param>
            <param-name>param3</param-name>
            <param-value>value3</param-value>
        </init-param>
        <init-param>
            <param-name>param4</param-name>
            <param-value>value4</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletA</servlet-name>
        <url-pattern>/servletA</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>ServletB</servlet-name>
        <url-pattern>/servletB</url-pattern>
    </servlet-mapping>

7.2. ServletContext的使用

ServletContext是Java Servlet API中的一个接口,它代表了Web应用程序的上下文,也称为应用域对象。在Web应用程序中,每个应用程序都会有一个唯一的ServletContext对象。这个对象由Servlet容器在应用程序启动时创建,并在整个应用程序的生命周期内保持存在。

ServletContext对象是所有Servlet共享的,这意味着在同一个Web应用程序中,所有的Servlet都可以访问和修改同一个ServletContext对象。这为Servlet之间的数据共享和协作提供了方便的机制。

ServletContext可以为所有的Servlet提供初始配置参数。这些参数可以在Web应用程序的部署描述符(web.xml文件)中定义。当Web应用程序启动时,容器会将这些参数传递给每个Servlet,作为它们的初始化参数。这样,Servlet就可以在初始化时获取到它们所需要的配置信息。

简单来说,ServletContext就像是一个大的共享容器,它存储了Web应用程序的配置信息,并且可以被所有的Servlet访问和修改。

ServletContext怎么用

  • 配置ServletContext参数
<?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
          version="5.0">
 
     <context-param>
         <param-name>paramA</param-name>
         <param-value>valueA</param-value>
     </context-param>
     <context-param>
         <param-name>paramB</param-name>
         <param-value>valueB</param-value>
     </context-param>
 </web-app>
  • 在Servlet中获取ServletContext并获取参数
package com.atguigu.servlet;
 
 import jakarta.servlet.ServletConfig;
 import jakarta.servlet.ServletContext;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServlet;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
 import java.io.IOException;
 import java.util.Enumeration;
 
 public class ServletA extends HttpServlet {
     @Override
     protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
         // 从ServletContext中获取为所有的Servlet准备的参数
         ServletContext servletContext = this.getServletContext();
         String valueA = servletContext.getInitParameter("paramA");
         System.out.println("paramA:"+valueA);
         // 获取所有参数名
         Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
         // 迭代并获取参数名
         while (initParameterNames.hasMoreElements()) {
             String paramaterName = initParameterNames.nextElement();
             System.out.println(paramaterName+":"+servletContext.getInitParameter(paramaterName));
         }
     }
 }

8. Servlet注解方式

8.1. 定义

@WebServlet注解是Java Servlet API的一部分,用于在Java Servlet应用程序中定义Servlet。它允许开发人员将Servlet类映射到特定的URL路径或Servlet名称,以便处理来自客户端的请求。

通过使用@WebServlet注解,开发人员可以将Servlet类与特定的URL模式关联起来,以便当客户端发出请求时,Servlet可以拦截和处理这些请求。这个注解可以用于将Servlet映射到根路径或特定的子路径,以及指定Servlet的初始化参数和其他配置选项。


8.2. 代码演示

MyServlet.java

不在web.xml进行配置

前端测试代码,action设置为注解的urlPatterns

启动服务器
 

从上面也看出来了,@WebServlet注解确实可以简化Servlet的映射设置过程。通过使用@WebServlet注解,开发人员可以更快速地将Servlet类与特定的URL路径进行关联,而无需在Web.xml文件中手动配置。这有助于减少开发时间和代码复杂度,特别是在小型项目中。然而,需要注意的是,@WebServlet注解是Java Servlet API的一部分,需要在支持Servlet规范的容器中运行。


8.3. @WebServlet注解

annotation就是注解的意思

package javax.servlet.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
import java.lang.annotation.Documented;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    
    /**
     * The name of the servlet
     *
     * @return the name of the servlet
     */
    String name() default "";
    
    /**
     * The URL patterns of the servlet
     *
     * @return the URL patterns of the servlet
     */
    String[] value() default {};

    /**
     * The URL patterns of the servlet
     *
     * @return the URL patterns of the servlet
     */
    String[] urlPatterns() default {};
    
    /**
     * The load-on-startup order of the servlet 
     *
     * @return the load-on-startup order of the servlet
     */
    int loadOnStartup() default -1;
    
    /**
     * The init parameters of the servlet
     *
     * @return the init parameters of the servlet
     */
    WebInitParam [] initParams() default {};
    
    /**
     * Declares whether the servlet supports asynchronous operation mode.
     *
     * @return {@code true} if the servlet supports asynchronous operation mode
     * @see javax.servlet.ServletRequest#startAsync
     * @see javax.servlet.ServletRequest#startAsync(ServletRequest,
     * ServletResponse)
     */
    boolean asyncSupported() default false;
    
    /**
     * The small-icon of the servlet
     *
     * @return the small-icon of the servlet
     */
    String smallIcon() default "";

    /**
     * The large-icon of the servlet
     *
     * @return the large-icon of the servlet
     */
    String largeIcon() default "";

    /**
     * The description of the servlet
     *
     * @return the description of the servlet
     */
    String description() default "";

    /**
     * The display name of the servlet
     *
     * @return the display name of the servlet
     */
    String displayName() default "";

}

上面是从IDEA上面扒下来的WebServlet.java的源码,简单概括就是

它是用来定义一个servlet的配置信息的:

  1. name():返回servlet的名字,默认为空字符串。
  2. value()urlPatterns():这两个方法是等价的,都是用来设置URL模式的。当请求匹配这些模式时,该servlet将被调用。
  3. loadOnStartup():设置servlet在应用启动时加载的顺序。默认值为-1,表示容器可自由选择加载时机。
  4. initParams():设置servlet的初始化参数。
  5. asyncSupported():声明servlet是否支持异步操作模式。如果为true,那么servlet可以使用startAsync()方法进行异步处理。
  6. smallIcon()largeIcon():分别设置servlet的小图标和大图标。默认都为空字符串。
  7. description():设置servlet的描述信息。默认为空字符串。
  8. displayName():设置servlet的显示名。默认为空字符串。

上面的例子就用到了name和urlPatterns,设定servlet的名字和它的URL地址


8.4. WebServlet注解原理

  1. 这是没有WebServlet注解的HTTP请求方式:
  2. Tomcat接收到HTTP请求后,会根据请求的URL路径在web.xml中进行匹配,找到对应的URL Pattern。

先在web.xml文件上找url-pattern是否有对应的,也就是“/hello”。如果有就会得到对应的servlet-name:HelloServlet。

同时,Tomcat维护了一个很大的HashMap<id,servlet>,查询HashMap中有没有这个servlet实例。根据servlet-name:HelloServlet去查询对应的id。

查询有这个servlet-name:HelloServlet的话,就会根据相应的servlet-class找到该类的全路径,找这个类在这个项目的哪里。

最后使用反射技术,将servlet实例化 -> init( )

并放到Tomcat维护的HashMap<id,Servlet>中去

  1. Tomcat会调用Servlet类的service()方法来处理HTTP请求。

在service()方法中,可以根据请求的类型(GET、POST等)和URL路径来确定 具体要执行的方法。

  1. 执行完service()方法后,Tomcat会返回响应给客户端。
  2. Tomcat会根据需要销毁或重新实例化Servlet类,以供下一次请求使用。

  1. 如果此时用了WebServlet注解,会有一些小变化:

当Tomcat找到匹配的URL Pattern时,它会查看Servlet类上是否有@WebServlet注解。注解中通常包含一个urlPatterns属性,该属性指定了该Servlet类应该映射到的URL路径。例如,@WebServlet(urlPatterns = "/hello")。

如果存在@WebServlet注解,Tomcat会根据注解中的urlPatterns属性将该Servlet类映射到相应的URL路径。然后,Tomcat会使用反射技术实例化该Servlet类,并调用它的init()方法进行初始化。

此时,web.xml文件不进行配置也是可以的

与之前不同的是,Tomcat不再维护一个HashMap<id, Servlet>来存储Servlet实例。相反,Tomcat使用注解的信息来动态地创建和销毁Servlet实例,以处理HTTP请求。这意味着每次请求都会创建一个新的Servlet实例(除非使用了持久化Servlet),而不是重用先前创建的实例。

总之,使用@WebServlet注解简化了Servlet的配置过程,并且允许动态地创建和销毁Servlet实例。然而,需要注意的是,使用注解可能会增加每次请求的处理开销,因为每次都需要动态地创建和销毁Servlet实例。在需要高性能或高并发的场景下,可能需要权衡使用注解和预创建Servlet实例的利弊。


9. 请求转发和响应重定位

9.1. 概述

请求转发和响应重定向是Web应用程序中常用的两种页面跳转方法。以下是关于这两种方法的详细解释:

请求转发(Request Forwarding):

请求转发是一种由Servlet实现的请求转发机制。当一个Servlet接收到一个HTTP请求后,它可以通过调用RequestDispatcher接口的forward()方法将请求转发给另一个Servlet或JSP页面。这个过程是服务器内部的操作,客户端并不知道。请求转发的优点是实现简单,性能较好。

举个例子,张三向李四借钱,但李四没有钱。于是李四向王五借钱,并告诉王五将钱借给张三。这个过程中,张三只向李四请求借钱,但实际上钱是从王五那里借来的。

响应重定向(Response Redirection):

响应重定向是另一种页面跳转方法,它通过在客户端进行操作来实现。当一个Servlet接收到一个HTTP请求后,它可以通过调用HttpServletResponse对象的sendRedirect()方法将客户端重定向到另一个页面。重定向是通过HTTP协议的3xx响应码实现的,客户端会收到一个新的URL,并重新向这个URL发送请求。

在举个例子,张三向李四借钱,但李四没有钱。李四告诉张三去找王五借钱。于是张三自己去找王五借钱,这个过程中,张三的请求被重定向到了王五那里。

总结一下,请求转发和响应重定向的区别:

  • 请求转发是在服务器内部进行的操作,客户端并不知道;而响应重定向是客户端接收到一个新的URL,并重新向这个URL发送请求。
  • 请求转发性能较好,因为只需要进行一次HTTP请求;而响应重定向需要重新发送请求,性能较差。
  • 请求转发只能用于同一个Web应用程序内;而响应重定向可以用于不同的Web应用程序之间。

9.2. 请求转发

  • 请求转发可以通过HttpServletRequest对象获取请求转发器实现。
  • 请求转发是服务器内部的行为,对客户端是屏蔽的。
  • 客户端只发送了一次请求,地址栏不变。
  • 服务端只产生了一对请求和响应对象,这一对对象会继续传递给下一个资源。
  • 请求参数和请求域中的数据都可以在请求转发中传递。
  • 请求转发可以用于转发给其他Servlet动态资源、静态资源或受保护的资源。
  • 请求转发不能用于转发到外部资源。

代码演示:


9.3. 响应重定向

  • 响应重定向是通过HttpServletResponse对象的sendRedirect方法实现的。
  • 响应重定向是服务端通过302响应码和路径告诉客户端自己去找其他资源,是由服务端提示下的客户端行为。
  • 响应重定向至少需要客户端发送两次请求,且客户端地址栏会发生变化。
  • 在响应重定向中,服务端会产生多对请求和响应对象,且请求和响应对象不会传递给下一个资源。
  • 因为整个过程中产生了多个HttpServletRequset对象,所以请求参数无法在响应重定向中传递,请求域中的数据也无法传递。
  • 响应重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转。
  • 响应重定向无法转发到受保护的资源,如WEB-INF下的资源。
  • 响应重定向可以转发到外部资源,即本项目以外的资源。

代码演示:


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<JavaEE> volatile关键字 -- 保证内存可见性、禁止指令重排序

目录 一、内存可见性 1.1 Java内存模型(JMM) 1.2 内存可见性演示 二、指令重排序 三、关键字 volatile 一、内存可见性 1.1 Java内存模型(JMM) 1&#xff09;什么是Java内存模型&#xff08;JMM&#xff09;&#xff1f;Java内存模型即Java Memory Model&#xff0c;简…

【重点】【双指针】11. 盛最多水的容器

题目 注意&#xff1a;二维接雨水&#xff0c;有墙的&#xff0c;有线的&#xff0c;着这个属于线的。 class Solution {public int maxArea(int[] height) {if (height.length < 2) {return 0;}int left 0, right height.length - 1, res 0;while (left < right) {…

三轴加速度计LIS2DW12开发(2)----基于中断信号获取加速度数据

三轴加速度计LIS2DW12开发.2--轮基于中断信号获取加速度数据 概述视频教学样品申请生成STM32CUBEMX串口配置IIC配置CS和SA0设置INT1设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置开启INT1中断设置传感器的量程配置过滤器链配置电源模式设置输出数据速率中断判断加速…

【动态规划】LeetCode-931.下降路径最小和

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

深度学习记录--logistic回归函数的计算图

计算图用于logistic回归函数 先回顾一下单一样本的logistic回归损失函数的公式&#xff0c;公式如下&#xff1a; 将logistic函数用计算图表示出来(以两个基础量为例)&#xff0c;计算图如下&#xff1a; 前向传播已经完成&#xff0c;接下来完成后向传播 运用链式法则依次求…

Vue---Echarts

项目需要用echarts来做数据展示&#xff0c;现记录vue3引入并使用echarts的过程。 1. 使用步骤 安装 ECharts&#xff1a;使用 npm 或 yarn 等包管理工具安装 ECharts。 npm install echarts 在 Vue 组件中引入 ECharts&#xff1a;在需要使用图表的 Vue 组件中&#xff0c;引入…

如何选择适合的光电传感器与 STM32 微控制器进行接口设计

本文介绍了如何选择适合的光电传感器与 STM32 微控制器进行接口设计的方法。首先我们将介绍一些选择光电传感器的关键因素&#xff0c;包括测量范围、响应时间、分辨率和输出类型。然后我们将介绍如何根据所选传感器的特性进行硬件连接和接口设计。最后&#xff0c;我们将提供示…

20231201将RK3399的挖掘机开发板在Andorid12系统下的强制横屏

20231201将RK3399的挖掘机开发板在Andorid12系统下的强制横屏 2023/12/1 22:54 【不完美的地方&#xff1a;修改之后不满屏】 百度&#xff1a;rk3399 android12 横屏 不满屏 Android 显示不满屏 build.prop https://blog.csdn.net/weixin_39966398/article/details/105595184?…

9.ROS的TF坐标变换(三):坐标系关系查看与一个案例

1 查看目前的坐标系变化 我们先安装功能包&#xff1a; sudo apt install ros-melodic-tf2-tools安装成功&#xff01; 我们先启动上次的发布坐标变换的节点&#xff1a; liuhongweiliuhongwei-Legion-Y9000P-IRX8H:~/Desktop/final/my_catkin$ source devel/setup.bash liuho…

RocketMQ- 深入理解RocketMQ的消息模型

1、RocketMQ客户端基本流程 ​ RocketMQ基于Maven提供了客户端的核心依赖&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>4.9.5</version> </dependency&…

RxJava

Single 使用 Flowable 比较重一般使用Single onSubscribe 产生订阅时调用 线程切换1 2 发送顺序事件.just just 源码 钩子方法,进行验证再处理 Single 对象 订阅,RxJavaPlugins.onSubscribe 钩子方法,产生订阅和过滤 Single 核心方法,抽象的,实现为SingleJust 订阅和执行成功回…

同旺科技 USB TO SPI / I2C --- 调试W5500_Ping测试

所需设备&#xff1a; 内附链接 1、USB转SPI_I2C适配器(专业版); 首先&#xff0c;连接W5500模块与同旺科技USB TO SPI / I2C适配器&#xff0c;如下图&#xff1a; 设置寄存器&#xff1a; SHAR&#xff08;源MAC地址寄存器&#xff09;&#xff0c;该寄存器用来设置源MAC…

网络入门---网络编程初步认识和实践

目录标题 前言准备工作udpserver.hpp成员变量构造函数初始化函数(socket,bind)start函数(recvfrom) udpServer.ccudpClient.hpp构造函数初始化函数run函数(sendto) udpClient.cc测试 前言 在上一篇文章中我们初步的认识了端口号的作用&#xff0c;ip地址和MAC地址在网络通信时…

HuggingFace学习笔记--Prompt-Tuning高效微调

1--Prompt-Tuning介绍 Prompt-Tuning 高效微调只会训练新增的Prompt的表示层&#xff0c;模型的其余参数全部固定&#xff1b; 新增的 Prompt 内容可以分为 Hard Prompt 和 Soft Prompt 两类&#xff1b; Soft prompt 通常指的是一种较为宽泛或模糊的提示&#xff0c;允许模型在…

规则引擎专题---3、Drools组成和入门

Drools概述 drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎&#xff0c;可以将复杂且多变的业务规则从硬编码中解放出来&#xff0c;以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中)&#xff0c;使得业务规则的变更不需要修改项目代码、重启…

初识RocketMQ

1、简介 RocketMQ 是阿里巴巴在 2012 年开源的消息队列产品&#xff0c;用 Java 语言实现&#xff0c;在设计时参考了 Kafka&#xff0c;并做出了自己的一些改进&#xff0c;后来捐赠给 Apache 软件基金会&#xff0c;2017 正式毕业&#xff0c;成为 Apache 的顶级项目。Rocket…

avue-crud中时间范围选择默认应该是0点却变成了12点

文章目录 一、问题二、解决三、最后 一、问题 在avue-crud中时间范围选择&#xff0c;正常默认应该是0点&#xff0c;但是不知道怎么的了&#xff0c;选完之后就是一直是12点。具体问题如下动图所示&#xff1a; <template><avue-crud :option"option" /&g…

YOLOv8改进 | 2023 | SCConv空间和通道重构卷积(精细化检测,又轻量又提点)

一、本文介绍 本文给大家带来的改进内容是SCConv&#xff0c;即空间和通道重构卷积&#xff0c;是一种发布于2023.9月份的一个新的改进机制。它的核心创新在于能够同时处理图像的空间&#xff08;形状、结构&#xff09;和通道&#xff08;色彩、深度&#xff09;信息&#xf…

计算机组成原理笔记——存储器(静态RAM和动态RAM的区别,动态RAM的刷新, ROM……)

■ 随机存取存储器 ■ 1.随机存取存储器&#xff1a;按存储信息的原理不同分为&#xff1a;静态RAM和动态RAM 2.静态RAM&#xff08;SRAM&#xff09;&#xff1a;用触发器工作原理存储信息&#xff0c;但电源掉电时&#xff0c;存储信息会丢失具有易失性。 3.存储器的基本单元…

代码随想录算法训练营第三十四天|62.不同路径,63. 不同路径 II

62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#…