JavaWeb学习笔记

JavaWeb学习笔记

一、基础概念

1.什么是JavaWeb

JavaWeb是所有通过java语言编写可以通过游览器访问的程序的总称。

2.请求和响应

  • 请求(Request):客户端给服务器发送数据。
  • 响应(Response):服务端给客户端回传数据。

3.Web资源的分类

  • 静态资源:html,css,js,txt,mp4,jpg
  • 动态资源:jsp页面,servlet程序

二、Http协议

Http协议是客户端和服务器之间通信时,发送的数据需要遵守的规则。协议中的数据又叫报文,请求格式一般为Get请求和Post请求两种。

1. 请求的Http协议格式

get请求

  • 请求行
    • 请求方式 GET
    • 请求的资源路径【+?+请求参数】
    • 请求的协议的版本号 HTTP/1.1
  • 请求头
    • key:value 不同的键值对表示不同的含义

post请求

  • 请求行

    • 请求方式 POST
    • 请求的资源路径
    • 请求的协议的版本号 HTTP/1.1
  • 请求头

    • key:value 不同的键值对表示不同的含义

      空行

  • 请求体 ------------>发送给服务器的数据

img

img

2 响应的Http协议格式

  • 响应行

    • 相应的协议和版本号
    • 响应状态码
    • 响应状态描述符
  • 响应头

    • key:value 不同的响应头对表示不同的含义

      空行

  • 响应体---------> 就是回传给客户端的数据

img

三,Tomcat

1.Tomcat目录

bin:专门存放Tomcat服务器的可执行程序
conf:专门存放Tomcat服务器的配置文件
lib:专门存放Tomcat服务器的jar包
logs:专门存放Tomcat服务器的运行时输出的日志信息
temp:专门存放Tomcat运行时产生的临时数据
webapps:专门存放部署的web工程
work:Tomcat工作时的目录,存放Tomcat运行时jsp翻译为Servlet的源码,和Session钝化的目录

批注:钝化把服务器不经常使用的session对象暂时序列化到系统文件,整个的过程是由服务器自动完成的。

2.修改端口号

img

img

批注:Http协议默认的端口号是:80

3.部署Web到Tomcat

**方式一:**将Web工程文件拷贝到Webapps目录下,访问http://localhost:8080/工程文件名

**方式二:**找到Tomcat下的==\Catalina\localhost==,创建如下的配置文件

img

Context标签表示工程上下文,path属性表示工程访问的路径,docBase表示工程文件所在的位置img

访问:http://localhost:8080/aaa

4.手动拖动html页面和输入地址访问的不同

手动拖动html页面到浏览器

img

输入地址访问

img

  • 手动拖动html页面使用File://协议,file协议表示告诉浏览器我们直接读取file:协议后面的路径,解析展示在浏览器上即可
  • 在地址栏中输入地址访问:http://ip:port/工程名/资源名,所使用的协议是Http协议,背后的原因完全不同

5.默认访问工程和默认访问资源

  • http://ip:port/ ------> 没有工程名的时候,默认访问的是root工程
  • http://ip:port/工程名 ------> 没有资源名的时候,默认访问的是index.html页面
    img

6.Web工程目录

img

7.给Idea部署Tomcat工程

img

img

img

四、Servlet

1.概述

  • Servlet是JavaEE规范之一,规范就是接口
  • Servlet就是JavaWeb三大组件之一,三大组件:Servlet程序、Filter过滤器、Listener监听器
  • Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并相应数据给客户端

2.实现

  • 编写一个类去实现Servlet接口
  • 实现Service方法,处理请求,并响应数据
  • 到web.xml中去配置servlet程序的访问地址
  • service方法是专门用来处理请求和响应的

类实现

package com.atguigu.servlet;

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

public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 被访问了");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

配置实现:

<?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标签给Tomcat配置Servlet程序-->
    <servlet>
        <!--给servlet程序起一个别名(一般是类名)-->
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    </servlet>
<!--servlet-mapping标签给Servlet程序配置访问地址-->
    <servlet-mapping>
        <!--告诉服务器,我当前配置的地址给哪个Servlet使用-->
        <servlet-name>HelloServlet</servlet-name>
        <!--配置访问地址-->
        <!--
            /:        表示地址为:http://ip:port/工程路径
            /hello:   表示地址为:hello://ip:port/工程路径/hello
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

img

