servlet基础语言

java数据 专栏收录该内容
25 篇文章 0 订阅

Servlet的相关信息

1) Servlet文件配置信息
 添加servlet类 在servlet中继承 extends HttpServlet 并在类里面实现这个方法protected void service(HttpServletRequest request, HttpServletResponse response) { }
每个servlet文件首先写的代码
 防止请求参数解码时,出现乱码只对post有效
 request.setCharacterEncoding(“utf-8”);
 设置服务端返回的数据类型
 设置content-type消息头的值out.println()方法在输出时,会使用指定的字符集来编码
 response.setContentType(“text/html;charset=utf-8”);
 获取输出流 PrintWriter out = response.getWriter();
 根据请求路径判断执行什么操作
 获取请求资源路径 String uri = request.getRequestURI();
 截取请求资源路径的一部分
 String path = uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
 System.out.println("**"+path);
 if("/add".equals(path)){ }
 在web.xml里面配置Servlet的方法

 helloServlet
 web.servlet.HelloServlet


 helloServlet
 /hello

 如果复制工程,运行复制后工程,会运行复制之前的工程,需要修改
工程名>右键>Properties>Web Project Settings>修改为复制后的名称
 ;
2) 传输方法
 获取页面传输的文本内容name的值
 格式 String request.getParamenter(String paramName);
 请求参数名如果写错,会获得null值,表单提交时,如果不填写任何数据,会获得""
 获取页面传输的文本内容name的值,当有多个请求参数名相同时
 格式 String[] request.getParameterValues(String paramName);
 对于多选框,如果用户一个月不选,会获得null值
 如:多选框
 把一个参数传回页面
 格式 request.setAttribute(“A”,B) A是传回页面的值,B是servlet中的值
 返回那个页面 response.sendRedirect(“addListStudent.jsp”);
重定向 容器在重定向之前,会清空response所有数据
 什么是重定向
 服务器通知浏览器像某个地址发生请求
 注: 服务器可以通过发送302状态码和Location消息头(Location消息头的值是一个地址,一般称之为重定向地址)给浏览器,浏览器收到之后,会立即向重定向地址发送请求
 如何重定向
 注: url就是重定向的地址
 容器在重定向之前,会清空response对象上存放的所有数据(响应数据包实体内容为空)
 特点:
 重定向地址是任意的
 重定向之后,浏览器地址的地址会发生变化
 response.sendRedirect("");
 是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下个页面,同时它可以重定向至不同的主机上,且在浏览器地址栏上会出现重定向页面的URL.
 转发
 什么是转发: 一个web组件将未完成的处理交给另外一个web组件继续做
 注: web组件: servlet或者jsp
 常见的场景: 一个Servlet获得数据之后,将数据交给jsp来呈现
 如何转发
 将数据绑定到request对象上
 Servlet转发: request.setAttribute(“users”,users);
 注:相当于 map.put(name,obj)
 获得转发器
 RequestDispatcher rd = request.getRequestDispatcher(String url)
 Jsp接收: request.getAttribute(“users”);
 request.getRequestDispatcher("").forward(request, response)
 特点:
 转发之后,浏览器地址栏的地址不变
 转发的目的地有限制,要求属于同一个文本应用
 转发与重定向的区别
 转发之后,浏览器地址栏的地址不变,重定向会变
 转发的目的地有限制(要求属于同一个web应用),重定向无限制
 转发所涉及的各个web组件可以共享同一个request组件,重定向不可以
 注: 容器收到请求之后,会立即创建request和response:当容器发送完响应之后,会立即销毁这俩个对象.也就是说request和response的生存时间是一次请求与响应期间存在.而重定向是俩次请求.

3) 请求方式
 get请求
 发送get请求的情况
 在浏览器地址栏输入某个地址
 点击链接 如标签
 表单默认的提交方式
 get请求的特点
 会将请求参数显示在浏览器地址栏,不安全 有一些网络设备会记录请求地址 如路由器
 get请求传递数据有限,请求行大约能够存放2k左右的数据
 post请求
 发送post请求的情况
 在from表单中设置method=“post”
 Post请求的特点
 不会将请求参数显示在浏览器地址栏中,相对安全
