JSP期末复习

本文主要介绍了JSP开发中的关键概念,包括HTTP协议的传输方式、请求和响应的处理、Response和Request对象的方法。详细讲解了如何解决中文乱码问题、请求重定向以及如何利用Referer请求头防止“盗链”。此外,还探讨了会话技术,包括Cookie和Session的使用。最后,简要概述了JSP的基础语法、内置对象以及过滤器(Filter)和监听器(Listener)在Web开发中的作用。

我只摘录了我觉得在开发过程中有用或可能有用的内容
考试考了里面的70分左右,嘻嘻嘻

HTTP协议的传输方式

(居然会考这个,TAT,我只知道POST和GET)

请求和响应

Servlet最主要的作用就是处理客户端请求,并向客户端做出响应。针对Servlet的每次请求,Web服务器在调用service()方法前,都会创建两个对象:HttpServletRequest和HttpServletResponse。其中HttpServletRequest用于封装HTTP请求消息,简称request对象;HttpServletResponse用于封装HTTP响应消息,简称response对象。
Web服务器只会创建一个实例对象,然而每次请求都会重新创建一个request对象和response对象。

404状态码表示找不到客户端请求的资源

Response对象的方法

getOutputStream() & getWriter()方法

getOutputStream返回OutputStream对象以字节流(二进制)输出
getWriter返回PrintWriter以字符输出

String data=“itcast”;
OutputStream out=response.getOutputStream();
out.write(data.getBytes());
PrintWriter print=response.getWriter();
print.write(data);

getOutputStream和getWrite不能同时使用,否则会发生IllegalStateException异常

setHeader用来设置响应头字段

解决中文乱码

response对象的字符输出采用ISO-8859-1编码
在doGet或doPost或Service最前端加

response.setCharacterEncoding(“utf-8);
response.setHeader(“Content-Type”,”text/html;charset=utf-8);

or

response.setContentType(“text/html;charset=utf-8”);
刷新跳转

2秒后刷新跳转到其他页面

