第2阶段 第13讲 Servlet进阶(上)

课程回顾

XML解析: DOM4J、DOM、SAX、JDOM, getParent() 获取父节点,再删除

HTTP协议: 0.9、1.0、1.1 无状态协议

反射技术: Class类反射入口、获取类信息、属性信息、方法信息、构造方法信息、main方法、创建对象(newInstance())、调用方法( invoke )、强制访问( setAccessible(true) )

动态代理: Proxy.newInstance( 类加载器, 接口数组,InvocationHandler ) MyBatis框架使用动态代理、SpringAOP也是

概述

我们在编写Servlet的时候,重写的doGet方法、doPost方法包括两个参数: HttpServletRequest, HttpServletResponse ;这两个参数表示的请求和响应对象。请求和响应对象的创建是由Tomcat服务器来实现的,我们开发人员并不需要显示的创建这两个对象;可以直接使用。Web服务器收到一个http请求,会针对每个请求创建一个HttpServletRequest和HttpServletResponse对象,从客户端取数据找HttpServletRequest,向客户端发送数据就是HttpServletResponse。
在这里插入图片描述

特别感谢: CSDN博客——扬俊的小屋做的动画

HttpServletResponse接口

接口定义

public interface HttpServletResponse extends ServletResponse

所在的包: javax.servlet.http,常见的属性和方法见文档。

HttpServletResponse对象代表服务器的响应。该对象可以向客户端发送三种类型的数据:

  1. 响应头:响应的头部信息
  2. 响应码:响应的状态码
  3. 响应体:响应的具体数据

查看HttpServletResponse的API,可以看到这些相关的方法。查看响应的相关信息:
在这里插入图片描述

发送响应头

package com.ujiuye.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/resp2")
public class MyResponse2 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String str = "对于IO操作来说,使用频率最高(也是最容易被遗忘)的就是close操作,好在Java规范使用了优雅的Closeable接口,这样我们只需简单封装调用此接口的方法即可。";
		System.out.println("原始字节长度:"+str.getBytes().length);
		//创建字节数组输出流,作为容器,默认长度32个字节
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		//创建压缩输出流,压缩,不存储
		GZIPOutputStream zip = new GZIPOutputStream(bos);
		//将原始字符串写到压缩输出流
		zip.write(str.getBytes());
		zip.close();
		//把容器转换成字节数组
		byte[] array = bos.toByteArray();
		System.out.println("压缩后的长度:"+array.length);
		//操作响应头
		response.setHeader("Content-Encoding", "gzip");
		response.setHeader("Content-Length", array.length+"");
		response.setHeader("Accept-Range", "bytes");
		response.setHeader("Cache-Control", "no-cache");
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

执行结果:
在这里插入图片描述

发送响应头控制浏览器内容类型
  • text/html;charset=utf8 文本或者HTML代码
  • jpeg 图片格式
  • pdf pdf文件

内容类型参考文件: apache-tomcat-8.5.51/conf/web.xml

package com.ujiuye.web;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/image")
public class MyResponseImage extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置响应头
		response.setHeader("Content-Type", "jpeg");
		//加载图片获取输入流
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/01.jpeg");
		//创建缓冲数组
		byte[] b = new byte[1024];
		//定义读取数据长度
		int len = 0;
		//循环读取并写到浏览器
		ServletOutputStream sos =  response.getOutputStream();
		while( (len=in.read(b) ) != -1) {
			sos.write(b, 0, len);
		}
		sos.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

http://localhost:8080/chapter13/image

发送响应头控制浏览器禁止缓存
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { 
	response.setDateHeader("expries", -1);
	response.setHeader("Cache-Control", "no-cache");
	response.setHeader("Pragma", "no-cache");
}
发送响应头控制浏览器定时刷新
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { 
	response.setHeader("refresh", "5");//设置refresh响应头控制浏览器每隔5秒钟刷新一次
    //response.setHeader("refresh", "3;url=https://www.baidu.com");//3秒钟跳转页面
}

发送响应码

