Web 常用对象1

Web对象

一.请求的方式

1. 地址栏输入

    在浏览器地址栏直接输入要访问的地址即可,此种方式可以看做是访问服务器的起始操作。
    格式:http://ip:port/path

2. 超链接

 使用超链接也可以向服务器发出请求

<a href="http://www.baidu.com">百度</a>
3. Form 表单

    当需要向服务器发送请求,并且传输一些用户输入的数据时,我们优先选择form 表单的方式发起请求。
在这里插入图片描述

前后台连接时action="..."<servlet-mapping>中的<url-pattern>值一致
Servlet3.0 和注解一致
4. ajax

    通过 ajax 发起的请求,属于异步请求,能实现局部刷新的效果,是一种比较常用的请求方式。

    通过 jQuery 中的 ajax(),get(),post(),getJSON()等方法都能发送请求

5. 请求转发

    通过服务器内部将请求进行一次转发,可以请求到其他资源

6. 重定向

    服务器通过给定一个新资源的地址,响应会客户端后,客户端自动再次发送一个请求到新资源的地址处。

二.HttpServletRequest 对象

1. 介绍

HttpServletRequest 对象主要作用是用来接收客户端发送过来的请求信息

    例如:请求的参数,发送的头信息等都属于客户端发来的信息,service()方法中形参接收的是 HttpServletRequest 接口的实例化对象,表示该对象主要应用在HTTP 协议上,该对象是由 Tomcat 封装好传递过来。

    HttpServletRequest 是 ServletRequest 的子接口,ServletRequest 只有一个子接口,就是 HttpServletRequest。既然只有一个子接口为什么不将两个接口合并为一个?
    从长远上讲:现在主要用的协议是 HTTP 协议,但以后可能出现更多新的协议。若以后想要支持这种新协议,只需要直接继承 ServletRequest 接口就行了。

    在 HttpServletRequest 接口中,定义的方法很多,但都是围绕接收客户端参数的。但是怎么拿到该对象呢?不需要,直接在 Service 方法中由容器传入过来,而我们需要做的就是取出对象中的数据,进行分析、处理。
    注:这里是重写service方法

2.常用形式
1). 常用方法

在这里插入图片描述

1.★获取请求的完整路径 (从http开始,到问号前面)
    getRequestURL()完整url
2.★获取部分资源路径(从站点名开始,到问号前面)
    getRequestURI()部分url
3.获取 请求的参数字符串 (从问号开始,到最后的字符串,不包含问号)
    getQueryString()
4.获取请求的类型 (GET/POST)
    getMethod()请求类型
5.获取请求协议版本
    getProtocol()协议版本
6.获取站点名(项目的对外访问路径)
    getContextPath()站点名
代码示例:
// 常用方法

// 获取请求的完整路径 (从http开始,到问号前面)

System.out.println("获取请求的完整路径: " + req.getRequestURL());

//获取请求的部分资源路径: /sr02/s01



// 获取部分资源路径(从站点名开始,到问号前面)

System.out.println("获取请求的部分资源路径: " + req.getRequestURI());

//获取请求的部分资源路径: /sr02/s01



// 获取 请求的参数字符串 (从问号开始,到最后的字符串,不包含问号)

System.out.println("获取 请求的参数字符串: " + req.getQueryString());

//获取 请求的参数字符串: uname=admin&upwd=123&hobby=sing&hobby=dance&hobby=rap



// 获取请求的类型  (GET/POST)

System.out.println("获取请求的类型: " + req.getMethod());

//获取请求的类型: GET



// 获取请求协议版本

System.out.println("获取请求协议版本: " + req.getProtocol());

//获取请求协议版本: HTTP/1.1



// 获取站点名(项目的对外访问路径)

System.out.println("获取站点名:" + req.getContextPath());

//获取站点名:/sr02
2). 获取请求头

在这里插入图片描述

获取单个请求头内容
    getHeader(String)
获取单个请求头名称集合
    Enumeration<String>getHeaderNames()
代码示例:
// 获取请求头 (键不区分大小写)
System.out.println("获取请求头:" + req.getHeader("host"));