response.setHeader(“Refresh”,2;URL=http://www.baidu.com”);

每隔3秒定时刷新当前页面

response.setHeader(“Refresh”,3);
response.getWriter.println(new java.util.Date());

请求重定向

请求重定向指Web服务器接收到客户端请求后,可能由于某些条件限制,不能访问当前请求URL所指向的Web资源,而是指定了一个新的资源路径,让客户端重新发送请求
会生成302响应码

需要使用绝对路径,路径前端加/

response.sendRedirect(/chapter04/welcome.html”);

路径前加 /

Request对象的方法

利用Referer请求头防止“盗链”(p130)

DownManagerServlet

PrintWriter out=response.getWriter();
String referer=request.getHeader(“referer”);
String sitePart=“http://+request.getServerName();
if(referer!=null&&referer.startsWith(sitePart)){//请求头是不是自身!!!
	out.println(“dealing download...);
}else{
	RequestDispatcher rd=request.getRequestDispatcher(/download.html”);
	rd.forward(request,response);
}

在WebContent根目录下编写download.html

<a href=“/chapter04/DownManagerServlet”>download</a>

浏览器中直接输入DownManagerServlet的URL,第一次访问时不会有Referer请求头,再点击download会显示结果。
链接才会产生请求头,就是说输入URL访问不会产生Referer!

获取请求参数

当网页中表单(form)提交时
String getParameter(String name)获取指定名称的参数值
String[] getParameterValues(String name)获取指定名称的参数列表(比如多选按钮传来的值)

//html部分
<input type=“text” name=“username”/>
<input type=“checkbox” name=“hobby” value=“sing”>唱歌
<input type=“checkbox” name=“hobby” value=“dance”>跳舞
<input type=“checkbox” name=“hobby” value=“football”>足球
//servlet部分
String name=request.getParameter(“username”);
String[] hobbys=request.getParameterValues(“hobby”);

如果获得的属性值不为String或者基本类型,需要进行数据转化,例如对一个User对象

User user=(User)request.getParameter(“user”);

解决请求中文乱码

只对POST有效对,GET无效

request.setCharacterEncoding(“utf-8);

GET提交表单时

String name=request.getParameter(“username”);
name=new String(name.getBytes(“iso8859-1),”utf-8); 

public void setAttribute(java.lang.String name,java.lang.Object o);

可以在请求转发时添加属性

请求转发

RequestDispatcher getRequestDispatcher(String path) 参数path必须以“/”开头,

RequestDispatcher接口的方法

1.forward(ServletRequest request,ServletResponse response) :对请求做初步处理后,转发给其他资源响应,其他资源处理完后直接将结果返回客户端;
2.include(ServletRequest request,ServletResponse response) :客户端端响应结果包含当前Servlet的,也包含其他Web资源的;

request.getRequestDispatcher(/ResultServlet”).forward(request,response);
request.getRequestDispatcher(/ResultServlet”).include(request,response);

请求转发时共享request资源,转发过程中,客户端URL不变

请求转发与重定向

1、forward:访问Servlet业务处理逻辑,然后forward到jsp显示处理结果,可以在中间setAttribute来增加属性,URL不变
2、redirect:提交表单,处理成功后跳转到另一个jsp,防止表单重复提交,URL改变!
3、forward是在服务器内部进行,所以绝对路径的根是本工程,而redirect是在客户端进行的访问,绝对路径要为“/当前Web程序根名称/资源名”

会话

在Web开发中,服务器跟踪用户信息的技术称为会话技术,在Servlet中,提供了两个用于保存会话数据的对象分别是Cookie和Session

Cookie

set-Cookie头字段
Set-Cookie: user=itcast; Path=/;
itcast表示Cookie的值,Path表示Cookie的属性,Cookie必须以键值对的形式存在,其属性可以有多个,但这些属性之间必须用分号空格分隔;
当用户第一次访问服务器时,服务器会在响应消息中增加Set-Cookie头字段;
public Cookie(java.lang.String name,java.lang.String value)
Cookie一旦创建,它的名称就不能更改,Cookie的值可以为任何值,允许被修改;

Cookie的常用方法

  • String getName()返回Cookie的名称
  • void setValue(String newValue)为Cookie设置一个新的值
  • String getValue()返回Cookie的值
  • void setMaxAge(int expiry)&getMaxAge设置Cookie在浏览器上保持的秒数,为正数时,将Cookie的信息保存在本地硬盘上;为负数时,浏览器将Cookie的值保存在缓存中,当浏览器关闭时,删除Cookie信息;为0时,立即删除。默认为-1;
  • void setPath(String uri)设置Cookie只对当前访问路径所属的目录及其子目录有效,设为“/”时,对所有目录下的访问路径都有效;
  • void setDomain(String pattern)&String getDomain()属性值为主机名,必须以‘ . ’开头
Cookie[] cookies=request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
	if(“lastAccess”.equals(cookies[i].getName())){
		lastAccessTime=cookies[i].getValue();
		break;
	}
}
//添加Cookie
String currentTime=new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”).format(new Date());
Cookie cookie=new Cookie(“lastAccess”,currentTime);
response.addCookie(cookie);

Session

Cookie技术可以将用户信息保存在各自浏览器中,Session是一种将会话数据保存到服务器端的技术
Session是借助Cookie来传递ID属性的!

public HttpSession getSession(boolean create)
public HttpSession getSession()
第一个方法如果参数为true,当不存在HttpSession对象时会创建一个新的HttpSession对象,否则返回null;第二的方法和true时相同
在web.xml中设置服务器的默认会话超时间隔,以分钟为单位,如果是0或一个负数则会话永不超时

<session-config>
	<session-timeout>30</session-timeout>
</session-config>

HttpSession方法

  • void invalidate()强制使Session对象无效
  • void setAttribute(String name,Object value)用于将一个对象与一个名称关联后存储到当前的HttpSession对象中
  • String getAttribute() 用于从当前的HttpSesion对象中返回指定名称的属性对象
  • void removeAttribute(String name)用于从当前HttpSession对象中删除指定名称的属性

