JavaWeb----servlet

基本概念

前言

web开发:网页
静态web:html css
动态web:每个人在不同的时间不同的地点看到的信息不同
技术栈:Servlet/JSP ASP, PHP
在Java中动态web资源开发的技术统称为javaweb

web应用程序

就是可以提供浏览器访问的程序

可以访问到的任何一个页面或者资源,都存在某个计算机上

URL:

这些统一的web资源就会被放在同一个文件夹下,web应用程序—》
Tomcat:服务器

一个web由多部分组成(静态web 动态web)

web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来统一管理

静态web

.htm,.html 这些都是网页的后缀,如果服务器上存在这些东西,我们就可以直接进行读取
在这里插入图片描述
静态web的缺点:
web页面无法动态更新,所有用户看到的都是同一个页面
无法和数据库交互(数据无法持久化。用户无法交互)

动态web

页面会动态展示,Web的页面展示效果因人而异
在这里插入图片描述
缺点:

   如果服务器的动态web资源出现了错误,需要重新编写后台程序,重新发布

优点:

  web页面动态更新,所有用户看到的都不是同一个页面
  可以与数据库交互(数据持久化)

在这里插入图片描述

web服务器

技术

ASP:

 微软:国内最早流行的服务器ASP
  在HTML中嵌入了VB的脚本

php

  PHP开发速度很快,功能很强大,跨平台,代码很简单
  无法承载大访问量的情况(局限性)

JSP/Servlet:

B.S:浏览器和服务器

C/S:客户端和服务器

sun公司主推的B/S架构
  基于java语言(所有的大公司,或者一些开源的组件,都是用Java写的)
  可以承载三高问题带来的影响

web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户的一些响应信息

iis
微软的 ASP windows中自带的

Tomcat

文件夹信息:
在这里插入图片描述
在这里插入图片描述
可以配置启动的端口号(默认端口号是8080)
mysql默认端口号:3306
http 80
https 443
在这里插入图片描述

可以配置主机的名称
默认主机名称:localhost->127.0.0.1
默认网站应用存放的位置 webapps
在这里插入图片描述

网站是如何进行访问的:

1.输入一个域名,回车
2.检查本机的配置文件下有没有这个域名映射
如果有:直接返回对应的IP地址,这个地址中,有需要访问的web程序,可以直接访问
没有的话就去DNS域名服务器上找,找到的话就返回找不到就返回找不到
在这里插入图片描述

发布网站

将写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了

http

概念

是一个简单的请求-响应协议,它通常运行在TCP之上。
HTTP是超文本传输协议
文本:html,字符串…
超文本:图片,音乐,视频 定位 地图…

两个时代

http1.0

 HTTP1.0:客户端与服务器连接后,只能获得一个web资源,断开连接
http2.0
HTTP1.1:客户端与服务器连接后,能获得多个web资源

Http请求

客户端----发送请求(Request)------服务器
在这里插入图片描述
在这里插入图片描述

请求行
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210530233840649.png

请求行的请求方式:GET
请求方式:Get Post
Get: 请求携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全但是高效
Post: 请求携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全但是不高效
消息头
在这里插入图片描述

Http响应

服务器------响应------客户端
在这里插入图片描述
响应体:
在这里插入图片描述
响应状态码
200:请求响应成功
404:找不到资源
3xx:请求重定向(重新到新位置去)
5xx:服务器代码错误

Maven

Maven项目架构管理工具

Maven的核心思想:约定大于配置
有约束不能去违反
maven会规定好如何编写java代码,必须按照这个规范来

下载安装maven

配置环境变量

阿里云镜像

mirrors:镜像
作用加速下载
国内建议使用阿里云的镜像

<mirror>
	<id>alimaven</id>
	<name>aliyun maven</name>
	<url>https://maven.aliyun.com/repository/central/</url>
	<mirrorOf>central</mirrorOf>
</mirror>

本地仓库

在idea中使用maven

项目创建成功后,注意观察maven的配置

Servlet