3.Servlet生命周期

  • 执行Servlet构造器方法:第一次访问创建Servlet程序的时候会调用
  • 执行init初始化方法:第一次访问创建Servlet程序的时候会调用
  • 执行service方法:每次访问都会调用
  • 执行destroy销毁方法:在Web工程停止的时候调用

4.请求分发处理

  • 判断请求的方式:ServletRequest的子类HttpServletRequest的方法 **getMethod()**方法即可判断
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("3--------------service方法");

    //类型转换(因为他有getMethod()方法)
    HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
    String method = httpServletRequest.getMethod();
    System.out.println(method);
    if("GET".equals(method)){
        doGet();

    }else if("POST".equals(method)){
       doPost();
    }
}

public void doGet(){
    System.out.println("Get请求");
    System.out.println("Get请求");
}

public void doPost(){
    System.out.println("Post请求");
    System.out.println("Post请求");
}

5.使用HttpServlet接口实现Servlet程序

一般在实际项目开发过程中,都是使用继承HttpServlet方式去实现Servlet程序

  • 编写一个类去继承HttpServlet类
  • 根据业务需要重写doGet()和doPost()方法
  • 到web.xml中的配置Servlet程序的访问地址

6.Servlet类的继承体系img

6.1 ServletConfig类

Servlet程序的配置信息类

  • 可以获取Servlet程序的别名Servlet-name的值

  • 获取初始化参数init-param

  • 获取ServletContext对象

//可以获取Servlet程序的别名Servlet-name的值
System.out.println("HelloServlet程序的别名是:"+servletConfig.getServletName());

//获取初始化参数init-param
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));

//获取servletContext对象
System.out.println("servletContext对象是:"+servletConfig.getServletContext());
6.2 ServletContext类
  • ServletContext是一个接口,表示Servlet上下文对象
  • 一个Web工程只有一个ServletContext对象实例
  • ServletContext对象是一个域对象
  • ServletContext对象是在Web工程部署启动的时候创建,是在Web工程停止的时候销毁(不同的Servlet程序只要在一个工程内可以获取对象创建的值)
//1.使用ServletContext获取Web.xml中配置的上下文参数
	ServletContext context = getServletConfig().getServletContext();
	String username = context.getInitParameter("username");
	System.out.println("context-param参数username的值是:"+username);
//2.获取当前的工程路径,格式:/工程路径
	System.out.println("当前工程路径"+context.getContextPath());
//3.获取工程部署后在服务器磁盘上的绝对路径
//   / 斜杠 表示被服务器解析地址为:http://ip:port/工程名/   映射到IDEA代码的Web目录
	System.out.println("工程部署的路径是:"+context.getRealPath("/"));
	System.out.println("工程下css目录的路径是:"+context.getRealPath("/css"));
//4.像map一样存取数据
	context.setAttribute("key1","value1");
	System.out.println("context1中获取域数据key1的值是:"+context.getAttribute("key1"));

6.3 HttpServletRequest类
  • 每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的Http协议信息解析好封装到Request对象中,然后传递到service方法(doGet、doPost)中给我们使用
  • 我们可以通过HttpServletRequest对象获取到所有请求的信息

常用API

img

批注:解决post请求乱码问题:req.setCharacterEncoding("utf-8");

请求转发

请求转发是指服务器收到请求后,从一个资源跳到另一个资源的操作叫请求转发

特点:

  • 浏览器地址栏没有变化
  • 他们是一次请求
  • 他们是共享Request域中的数据(域数据)
  • 可以转发到WEB-INF目录下(若页面在WEB-INF目录下,使用浏览器访问不了,只能使用转发方式进入)
  • 不可以访问工程以外的资源,无法出站

请求重定向

客户端向服务器发请求,然后服务器告诉客户端说,我给你一些地址,你去新地址访问,叫请求重定向(因为之前的地址可能已经废弃)

特点:

  • 浏览器地址栏会发生改变
  • 两次请求
  • 不共享Request域中的数据
  • 不能访问WEB-INF下的资源
  • 可以访问工程外的资源,比如百度

/斜杠的不同意义

在Web中 /斜杠是一种绝对路径

/ 斜杠如果被浏览器解析,得到的地址是:http://ip:port/

/ 斜杠如果被服务器解析,得到的地址是:http://ip:port/工程路径

6.4 HttpServletResponse类

每次只要有请求进入Tomcat服务器,Tomcat服务器都会创建一个response对象传递给Servlet程序去使用,HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息

常用的两个输出流:

流类型方法名用途
字节流getOutputStream()常用于下载(传递二进制数据)
字符流getWriter()常用于回传字符串