购物车p152
在登陆后要建立用户信息session,在获取session对象时需要强制类型转换!,例如:

User  user=(User)request.getSession().getAttribute(“user”);

session的信息在整个Web中共享

JSP

JSP全名是Java Server Pages,它是建立在Servlet范围之上的动态网页开发技术。在JSP文件中,HTML代码与Java代码共同存在,其中,HTML代码用来实现网页中静态内容的显示,Java代码用来实现网页中动态内容的显示。扩展名为.jsp。

JSP技术所开发的Web应用程序是基于Java的,特征:

  • 跨平台
  • 业务代码相分离:JSP引擎(Tomcat)负责解析JSP标签和脚步程序,并将执行结果以HTML页面的形式返回到浏览器
  • 组件重用:适用JavaBean编写业务组件
  • 预编译:用户第1次通过浏览器访问JSP页面代码进行编译,并且仅执行一次编译

JSP运行原理

JSP的工作模式是请求/响应模式,在一个JSP文件第一次被请求时,JSP引擎会把该文件转化为一个Servlet
JSP的运行过程p172

JSP基本语法

<% %>正常Java语句
<%! %>定义的变量或方法
<%= %>将程序数据输出到客户端,“<%”和“=”之间不能有空格,JSP表达式中变量或表达式后面不能有分号
<%— —%>注释

JSP内置对象

JSP指令

page指令

常用属性:language(默认Java),session,isErrorPage,contentType,pageEncoding,import(唯一可以声明多次的page指令,中间用英文逗号隔开)
除了import属性外,其他属性只能出现一次,否则编译失败
page指令属性名区分大小写
page指令对整个页面有效,与书写位置无关
<%@ page 属性名=属性值...%>

<%@ page lauguage=“java” contentType=“text/html;charset=UTF-8” pageEnoding=“UTF-8%>
<%@ page import=“java.awt.*”>
<%@ page import=“java.util.*”,”java.awt.*”>

include指令

<%@ include file=“”%>include只有一个file属性,一般不以“/”开头,使用相对路径(相对于文件的)
在制作所用页面共用的部分时,用include加入;

out对象

out隐式对象写入数据相对于将数据插入到JspWriter对象的缓冲区中,只用调用ServletResponse.getWriter(),缓冲区的数据才可以进入Servlet引擎提供的缓冲区,否则整个页面结束才会写入Servlet引擎提供的缓冲区
或者<%@ page buffer=“0kb”%>,对象内容充满out缓冲区,也会写入Servlet引擎提供的缓冲区

<jsp:forward page=“relativeURL”>

用于请求转发,浏览器地址不会变

JavaBean

JavaBean是Java开发语言中一个可以重复使用的软件组件,它本质是一个Java类,编码规范:

  • (1)它必须具有一个公共的、无参的构造方法,可以是编译器自动产生的默认构造方法
  • (2)它提供公共的setter方法和getter方法,让外部程序设置和获取JavaBean的属性

在开发JavaBean时每个属性都定义为读写属性,如果属性的值为boolean,那么命名应为is/get,而不是set/get

EL表达式

EL是expression Lauguage的缩写,它是一种简单的数据访问语言;
当Servlet中request.setAttribute(“username”,”yw”)
JSP中用${username}读取数据
EL中定义标识符规范

  • 不能以数字开头
  • 不能是EL中的保留字,如and,or,gt
  • 不能是EL的隐式对象,如pageContext
  • 不能包含单引号(‘)、双引号(“)、减号(-)和正斜杠(/)等特殊字符
    ${student.name}等价于${student[“name”]}
    .和[]混合使用${users[0].username},访问集合或数组中第一个元素的username属性
    lt <; gt > ;le <=;ge >= 如果运算符后面是数字,在运算符和数字之间至少有一个空格,例 ${1lt 2}
    除法/或div ,例 ${10 div 2},结果为2.5!
    empty运算符判断是否为null,${empty var}
    sessionScope 获得session的属性
    param.num 获得?后面的属性或者表单提交的属性;
    paramValues.num[n]获得多选项的值