注: http协议并不会对数据包中数据加密,如果传递的数据需要加密的话可以使用https协议
 会将请求参数添加到实体内容里面,可以提交大量数据
 ;
4) 常见的错误
 200 正确
 404错误
 含义: 服务器依据请求路径找不到对应的资源
 原因:
 请求路径写错了
 应用没有部署,或部署失败
 500错误
 含义: 服务器端发生错误
 原因:
 没有严格按照规范来写Servlet 如没有继承HttpServlet,web.xml配置写错
 代码写的不严谨 如对用户提交的数据没有做检查就做处理(如类型转换)
 405错误
 含义: 服务器找不到处理该请求的方法
 原因: 没有正确写HttpServlet的service方法
 ;
5) DAO
 什么是DAO: DAO(Data Access Object)数据访问对象
 封装了数据访问逻辑的一个对象
 DAO的优点:
 DAO封装了数据访问逻辑,调用者不用关心底层数据库访问逻辑是如何实现的,方便代码的维护 如:数据访问逻辑发生了改变(从jdbc变成了mybatis)对调用者没有任何影响
 方便测试 如:将数据访问逻辑写在DAO里面,可以直接测试.如果将数据访问逻辑写在Servlet里面,就需要部署整个应用才能测试
 ;
6) Servlet的生命周期
 实例化
 什么是实例化 容器调用servlet的构造器,创建servlet对象
 什么时候实例化
 默认情况下,容器收到请求之后,才会创建
 容器启动后,立即实例化 1

lifeCycleServlet
web.servlet.LifeCycleServlet

1

 初始化 init(ServletConfig config)
 什么是初始化 容器在创建完servlet对象之后,会立即调用该对象的init方法
 注: 该方法只会执行一次
 GenericServlet已经提供了init方法的实现
 将容器传递过来的ServletConfig对象保存下来,并且提供了一个getServletConfig方法来获得该对象
 如何实现自己的初始化处理逻辑?
 Override GenericServlet的init()方法即可
 初始化参数的使用
 <!—配置初始化–>

 company
 IBM

 <!—读取初始化参数–>
 ServletConfig config = getServletConfig();
 String company = config.getInitParameter(“company”)
 就绪 service(ServletRequest req,ServletResponse res)
 什么是就绪: 容器收到请求后,会调用servlet对象的service
 HttpServlet已经提供了service方法的实现
依据请求类型,调用对应的doXXX方法( doget()或dopost() )
如: get请求调用doGet()方法,post请求调用doPOST()方法
 销毁 destroy()
 什么是销毁
 容器在删除Servlet对象之前,会调用该对象的destroy()方法
 注: 该方法只能执行一次
 GenericServlet已经提供了destroy()方法的基本实现
 可以override destroy方法来实现自己的销毁处理逻辑
7) 生命周期相关的几个接口与类(了解)
 Servlet接口
 init(ServletConfig config)
 service(ServletRequest req,ServletResponse res)
 destroy()
 GenericServlet抽象类
 实现了Servlet接口的部分方法(init,destroy)
 HttpServlet抽象类
 继承了genericServlet,实现了service方法
8) 状态管理
 什么是状态管理
 将浏览器与web服务器之间多次交互当作一个整体来处理,并且将多次交互所涉及的数据(即状态)保存下来。
 如何进行状态管理
 方式一:将状态保存在浏览器端(Cookie)。
 方式二:将状态保存在服务器端(Session).
 Cookie
 什么是Cookie?
 服务器临时存放在浏览器端的少量数据,用于跟踪用户的状态。
 注:当浏览器第一次访问服务器时,服务器可以将少量数据以set-cookie消息头的形式发送给浏览器,浏览器会将这些数据临时保存下来—当浏览器再次访问服务器时,会将这些数据以cookie消息头的形式发送给服务器。
 添加Cookie
 Cookie c = new Cookie(String name,String value);
 response.addCookie©;
 读取Cookie
 Cookie[] cookie = request.getCookies();
 注:该方法有可能返回null。
 String cookie.getName();
 String cookie.getValue();