两个流只能使用一个,使用了字节流就不能再使用字符流,反之亦然,否则就会报错

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //解决乱码
    resp.setContentType("text/html;charset=utf-8");
    
    PrintWriter writer = resp.getWriter();
    writer.write("我写入了!");
}

五、JSP

1.概述

  • jsp的全称是 java serve page,java的服务器页面
  • jsp的主要作用是代替Servlet程序回传html的数据
  • 因为Servlet程序回传html页面数据是一件非常繁琐的事情,开发成本和维护成本都极高
  • jsp页面本质上是一个Servlet程序,Tomcat会帮我们帮jsp页面翻译成一个java源文件

2.脚本

脚本可以声明java代码,在jsp页面上输出数据。

声明脚本<%! 声明java代码 %>

作用:可以给jsp翻译出来的java类定义属性和方法甚至是静态代码块、内部类等

<%--1.声明类属性--%>
<%!
    private Integer id;
    private String name;
    private static Map<String,Object> map;
%>

<%--2.声明static静态代码块--%>
<%!
    static{
        map=new HashMap<String,Object>();
        map.put("key1","value1");
    }
%>

<%--3.声明类的方法--%>
<%!
    public int abc(){
        return 12;
    }
%>

<%--4.声明内部类--%>
<%!
    public static class A{
        private Integer id=12;
        private String abc;
    }
%>

表达式脚本:<% =表达式 %>

作用:在jsp页面上输出数据

特点:

  • 所有的表达式脚本都会被翻译到**_jspService()**方法中
  • 表达式脚本都会被翻译成为**out.print()**输出到页面上
  • 由于表达式脚本翻译的内容都在_ jspService()中,所以_ jspService()中的所有对象(request、reponse)都可以使用
  • 表达式脚本中的表达式不能以分号结束
<%--1.输出整型--%>
<%=12%> <br>
<%--2.输出浮点型--%>
<%=12.12%> <br>
<%--3.输出字符串--%>
<%="我是字符串"%>
<%--4.输出对象--%>
<%=map%>

代码脚本<% java语句 %>

  • 作用:可以在jsp页面中,编写我们自己需要的功能(写的是java语句)

特点:

  • 所有的表达式脚本都会被翻译到**_jspService()**方法中

  • 代码脚本由于翻译到**_jspService()**方法中,所以在_jspService()方法中的先有对象都可以直接使用

  • 还可以由多个代码脚本块组合完成一个完整的java语句

  • 代码脚本还可以和表达式脚本一起组合使用,在jsp上输出使用数据

<%--if语句--%>

<%
    int i=12;
    if(i==12){
        System.out.println("海锋好帅");
}else {
        System.out.println("海锋又骗人了");
    }
%>

<%--for循环--%>
<%
    for (int j = 0; j <4 ; j++) {
        System.out.println(j);
    }
%>

<%--翻译后java文件中_jspService方法内的代码都可以写--%>
<%
    String username = request.getParameter("username");
    System.out.println("用户名的请求参数是:"+username);
%>

3.jsp九大内置对象

对象类型说明
request请求对象获取用户请求信息
response响应对象响应客户端请求,并将处理信息返回到客户端
session会话对象用来保存用户信息
applicationServletContext对象所有用户共享信息
configervletConfig对象这是一个 Servlet 配置对象,用于 Servlet 和页面的初始化参数
page指向当前jsp的对象类似于 Java 类的 this 关键字,表示当前 JSP 页面
pageContextjsp的上下文对象JSP 的页面容器,用于访问 page、request、application 和 session 的属性
outjsp输出流对象输出内容到 HTML 中
exception异常对象该对象用于处理 JSP 文件执行时发生的错误和异常;只有在 JSP 页面的 page 指令中指定 isErrorPage 的取值 true 时,才可以在本页面使用 exception 对象。

JSP 的内置对象主要有以下特点:

  • 由 JSP 规范提供,不用编写者实例化;
  • 通过 Web 容器实现和管理;
  • 所有 JSP 页面均可使用;
  • 只有在脚本元素的表达式或代码段中才能使用。

4.jsp四大域对象

域对象存取范围
pageContext当前jsp页面范围内有效
request一次请求内有效
session一个会话范围内有效(打开浏览器访问服务器,直到关闭服务器)
application整个Web工程范围内都有效(只要Web工程不停止,数据都在)

5、JSTL标签库