JSTL

jstl.jarstandard.jar复制到lib目录下
在使用c前缀到标签时,需要加入
<%@ taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c”%>
输出,value为null是输出default,escapeXml为true时会将内容原样输出,默认为true

<c:out value=“value” [escapeXml=“true/false”]>
	default
</c:out> 

设置变量

<c:set value=“value” var=“var”/>

if语句

<c:if test=“test”>
</c:if>

多重选择

<c:choose>
	<c:when test=“testcondition”>
	</c:when>
	<c:otherwise>
	</c:otherwise>
</c:choose>

循环

<c:forEach var=“varname” items=“collection” begin=“begin” end=“end” step=“step”>
</c:forEach>

Filter 过滤器

Filter被称为过滤器,其基本功能就是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理前后实现一些特殊功能

Filter接口的方法

1、init() 在Web应用程序加载时调用,只调用一次
2、doFilter() 只要有客户端请求就会被调用,Filter所有工作集中在doFilter方法中
3、destroy() 在Web应用程序卸载时调用,只调用一次

xml配置

  • 根元素用于注册一个Filter
  • 子元素用于设置Filter名称
  • 子元素用于设置Filter的完整名称
  • 根元素用于设置一个过滤器所拦截的资源
  • 子元素必须与中的相同
  • 子元素用于匹配用户请求的URL,例如“/MyServlet”,可以使用通配符“ * ”,例如“ *.do”,适用于所有以“.do”结尾的Servlet路径
  • REQUEST直接访问页面才会调用过滤器;INCLUDE通过RequestDispatcher的include方法访问,才调用过滤器; FORWARD通过RequestDispatcher的forward方法访问,才调用过滤器;通过<dispatcher>设置
    除法/或div ,例 ${10 div 2},结果为2.5!
    empty运算符判断是否为null,${empty var}
