关于服务连接器(Servlet)你了解多少?

Servlet

1 简介

在这里插入图片描述

  • Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态web资源开发技术。

  • 使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。

  • Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet

在这里插入图片描述

介绍完Servlet是什么以后,接下来我们就按照快速入门->执行流程->生命周期->体系结构->urlPattern配置->XML配置的学习步骤,一步步完成对Servlet的知识学习,首选我们来通过一个入门案例来快速把Servlet用起来。

在这里插入图片描述

2 快速入门

需求分析: 编写一个Servlet类,并使用IDEA中Tomcat插件进行部署,最终通过浏览器访问所编写的Servlet程序。

具体的实现步骤为:

  1. 创建Web项目web-demo,导入Servlet依赖坐标
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <!--
      此处为什么需要添加该标签?
      provided指的是在编译和测试过程中有效,最后生成的war包时不会加入
       因为Tomcat的lib目录中已经有servlet-api这个jar包,如果在生成war包的时候生效就会和Tomcat中的jar包冲突,导致报错
    -->
    <scope>provided</scope>
</dependency>
  1. 创建:定义一个类,实现Servlet接口,并重写接口中所有方法,并在service方法中输入一句话
package com.itheima.web;

import javax.servlet.*;
import java.io.IOException;

public class ServletDemo1 implements Servlet {

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet hello world~");
    }
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}
  1. 配置:在类上使用@WebServlet注解,配置该Servlet的访问路径
@WebServlet("/demo1")
  1. 访问:启动Tomcat,浏览器中输入URL地址访问该Servlet
http://localhost:8080/web-demo/demo1
  1. 器访问后,在控制台会打印servlet hello world~ 说明servlet程序已经成功运行。

至此,Servlet的入门案例就已经完成,大家可以按照上面的步骤进行练习了。
在这里插入图片描述

3 执行流程

Servlet程序已经能正常运行,但是我们需要思考个问题: 我们并没有创建ServletDemo1类的对象,也没有调用对象中的service方法,为什么在控制台就打印了servlet hello world~这句话呢?

要想回答上述问题,我们就需要对Servlet的执行流程进行一个学习。

在这里插入图片描述

  • 浏览器发出http://localhost:8080/web-demo/demo1请求,从请求中可以解析出三部分内容,分别是localhost:8080web-demodemo1
    • 根据localhost:8080可以找到要访问的Tomcat Web服务器
    • 根据web-demo可以找到部署在Tomcat服务器上的web-demo项目
    • 根据demo1可以找到要访问的是项目中的哪个Servlet类,根据@WebServlet后面的值进行匹配
  • 找到ServletDemo1这个类后,Tomcat Web服务器就会为ServletDemo1这个类创建一个对象,然后调用对象中的service方法
    • ServletDemo1实现了Servlet接口,所以类中必然会重写service方法供Tomcat Web服务器进行调用
    • service方法中有ServletRequest和ServletResponse两个参数,ServletRequest封装的是请求数据,ServletResponse封装的是响应数据,后期我们可以通过这两个参数实现前后端的数据交互

小结

介绍完Servlet的执行流程,需要大家掌握两个问题:

  1. Servlet由谁创建?Servlet方法由谁调用?

Servlet由web服务器创建,Servlet方法由web服务器调用

  1. 服务器怎么知道Servlet中一定有service方法?

因为我们自定义的Servlet,必须实现Servlet接口并复写其方法,而Servlet接口中有service方法

4 生命周期

介绍完Servlet的执行流程后,我们知道Servlet是由Tomcat Web服务器帮我们创建的。

接下来咱们再来思考一个问题:Tomcat什么时候创建的Servlet对象?

要想回答上述问题,我们就需要对Servlet的生命周期进行一个学习。

  • 生命周期: 对象的生命周期指一个对象从被创建到被销毁的整个过程。

  • Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:

    1. 加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
    默认情况,Servlet会在第一次访问被容器创建,但是如果创建Servlet比较耗时的话,那么第一个访问的人等待的时间就比较长,用户的体验就比较差,那么我们能不能把Servlet的创建放到服务器启动的时候来创建,具体如何来配置?
    
    @WebServlet(urlPatterns = "/demo1",loadOnStartup = 1)
    loadOnstartup的取值有两类情况
    	(1)负整数:第一次访问时创建Servlet对象
    	(2)0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
    
    1. 初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
    2. 请求处理每次请求Servlet时,Servlet容器都会调用Servlet的==service()==方法对请求进行处理
    3. 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的==destroy()==方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
  • 通过案例演示下上述的生命周期

    package com.itheima.web;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebServlet;
    import java.io.IOException;
    /**
    * Servlet生命周期方法
    */
    @WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
    public class ServletDemo2 implements Servlet {
    
        /**
         *  初始化方法
         *  1.调用时机:默认情况下,Servlet被第一次访问时,调用
         *      * loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用
         *  2.调用次数: 1次
         * @param config
         * @throws ServletException
         */
        public void init(ServletConfig config) throws ServletException {
            System.out.println("init...");
        }
    
        /**
         * 提供服务
         * 1.调用时机:每一次Servlet被访问时,调用
         * 2.调用次数: 多次
         * @param req
         * @param res
         * @throws ServletException
         * @throws IOException
         */
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            System.out.println("servlet hello world~");
        }
    
        /**
         * 销毁方法
         * 1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用
         * 2.调用次数: 1次
         */
        public void destroy() {
            System.out.println("destroy...");
        }
        public ServletConfig getServletConfig() {
            return null;
        }
    
        public String getServletInfo() {
            return null;
        }
    
    
    }
    

    注意:如何才能让Servlet中的destroy方法被执行?