JSTL标签库,全程是指JSP Standard Tag Library jsp标准标签库,是一个不断完善的开放源代码的jsp标签库

六、Listener监听器

1.概述

  • Listener监听器是JavaWeb三大组件之一,三大组件分别是:Servlet程序、Filter过滤器、Listener监听器
  • Listener它是javaEE的规范,就是接口
  • 监听器的作用就是监听某种事物的变化通过回调函数反馈给客户(程序)去做一些相应的处理

2.ServletContextListener

  • ServletContextListener可以监听ServletContext对象的创建和销毁
  • ServletContext对象在Web工程启动的时候创建,在Web工程停止的时候销毁
  • 监听到创建和销毁之后会分别调用ServletContextListener监听器的方法反馈
//在ServketContext对象创建之后马上调用,做初始化
default void contextInitialized(ServletContextEvent sce) {
}

//在ServletContext对象销毁之后调用
default void contextDestroyed(ServletContextEvent sce) {
}

七、EL表达式

1.EL表达式的概述

替代jsp页面中表达式脚本在jsp页面中进行

输出的格式是:${key1}

EL表达式在输出null值的时候,输出的是空串,jsp表达式脚本输出null值的时候,输出的是null字符串

2.EL表达式搜索域数据的顺序

当四个域中都有相同key的数据的时候,EL表达式会按照四个域的从小到大的数据去进行搜索,找到就输出

3.EL表达式输出复杂Bean对象

创建一个bean类

img

新建jsp文件

img

为里面的每一个属性赋值。注意不同的类型不同的赋值方法。用EL表达式进行输出:

img

img

来源

4.EL表达式运算

img

img

img

**empty运算:**判断一个数据是否为空,如果为空则输出true,不为空则输出false

为空的情况:

  • 值为null值
  • 值为空串
  • 值是Object类型数组,长度为0
  • list集合,元素个数为0
  • map集合,元素个数为0

5.EL表达式中11个隐含对象

变量类型作用
pageContextPageContextImpl可以获取jsp中的九大内置对象
pageScopeMap<String,Object>可以获取PageContext域中的数据
requestScopeMap<String,Object>可以获取reques域中的数据
sessionScopeMap<String,Object>可以获取session域中的数据
applicationScopeMap<String,Object>可以获取ServletContext域中的数据
paramMap<String,String>可以获取请求参数的值
paramValuesMap<String,String[]>可以获取请求参数的值,获取多个值的时候使用
headerMap<String,String>可以获取请求头的信息
headerValuesMap<String,String[]>可以获取请求头的信息,获取多个值的时候使用
cookieMap<String,Cookie>可以获取当前请求的Cookie信息
initParamMap<String,String>可以获取在Web.xml中配置的上下文参数

八、文件的上传和下载

1.文件的上传

1.1 上传网页编写

使用form标签,method=post请求

form便签的encType属性值必须为multipart/form-data值,表示提交的数据以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
在form标签中使用input type=file添加上传的文件

<body>
    <form action="http://localhost:8080/uploadservlet" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username"/> <br>
        头像:<input type="file" name="photo"/> <br>
        <input type="submit" value="上传">
    </form>
</body>
1.2 上传服务器接收处理

必须使用流的形式来进行接受:

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("文件上传进来了");
    ServletInputStream inputStream = req.getInputStream();
    byte[] buffer= new byte[102400];
    int read = inputStream.read(buffer);
    System.out.println(new String(buffer,0,read));

}

2.下载

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //1.获取要下载的文件名
    String downloadFileName="1.jpg";
    //2.读取要下载的文件内容(通过ServletContext对象可以读取)
    ServletContext servletContext = getServletContext();
    //获取要下载的文件类型
    String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
    System.out.println("下载的文件类型:"+mimeType);
    //4.在回传前,通过响应头告诉客户端返回的数据类型
    resp.setContentType(mimeType);
    //5.告诉客户端收到的数据是用于下载的(使用响应头)
    //Content-Disposition响应头:表示收到的数据怎么处理   Content-Disposition:表示附件,下载使用    filenma=表示指定下载的文件名
    resp.setHeader("Content-Disposition","attachment;filename"="美女.jpg");
    //解决中文乱码问题
    //resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode("美女.jpg","utf-8"));
    InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
    //获取相应的输出流
    OutputStream outputStream=resp.getOutputStream();
    //3.将下载的文件内容回传给客户端
    //读取输入流中全部的数据,复制给输出流,输出给客户端
    IOUtils.copy(resourceAsStream,outputStream);

}