for(Cookie c:cookie){
String name = c.getName();
String value = c.getValue();
}
 Cookie的生存时间
 默认情况下,浏览器会将cookie保存在内存里面,浏览器如果关闭,则cookie会被删除。可以调用setMaxAge方法来设置cookie的生存时间。
 cookie.setMaxAge(int seconds);
 注:----单位是秒。
seconds > 0: 浏览器会将cookie保存在硬盘上。超过指定的
时间,cookie会被删除(失效)。
seconds < 0: 默认情况(将cookie保存在内存里面)。
seconds = 0: 删除cookie。
比如,要删除一个名称为"username"的cookie:
Cookie c = new Cookie(“username”,"");
c.setMaxAge(0);
response.addCookie©;
 cookie的编码问题
 什么是cookie的编码问题?
 cookie只能存放合法的ascii字符,对于非ascii字符(比如中文)需要转换成对应的ascii字符的形式。
 如何解决?
 添加cookie时,使用encode方法对要添加的字符串进行编码,
 读取cookie时,使用decode方法来解码。
 String URLEncoder.encode(String str,String charset);
 String URLDecoder.decode(String str,String charset);
 建议:在添加cookie时,不管是否是ascii字符,统一使用encode方法来编码。
 Cookie的路径问题
 什么是cookie的路径问题?
 浏览器在访问服务器时,会比较请求路径是否与cookie的路径匹配,只有匹配条件的cookie才会被发送出去。
 cookie默认路径
 cookie的默认路径等于添加该cookie的web组件的路径。
 比如,/servlet07/biz01/addCookie.jsp添加了一个cookie,
 则该cookie默认路径就是"/servlet07/biz01"
 匹配规则
 请求路径要么等于cookie的路径,要么是cookie的子路径,该cookie才会被发送。
 比如,cookie的路径是"/servlet07/biz01",则:
 请求地址是/servlet07/findCookie1.jsp,则cookie不会被发送;
 请求地址是/servlet07/biz01/findCookie2.jsp,会发送;
 请求地址是/servlet07/biz01/sub/findCookie3.jsp,会发送。
 如何修改cookie的路径?
 cookie.setPath(String path);
 Cookie限制
cookie可以被用户禁止
cookie不安全
cookie只能存放少量数据,大约4k左右
cookie数量也有限制
cookie只能存放字符串
 Session
 什么是session
 服务器为了保存用户状态,而创建的一个特殊的对象
 注: 当浏览器第一次访问服务器时,服务器创建一个session对象(该对象有一个唯一的id,一般称之为sessionId),服务器会将sessionId以cookie的方式发送给浏览器。 当浏览器再次访问服务器时,会将sessionId发送过来,服务器依据sessionId就可以找到对应的session对象。
 如何获得session对象?
 方式一: HttpSession session = request.getSession(boolean flag);
 注: HttpSession是一个接口。
 当flag为true时:先查看请求当中是否有sessionId,如果没有,则创建一个session对象。如果有,则依据sessionId查找对应的session对象,如果找到了,则返回该对象,如果找不到,创建一个新的session对象。
 当flag为false时:先查找请求当中是否有sessionId,如果没有,返回null。如果有,则依据sessionId查找对应的session对象,如果找到了,则返回该对象,如果找不到,返回null。
 方式二: HttpSession session = request.getSession();
 等价于request.getSession(true);
 常用方法
 绑订数据: session.setAttribute(String name,Object obj);
 依据绑订名获得绑订值:Object obj = session.getAttribute(String name);
 注:如果绑订名对应的值不存在,返回null。
 解除绑订:session.removeAttribute(String name);
 session销毁
 为了避免Session中存储的数据过大,Session需要销毁
 超时自动销毁
 从用户最后一次访问网站开始,超过一定时间后,服务器自动销毁Session,以及保存在Session中的数据。
 Tomcat 服务器默认的Session超时时间是30分钟
 可以利用web.xml设置超时时间单位是分钟,设置为0表示不销毁。
 </session-config/>
 </session-timeout/>20</session-timeout/>
 </session-config/>
 调用API方法,主动销毁Session
 session.invalidate()