Servlet在接收用户请求并进行业务处理之后要转向到另一个页面,譬如成功或失败页面,这个页面跳转过程称为重定向。HttpServletResponse中一般用sendRedirect进行重定向,也就是跳转到另一个页面或者Servlet。sendRedirect进行重定向做了下面2件事:

  1. 设置HTTP响应报头中的Status为302
  2. 设置HTTP响应报头中的Location值为指定的URL

HttpServletResponse定义了很多状态码的常量(具体可以查看Servlet的API),当需要向客户端发送响应状态码时,可以使用这些常量,避免了直接写数字,常见的状态码对应的常量:

  • 状态码404对应的常量 SC_NOT_FOUND
  • 状态码200对应的常量 SC_OK
  • 状态码500对应的常量 SC_INTERNAL_SERVER_ERROR
用法
HttpServletResponse.sendRedirect("url?参数名1=参数值&参数名2=参数值");
实例
protected void doGet(HttpServletRequest request,  
	HttpServletResponse response) throws ServletException, IOException {  
	/*方法一:使用response.sendRedirect*/  
	//response.sendRedirect("index.html");  
	  
	/*方法二:设置响应头和重定向地址*/  
	response.setHeader("Location", "index.html");  
	response.setStatus(HttpServletResponse.SC_FOUND);//设置302状态码,等同于response.setStatus(302);       
} 

发送响应体

通过response对象返回具体数据到浏览器是需要的数据传输媒介,分为: 字节流和字符流。

package com.ujiuye.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/refresh")
public class MyResponseRefresh extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf8");
        /**
         * 多学一招:使用HTML语言里面的标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为
		 * response.setHeader("content-type", "text/html;charset=UTF-8");
         */
		String str = "3秒钟跳转页面";
		//输出中文: 字节流
        //ServletOutputStream sos = response.getOutputStream();
        //sos.write(str.getBytes());
        //out.write("使用OutputStream输出数字:".getBytes("utf-8"));
        //out.write( (1+"").getBytes());//字母d, 
		//字符流
		PrintWriter out = response.getWriter();
		out.println("字符流:" + str);
		
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

注意:getOutputStream()和getWriter()这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。

综合案例:文件下载

编写Servlet
package com.ujiuye.web;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/download")
public class MyResponseDownload extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置文件下载响应头
		response.setHeader("Content-disposition", "attachment;filename=01.jpeg");
		//加载图片获取输入流
		InputStream in = getServletContext().getResourceAsStream("/WEB-INF/01.jpeg");
		//获取输出流
		ServletOutputStream out = response.getOutputStream();
		//创建缓冲池
		byte[] b = new byte[1024];
		int len = 0;
		while(  (len = in.read(b)) != -1 ) {
			out.write(b, 0, len);
		}
		out.close();
        in.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

编写HTML页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="download">文件下载</a>
</body>
</html>
支持中文文件名
package com.ujiuye.web;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/download")
public class MyResponseDownload extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//加载图片获取输入流
		String realPath = getServletContext().getRealPath("/WEB-INF/美女.jpeg");
		String fileName = realPath.substring(realPath.lastIndexOf("/") + 1);
		System.out.println("文件名称:"+fileName);
		//设置文件下载响应头
		response.setHeader("Content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "utf-8"));
		
		//InputStream in = getServletContext().getResourceAsStream("/WEB-INF/01.jpeg");
		
		//获取流
		FileInputStream in  = new FileInputStream(realPath);
		ServletOutputStream out = response.getOutputStream();
		//创建缓冲池
		byte[] b = new byte[1024];
		int len = 0;
		while(  (len = in.read(b)) != -1 ) {
			out.write(b, 0, len);
		}
		in.close();
		out.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

综合案例:图片验证码

package com.ujiuye.web;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/code")
public class MyResponseCode extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 0.设置refresh响应头控制浏览器每隔5秒钟刷新一次
		response.setHeader("refresh", "5");
		// 1.在内存中创建一张图片
		BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
		// 2.得到图片
		// Graphics g = image.getGraphics();
		Graphics2D g = (Graphics2D) image.getGraphics();
		g.setColor(Color.WHITE);// 设置图片的背景色
		g.fillRect(0, 0, 80, 20);// 填充背景色
		// 3.向图片上写数据
		g.setColor(Color.BLUE);// 设置图片上字体的颜色
		g.setFont(new Font(null, Font.BOLD, 20));
		g.drawString(makeNum(), 0, 20);
		// 4.设置响应头控制浏览器浏览器以图片的方式打开
		response.setContentType("image/jpeg");// 等同于response.setHeader("Content-Type", "image/jpeg");
		// 5.设置响应头控制浏览器不缓存图片数据
		response.setDateHeader("expries", -1);
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		// 6.将图片写给浏览器
		ImageIO.write(image, "jpg", response.getOutputStream());
	}

	/**
	 * 生成随机数字
	 */
	private String makeNum() {
		Random random = new Random();
		String num = random.nextInt(9999999) + "";
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < 7 - num.length(); i++) {
			sb.append("0");
		}
		num = sb.toString() + num;
		return num;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