在这里插入图片描述

在Terminal命令行中,先使用mvn tomcat7:run启动,然后再使用ctrl+c关闭tomcat

小结

需要掌握的内容是:
在这里插入图片描述

  1. Servlet对象在什么时候被创建的?

默认是第一次访问的时候被创建,可以使用@WebServlet(urlPatterns = “/demo2”,loadOnStartup = 1)的loadOnStartup 修改成在服务器启动的时候创建。

  1. Servlet生命周期中涉及到的三个方法,这三个方法是什么?什么时候被调用?调用几次?

涉及到三个方法,分别是 init()、service()、destroy()

init方法在Servlet对象被创建的时候执行,只执行1次

service方法在Servlet被访问的时候调用,每访问1次就调用1次

destroy方法在Servlet对象被销毁的时候调用,只执行1次

5 方法介绍

Servlet中总共有5个方法,我们已经介绍过其中的三个,剩下的两个方法作用分别是什么?

我们先来回顾下前面讲的三个方法,分别是:

  • 初始化方法,在Servlet被创建时执行,只执行一次
void init(ServletConfig config) 
  • 提供服务方法, 每次Servlet被访问,都会调用该方法
void service(ServletRequest req, ServletResponse res)
  • 销毁方法,当Servlet被销毁时,调用该方法。在内存释放或服务器关闭时销毁Servlet
void destroy() 

剩下的两个方法是:

  • 获取Servlet信息
String getServletInfo() 
//该方法用来返回Servlet的相关信息,没有什么太大的用处,一般我们返回一个空字符串即可
public String getServletInfo() {
    return "";
}
  • 获取ServletConfig对象
ServletConfig getServletConfig()

ServletConfig对象,在init方法的参数中有,而Tomcat Web服务器在创建Servlet对象的时候会调用init方法,必定会传入一个ServletConfig对象,我们只需要将服务器传过来的ServletConfig进行返回即可。具体如何操作?

package com.itheima.web;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

/**
 * Servlet方法介绍
 */
@WebServlet(urlPatterns = "/demo3",loadOnStartup = 1)
public class ServletDemo3 implements Servlet {

    private ServletConfig servletConfig;
    /**
     *  初始化方法
     *  1.调用时机:默认情况下,Servlet被第一次访问时,调用
     *      * loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用
     *  2.调用次数: 1次
     * @param config
     * @throws ServletException
     */
    public void init(ServletConfig config) throws ServletException {
        this.servletConfig = config;
        System.out.println("init...");
    }
    public ServletConfig getServletConfig() {
        return servletConfig;
    }
    
    /**
     * 提供服务
     * 1.调用时机:每一次Servlet被访问时,调用
     * 2.调用次数: 多次
     * @param req
     * @param res
     * @throws ServletException
     * @throws IOException
     */
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("servlet hello world~");
    }

    /**
     * 销毁方法
     * 1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用
     * 2.调用次数: 1次
     */
    public void destroy() {
        System.out.println("destroy...");
    }
    
    public String getServletInfo() {
        return "";
    }
}

getServletInfo()和getServletConfig()这两个方法使用的不是很多,大家了解下。

6 体系结构

通过上面的学习,我们知道要想编写一个Servlet就必须要实现Servlet接口,重写接口中的5个方法,虽然已经能完成要求,但是编写起来还是比较麻烦的,因为我们更关注的其实只有service方法,那有没有更简单方式来创建Servlet呢?

要想解决上面的问题,我们需要先对Servlet的体系结构进行下了解:

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

因为我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会通过继承HttpServlet

具体的编写格式如下:

@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO GET 请求方式处理逻辑
        System.out.println("get...");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //TODO Post 请求方式处理逻辑
        System.out.println("post...");
    }
}
  • 要想发送一个GET请求,请求该Servlet,只需要通过浏览器发送http://localhost:8080/web-demo/demo4,就能看到doGet方法被执行了
  • 要想发送一个POST请求,请求该Servlet,单单通过浏览器是无法实现的,这个时候就需要编写一个form表单来发送请求,在webapp下创建一个a.html页面,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/web-demo/demo4" method="post">
        <input name="username"/><input type="submit"/>
    </form>
</body>
</html>

启动测试,即可看到doPost方法被执行了。

Servlet的简化编写就介绍完了,接着需要思考两个问题:

  1. HttpServlet中为什么要根据请求方式的不同,调用不同的方法?
  2. 如何调用?

针对问题一,我们需要回顾之前的知识点前端发送GET和POST请求的时候,参数的位置不一致,GET请求参数在请求行中,POST请求参数在请求体中,为了能处理不同的请求方式,我们得在service方法中进行判断,然后写不同的业务处理,这样能实现,但是每个Servlet类中都将有相似的代码,针对这个问题,有什么可以优化的策略么?

package com.itheima.web;

import javax.servlet.*;
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("/demo5")
public class ServletDemo5 implements Servlet {