9) 过滤器
 Servlet 标准中定义了过滤器,可以拦截任意的服务器请求和响应。
 实现过滤器的步骤:
 创建一个过滤器类实现javax.servlet.Filter接口
 重写(实现)全部抽象方法
 业务逻辑写到 doFilter中
 如果在doFilter中调用了 chain.doFilter方法则处理后续逻辑,如果不执行这个方法,表示对后续逻辑的拦截。
 在web.xml(部署描述文件)配置filter,将filter配置到请求之前。
 可以配置多个filter-mapping,这样可以复用同一个Filter
 可以使用 .png 或者 / 过滤一组url
 当有多个过滤器过滤统一个资源时候,按照配置的先后执行。
 </filter/>
 </filter-name/>demo</filter-name/>
 </filter-class/>web.DemoFilter</filter-class/>
 </filter/>
 </filter-mapping/>
 </filter-name/>demo</filter-name/>
 </url-pattern/>/img.png</url-pattern/>
 </filter-mapping/>
 过滤器方法参数 ServletRequest 和 ServletResponse,是 HttpServletRequest 和 HttpServletResponse 的父类型,方法比较少! 如果需要使用HttpServletRequest 和 HttpServletResponse 的方法,需要进行强制类型转换!
 比如需要使用 request.getSession() 方法:
 HttpServletRequest req = (HttpServletRequest)request;
 HttpSession session = req.getSession();
 利用 web.xml 可以向Filter 传递初始化参数。写在Filter里面
 </init-param/>
 </param-name/>start</param-name/>
 </param-value/>8</param-value/>
 </init-param/>
 获取配置信息 config.getInitParamter(“start”);
 Filter 对象的生命周期
 在Web容器启动时候创建Filter对象,Filter对象是单例的(只创建一个Filter对象)!
 创建以后,立即执行init()方法,只执行一次
 在有url请求时候,会执行匹配的doFilter(),doFilter()是并发执行的。
 Filter对象在容器关闭时候销毁,销毁时候执行destroy()
 编写Servlet
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
 System.out.println(“在chain.doFilter之前的执行”);
 chain.doFilter(request, response);
 }
 配置web文件
 </filter/>
 </filter-name/>TestFilter</filter-name/>
 </filter-class/>web.TestFilter</filter-class/>
 </filter/>

 </filter-name/>TestFilter</filter-name/>
 </url-pattern/>.png</url-pattern/>
 </filter-mapping/>
 配置web.xml文件 有参数
 </filter/>
 </filter-name/>ImageFilter
 web.ImageFilter
 </init-param/>
 </param-name/>start</param-name/>
 </param-value/>8</param-value/>
 </init-param/>
 </filter/>
 </filter-mapping/>
 ImageFilter</filter-name/>
.png</url-pattern/>
 </filter-mapping/>
10) 监听器
 在Web容器的工作时候,在出现特定情况下,会自动的执行用户定义的监听器程序。利用监听器程序,可以将用户程序嵌入到Web容器中工作。
 特定情况包括:
 对象创建情况:
 request对象,response对象,session对象,ServletContext对象等。
 对象的创建和销毁时候执行 事件代码。
 在对象中添加、删除数据时候(setAttribute,removeAttribute)
 其他的工作状态改变的时候
 如使用:HttpSessionListener
 创建 类 实现HttpSessionListener
 重写方法 sessionCreated()
 重写方法 sessionDestroyed()
 在web.xml 中配置
 启动web容器
 当web容器工作期间创建了session对象时候,会自动执行 sessionCreated()
 当web容器工作期间销毁了session对象时候, 会自动执行sessionDestroyed()
 配置Listener

 web.DemoListener

 最重要的监听器:ServletContextListener
 contextInitialized() 会在Web服务器启动时候执行。 在软件中需要初始化的程序写到这个方法中。
 contextDestoryed() 会在Web服务器关闭时候执行。如果需要在关闭时候清除的资源,可以写到这个方法中。
 ;