Servlet就是sun公司开发动态web的一门技术
sun公司在这些API中提供了一种接口叫做Servlet,如果想要开发一个Servlet程序,只需要完成两个步骤:
1.编写好一个类,实现Servlet接口
2.把开发好的java类部署到web服务器中
把实现了Servlet接口的Java程序叫做Servlet

Servlet规范

在这里插入图片描述

Servlet接口实现类

在这里插入图片描述

Servlet接口实现类开发步骤

在这里插入图片描述

Servlet对象的生命周期:

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

helloservlet

1.构建一个普通的Maven项目,删除里面的src目录,在这个项目里面建立Moudel,这个空的工程就是Maven主工程
2.对于Maven父子工程的理解:父项目中会有
Servlet接口sun公司提供了实现类HttpServlet,GenericServlet

     <modules>
        <module>servlet-01</module>
    </modules>

子项目会有

<parent>
    <artifactId>javaweb-02-servlet</artifactId>
    <groupId>com.kuang</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

父项目中的东西子项目可以直接使用
3.Maven的环境优化
1.修改web.xml为最新的
2.将Maven的结构搭建完整
4.编写一个Servlet程序

package com.zhangyu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();//响应流
        writer.print("hello,servlet");
    }

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

    }
}

5.编写Servlet的映射
因为我们编写的是java程序,但是要通过浏览器访问,而浏览器需要访问web服务器,所以需要在web服务中注册我们写的Servlet,并且给他一个浏览器能够访问的路径

 <!--    注册servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.zhangyu.servlet.HelloServlet</servlet-class>
    </servlet>
<!--    servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

6.配置Tomcat
配置项目发布路径

Servlet运行原理

在这里插入图片描述

Mapping问题

1.一个Servlet可以指定一个映射路径

<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

2.一个Servlet可以指定多个映射路径

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello3</url-pattern>
</servlet-mapping>

3.一个Servlet可以指定通用映射路径

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>

优先级问题

指定了固定的映射路径优先级最高,如果找不到就会走默认的处理请求

<servlet>
    <servlet-name>error</servlet-name>
    <servlet-class>com.zhangyu.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>error</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

ServletContext

web容器在启动的时候,他会为每个web程序都创建对应的ServletContext对象,它代表了当前的web应用
共享数据(在这个Servlet中保存的数据,可以在另外一个Servlet中拿到)

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = "张宇";
        context.setAttribute("username", username);//将一个数据都保存在了SrevletContext中,名字为username,值 username
        System.out.println("hello");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
public class ReadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().print("名字" + username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>com.kuang.servlet.ReadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>

获取初始化参数

<!--    配置一些web应用初始化参数-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");
        resp.getWriter().print(url);
    }

请求转发

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    RequestDispatcher dispatcher = context.getRequestDispatcher("/gp");//转发的请求路径
    dispatcher.forward(req, resp);//调用forward实现请求转发
}

读取资源文件

Properties
在Java目录下新建properties
在resourses目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径是类路径
思路:需要一个文件流
Properties

username=root
password=123456
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties prop = new Properties();
        prop.load(is);
        String user = prop.getProperty("username");
        String pwd = prop.getProperty("password");
        resp.getWriter().print("user:"+user);
        resp.getWriter().print("password"+pwd);

    }

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

HttpServletResponse接口

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse,如果获取客户端请求过来的参数:找HttpServletRequest,如果要给客户端响应的一些信息,找HttpServletResponse
介绍
在这里插入图片描述
主要功能
在这里插入图片描述

HttpServletRequest接口