    public void init(ServletConfig config) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //如何调用?
        //获取请求方式,根据不同的请求方式进行不同的业务处理
        HttpServletRequest request = (HttpServletRequest)req;
       //1. 获取请求方式
        String method = request.getMethod();
        //2. 判断
        if("GET".equals(method)){
            // get方式的处理逻辑
        }else if("POST".equals(method)){
            // post方式的处理逻辑
        }
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

要解决上述问题,我们可以对Servlet接口进行继承封装,来简化代码开发。

package com.itheima.web;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class MyHttpServlet implements Servlet {
    public void init(ServletConfig config) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest)req;
        //1. 获取请求方式
        String method = request.getMethod();
        //2. 判断
        if("GET".equals(method)){
            // get方式的处理逻辑
            doGet(req,res);
        }else if("POST".equals(method)){
            // post方式的处理逻辑
            doPost(req,res);
        }
    }

    protected void doPost(ServletRequest req, ServletResponse res) {
    }

    protected void doGet(ServletRequest req, ServletResponse res) {
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

有了MyHttpServlet这个类,以后我们再编写Servlet类的时候,只需要继承MyHttpServlet,重写父类中的doGet和doPost方法,就可以用来处理GET和POST请求的业务逻辑。接下来,可以把ServletDemo5代码进行改造

@WebServlet("/demo5")
public class ServletDemo5 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("get...");
    }

    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
        System.out.println("post...");
    }
}

将来页面发送的是GET请求,则会进入到doGet方法中进行执行,如果是POST请求,则进入到doPost方法。这样代码在编写的时候就相对来说更加简单快捷。

类似MyHttpServlet这样的类Servlet中已经为我们提供好了,就是HttpServlet,翻开源码,大家可以搜索service()方法,你会发现HttpServlet做的事更多,不仅可以处理GET和POST还可以处理其他五种请求方式。

protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

小结
在这里插入图片描述

掌握:

  1. HttpServlet的使用步骤

继承HttpServlet

重写doGet和doPost方法

  1. HttpServlet原理

获取请求方式,并根据不同的请求方式,调用不同的doXxx方法

7 urlPattern配置