// 获取所有的请求头名称
Enumeration<String> enumeration = req.getHeaderNames();

//获取请求头:localhost:8080

// 遍历枚举集合
while(enumeration.hasMoreElements()) { System.out.println(enumeration.nextElement());
}
//host
//connection
//upgrade-insecure-requests
//user-agent
//accept
//accept-encoding
//accept-language
3). 获取客户端请求参数(客户端提交的数据)

在这里插入图片描述

获取指定名称的参数★
    getParameter(name)
获取指定名称参数的所有值
    getParameter(String name)
获取一个包含请求消息中的所有参数名的Enumeration对象
    getParameterNames()
返回一个保存了请求信息中的所有参数名称和值的Map对象
    getParameterMap()
代码示例:
// ============获取客户端请求参数(客户端提交的数据)============

// 获取指定名称的参数值 字符串

String uname = req.getParameter("uname");
String upwd = req.getParameter("upwd");
System.out.println("姓名:" + uname + ",密码:" +upwd);

//姓名:admin,密码:123



// 获取指定名称的参数的所有值 数组

String[] hobbys = req.getParameterValues("hobby");

// 判断非空

if (hobbys != null && hobbys.length > 0) {

	for (String string : hobbys) {

	System.out.println(string);

	}
}
//sing
//dance
//rap

// 获取所有请求参数的名称 枚举对象

Enumeration<String> enumeration2 = req.getParameterNames();

while(enumeration2.hasMoreElements()) {

System.out.println(enumeration2.nextElement());

}
//uname
//upwd
//hobby

// 获取包含参数名和参数值的map对象 map对象

Map<String,String[]> map = req.getParameterMap();

for (String key : map.keySet()) {

System.out.println("参数名: " + key);

// 通过key获取值

String[] strings = map.get(key);

	for (String string : strings) {

	System.out.println(string);
	}
}
参数名: uname
//admin
//参数名: upwd
//123
//参数名: hobby
//sing
//dance
//rap
3. 请求乱码解决 ★
1).乱码原因:

    由于现在的 request 属于接收客户端的参数,所以必然有其默认的语言编码,主要是由于在解析过程中默认使用的编码方式为 ISO-8859-1(此编码不支持中文),所以解析时一定会出现乱码。
    要想解决这种乱码问题,需要设置 request 中的编码方式,告诉服务器以何种方式来解析数据。或者在接收到乱码数据以后,再通过相应的编码格式还原。

TomCat 8 及以上版本TomCat 7 及以下版本
POST乱码乱码
GET不乱码(不需处理)乱码
2). 解决方式一:post
String uname = request.setCharacterEncoding("UTF-8");

在这里插入图片描述这种方式只针对 POST 有效(必须在接收所有的数据之前设定)
不会对get造成影响

3). 解决方式二:get && post
String uname = new String(request.getParameter(name).getBytes("ISO-8859-1"));

在这里插入图片描述借助了 String 对象的方法,该种方式对任何请求有效,是通用的。
Tomcat8 起,以后的 GET 方式请求是不会出现乱码的。
缺点: 本身不乱码的(例如:TomCat 8及以后 的get 会出现乱码),设置后会出现另一种乱码,而且一次只能处理一个参数
示例:

//tomcat容器默认采用了iso-8859-1的编码方法
//通过本为UTF-8编码却被tomcat用iso-8859-1解码的字进行恢复,
//其将解码后的字通过iso-8859-1反解码成二进制数组,再将该字节数组用	UTF-8解码。
//最终被new String成字符串。
value = new String(value.getBytes("iso8859-1"),"UTF-8");
这里的value是 String value = request.getParameter(name);
4). 额外知识点:
// 抑制警告
@SuppressWarnings("serial") 
//添加序列号
private static final long serialVersionUID = 1L;
4. 请求转发 ★
1). 特点: 页面地址不改变 但页面跳转
2). 定义:

    请求转发,是一种服务器的行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的 URL 地址不会改变,得到响应后,服务器端再将响应发送给客户端,从始至终只有一个请求发出。
    实现方式如下,达到多个资源协同响应的效果