11) ServletContext
Context: 上下文,当前事物存在的前后环境场景。
Servlet 上下文:当前Servlet存在的运行环境。代表Web容器
 任何获取 ServletContext 的方法获取的对象都是同一个ServletContext对象的引用
 调用从 HttpServlet继承的方法获取ServletContext
 ServletContext ctx1 = getServletContext();
 调用request对象getServletContext()方法获取ServletContext
 ServletContext ctx2 = request.getServletContext();
 可以使用ServletContext提供的方法与当前Web容器进行通讯
 ctx1.getServerInfo() 获取当前容器版本信息
 ctx1.getRealPath() 获取当前程序的实际路径,硬盘物理位置使用这个方法可以获取图片等资源的磁盘位置,进而使用IO API进行操作。
 ctx1.getContextPath() 获取当前应用程序的上下文路径用于拼接web绝对路径,解决路径问题。
 ServletContext对象可以绑定共享当前应用的全局数据
 setAttribute()
 getAttribute()
 removeAttribute()
 建议在修改期间进行同步(加锁)处理
 数据共享范围 request session servletContext
 Web编程时候,可以利用request session servletContext共享数据,称为共享范围(scope),在使用数据共享范围时候,尽量使用小范围。
**12) EL 通过KaTeX parse error: Unexpected character: '' at position 17: …}获取 13) JSTL** ̲ JSTL 是一组自定义标签组…{num == 0}"> </c:if>
 c:choose 多路分支(双路)

  1. <c:choose>
  2.  	<c:when test="${user.age<12}">
    
  3.  	</c:when>
    
  4.  	<c:when test="${user.age<22}">
    
  5.  	</c:when>
    
  6.  	<c:otherwise>
    
  7.  	</c:otherwise>		
    
  8. </c:choose>
     c:forEach 遍历
     <c:forEach items="${users}" var=“user”>
     格式标签库 fmt,不常用
     数字: 5660 -> RMB5,660.00
     <fmt:formatNumber value="1236.23"pattern=“RMB###,###,###.00” />
     日期表格化: 2019-06-12
     <fmt:formatDate value=“2018-02-23” pattern=“yyyy-mm-dd”/>
     XML 标签库 xml,不用了解
     SQL 标签库 sql,不用了解
  1. JSP内置对象
    A. 9大内置对象
    a) 为何有9大内置对象
    使用方便:不用声明变量,不用初始化,直接使用
    已经预定好的变量:
  1. -out JSPWriter 常见考点 out对象用于向页面输出信息
  2. -request HttpServletRequest request用于获取浏览器发送来的请求信息
  3. -response HttpServletResponse response用于向浏览器发送响应数据
  4. -session HttpSession session代表当前的会话对象
  5. -application ServletContext application 代表当前ServletContext
  6. -分界线 上边常用 下边不常用
  7. -config ServletConfig config代表JSP页面配置信息
  8. -page Servlet 当前对象引用 page代表当前页面对象,用于访问当前对象的属性或方法
  9. -pageContext PageContext 是当前页面的上下文(管家),用于管理其他的内置对象,用于在当前页面内部共享数据
    <%
    JspWriter o = pageContext.getOut();
    o.print(“试试???”);
    pageContext.setAttribute(“msg”, “测试信息”);
    String msg = (String) pageContext.getAttribute(“msg”);
    out.println(msg);
    %>
  10. -exception Exception 只有在异常处理页面使用 代表其他页面传递过来的异常

15) 注解:
19. Java 5 提供了一种代码标注功能。
20. 利用注解可以实现动态代码执行功能。
21. 在软件运行期间动态解析注解动态执行方法。
22. 使用注解:利用反射API解析使用注解
23. 放到方法上 @RequestMapping("/add.do")
a) @Retention(RUNTIME) //注解一值保留到运行期
b) @Target(METHOD) //此注解只能写在方法上
c) public @interface RequestMapping {
a) String value(); //利用value()可以给注解添加默认参数
d) }