<filter>
	<filter-name>MyFilter</filter-name>
	<filter-class>cm.itcast.MyFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>MyFilter</filter-name>
	<url-pattern>/MyServlet</url-pattern>
	<url-pattern>/*</url-pattern>  //拦截所有请求
	<dispatcher>FORWARD</dispatcher> //拦截forward的转发
</filter-mapping>

FIlter链

一个Web应用程序可以注册多个Filter程序,如果多个Filter程序都对同一个URL进行拦截,那么这些Filter就会组成一个Filter链(也叫过滤器链)

过滤器doFilter方法定义

public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain){
//...
chain.doFilter(request,response);//放行!否则不会跳往目标url!
}

在xml中位置靠前的Filter先过滤,过滤器的结果和include转发一样,每个过滤器的信息都会显示
全站统一编码p251

Listener监听器

Servlet事件监听器就是一个实现了特点接口的Java程序,专门用于监听Web应用程序中ServletContext、HttpSession和ServletRequest等域对象的创建和销毁过程,监听这些域对象属性的修改以及感知绑定到HttpSesison域中某个对象的状态。

JDBC

JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对于数据库中数据的增删改查操作。

是应用程序和数据库的桥梁,JDBC访问数据库时,通过不同的数据库驱动与不同的数据库进行连接,随后执行相应操作。
JDBC API位于java sql 包中;

数据库操作过程:

1.加载驱动Driver
2.获得Connection连接对象,只有获得连接对象后才能访问数据库
3.通过Connection获得Statement接口对象
4.Statememt接口调用相应方法,执行SQL语句,excuteUpdate()返回int型,表示受该SQL语句影响的记录条数
5.查询语句返回Result接口对象,访问数据;
6.最后释放资源

Statement stmt = null;
ResultSet res=null;
Connection conn=null;

建立数据库连接及释放连接

// JDBCUtils.java
public static Connection getConnection() throws SQLException,ClassNotFoundException{ 
	Class.forName(“com.mysql.jdbc.Driver”);
	String url = “jdbc:mysql://localhost:3306/jdbc”;//jdbc是数据库名
	String username = “root”; //可以自定义
	String password = “root”; //可以自定义
	conn = DriverManager.getConnection(url,username,passsword);
	return conn;
}
public static void release(Statamemt stmt, Connection conn)
{
	if(stmt != null){
		try{
			stmt.close();
		}//...
		stmt=null;
	}
	if(conn != null){
		try{
			conn.close();
		}//...
		conn=null;
	}
}
public static void release(ResultSet rs, Statamemt stmt, Connection conn){
 	if(rs != null){
		try{
			rs.close();
		}//...
		rs = null;	
	}
	release(stmt,conn);
}

conn = JDBCUtils.getConnection();
stmt = conn.createStatememt();
String sql = “INSERT INTO users(id,name) VALUES(+user.getId()+,’”+user.getName()+”’);  //字符串要用‘’
int num = stmt.executeUpdate(sql);
if(num>0)
	return true;
return false;

conn = JDBCUtils.getConnection();
stmt = conn.createStatememt();
String sql = “SELECT * FROM users”;
// sql = “SELECT * FROM users WHERE id=”+id; //查找指定值;
rs = stmt.executeQuery(sql);
while(rs.next()){
	int id = rs.getInt(“id”);                                                                                                                                                                                                                                                                                        	String name = rs.getString(“name”);
	String password = rs.getString(“password”);
	//...
}

conn = JDBCUtils.getConnection();
stmt = conn.createStatememt();
String sql = “DELECT FROM users WHERE id=+ id;
int num = stmt.executeUpdate(sql);
if(num > 0)
	return true;
return false;

conn = JDBCUtils.getConnection();
stmt = conn.createStatememt();
String sql = “UPDATE users set name=‘yangwei ‘ WHERE id=+id;
int num = stmt.executeUpdate(sql);
if(num>0)
	return true;
return false;

Java获得时间,与MySQL 的DATE对应

SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd”);

数据库连接池

在JDBC编程中,每次创建和断开Connection对象都会消耗时间和IO资源,因为在Java程序与数据库之间建立连接时,数据库端都要验证用户名和密码,并且要为这个连接分配资源,Java程序则要把代表连接的java.sql.Connection对象加载到内存中;如果频繁的创建,断开数据库连接会影响数据库的访问效率,甚至导致数据库崩溃。因此产生数据库连接池技术,数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立。应用程序反问数据库时是向连接池“申请”一个Connection,如果连接池中有空闲Connection就返回,否则创建新的Connection。使用完毕Connecion后,连接池会回收,交付给其他的线程使用。

JDBC提供javax.sql.DataSource接口,负责与数据库连接,返回Connection对象;
常用数据源:DBCP数据源C3P0数据源

1、DBCP数据源

需要两个jar包:commons-dbcp.jar和commons-pools.jar

2、C3P0数据源

先配置c3p0-config.xml文件,放在src中

<?xml version="1.0" encoding="UTF-8"?>
	<c3p0-config>
  		<default-config>
    		<property name="driverClass">com.mysql.jdbc.Driver</property>
  			<property name="jdbcUrl">jdbc:mysql://localhost:3308/cdooj?&amp;useSSL=false&amp;serverTimezone=UTC</property>
    		<property name="user">root</property>
    		<property name="password">mysql</property>
    		<property name="initialPoolSize">5</property>
   		 	<property name="maxPoolSize">15</property>
    		<property name="checkoutTimeout">3000</property>
  		</default-config>
  	<named-config name="otherc3p0"> 
  	</named-config>
</c3p0-config>

建立获得数据库连接的工具类C3p0Utils.java

import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Utils{
	private static DataSource ds;
	static {
		ds = new ComboPooledDataSource();
	}
	public static DataSource getDateSource(){
		return ds;
}

QueryRunner类执行SQL语句

BeanHandler: 将结果集中的第一行数据封装到一个对应的JavaBean实例中;
BeanListHandler: 将结果集中每一行数据都封装到一个对应的JavaBean中,并存放到List里;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;  //!
import org.apache.commons.dbutils.handlers.BeanHandler; //!
import org.apache.commons.dbutils.handlers.BeanListHandler; //!
import object.User;

public class userDao {
	public User findOne(String username) throws SQLException {
		QueryRunner runner = new QueryRunner(userUtils.getDataSource());
		String sql="select * from users where username=?";
		User user=(User)runner.query(sql, new BeanHandler(User.class),new Object[] {username});
		return user;
	}
	public List findAll()throw SQLException{
		QueryRunner runner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = “select * from users”;
		List list = (List) runner.query(sql,new BeanListHandler(User.class));
		return list;
	}
	public boolean insert(User user) throws SQLException {
		QueryRunner runner = new QueryRunner(userUtils.getDataSource());
		String sql="insert into users(username,password,nickname,gender,school,email,tnum,qset) values (?,?,?,?,?,?,?,?)";
		int num=runner.update(sql,new Object[] {user.getUsername(),user.getPassword(),user.getNickname(),user.getGender(),user.getSchool(),user.getEmail(),user.getTnum(),user.getQset()});
		if(num>0)
				return true;
		return false;
	}
	public boolean update(User user) throws SQLException {
		QueryRunner runner = new QueryRunner(userUtils.getDataSource());
		String sql="update users set tnum=?,qset=? where username=?";
		int num=runner.update(sql, new Object[] {user.getTnum(),user.getQset(),user.getUsername()});
		if(num>0)
			return true;
		return false;
	}
	public Boolean delete(int id)throws SQLException{
		QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
		String sql = “delete from users where id=?;
		int num = runner.update(sql,id);
		if(num>0)
			return true;
		return false;
	}
}




JSP开发模型

JSP Model1

JSP Model1采用JSP+JavaBean的技术,将页面显示和业务逻辑分开。其中,JSP实现流程控制和页面显示,JavaBean封装数据和业务逻辑。

JSP Model2

JSP Model2架构模型采用JSP+Servlet+JavaBean的技术,实际上就是MVC设计模式(模型Model-视图View=控制器Controller)

MVC设计模式

模型

封装程序内部的数据状态,封装业务处理方法,内部状态改变通知视图

视图

显示模型中的数据,接收模型的数据更新通知,将用户操作传递给控制器

控制器

接收用户的操作,调用模型的业务处理方法,选择响应用户操作的视图

Jsp期末复习资料 习题部分 第一章 JSP概述 1.JSP技术是由 A 语言作为脚本语言。 A.Java B.C++ C.C# D.C 2.Web是与平台无关、分布式的、图形化的和易于导航的,定义了客户端和服务器端如何通信。 3.HTTP(超文本传输协议)是一种Internet上常见的协议,用于传输超文本标记语言(HTML)编写的文件,也就是通常所说的网页。 4.网站一般分为3层,分别是用户界面交互层、应用程序层、数据库层。 5.Servlet的生命周期是载入、初始化、执行和删除。 6.JSP技术是在传统的网页文件HTML中加入java程序片段和JSP标记构建的JSP网页 7.什么是C/S结构?什么是B/S结构?两者由什么区别? 答:C/S是Client/Server(客户机/服务器)结构,B/S是Browser/Server(浏览器/服务器)结构。B/S结构是三层体系结构,B/S结构要求客户端只需要安装一个浏览器(Browser),客户端通过浏览器将请求发送给Web服务器,Web服务器负责与后端数据库服务器进行数据通信;C/S结构是二层结构平台模式,C/S结构要求客户端要安装指定的软件,客户端负责执行前端的数据处理,服务端进行后端的服务处理。 8.简述JSP技术和Servlet技术的区别和联系。 ♦区别:⑴JSP技术主要用来表现页面,而Servlet技术主要用来完成大量的逻辑处理。 ⑵JSP主要用来发送给前端的用户,而Servlet主要来响应用户的请求,完成请求 的逻辑处理。 ♦联系:在实际开发中,往往先把JSP页面开发出来,然后再将JSP代码转换成Servlet。 实验三: <%=1+1 %>
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值