九、Cookie和Session

1.区别和用法

  • cookie数据存放在客户的浏览器上,session数据放在服务器上
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie
  • 单个cookie在客户端的限制是4K,session大小可以在服务端自定义

总结:将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中

2.Cookie和Session的创建与获取与修改

创建
protected void createcookie(HttpServletRequest req, HttpServletResponse resp) throws  IOException {
    //1.创建Cookie对象
    Cookie cookie = new Cookie("key1","value1");
    //2.通知客户端保存Cookie
    resp.addCookie(cookie);
    resp.getWriter().write("Cookie创建成功");
}

protected void createorgetsession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //创建和获取Session会话对象
    HttpSession session = req.getSession();
    //判断当前Session会话是否是新创建出来的
    boolean aNew = session.isNew();
    //获取session会话的唯一标识
    String id = session.getId();

    resp.getWriter().write("得到的Session它的id是:"+id+"<br/>");
    resp.getWriter().write("这个Session是否是新创建的:"+aNew+"<br/>");
}

获取
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
    //getName()方法:返回cookie的key
    //getValue()方法:返回cookie的值
    resp.getWriter().write("cookie["+cookie.getName()+"="+cookie.getValue()+"]");
}

//获取Session的方法也是request.getSession(),用isNew()判断到底是不是刚创建出来的,true:表示刚创建;false:获取之前创建的。
修改

cookie

**方法一:**创建一个同名的cookie赋新值,调用response.addCookie(Cookie)方法直接覆盖。

**方法二:**找到要修改的cookie对象,调用setValue()方法赋予新的Cookie值,调用response.addCookie()通知客户端保存修改。

session存取数据:

protected void setattribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.getSession().setAttribute("key1","value1");
    resp.getWriter().write("已经往Session中保存了数据");
}

protected void getattribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    Object attribute = req.getSession().getAttribute("key1");
    resp.getWriter().write("从Session中获取出key1的数据是:"+attribute);
}

3.Cookie和Session的生命控制

Cookie:

setMaxAge()

  • 正数,表示在指定的秒数后过期
  • 负数,表示浏览器一关,Cookie就会被删除
  • 零,表示马上删除Cookie
Session:

setMaxInactiveInterval()

正数,设定Session的超时时长;

负数,表示永不超时(极少使用)

十、Filter过滤器

1.概念

  • Filter过滤器她是JavaWeb三大组件之一。三大组件分别是:Servlet、Listener、Filter
  • Filter过滤器它是javaEE的规范,也就是接口
  • Filter过滤器的作用:拦截请求,过滤响应
  • 拦截请求常见的应用场景:
    • 权限检查
    • 日记操作
    • 事务管理

2.Filter生命周期

Filter的生命周期包含几个方法:

  • 构造器方法:Web工程启动时候执行
  • init初始化方法:Web工程启动时候执行
  • doFilter过滤方法:每次拦截到请求就会执行
  • destroy销毁方法:停止Web工程时候就会执行(停止Web工程,也会销毁Web过滤器)

3.Filter-Chain过滤器链

img

十一、 JSON

  • JSON(JavaScr ipt Object Notaticn)是一种轻量级的数据交换格式。
  • json的轻量级指的是跟xml作比较,数据交换指的是客户端和服务器之间业务数据的传递格式

json的存在有两种形式:

对象的形式存在,我们叫它json对象

字符串的形式存在,我们叫它json字符串

一般我们要操作json中的数据的时候,需要json对象的格式

一般我们需要在客户端和服务器之间进行数据交换的时候,使用json字符串的格式

json.stringfy():将json对象转换称为json字符串

json.parse():将json字符串转换为json对象
json可以和java中的javaBean,List,Map相互转换

十二、AJAX

  • AJAX即“Asynchronous JavascriptcAnd XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
  • ajax是一种浏览器通过js异步发起请求。局部更新页面的技术。
jQuery中的AJAX请求

$ajax方法
url 请求的地址
type 请求的类型是GET或POST
data 发送给服务器的数据
格式有两种:1.name=value && name=value 2.{key:value}
success 请求成功,相应的回调函数
dataType 相应的数据类型:常用的数据类型有:text(纯文本)、xml(xml数据)、json(json对象)

[参考](AJAX 教程 | 菜鸟教程 (runoob.com))

注:本笔记为参照https://blog.csdn.net/lyyrhf/article/details/115548637进行修改所做的学习笔记。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值