16) 反射
24. Java 提供的核心API
1. java.lang.reflect 包中的系列API
25. 提供功能:
1. 动态解析对象的类型和内部结构,解析注解
2. 动态加载类型
3. 动态创建对象
4. 动态执行方法
演示:
public static void test(Object obj) {
//obj 引用对象的类型,以及内部结构是什么?
//利用反射就可以动态检查对象的类型和内部结构
// getClass() 获取当对象的实际类型
Class cls = obj.getClass();
System.out.println(cls);
//检查类型的内部结构
// Declared 声明的 Field 字段、属性
Field[] fields=cls.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//Method: 方法 检查类型中声明的方法
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
演示
public static void main(String[] args) throws Exception{
/**
* 动态解析类方法上标注的注解
/
Scanner in= new Scanner(System.in);
System.out.print(“输入类名:”);
String className=in.nextLine();
//获取Demo的类型信息
//Class cls = Demo.class;
//forName() 可以动态加载一个类到内存中
Class cls = Class.forName(className);
//获取类型上全部的方法
Method[] methods=cls.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
//Annotation:注解
//method.getAnnotations() 获取在方法上
//标注的注解。此注解必须是 RUNTIME 注解
Annotation[] anns=method.getAnnotations();
//方法上只标注了一个注解,获取第一个注解
Annotation ann = anns[0];
System.out.println(ann);
//读取注解上的value值
if(ann instanceof RequestMapping) {
RequestMapping rm=(RequestMapping)ann;
System.out.println(rm.value());
}
}
}
利用反射调用方法:
26. 加载类
27. 在类找到要执行的方法
28. 创建对象
29. 在对象上执行方法
public static void main(String[] args) throws Exception{
/

* 利用反射执行方法
1. 加载类
2. 在类找到要执行的方法
3. 创建对象
4. 在对象上执行方法
*/
Scanner in = new Scanner(System.in);
System.out.print(“输入类名:”);
String className = in.nextLine();
//Class cls 是反射API的使用入口
//动态加载类
Class cls = Class.forName(className);
//输入方法名
System.out.print(“输入方法名:”);
String name = in.nextLine();
//动态找到类上声明的方法,如果找不到就抛出异常!
Method method = cls.getDeclaredMethod(name);
//创建对象:动态创建对象, Instance实例
//newInstance的使用前提是类型必须包含无参构造器
Object obj = cls.newInstance();
//在对象obj上调用method方法:
//如果参数错误,或者对象上没有方法,或者方法执行
//期间出现故障,都会抛出异常。
method.setAccessible(true); //可以访问私有的方法
Object val = method.invoke(obj);
System.out.println(val);
}
利于反射可以动态检查对象的类型和内部结构
method.setAccessible(true); //可以访问私有的
17) SmartMVC 自定义框架
A. MVC 模式: 解决用户界面问题的标准模式(套路)
B. M Model 模型,封装业务逻辑
C. V View 视图,代表显示界面
D. C Controller 控制器,是用于连接整合 M和V
E. Sun给出web用户界面的建议:
30. 使用Java Bean 作为Model,处理业务逻辑
31. 使用JSP 作为视图,显示数据
32. 使用Servlet作为控制器,整合JSP和JavaBean
F. 一般情况将如上建议封装为框架(工具)减少后续编程量
G. 框架实现步骤:
33. 拆分控制器为 前端控制器和子控制器
拆分的目的是将Web编程逻辑与业务处理逻辑进行剥离,将Web编程逻辑封装到前端控制器,达到简化子控制器逻辑,复用前端控制器的目的。
34. 利用request参数将控制器中的数据共享到JSP
为了避免用户直接访问JSP视图组件,将JSP保存到 /WEB-INF/jsp 文件夹中。
35. 利用注解将用户请求URL映射到子控制器的方法上
36.
19) 基础性项目需要的技术
前端:jsp(freemarker,velocity),js,jquery,bootsrap(页面布局/插件)[exit,easyUI]
控制层:servlet(springMVC,struts1,struts2,webwork)
持久层:mybatis(jdbc,hibernate,ibatis)
O-R Mapping
整合:手动(spring)

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

留恋不舍

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值