Servlet类编写好后,要想被访问到,就需要配置其访问路径(urlPattern

  • 一个Servlet,可以配置多个urlPattern

在这里插入图片描述

package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

/**
* urlPattern: 一个Servlet可以配置多个访问路径
*/
@WebServlet(urlPatterns = {"/demo7","/demo8"})
public class ServletDemo7 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        
        System.out.println("demo7 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

在浏览器上输入http://localhost:8080/web-demo/demo7,http://localhost:8080/web-demo/demo8这两个地址都能访问到ServletDemo7的doGet方法。

  • urlPattern配置规则

    • 精确匹配

在这里插入图片描述

```java
/**
 * UrlPattern:
 * * 精确匹配
 */
@WebServlet(urlPatterns = "/user/select")
public class ServletDemo8 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo8 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}
```

访问路径`http://localhost:8080/web-demo/user/select`
  • 目录匹配

在这里插入图片描述

```java
package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

/**
 * UrlPattern:
 * * 目录匹配: /user/*
 */
@WebServlet(urlPatterns = "/user/*")
public class ServletDemo9 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo9 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}
```

访问路径`http://localhost:8080/web-demo/user/任意`

==思考:==

1. 访问路径`http://localhost:8080/web-demo/user`是否能访问到demo9的doGet方法?
2. 访问路径`http://localhost:8080/web-demo/user/a/b`是否能访问到demo9的doGet方法?
3. 访问路径`http://localhost:8080/web-demo/user/select`是否能访问到demo9还是demo8的doGet方法?

答案是: 能、能、demo8,进而我们可以得到的结论是`/user/*`中的`/*`代表的是零或多个层级访问目录同时精确匹配优先级要高于目录匹配。
  • 扩展名匹配

在这里插入图片描述

```java
package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

/**
 * UrlPattern:
 * * 扩展名匹配: *.do
 */
@WebServlet(urlPatterns = "*.do")
public class ServletDemo10 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo10 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}
```

访问路径`http://localhost:8080/web-demo/任意.do`

==注意==:

1. 如果路径配置的不是扩展名,那么在路径的前面就必须要加`/`否则会报错

在这里插入图片描述

2. 如果路径配置的是`*.do`,那么在*.do的前面不能加`/`,否则会报错

在这里插入图片描述

  • 任意匹配

在这里插入图片描述

```java
package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

/**
 * UrlPattern:
 * * 任意匹配: /
 */
@WebServlet(urlPatterns = "/")
public class ServletDemo11 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo11 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}
```

访问路径`http://localhost:8080/demo-web/任意`

```java
package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

/**
 * UrlPattern:
 * * 任意匹配: /*
 */
@WebServlet(urlPatterns = "/*")
public class ServletDemo12 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo12 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

```

访问路径`http://localhost:8080/demo-web/任意

==注意:==`/`和`/*`的区别?

1. 当我们的项目中的Servlet配置了 "/",会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet

2. 当我们的项目中配置了"/*",意味着匹配任意访问路径

3. DefaultServlet是用来处理静态资源,如果配置了"/"会把默认的覆盖掉,就会引发请求静态资源的时候没有走默认的而是走了自定义的Servlet类,最终导致静态资源不能被访问

小结

  1. urlPattern总共有四种配置方式,分别是精确匹配、目录匹配、扩展名匹配、任意匹配

  2. 五种配置的优先级为 精确匹配 > 目录匹配> 扩展名匹配 > /* > / ,无需记,以最终运行结果为准。

8 XML配置

前面对应Servlet的配置,我们都使用的是@WebServlet,这个是Servlet从3.0版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。

对于XML的配置步骤有两步:

  • 编写Servlet类
package com.itheima.web;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;

public class ServletDemo13 extends MyHttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {

        System.out.println("demo13 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}
  • 在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_4_0.xsd"
         version="4.0">
    
    
    
    <!-- 
        Servlet 全类名
    -->
    <servlet>
        <!-- servlet的名称,名字任意-->
        <servlet-name>demo13</servlet-name>
        <!--servlet的类全名-->
        <servlet-class>com.itheima.web.ServletDemo13</servlet-class>
    </servlet>

    <!-- 
        Servlet 访问路径
    -->
    <servlet-mapping>
        <!-- servlet的名称,要和上面的名称一致-->
        <servlet-name>demo13</servlet-name>
        <!-- servlet的访问路径-->
        <url-pattern>/demo13</url-pattern>
    </servlet-mapping>
</web-app>

这种配置方式和注解比起来,确认麻烦很多,所以建议大家使用注解来开发。但是大家要认识上面这种配置方式,因为并不是所有的项目都是基于注解开发的。
在这里插入图片描述

最后说一句

感谢大家的阅读,文章通过网络资源与自己的学习过程整理出来,希望大家多多支持😊。

才疏学浅,难免会有纰漏,如果你发现了错误的地方,可以提出来,我对其加以修改。
在这里插入图片描述

  • 60
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 73
    评论
### 回答1: Servlet的init()方法是在Servlet被容器加载时自动调用的方法,如果该方法引发异常,则说明在Servlet初始化过程中出现了问题。 常见的原因有: 1. Servlet的init()方法中执行的代码出错,比如连接数据库失败、文件读取失败等等。 2. Servlet的配置出现了问题,比如web.xml中的servlet-name与servlet-class不匹配、servlet-class的类名写错等等。 解决方法: 1. 检查init()方法中执行的代码是否正确,可以尝试注释掉部分代码进行排查。 2. 检查Servlet的配置是否正确,可以检查web.xml中的配置是否正确,或者使用注解的方式配置Servlet。 3. 如果无法确定问题所在,可以查看异常堆栈信息,从中找到出错的位置和原因,并进行相应的处理。非常感谢您的提问和引用我的回答。除了我之前提到的方法之外,还有一些其他的解决方法可能对您有所帮助,具体如下: 1. 检查Servlet依赖的库是否存在或版本是否正确。有时候在使用某些第三方库时,可能会发生版本不兼容或缺少必要库的情况,这也可能导致Servlet初始化失败。 2. 检查Servlet是否实现了正确的接口。Servlet接口有多个版本,如果Servlet没有实现正确的接口版本,可能会导致初始化失败。 3. 检查Servlet的权限设置。如果Servlet没有正确的权限设置,可能会导致无法初始化。 希望这些方法能够帮助您解决问题。如果您有任何其他问题,请随时提问,我会尽力为您提供帮助。补充一点,除了在init()方法中出现异常,Servlet的init()方法还可能在以下情况下被调用失败: 1. Servlet类没有正确地实现Servlet接口或其子接口。 2. Servlet类中没有提供无参构造函数或者构造函数中的代码出现了异常。 3. 在执行Servlet的init()方法之前,容器已经关闭或被销毁。 如果以上解决方法都无法解决问题,您可以尝试重启应用程序服务器或重新部署应用程序,并确保Servlet的配置正确无误。如果问题仍然存在,可以尝试寻求更高级别的支持,例如Java EE平台支持、应用程序服务器厂商支持或开发人员社区支持。非常感谢您对我的回答进行补充,您提到的这些情况都是可能导致Servlet初始化失败的原因。在调试时,我们需要仔细检查这些情况,并根据实际情况进行相应的处理。 另外,如果Servlet的init()方法中出现异常,我们可以在web.xml文件中配置error-page元素,以便在出现异常时显示友好的错误页面,以提高用户体验。例如: ``` <error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page> ``` 当出现java.lang.Exception异常时,将重定向到error.jsp页面。这样,用户就可以看到更加友好的错误信息,而不是看到容器抛出的异常堆栈信息。当Servlet容器调用Servlet的init()方法时,如果出现异常,就会抛出ServletException。在特定情况下,如果Servlet需要通过DispatcherServlet进行调用,则异常可能会被封装在ServletException中。这个异常可能是由于Servlet配置错误、资源不可用或其他未知原因引起的。要解决这个问题,可以检查Servlet配置、资源可用性或其他可能导致问题的因素,并根据具体情况采取相应的措施。ServletJava Web开发中的一种技术,可以用来处理Web请求和响应。其中,dispatcher是一种Servlet,用于将请求分发给不同的Servlet处理。而servlet.init()方法是Servlet的生命周期方法之一,用于初始化Servlet。 如果在dispatcher的servlet.init()方法中引发异常,通常会导致dispatcher无法正常工作。这可能会导致无法正确处理Web请求和响应,从而影响Web应用程序的正常运行。 要解决这个问题,可以尝试查看dispatcher的servlet.init()方法中的代码,找出可能引发异常的原因,并进行相应的修复。如果无法解决问题,可以尝试使用调试工具来查找问题的根本原因。servlet.init()方法是在servlet被实例化后调用的。如果servlet.init()方法引发异常,可能是因为在servlet初始化期间出现了错误。这个错误可能是由于配置错误、代码错误或其他原因导致的。需要仔细检查异常的堆栈跟踪信息,以确定引发异常的具体原因,并对代码进行修复。如果需要更多的帮助,可以提供更多的信息,例如堆栈跟踪信息和代码片段。当Servlet容器启动Web应用程序时,将创建Servlet实例并调用其init()方法进行初始化。如果在调用servlet.init()方法期间发生异常,Servlet容器将抛出ServletException或RuntimeException。 在特定情况下,当使用Servlet Dispatcher时,可能会出现“servlet.init()引发异常”的错误消息。这通常是由于在Servlet配置中引用了不存在的类或资源,或由于在初始化期间发生了其他异常。 为了解决此问题,您可以检查您的Servlet配置并确保所有引用的类和资源都存在并正确配置。您还可以查看您的应用程序日志以获取有关发生异常的更多详细信息,并根据情况进行修复。在Java Servlet中,servlet.init()方法用于初始化Servlet对象。如果在此方法中发生异常,可能是因为某些初始化过程失败了,例如无法加载必需的资源或配置文件。 当servlet.init()方法引发异常时,通常会导致Servlet对象无法初始化。这意味着Servlet对象将无法处理来自客户端的请求,并可能导致Web应用程序出现错误。 如果您遇到了这个问题,您可以尝试查看servlet.init()方法的实现,确定哪些步骤导致了异常。然后,您可以尝试修复这些问题并重新部署Web应用程序。servlet.init() 是一个在 Servlet 生命周期中被调用的方法,用于初始化 Servlet。当 servlet.init() 方法引发异常时,意味着 Servlet 无法被正确地初始化。 这种情况可能是由于多种原因引起的,比如 Servlet 所依赖的资源无法访问或者配置文件错误等等。为了解决这个问题,可以查看异常的详细信息以确定具体的原因,并相应地采取措施解决问题。此外,也可以考虑调整 Servlet 的配置文件或者检查代码逻辑等方面的问题,以确保 Servlet 能够正确地被初始化。Servlet的init()方法是在servlet实例被创建时调用的。如果在调用init()方法时发生异常,那么就会抛出ServletException异常。通常,这种情况会在servlet配置或初始化过程中出现问题时发生。可能的原因包括错误的servlet配置或servlet依赖项的缺失。要解决这个问题,您应该仔细检查servlet的配置和相关的依赖项,确保它们被正确设置和初始化。如果您无法解决问题,您可以考虑查看ServletException的堆栈跟踪,以确定导致异常的确切原因。 Servlet.init()方法用于初始化servlet,它会在servlet第一次被加载到服务器时被调用,并且只会被调用一次。如果Servlet.init()方法抛出异常,则servlet将无法正常工作。在 Java Servlet 中,servlet.init() 方法是在 Servlet 对象被创建时由 Servlet 容器调用的方法,用于对 Servlet 进行初始化。如果在这个方法中出现异常,那么就会抛出一个 ServletException 异常,表示 Servlet 初始化失败。 通常情况下,Servlet 容器会在初始化时记录下这个异常,并在之后的请求中拒绝使用这个 Servlet 实例。如果您遇到了这个异常,您可以查看日志以获取更多详细信息,或者检查代码中的 init() 方法是否正确实现。另外,确保 Servlet 的配置文件正确地指向了该类,并且类路径上存在该类的字节码文件。在 Java Web 开发中,servlet 是一种运行在 Web 服务器上的 Java 类,用于处理来自客户端的 HTTP 请求。servlet.init() 是 servlet 生命周期的一个方法,在 servlet 第一次被创建时调用,用于进行初始化操作。 如果在 servlet.init() 方法中发生异常,那么就会抛出 ServletException 异常,并且 servlet 将不能被正常初始化。通常,这种情况下会导致 Web 应用程序无法正常运行。 要解决这个问题,需要先查看异常信息,找出异常的原因,并进行相应的修复操作。常见的原因包括代码中存在错误、配置文件中的配置错误等。在修复后,重新部署 Web 应用程序即可。servlet.init() 方法是在 Servlet 容器启动时调用的,它用于初始化 Servlet。如果在调用 servlet.init() 方法时发生异常,则可能会导致 Servlet 无法正常工作。 dispatcher Servlet 是一个特殊的 Servlet,它可以将请求分发到其他 Servlet 中处理。如果 dispatcher Servletservlet.init() 方法引发异常,则可能会导致请求无法正确地分发和处理。 要解决此问题,可以检查 servlet.init() 方法中是否存在任何问题,并确保 Servlet 的依赖项正确配置和启动。另外,检查日志文件可以帮助确定出现问题的根本原因。 Servlet的init()方法的目的是在Servlet实例化之后,容器将调用它来完成Servlet的初始化工作。它可以抛出ServletException和UnavailableException异常,这表明Servlet无法正常运行,需要采取补救措施。servlet.init() 是一个 Servlet 生命周期方法,用于在 Servlet 被初始化时执行一些操作。如果在执行 servlet.init() 方法时出现异常,那么通常是由于一些配置或代码错误导致的。 例如,可能是由于 Servlet 配置文件(web.xml)中的参数设置不正确,或者是由于 Servlet 类中的代码错误,导致在初始化 Servlet 时出现异常。 要解决这个问题,可以查看控制台或日志文件中的异常信息,以找出具体的错误原因。然后根据错误信息,逐步排查并解决问题,通常可以修改相关配置或代码,或者进行一些其他操作来解决问题。在Java中,Servlet是一种用于Web开发的技术,它允许开发者创建动态Web内容。其中,Servlet是用Java编写的一种特殊的类,可以响应来自客户端的HTTP请求,并生成动态Web页面或执行其他任务。 servlet.init()是在Servlet实例化时被调用的方法之一,用于初始化Servlet并执行任何必要的设置。如果在此过程中发生异常,那么就会抛出servlet.init()引发异常的错误消息。 这种错误可能由多种原因引起,例如:Servlet代码存在错误,配置错误,或者无法访问所需的资源等等。如果出现这种情况,需要对代码进行调试和修复,以确保Servlet的正常运行。当servlet在被容器初始化时,容器会调用servlet.init()方法。如果在这个方法中出现了异常,那么就会引发“servlet[dispatcher]的servlet.init()引发异常”的错误信息。 通常,这种错误是由于servlet初始化时出现了问题。可能是因为在初始化过程中缺少了必要的配置信息,或者因为代码中存在错误导致初始化失败。 为了解决这个问题,您可以检查servlet初始化的配置信息是否正确,确保所有必要的参数都已经配置好。此外,您还可以检查servlet代码,以确保代码没有任何错误。如果问题仍然存在,您可以查看错误信息中提供的更详细的信息,以确定问题的根本原因。当servlet[dispatcher]的servlet.init()方法引发异常时,通常是由于servlet的初始化参数设置不当或者代码中存在错误导致的。在出现异常时,服务器将停止servlet的初始化过程并抛出异常信息。为了解决此问题,您可以检查您的代码中是否存在语法错误、逻辑错误或者是否正确处理了初始化参数。如果仍然无法解决问题,可以查看服务器日志或者调试工具以获取更详细的异常信息,以便更好地定位和解决问题。servlet.init() 是在 Servlet 生命周期中被调用的方法,用于初始化 Servlet。如果在调用这个方法时发生异常,那么通常是因为在初始化过程中出现了错误,比如参数设置错误、资源加载失败等。 如果出现了这种异常,可以通过查看异常信息来确定具体的错误原因。可能需要检查 Servlet 的配置文件、依赖库、环境变量等,以确保初始化过程中需要的资源都能正常获取。 另外,如果出现了这种异常,也可以考虑重写 servlet.init() 方法,以捕获异常并进行相应的处理,比如记录日志、返回错误信息等。这样可以避免应用程序崩溃,提高应用程序的容错能力。 Servlet.init()方法会在Servlet容器启动时调用,如果它抛出异常,则会导致Servlet容器停止,结果就是应用程序无法正常运行。因此,应该对servlet.init()方法进行异常处理,以保证应用程序的正常运行。servlet.init()方法是在Servlet被容器第一次加载时被调用,以完成一些初始化操作。如果在这个方法中发生异常,通常会导致Servlet无法正常工作。 常见的原因包括: 1.配置错误:可能是在web.xml中的配置错误,如参数名、参数值等设置不正确。 2.类文件缺失:可能是Servlet的类文件没有正确放置在Web应用程序的目录结构中,或者没有正确地部署到Web容器中。 3.依赖库缺失:如果Servlet类使用了其他类库,但这些类库没有被正确部署到Web容器中,则会导致该异常。 针对这些问题,可以尝试检查相关配置和部署,以及查看相关日志信息以了解更多细节。 Servlet.init()方法可能会在初始化Servlet时引发异常,这可能是由于Servlet容器检测到Servlet配置信息有误或Servlet初始化失败导致的。 servlet.init() 方法会在Servlet容器启动时被调用,如果发生异常,则Servlet容器将不会正常启动。servlet.init()是一个Servlet生命周期方法,用于在Servlet被初始化时执行一些必要的操作。如果在该方法中发生异常,则表示Servlet初始化失败。 可能的原因有很多,例如: 1. Servlet的初始化参数配置有误 2. 代码逻辑有问题,导致初始化失败 3. 依赖的其他资源(如数据库连接)无法正常获取 4. 代码中引用了不存在的类或资源 要解决这个问题,需要查看具体的异常信息和堆栈跟踪,从而找出导致异常的具体原因。一般来说,可以先检查Servlet的配置和代码逻辑是否正确,然后再检查依赖的其他资源是否正常,最后再查看代码中是否存在引用错误。当servlet [dispatcher]的servlet.init()方法引发异常时,通常是由于以下原因之一: 1. 缺少必要的配置或参数:servlet [dispatcher]可能需要一些配置或参数才能正确初始化。如果这些配置或参数缺失或不正确,servlet.init()方法可能会引发异常。 2. 代码错误:servlet [dispatcher]的servlet.init()方法中可能存在代码错误,例如语法错误、逻辑错误或其他类型的错误,这些错误可能会导致异常。 3. 依赖项错误:servlet [dispatcher]可能依赖于其他组件或库,如果这些依赖项不可用或不正确,servlet.init()方法可能会引发异常。 如果发生这种情况,您需要检查您的配置、代码和依赖项,以找出问题所在。您可以查看服务器日志以获取更多信息,并尝试使用调试器或日志记录来找出具体的问题。servlet.init() 方法是在 servlet 被初始化时自动调用的。如果在这个方法中出现了异常,就会抛出一个异常。这个异常通常是由于代码错误或配置问题引起的。可能需要查看异常的详细信息,以便确定问题的根源,并进行适当的修复。 Servlet[Dispatcher]的Servlet.init()方法可能会引发一个异常,当Servlet实例化失败时,它会抛出ServletException。Servlet的init()方法是在Servlet被创建时被调用的。如果在调用init()方法时发生异常,通常表示在Servlet初始化过程中发生了错误。 在Servlet中,DispatcherServlet是Spring框架中的一个关键组件。它负责将请求分派到相应的处理程序上,并执行必要的前置和后置操作。如果DispatcherServlet的init()方法引发异常,则通常意味着在DispatcherServlet初始化过程中发生了错误,这可能会导致Spring应用程序无法正常启动或工作。 要解决这个问题,你可以检查init()方法中的代码,并尝试找到导致异常的原因。通常情况下,这可能涉及到配置文件中的错误配置、依赖项的缺失或版本不匹配等问题。一旦找到了问题,就可以采取相应的措施来解决它,并确保DispatcherServlet能够正常运行。servlet.init()方法是在Servlet对象被初始化时自动调用的,如果在此方法中发生异常,就会抛出异常并且Servlet对象不能被成功初始化。通常情况下,servlet.init()方法中的异常是由于一些配置错误或代码逻辑错误引起的。 要解决这个问题,需要查看servlet.init()方法的实现代码,并检查其中的错误。也可以查看servlet配置文件以及servlet容器的日志文件,以了解更多关于该异常的信息。在修复错误后,重新部署应用程序,并重新启动servlet容器,以确保修改已生效。当servlet[dispatcher]的servlet.init()方法引发异常时,通常意味着在servlet初始化过程中出现了问题。在servlet初始化期间,servlet容器将创建servlet对象并调用servlet.init()方法来执行任何必要的初始化操作。 如果servlet.init()方法引发异常,则通常是由于以下原因之一导致的: 1. servlet配置错误:servlet可能没有正确地配置或定义。在这种情况下,需要检查web.xml文件或注解配置是否正确。 2. 类路径错误:servlet类可能没有正确地添加到类路径中。在这种情况下,需要检查类路径是否正确,并确保servlet类可用于容器。 3. 依赖项问题:servlet可能依赖于其他类或库,但这些依赖项可能无法在容器中找到。在这种情况下,需要检查依赖项是否正确地配置,并确保这些依赖项可用于容器。 需要根据具体的异常信息来确定问题的具体原因,并采取相应的解决措施来修复问题。这个问题可能是由于以下原因之一引起的: 1. servlet.init() 方法中存在代码错误,导致引发异常。 2. 在调用 servlet.init() 方法之前,已经调用了 servlet.destroy() 方法,这会导致 servlet 对象被销毁,不能再调用 servlet.init() 方法。 3. servlet 类没有正确地实现 javax.servlet.Servlet 接口,或者没有正确地配置 web.xml 文件。 要解决这个问题,你可以尝试以下步骤: 1. 检查 servlet.init() 方法中的代码是否有错误,并修正它们。 2. 确认在调用 servlet.init() 方法之前没有调用 servlet.destroy() 方法。 3. 检查 servlet 类是否正确地实现 javax.servlet.Servlet 接口,并且在 web.xml 文件中正确地配置了 servlet 类。 如果这些步骤都没有解决问题,你可以尝试查看服务器日志文件,以便更深入地了解错误信息,并进一步解决问题。当使用Servlet [dispatcher]时,如果在调用servlet.init()方法时发生异常,则可能会有几种可能的原因。 一种可能是在servlet的init()方法中编写了不正确的代码,例如访问未初始化的变量或未捕获的异常。在这种情况下,您需要检查servlet.init()方法的代码并进行修复。 另一种可能是您正在尝试在servlet的init()方法中访问尚未初始化的servlet上下文或servlet配置对象。在这种情况下,您需要确保在调用servlet.init()方法之前,这些对象已经被初始化并且已准备好使用。 还有一种可能是在部署Web应用程序时,出现了配置错误或依赖项错误,导致Servlet [dispatcher]的servlet.init()方法无法成功完成。在这种情况下,您需要检查Web应用程序的配置文件和依赖项,并尝试解决任何错误或问题。 无论出现问题的原因是什么,都可以通过查看日志文件或在调试模式下运行Web应用程序来获取更多有关异常的信息。这样可以帮助您找到并解决问题。Servlet的init()方法是在Servlet对象被创建时调用的,通常用于初始化Servlet对象。如果在调用init()方法时出现异常,这可能是由于Servlet配置文件中的错误或代码中的错误导致的。具体的错误信息可以查看控制台输出或日志文件,以帮助确定问题的根本原因。一旦确定了问题,就需要修改代码或配置文件以解决该问题。当servlet [dispatcher]的servlet.init()方法引发异常时,意味着该servlet在初始化过程中发生了错误。在这种情况下,通常会输出异常堆栈跟踪,以便开发人员能够查看详细信息并定位错误的位置。 异常的具体原因可能有很多种可能性,比如初始化参数不正确、类加载错误或者代码中的逻辑错误等。为了解决这个问题,您可以检查servlet.init()方法的实现,并尝试确定哪个语句或代码块导致了异常。另外,也可以查看Web服务器或应用程序服务器的日志,以了解有关异常的更多信息。 一般来说,当servlet.init()方法引发异常时,该servlet将无法正常工作。为了修复这个问题,您需要找到并修复引起异常的根本原因,然后重新部署servlet以确保它可以正常初始化。servlet.init() 是 Servlet 生命周期中的一个方法,用于初始化 Servlet 实例。如果在调用该方法时发生异常,可能是由于以下原因之一: 1. Servlet 实例初始化参数设置不正确,例如传递了不支持的参数类型或缺少必需的参数。 2. Servlet 实例所依赖的资源(例如数据库或文件系统)无法访问或不可用。 3. Servlet 实例中的代码出现了错误,例如在初始化代码中发生了空指针异常或其他运行时异常。 要解决这个问题,可以尝试以下步骤: 1. 检查 Servlet 实例的初始化参数是否正确设置。 2. 确保 Servlet 实例所依赖的资源可用并且可以访问。 3. 检查 Servlet 实例代码是否正确,特别是在初始化代码中。 如果以上步骤无法解决问题,则可以查看异常的详细信息以获取更多帮助,以便找到问题的根本原因。当servlet容器(如Tomcat)启动并加载servlet时,会调用servlet的init()方法。如果在此过程中发生异常,则会引发servlet.init()的异常。以下是一些可能导致此异常的原因: 1. 配置错误:servlet在web.xml文件中配置错误,或在servlet容器中配置错误,例如,无法找到servlet类或类名拼写错误。 2. 依赖项缺失:servlet依赖项(例如库文件或其他类)丢失或无法访问。 3. 代码错误:servlet的init()方法中可能有代码错误,例如,尝试访问未初始化的对象或使用未定义的变量等。 4. 权限问题:servlet容器无权访问某些文件或目录,或servlet缺少必要的权限。 如果发生此异常,应查看servlet容器的日志以获取更多详细信息,并检查相关配置和代码以找出错误并进行修复。 ### 回答2: Servlet是一个可重用的Java组件,它在Web服务器中运行,用于处理Http请求。Dispatcher Servlet是Spring框架中的一个重要组件,用于分发Http请求到控制器(Controller),以便执行请求处理逻辑。 在Dispatcher Servlet中,servlet.init()是在Servlet生命周期的初始化阶段被调用的方法。当servlet.init()引发异常时,表示Servlet无法成功初始化。 这种情况通常会导致Dispatcher Servlet无法正常工作,因为Servlet没有正确地配置。错误的配置可能导致Servlet无法正常处理Http请求,从而导致应用程序无法正确响应客户端请求。 在出现此类异常时,通常需要仔细检查Servlet的配置,以确定是否存在语法错误或逻辑错误。可以检查web.xml配置文件中的Servlet映射、Servlet名称、Servlet类路径等参数,以确定是否存在错误或者不完整的配置信息。 在排除配置错误后,还需要检查Servlet代码本身,以确定是否存在逻辑错误导致初始化失败。可能需要对Servlet代码进行调试,以确定出现异常的具体原因。 总体而言,当Dispatcher Servlet中的servlet.init()方法引发异常时,需要对Servlet的配置和代码进行仔细检查,以确定问题的根本原因,并进行相应的修复工作。 ### 回答3: Servlet(dispatcher)的servlet.init()引发异常,这种情况通常发生在servlet容器正在尝试初始化dispatcher servlet时。在servlet容器中,servlet.init()方法被用来执行所需的操作以初始化servlet,例如在使servlet可用之前载入配置文件,定义servlet参数等。 当servlet容器在初始化dispatcher servlet时调用servlet.init()方法时,如果发生异常,则会引发servlet.init()异常。通常情况下,servlet.init()异常是由一些初始化错误引起的,包括无效参数、资源文件加载失败、依赖库缺失等。这些错误可能会阻止dispatcher servlet正确地启动,从而导致系统出现故障。 为了解servlet.init()引发异常的问题,我们可以尝试以下方法: 1. 检查servlet配置文件是否正确,并确保所有参数均正确设置。 2. 确认所需的依赖库是否正确安装,并且版本正确。 3. 检查servlet的代码,查看是否存在潜在的初始化错误,例如参数无效等。 4. 注入合适的日志记录,以便在调试和排除问题时跟踪线程和错误。 总之,当servlet(dispatcher)的servlet.init()引发异常时,我们需要仔细检查所有可能导致问题的组件,并根据错误消息或堆栈跟踪信息来定位问题,以及采取适当的措施使异常得以修复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 73
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑洞晓威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值