在这里插入图片描述

3). 格式:

request.getRequestDispatcher().forward()

request.getRequestDispatcher("跳转的路径").forward(request, response);
4).与重定向区别:
  1. 服务端行为,由服务器控制跳转
  2. 跳转后地址栏不发生改变
  3. 从始至终只有一个请求发出,请求对象可以共享(request和response对象是同一个)
5. request作用域对象 ★

(还有Session会话 和ServletContext)

1). 作用:

一般用作前台提取数据,通过该对象可以在一个请求中传递数据

2). 作用范围:

在一次请求中有效,即服务器跳转有效。

3). 三大方法:

request.setAttribute():设置域对象内容;
request.getAttribute(String name):获取域对象内容;
request.removeAttribute(String name): 删除域对象内容。

4).示例:
// 设置域对象
request.setAttribute("uname", "zhangsan");
request.setAttribute("uage", 18);
// 请求转发跳转到servlet01
request.getRequestDispatcher("s01").forward(request, response);

    request 域对象中的数据在一次请求中有效,则经过请求转发,request 域中的数据依然 存在,则在请求转发的过程中可以通过 request 来传输/共享数据。

三.HttpServletResponse 对象

HttpServletRequest request,HttpServletResponse` response
1. 介绍

    Web 服务器收到客户端的 http 请求,会针对每一次请求,分别创建一个用于代表请求的 request 对象和代表响应的 response 对象。

    request 和 response 对象代表请求和响应:获取客户端数据,需要通过request 对象;向客户端输出数据,需要通过 response 对象。

    HttpServletResponse 的主要功能用于服务器对客户端的请求进行响应,将Web 服务器处理后的结果返回给客户端。 service()方法中形参接收的HttpServletResponse 接口的实例化对象,这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。

2. 常用方法

在这里插入图片描述

1).添加指定的键值到响应头信息中
    addHeader(String name , String value)
2).判断响应的头部是否被设置
    containsHeader(String name)
3).编码指定的URL
    encodeURL(String url)
4).使用指定状态码发送一个错误到客户端
    sendError(int sc)
5).设置指定响应头的值
    setHeader(String name , String value)
6).给当前响应设置状态
    setStatus(int sc)
7).设置数据的响应类型★
    setContentType("text/html")

    response.setContentType(MIME)的作用是使客户端浏览器,区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
    例如:web浏览器就是通过MIME类型来判断文件是GIF图片。通过MIME类型来处理json字符串。
    示例:resp.setContentType("text/html;charset=UTF-8");
一般同时设置字符集

8).获取字符流(只能响应回字符);★
    getWriter()

示例:

PrintWriter writer = resp.getWriter();
	writer.write("Hello");
	writer.write("<h2>Hello1</h2>");
	writer.close();
9).获取字节输出流(能响应一切数据)。
    getOutputStream()
=>响应的数据回到客户端被浏览器解析。

示例:

PrintWriter writer = resp.getWriter();
	writer.write("<input type='text' value='123' />");
	writer.close();

**注意:**上述两种流不能同时使用。异常:

java.lang.IllegalStateException: 
	getWriter() has already been called for this response
3.刷新和页面自动跳转

    所有头信息都是随着请求和回应自动发送到服务器端(客户端),在response 中一个比较常用的头信息就是刷新的指令,可以完成定时刷新的功能。
    resp.setHeader("refresh","2");
    对于刷新的头信息,除了定时的功能外,还具备了定时跳转的功能,可以让一个页面定时跳转到一个指定的页面。(已经注册成功,两秒后跳转到登陆页面)
    response.setHeader("refresh","3;URL=ok.html");
    但是这种跳转不是万能的,有时候根本就无法进行跳转操作,返回后刷新不会跳转;对于这种定时跳转的头信息,也可以采用 HTML 的方式进行设置,HTML 本身也可以设置头信息。(客户端跳转)
在这里插入图片描述

//设置响应头
resp.addHeader("uname", "admin");

// 设置页面报错
resp.sendError(500);
resp.sendError(404, "无法访问!");

// 自动刷新  3秒钟刷新一次
resp.setHeader("refresh", "3");

// 跳转   3秒钟后跳转到百度
resp.setHeader("refresh", "3;http://www.baidu.com");
4. 数据响应★

    接收到客户端请求后,可以通过 HttpServletResponse 对象直接进行响应,响应时需要获取输出流,有两种形式 getWriter()获取字符流(只能响应回字符);getOutputStream()获取字节流(能响应一切数据)。响应回的数据到客户端被浏览器解析。注意:两者不能同时使用。
在这里插入图片描述
在这里插入图片描述

5. 乱码解决响应乱码问题
1).乱码原因:

    1.服务器响应的数据也会经过网络传输,服务器端有一种编码方式,在客户端也存在一种编码方式,当两端使用的编码方式不同时则出现乱码。
    2.注:如果服务端和客户端编码一致,但编码不支持中文,也会乱码。

2).乱码情况:

    1. getWriter()的字符乱码
    对于 getWriter()获取到的字符流,响应中文必定出乱码,由于服务器端在进行编码时默认会使用 ISO-8859-1 格式的编码,该编码方式并不支持中文。
    设置服务端的编码
    resp.setCharacterEncoding("UTF-8");
在这里插入图片描述
    2. getOutputStream()字节乱码
    对于 getOutputStream()方式获取到的字节流,响应中文时,由于本身就是传输的字节, 所以此时可能出现乱码,也可能正确显示。
    ★同时设置服务端和客户端的编码及响应类型
    resp.setContentType("text/html;charset=UTF-8");

3).总结:

    要想解决响应的乱码,只需要保证使用支持中文的编码格式。并且保证服务器端 和客户端使用相同的编码方式即可。
    setContentType()设置数据的响应类型及编码

6. 响应图片 ★

    在学习 HTML 的时候我们知道使用的方式可以显示图片。但有的时候我们并不知道(或不能确定)图片的路径,需要通过请求服务器资源动态地响应图片给客户端。这种方式和文件拷贝的理念是一致的,客户端请求服务器的资源,在服务端获取到真实的图片资源,通过输入流读取到内存,然后通过输出流写出到客户端即可。
    值得注意的是,在客户端解析资源时默认是以文本(text/html)的形式,当响应图片时 需要指定响应头信息,告知客户端响应内容为图片形式,使用一种叫做 MIME 类型的东西来指定。MIME 类型见 Tomcat 的 web.xml 文件。

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型
在这里插入图片描述
定义某一个扩展名和某一个 MIME Type 做对应,包含两个子元素:
<extension></extension>扩展名的名称
<mime-type></mime-type>MIME 格式
在这里插入图片描述

代码:
@SuppressWarnings("serial")
public class Servlet04 extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("Servlet04....");		
		// 获取项目在服务器中的真实路径
		String realPath = req.getServletContext().getRealPath("/");
		System.out.println(realPath);
		// 得到图片的存放路径  
		String filePath = realPath + "/WEB-INF/images/jay.jpg";
		// 通过路径得到file对象
		File file = new File(filePath);
		// 判断文件是否存在,且是一个标准文件
		if  (file.exists() && file.isFile()) {		
			// 设置响应类型
			resp.setContentType("image/jpeg");		
			// 得到文件的输入流
			InputStream in = new FileInputStream(file);
			// 得到字节输出流
			ServletOutputStream out = resp.getOutputStream();		
			byte[] bytes = new byte[1024];
			int len = 0;
			while((len = in.read(bytes)) != -1) {
				out.write(bytes, 0, len);
			}			
		} else {
			// 设置响应类型及编码
		resp.setContentType("text/html;charset=UTF-8");
			resp.getWriter().write("<h2>文件不存在!</h2>");
			resp.getWriter().close();
		}
	}

7. 重定向跳转 ★

    重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务器接收,经过处理服务器进行响应,与此同时,服务器给客户端一个地址(下次请求的地址 resp.sendRedirect(“url”);),当客户端接收到响应后,立刻、马上、自动根据服务器 给的地址进行请求的发送第二个请求,服务器接收请求并作出响应,重定向完成。从描述中可以看出重定向当中有两个请求存在,并且属于客户端行为。实现方式如下:
在这里插入图片描述
    通过观察浏览器我们发现第一次请求获得的响应码为 302,并且含有一个location 头信息。并且地址栏最终看到的地址是和第一次请求地址不同的,地址栏已经发生了变化。

请求转发和重定向比较:
在这里插入图片描述

重定向
    response.sendRedirect()
请求转发
    request.getRequestDispatcher().forward()

两者都可进行跳转,根据实际需求选取即可。

请求转发和重定向区别:
1).请求转发
	1、地址栏不发生改变
	2、服务端跳转
	3、只有一次请求
	4、request作用域共享 (一次请求中有效)
	5、跳转的地址定位到站点名后 (请求转发到当前项目的资源路径)
2).重定向
	1、地址栏发生改变
	2、客户端跳转
	3、存在两次请求
	4、request作用域不共享
	5、跳转的地址定位到http (可以重定向到任意地址)

四、请求时的路径问题 ★

1.相对路径

    相对于当前资源的路径

2.绝对路径

    资源的完整路径

1).完整绝对路径

    以 http://开头的,该种绝对路径已经跨域,即任何地方的资源都能访问

2).部分绝对路径

/开头,从当前域名|IP|主机后的端口号开始的,不能跨域

/的含义:
    请求转发:
        代表的是 http://localhost:8080/站点名/
    重定向(客户端跳转):
        代表的是 http://localhost:8080/

代码:
// ================请求转发================
// (OK)相对路径
req.getRequestDispatcher("index.html").forward(req, resp); 

// (OK)在请求转发时,"/"代表的是到站点名后    
//http://loaclhost:8080/sr03     /index.html
req.getRequestDispatcher("/index.html").forward(req, resp); 
	
// (404)地址定位在站点名    
//http://loaclhost:8080/sr03   sr03/index.html
req.getRequestDispatcher("sr03/index.html").forward(req, resp); 
	
// (404)地址定位在站点名    
//http://loaclhost:8080/sr03   sr03/index.html
req.getRequestDispatcher("/sr03/index.html").forward(req, resp); 
	
// (404)地址定位在站点名    
//http://loaclhost:8080/sr03   http://loaclhost:8080/sr03/index.html
	 													req.getRequestDispatcher("http://localhost:8080/sr03/index.html").forward(req, resp); 
// ================重定向================
// (OK)相对路径
resp.sendRedirect("index.html");
	
// (404)绝对路径定位到端口后,http://loaclhost:8080    /index.html
resp.sendRedirect("/index.html");
	
// (404)相对路径,http://loaclhost:8080/sr03    sr03/index.html
resp.sendRedirect("sr03/index.html");
	
// (OK)绝对路径定位到端口后,http://loaclhost:8080   /sr03/index.html
resp.sendRedirect("/sr03/index.html");
	
// (OK)完整的绝对地址,从http开始
resp.sendRedirect("http://localhost:8080/sr03/index.html");

五、Cookie(储存在用户本地终端上的数据)

在这里插入图片描述

定义:

    Cookie 是浏览器提供的一种技术,通过服务器的程序能将一些只须保存在客户端,或者在客户端进行处理的数据,放在本地的计算机上,不需要通过网络传输,因而提高网页处理的效率,并且能够减少服务器的负载,但是由于 Cookie 是服务器端保存在客户端的信息, 所以其安全性也是很差的。例如常见的记住密码则可以通过 Cookie 来实现。
    cookie的大小在4kb左右,每个浏览器在同一域名下能存放cookie数量是有限的,谷歌浏览器大概是50个。
    Cookie不跨浏览器,换电脑也无效。
    有一个专门操作 Cookie 的类 javax.servlet.http.Cookie。随着服务器端的响应发送给客户端,保存在浏览器。当下次再访问服务器时把 Cookie 再带回服务器。
    Cookie 的格式:键值对用 =链接,多个键值对间通过 “;” 隔开

优缺点:

    提高网页的效率,减轻服务器的负载。
    安全性较差。

1.创建Cookie 对象

    new Cookie("key","value");
通过 new Cookie(“key”,“value”);来创建一个 cookie对象
    Cookie cookie = new Cookie("cookie的名称","cookie的值");
    注:键和值都是字符串,不支持中文

2.发送Cookie 对象

    response.addCookie(cookie);
    要想将 Cookie 随响应发送到客户端,需要先添加到 response 对象中,resp.addCookie(cookie);此时该 cookie 对象则随着响应发送至了客户端。在浏览器上可以看见。
在这里插入图片描述
F12 查看
在这里插入图片描述

3. Cookie 的获取

    request.getCookies();
    返回的是所有的cookie的数组
    在服务器端只提供了一个 getCookies()的方法用来获取客户端回传的所有cookie 组成的一个数组,如果需要获取单个 cookie 则需要通过遍历,getName()获取 Cookie 的名称,getValue()获取 Cookie 的值。
在这里插入图片描述

4. Cookie 到期时间的设定

注:Cookie是浏览器技术,关闭服务器不会影响cookie的变化
    到期时间,到期时间用来指定该 cookie 何时失效。
    默认为当前浏览器关闭即失效。
    手动设定 cookie 的有效时间(通过到期时间计算)
    通过 setMaxAge(int time);方法设定 cookie 的最大有效时间,以秒为单位。
    大于 0 的整数,表示存储的秒数;若为负数,则表示不存储该 cookie;若为 0,则删 除该 cookie。
    负整数:cookie 的 maxAge 属性的默认值就是-1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那么 cookie 就会消失。
    正整数:表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie 也
会存活相应的时间。
    零:cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 Cookie 的setMaxAge(0)来删除这个 Cookie。 无论是在浏览器内存中,还是在客户端硬盘上都会删除这个 Cookie。

5. Cookie 的注意不能存中文

(encode 编码 decode解码)
    在一般的站点中常常有记住用户名这样一个操作,该操作只是将信息保存在本机上,换电脑以后这些信息就无效了。而且 cookie 还不能跨浏览器。
    Cookie 中不能出现中文,如果有中文则通过
URLEncoder.encode()来进行编码,
    获取时通过
URLDecoder.decode()来进行解码。
在这里插入图片描述
    不同的浏览器对 Cookie 也有限定,Cookie 的存储有是上限的。Cookie 是存储在客户端(浏览器)的,而且一般是由服务器端创建和设定。后期结合 Session来实现回话跟踪。

6. Cookie 的覆盖

    如果服务器端发送重复的 Cookie 那么会覆盖原有的 Cookie。

7. Cookie 的路径path

    浏览器在访问 BServlet 时,是否会带上 AServlet 保存的 Cookie,这取决于Cookie 的 path。
    在项目中的配置文件 web.xml
在这里插入图片描述
在 Cookie01.java 中添加一个 cookie
在这里插入图片描述
在这里插入图片描述
在 Cookie02.java 中获取 cookie01.java 中添加的 cookie
在这里插入图片描述
在 Cookie.java 中获取 cookie01.java 中添加的 cookie
在这里插入图片描述
    在 Servlet 中保存的 Cookie 如果没有设置 path,那么它的 path 默认为当前 Servlet 的所在路径;
    当访问的路径包含了 cookie 的路径时,则该请求将带上该 cookie;如果访问路径不包含 cookie 路径,则该请求不会携带该 cookie

// 创建cookie
Cookie cookie =  new Cookie("uname","admin");
// 设置path (当前服务器下任意资源都可访问)
cookie.setPath("/");
// 发送cookie
resp.addCookie(cookie);
				
// 创建cookie
Cookie cookie2 = new Cookie("userName","zhangsan");
// 设置path
cookie2.setPath("/sc04/test/aa");
// 发送cookie
resp.addCookie(cookie2);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值