访问地址: http://localhost:8080/chapter13/code

HttpServletRequest接口

接口定义

HttpServletRequest接口的定义

public interface HttpServletRequest extends ServletRequest

父接口: ServletRequest接口的定义, 从定义可以看出ServletRequest是根接口。

public interface ServletRequest

Defines an object to provide client request information to a servlet. The servlet container creates a ServletRequest object and passes it as an argument to the servlet’s service method.

定义一个提供客户端请求信息到一个Servlet的对象,Servlet容器创建一个ServletRequest对象并作为一个参数传递给Servlet的seivice方法。

A ServletRequest object provides data including parameter name and values, attributes, and an input stream. Interfaces that extend ServletRequest can provide additional protocol-specific data (for example, HTTP data is provided by HttpServletRequest.

一个ServletRequest对象提供的数据包括: 参数名称和参数值、属性值、输入流。继承自ServletRequest接口可以提供额外指定的协议参数,( 例如Http协议 )

实现类: HttpServletRequestWrapper

public class HttpServletRequestWrapper extends ServletRequestWrapper
    implements HttpServletRequest

查看请求的相关信息:
在这里插入图片描述

获取请求行信息

package com.ujiuye.web2;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/line")
public class RequestLine extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String scheme   = request.getScheme();//获取协议
		String method   = request.getMethod(); //请求方法
		String url      = request.getRequestURL().toString();//请求的URL
		String uri      = request.getRequestURI();//请求的URI
		String param    = request.getQueryString();//请求的参数
		String protocol = request.getProtocol();//请求的协议
		String path     = request.getContextPath();//获取项目名称
		response.setContentType("text/html;charset=utf8");
		PrintWriter out = response.getWriter();
        out.println("scheme:"   + scheme + "<br/>");
		out.println("method:"   + method + "<br/>");
		out.println("url:"      + url + "<br/>");
		out.println("uri:"      + uri + "<br/>");
		out.println("param:"    + param + "<br/>");
		out.println("protocol:" + protocol + "<br/>");
		out.println("path:"     + path + "<br/>");
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

http://localhost:8080/chapter13/line?username=admin&password=123456
在这里插入图片描述

获取请求头信息

获取请求的报文头信息:

  • request.getHeader(“xx”) 根据指定的请求头获取值
  • request.getHeaders(“xx”)根据指定的请求头获取值,值是多个;Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
  • request.getHeaderNames()获取所有的请求头的名称,然后就可以根据名称再获取值
package com.ujiuye.web2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/header")
public class RequestHeader extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf8"); 
		PrintWriter out = response.getWriter();
		Enumeration<String> en =  request.getHeaderNames();//Iterator
		 while(en.hasMoreElements()) {
			String name =  en.nextElement();
			String value = request.getHeader(name);
			out.println(name + "-->" + value + "<br/>");
		 }
		 out.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

执行结果:
在这里插入图片描述

获取请求体信息

获得客户机请求参数(客户端提交的数据)

  • getParameter(String)方法**(常用)**
  • getParameterValues(String name)方法**(常用)**
  • getParameterNames()方法(不常用)
  • getParameterMap()方法**(编写框架时常用)**
注册页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="download">文件下载</a>

<h1>用户注册</h1>
<form name="regForm" action="registerServlet" method="post" id="regForm">
姓名: <input type="text" name="name" id="name"><br>
性别: 男<input type="radio" name="sex" id="radio1" value="" checked><input type="radio" name="sex" id="radio2" value=""><br>
爱好: 
抽烟<input type="checkbox" name="hobbies" value="抽烟">
喝酒<input type="checkbox" name="hobbies" value="喝酒">
打豆豆<input type="checkbox" name="hobbies" value="打豆豆" checked>
泡妞<input type="checkbox" name="hobbies" value="泡妞"><br/>
简介: <textarea name="mark" id="" cols="30" rows="10"></textarea><br>
学历: <select name="education" id="selEdu">
    <optgroup label="非正常学历">
        <option value="野鸡大学">野鸡大学</option>
        <option value="家里蹲大学">家里蹲大学</option>
        <option value="社会大学">社会大学</option>
    </optgroup>
    <optgroup label="正常学历">
        <option value="初中">初中</option>
        <option value="高中" selected="selected">高中</option>
        <option value="大学">大学</option>
    </optgroup>
</select><br>
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
注册Servlet
package com.ujiuye.web2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/registerServlet")
public class RequestBody extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		//第一种方法: 根据表单组件名称获取值
		String name      = request.getParameter("name");
		String sex       = request.getParameter("sex");
		String hobbies[] = request.getParameterValues("chk_hobbies");
		String mark      = request.getParameter("mark");
		String edu       = request.getParameter("education");
		
		out.println("name:" + name + "<br/>");
		out.println("sex:" + sex + "<br/>");
		out.println("hobbies:" + Arrays.toString(hobbies) + "<br/>");
		out.println("mark:" + mark + "<br/>");
		out.println("edu:" + edu + "<br/>");
		out.println("<hr/>");
		//第二种方法: 如果表单的内容不详,如何获取表单数据? Map
		Map<String,String[]> map = request.getParameterMap();
		for(Map.Entry<String, String[]> entry : map.entrySet()) {
			String names = entry.getKey();
			String values[] = entry.getValue();
			out.println(names + "--->" + Arrays.toString(values).replace("[", "").replace("]", "")+"<br/>");
		}
		//第三种方法: 先获取所有的名称,再跟据名字获取内容
		out.println("<hr/>");
		Enumeration<String> en =  request.getParameterNames();
		while(en.hasMoreElements()) {
			String namess = en.nextElement();
			if(namess.startsWith("chk_")) {
				String [] values = request.getParameterValues(namess);
				out.println(namess + "--->" + 
                            Arrays.toString(values).replace("[", "").replace("]", "")+"<br/>");
			}else {
				String value = request.getParameter(namess);//多选的问题
				out.println(namess + "--->" + value+"<br/>");
			}
		}
		out.close();
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}
执行效果