public class ThreeServlet extends HttpServlet {
    /**
     *  问题:以get方式发送中文参数内容时,控制台得到的时正常的中文结果
     *  以post方式发送中文参数内容时,得到的时乱码
     *  原因:
     *  浏览器以get方式发送请求,请求参数保存在请求头中,在Http协议包到达Http服务器之后,第一件事
     *  就是进行解码,请求头的二进制内容有Tomcat进行解码,Tomcat9.0默认使用的是utf-8字符集,可以解释
     *  一切国家文字
     *
     *  浏览器以post方式发送请求,请求参数保存在请求体中,在Http请求协议包到达http服务器之后,第一件事
     *  就是进行解码,请求体的二进制内容由当前对象request负责解码,request是默认使用的字符集是ISO-8859-1
     *  ,是一个东欧语系字符集,此时如果请求体参数内容是中文,就会出现解码失败乱码的情况
     *
     *  解决方法:
     *  在post请求方式下在读取请求体 内容之前,通知对象使用utf-8字符集对请求体内容进行编码
     *   request.setCharacterEncoding("utf-8");
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过请求对象读取请求体参数信息
        request.setCharacterEncoding("utf-8");
        String value = request.getParameter("username");
        System.out.println("从请求体中得到参数值:"+value);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过请求对象读取请求头中的参数信息
        String username = request.getParameter("username");
        System.out.println("从请求头得到参数值:"+username);
    }
}

请求对象和响应对象生命周期

1.在Http服务器收到浏览器的请求协议包后自动为当前的Http请求协议包生成一个请求对象和响应对象
2.在Http服务器调用doget或者dopost方法时,负责将请求对象和响应对象作为实参传递到方法,确保doget和dopost正确执行。
3.Http服务器准备推送Http相应协议包之前,负责将本次请求关联的请求对象和响应对象销毁。

用户注册流程图

在这里插入图片描述

欢迎资源文件

1.前提

用户可以记住网站名,但是不会记住网站资源文件名

2.默认欢迎资源文件

用户发送了一个针对某个网站的默认请求时,此时由http服务器自动从当前网站返回的资源文件
正常请求:http://localhost:8080/myWeb/index.html
默认请求:http://localhost:8080/myWeb/

3.Tomcat对于默认欢迎资源文件定位规则

1.规则位置:Tomcat安装位置/conf/web.xml
在这里插入图片描述
4.设置当前网站的默认欢迎资源文件规则
1.规则位置:网站/web/web_inf/web.xml
2.规则命令:

<welcome-file-list>
         <welcome-file>login.html</welcome-file>
 </welcome-file-list>

3.网站设置自定义默认文件定位规则,此时Tomcat自带定位规则将失效(servlet作为默认欢迎资源文件时要把开头的/去掉)

Http状态码

1.介绍

1.有三位数字组成的一个符号
2.Http服务器在推送响应包之前,根据本次请求处理情况将Http状态码写入到响应包(状态行中)
3.如果Http服务器针对本次请求,返回了对应的资源文件,通过Http状态码通知浏览器如何处理这个结果
如果Http服务器针对本次请求,无法返回对应的资源文件,通过Http状态码向浏览器解释不能提供服务的原因

2.分类

1.组成
100----599分为五个大类
2.1xx:
最有特征的100;通知浏览器本次返回的资源文件并不是一个独立的资源文件,需要浏览器在接收响应包之后,继续向Http服务器索要依赖的其他资源文件
3.2xx:
最有特征200,通知浏览器本次返回的资源文件是一个完整独立资源文件,浏览器在接收到之后不需要索要其他关联文件
4.3xx:
最有特征302,通知浏览器本次返回的不是一个资源文件内容,而是一个资源文件地址,需要浏览器根据这个地址自动发起请求来索要这个资源文件:
response.sendRedirect(“资源文件地址”)写入到响应头中,这个行为将导致Tomcat将302状态码写入到状态行
5.4xx:
404:通知浏览器,由于在服务端没有定位到被访问的资源文件,因此无法提供帮助
405:通知浏览器,在服务端已经定位到被访问的文件(Servlet)但是这个Servlet对于浏览器采用的请求方式不能处理
6.5xx:
500:通知浏览器,在服务端已经定位到被访问的资源文件(Servlet)这个Servlet可以接收浏览器的采用请求方式,但是Servlet在处理请求期间,由于java异常导致处理失败

多个Serlvet之间调用规则

1.前提条件

某些来自于浏览器发送请求,往往需要服务端中多个Servlet协同处理,但是浏览器一次只能访问一个Servlet,导致用户需要手动通过浏览器发起多次请求才能得到服务。这样增加用户获得服务难度,导致用户放弃当前网站

2.提高用户使用感受规则

无论本次请求涉及到多少Servlet用户只需要手动通知浏览器发起一次请求即可

3.多个Servlet之间调用规则

1.重定向解决方案
2.请求转发解决方案

重定向解决方案

1.工作原理

在这里插入图片描述

用户第一次通过手动方式通知浏览器访问OneServlet,OneServlet工作完毕后,将TwoServlet地址写入到响应头location属性中,导致Tomcat将302状态码写入到状态行
在浏览器接收到响应包之后,会读取到302状态,此时浏览器自定会根据响应头中location属性地址发起第二次请求,访问TwoServlet去完成请求中剩余任务

2.实现命令

response.sendRedirect(“请求地址”)
将地址写入到响应包中的响应头location属性

3.特征

1.请求地址:
既可以把当前网站内部资源文件地址发送给浏览器(/网站名/资源文件名)
也可以把其他网站资源地址发送给浏览器(http://ip地址:端口号/网站名/资源文件名)
2.请求次数:
浏览器至少发送两次请求,但是只有第一次请求是用户手动发送,后续请求都是浏览器自动发送的
3.请求方式:
重定向解决方案中,通过地址栏通知浏览器发起下一次请求,因此通过重定向解决方案调用的资源文件接收的请求方式·一定是get

4.缺点

重定向解决方案需要在浏览器与服务器之间进行多次往返,大量时间消耗在往返次数上,增加用户等待服务时间。

请求转发解决方案

在这里插入图片描述

1.原理

用户第一次通过手动方式要求浏览器访问OneServlet,OneServlet工作完毕后,通过当前的请求对象代替浏览器向Tomcat发送请求,申请调用TwoServlet,Tomcat在接受到这个请求之后,自动调用TwoServlet来完成剩余任务

2.实现命令(请求对象代替浏览器向Tomcat发送请求)

//1.通过当前请求对象生成资源文件申请报告对象
RequestDispatcher report = request.getRequestDispatcher("/资源文件名");
一定要以斜线为开头
//2.将报告发送给Tomcat
report.forward(当前请求对象,当前响应对象);

3.优点

1.无论请求涉及到多少个Servlet,用户只需要手动通过浏览器发送一次请求
2.Servlet之间调用发生在服务端计算机上,节省服务端与浏览器之间往返次数,增加处理服务速度

4.相关特征

1.请求次数
在请求转发过程中,浏览器只发送一次请求
2.请求地址
只能向Tomcat服务器申请调用当前网站下资源文件地址
request.getRequestDispathcer("/资源文件名")*不要写网站名
3请求方式
在请求转发过程中,浏览器只发送了一个Http请求协议包,参与本次请求的所有Servlet共享同一个请求协议包,因此,这些Servlet接收的请求方式与浏览器发送的请求方式保持一致

多个Servlet之间数据共享实现方案

1.数据共享

OneServlet工作完毕后,将产生数据交给TwoServlet来使用

2.Servlet规范中提供四种数据共享方案

1.ServletContext接口
2.Cookie类
3.HttpSession接口
4.HttpServletRequest接口

ServletContext接口

1.介绍:

1.来自于Servlet规范中的一个接口,在Tomcat中存在servlet-api.jar在Tomcat中负责提供这个接口实现类
2.如果两个Servlet来自于同一个网站,彼此之间通过网站的ServletContext实例对象实现数据共享
3.开发人员习惯将ServletContext对象称为全局作用域对象

2.工作原理

在这里插入图片描述
每一个网站都存在一个全局作用域对象,这个作用域对象相当于一个Map,在这个网站中OneServlet可以将一个数据存入到全局作用域对象,当前网站中的其他Servlet此时都可以从全局作用域对象,得到每个数据进行使用

3.全局作用域对象的生命周期

1.在Http服务器启动过程中,自动为当前网站内存中创建一个全局作用域对象。
2.在Http服务器运行期间,一个网站只有一个全局作用域对象。
3.在Http服务器运行期间,全局作用域对象一直处于存活状态
4.在Http服务器准备关闭时,负责将当前网站中的全局作用域对象进行销毁处理

全局作用域对象证明周期贯穿网站整个运行期间***

4.命令实现

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

Cookie

1.介绍

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

2.原理

在这里插入图片描述

3.实现命令

在这里插入图片描述

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

Coolie销毁时机

1.在默认情况下Cookie对象存放在浏览器的缓存中,因此只要浏览器关闭,Cookie对象就会被销毁。
2.在手动设置的情况下,可以要求浏览器将接收的Cookie存放在客户端计算机硬盘上,同时需要指定Cookie在硬盘上存活时间,在存活时间范围内,关闭浏览器关闭客户端计算机,关闭服务器,都不会导致Cookie被销毁,在存活时间到达时,Cookie自动从硬盘上被删除。
cookie.setMaxAge(60);//cookie在硬盘上存活一分钟

Httpsession接口

1.介绍

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

命令实现

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

Http服务器如何将HttpSession关联起来

通过cookie
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

HttpServletRequest接口实现数据共享

1.介绍

1.在同一个网站中,如果两个Servlet之间通过请求转发方式进行调用,彼此之间共享同一个请求协议包,而一个请求协议包只对应一个请求对象,因此servlet之间共享同一个请求对象此时可以利用这个请求对象在两个Servlet之间实现数据共享。
2.在请求对象实现Servlet之间数据共享功能时,开发人员将请求对象称为请求作用域对象。

2.命令实现

在这里插入图片描述

Servlet规范扩展-------监听器接口

1.介绍

1.一组来自于Servlet规范下接口,共有8个接口,在Tomcat存在servlet-api.jar包中。
2.监听器对象需要由开发人员亲自实现,Http服务器提供jar包并没有对应的实现类。
3.监听器接口,用于监控作用域对象生命周期变化时刻以及作用域对象共享数据变化时刻。

2.作用域对象

1.在Servlet规范中,认为在服务端内存中可以在某些条件下为两个Servlet之间提供数据共享方案方案的对象被称为作用域对象
2.Servlet规范下作用域对象
ServletContext:全局作用域对象
HttpSession:会话作用域对象
HttpServletRequest:请求作用域对象

3.监听器接口实现类开发规范(3步)

1.根据监听的实际情况,选择对应监听器接口进行实现
2.重写监听器接口声明监听事件处理方法
3.在web.xml文件将监听器接口实现类注册到Http服务器

4.ServletContextListener接口

1.作用:通过这个接口合法检测全局作用域对象被初始化时刻和被销毁时刻
2.监听事件处理方法:
public void contextInitlized():在全局作用域对象被Http服务器初始化被调用
public void contextDestory(): 在全局作用域对象被Http服务器销毁时候触发调用

5.ServletContextAttributeListener接口

1.作用:通过这个接口合法检测全局作用域对象共享数据变化时刻
2.监听事件处理方法:
public void contextAdd();在全局作用域对象添加共享数据时被调用
public void contextReplaced()在全局作用域对象更新共享数据时被调用
public void contextRemove() 在全局作用域对象删除共享数据时被调用

6.全局作用域对象共享数据变化时刻

在这里插入图片描述

Filter接口------过滤器接口

1.介绍

1.来自于Servlet规范下接口,在Tomcat中存在于servlet-apijar包中
2.Filter接口实现类由开发人员负责提供,Http服务器不负责提供
3.Filter接口在Http服务器调用资源文件之前,对Http服务器进行拦截·

2.具体作用

1.拦截服务器,帮助Http服务器检测当前请求合法性
2.拦截http服务器,对当前请求进行增强操作

3.Filter接口类开发步骤

1.创建一个java类实现Filter接口
2.重写Filter接口中的doFilter方法
3.web.xml将过滤器接口实现类注册到Http服务器

4.Filter拦截地址格式

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值