在这里插入图片描述

获取请求客户端信息

package com.ujiuye.web2;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/remote")
public class RequestRemote  extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String addr = request.getRemoteAddr();//客户端IP地址
		String host = request.getRemoteHost();//客户端主机
		int port    = request.getRemotePort();//客户端端口
		String user = request.getRemoteUser();//客户端用户名称
		
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("addr:" + addr+"<br/>");
		out.println("host:" + host+"<br/>");
		out.println("port:" + port+"<br/>");
		out.println("user:" + user+"<br/>");
	}
}

获取本地服务器信息

package com.ujiuye.web2;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/local")
public class RequestLocal  extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String addr = request.getLocalAddr();//服务器IP
		String host = request.getLocalName();//服务器名称
		int port    = request.getLocalPort();//服务器端口
		
		//具体的服务器
		String serverName = request.getServerName();
		int serverPort    = request.getServerPort();
		//代表的本地信息,国家、语言
		Locale local = request.getLocale();
		
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("addr:" + addr+"<br/>");
		out.println("host:" + host+"<br/>");
		out.println("port:" + port+"<br/>");
		out.println("local:" + local.getDisplayCountry() + ","+
                               local.getDisplayLanguage() +"<br/>");
		
		out.println("serverName:" + serverName+"<br/>");
		out.println("serverPort:" + serverPort+"<br/>");
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值