jsp

jsp概念


JSP全称Java Server Pages
简化的servlet设计,在html标签中嵌套Java代码,用以高效开发web应用的动态标签。

  • jsp的作用:

替换显示页面部分的servlet(使用*.jsp文件替换XXXJSP.java)

jsp结构


  • 网络服务器需要一个 JSP 引擎,也就是一个容器来处理 JSP 页面。容器负责截获对 JSP 页面的请求
  • JSP 容器与 Web 服务器协同合作,为JSP的正常运行提供必要的运行环境和其他服务,并且能够正确识别专属于 JSP 网页的特殊元素。

在这里插入图片描述

  • jsp处理流程
  1. 详细解析图
    在这里插入图片描述
  2. 大体图(概括)
    在这里插入图片描述

jsp的生命周期


  • 以下是JSP生命周期中所走过的几个阶段:

       编译阶段:
      servlet容器编译servlet源文件,生成servlet类,分为三个步骤
      ---------------------------------------------------
      	* 解析JSP文件。
      	* 将JSP文件转为servlet。
      	* 编译servlet。
    
      初始化阶段:
      加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法
      ---------------------------------------------------
      	* 容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()方法。
      	* 如果您需要执行自定义的JSP初始化任务,复写jspInit()方法就行了
      
      执行阶段:
      调用与JSP对应的servlet实例的服务方法
      ---------------------------------------------------
       * 当JSP网页完成初始化后,JSP引擎将会调用_jspService()方法。
      		
      销毁阶段:
      调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例
      ---------------------------------------------------
       * jspDestroy()方法在JSP中等价于servlet中的销毁方法
    
  • 生命周期的代码练习

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>life</title>
</head>
<body>
<%!
    private int initVar=0;
    private int serviceVar=0;
    private int destoryVar=0;
%>
<%!
    //初始化的方法
   public void jspInit(){
       initVar++;
       System.out.println("jspInit(): JSP被初始化了"+initVar+"次");

   }
    //  销毁jsp的方法
   public void jspDestory(){
       destoryVar++;
       System.out.println("jspDestroy(): JSP被销毁了"+destoryVar+"次");
   }
%>
<%
    serviceVar++;
    System.out.println("_jspService(): JSP共响应了"+serviceVar+"次请求");
    String content1="初始化次数 : "+initVar;
    String content2="响应客户请求次数 : "+serviceVar;
    String content3="销毁次数 : "+destoryVar;
%>
<h1>菜鸟教程jsp测试实例</h1>
<p><%=content1 %></p>
<p><%=content2 %></p>
<p><%=content3 %></p>
</body>
</html>
  • 第一次请求
    在这里插入图片描述
  • 第二次访问
    在这里插入图片描述

jsp的语法


  • 脚本程序

脚本程序可以包含任意量的Java语句、变量、方法或表达式,只要它们在脚本语言中是有效的。

  • 脚本程序的格式
<% 代码片段 %>
  • or
<jsp:scriptlet>
   代码片段
</jsp:scriptlet>

任何文本、HTML标签、JSP元素必须写在脚本程序的外面。

  • 中文编码问题
  • 如果我们要在页面正常显示中文,我们需要在 JSP 文件头部添加以下代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  • JSP注释
  • <%-- 该部分注释在网页中不会被显示–%>
  • 快捷键:单行注释 Ctrl+/
  • 多行注释: Shift+Ctrl+/
  • jsp的指令
    在这里插入图片描述
  • jsp 行为
  • jsp的格式
<jsp:action_name attribute="value" />

在这里插入图片描述

  • jsp中的控制流语句
  • 判断语句的代码演示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%
        int day =3;
    %>
</head>
<body>
<h3>IF...ELSE 实例</h3>
        <%
            if(day> 1& day<7){

        %>
        <h4>今天是周内</h4>
        <%}else {
        %>
        <h4>今天不是周内</h4>
        <%
            }
        %>

</body>
</html>

-

  • switch case
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%! int day = 3; %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    <%
        int day=3;
    %>
</head>
<body>
<h3>SWITCH...CASE 实例</h3>
<%
    switch(day) {
        case 0:
            out.println("星期天");
            break;
        case 1:
            out.println("星期一");
            break;
        case 2:
            out.println("星期二");
            break;
        case 3:
            out.println("星期三");
            break;
        case 4:
            out.println("星期四");
            break;
        case 5:
            out.println("星期五");
            break;
        default:
            out.println("星期六");
    }
%>
</body>
</html>

在这里插入图片描述

  • 循环语句

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>for循坏练习</title>
    <%
        int a;
    %>
</head>
<body>

    <h3>for循环的练习</h3>
    <%
        for (a=1;a<=5;a++){
           out.println(a);
        }%>
</body>
</html>

在这里插入图片描述

  • while循环
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%! int fontSize=0; %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h3>While 循环实例</h3>
<%while ( fontSize <= 3){ %>
<font color="green" size="<%= fontSize %>">
    菜鸟教程
</font><br />
<%fontSize++;%>
<%}%>
</body>
</html>

在这里插入图片描述

jsp 的隐式对象
JSP隐式对象是JSP容器为每个页面提供的Java对象,开发者可以直接使用它们而不用显式声明。
JSP隐式对象也被称为预定义变量。

在这里插入图片描述

  • request对象

      每当客户端请求一个JSP页面时,JSP引擎就会制造一个新的request对象来代表这个请求。
    
  • response对象

       当服务器创建request对象时会同时创建用于响应这个客户端的response对象。
      response对象也定义了处理HTTP头模块的接口。
      通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。
    
  • out对象

      用来在response对象中写入内容。是一个输出流
    
  • session对象

       和Java Servlets中的session对象有一样的行为。
      session对象用来跟踪在各个客户端请求间的会话。
    
  • application对象

       这个对象在JSP页面的整个生命周期中都代表着这个JSP页面。
       这个对象在JSP页面初始化时被			创建,随着jspDestroy()方法的调用而被移除。
      通过向application中添加属性,则所有组成您web应用的JSP文件都能访问到这些属性。
    
  • config对象

       这个对象允许开发者访问Servlet或者JSP引擎的初始化参数,比如文件路径等。
    
  • pageContext 对象

      pageContext对象是javax.servlet.jsp.PageContext 类的实例,用来代表整个JSP页面。
    
      这个对象主要用来访问页面信息,同时过滤掉大部分实现细节。
    
      这个对象存储了request对象和response对象的引用。
      application对象,config对象,session对象,out对象可以通过访问这个对象的属性来导出。
      
      pageContext对象也包含了传给JSP页面的指令信息,
      包括缓存信息,ErrorPage URL,页面scope等。
      
      PageContext类定义了一些字段,
      包括PAGE_SCOPE,REQUEST_SCOPE,SESSION_SCOPE, APPLICATION_SCOPE。
      它也提供了40余种方法,有一半继承自javax.servlet.jsp.JspContext 类。
      
      其中一个重要的方法就是 removeAttribute(),它可接受一个或两个参数。
      比如,pageContext.removeAttribute("attrName") 移除四个scope中相关属性,
      但是下面这种方法只移除特定 scope 中的相关属性:
    
  • page 对象

      这个对象就是页面实例的引用。它可以被看做是整个JSP页面的代表。
      
      page 对象就是this对象的同义词。
    
  • exception 对象

      exception 对象包装了从先前页面中抛出的异常信息。
      它通常被用来产生对出错条件的适当响应。
    
  • jsp动作属性

  1. jsp:include动作元素

jsp:include动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面
而这里的jsp:include动作不同,插入文件的时间是在页面被请求的时候。

<jsp:include page="相对 URL 地址" flush="true" />
  • 代码实现案里
  • date.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>date</title>
</head>
<body>
    <p>
        今天是你的生日:<%= (new java.util.Date()).toLocaleString() %>
    </p>
</body>
</html>
  • main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>main</title>
</head>
<body>
    <h2>include实例</h2>
    <jsp:include page="07-date.jsp" flush="true"/>
</body>
</html>

在这里插入图片描述
2. jsp:useBean动作元素

用来加载一个将在JSP页面中使用的JavaBean
在类载入后,我们既可以通过 jsp:setProperty 和 jsp:getProperty 动作来修改和检索bean的属性。

<jsp:useBean id="name" class="package.class" />
  1. jsp:setProperty动作元素

jsp:setProperty用来设置已经实例化的Bean对象的属性,

  1. jsp:getProperty动作元素

jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出

  • 2,3,4相关的案例
  • 先创建一个bean
package com.lty.pojo;
public class Student {
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
  • 测试的jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
</head>
<body>
    <h3>jsp:useBean动作元素案例</h3>

    <jsp:useBean id="student" class="com.lty.pojo.Student"/>
    <%--设置学生的姓名--%>
    <jsp:setProperty name="student" property="name" value="lty"/>

    <p>输出学生的信息</p>
    <%--获取学生的姓名--%>
    <jsp:getProperty name="student" property="name"/>

</body>
</html>

在这里插入图片描述
5. jsp:forward 动作元素

jsp:forward动作把请求转到另外的页面。jsp:forward标记只有一个属性page。
page属性包含的是一个相对URL。page的值既可以直接给出,也可以在请求的时候动态计算,可以是一个JSP页面或者一个 Java Servlet.

<jsp:forward page="相对 URL 地址" />
  • 案例
  • date页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>date</title>
</head>
<body>
    <p>
        今天是你的生日:<%= (new java.util.Date()).toLocaleString() %>
    </p>
</body>
</html>

  • main页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>main</title>
</head>
<body>
    <%--<h2>include实例</h2>
    <jsp:include page="07-date.jsp" flush="true"/>--%>
    <h2>forward动作实例</h2>
    <jsp:forward page="07-date.jsp"/>
</body>
</html>

  • 输出结果

访问的是main页面,因为有<jsp:forward page=“07-date.jsp”/>,
所以最后我们看到的是date页面
如下图所示
在这里插入图片描述

  1. jsp:plugin动作元素

      jsp:plugin动作用来根据浏览器的类型,插入通过Java插件 运行Java Applet所必需的OBJECT或EMBED元素。
     
     如果需要的插件不存在,它会下载插件,然后执行Java组件。 Java组件可以是一个applet或一个JavaBean。
     
     plugin动作有多个对应HTML元素的属性用于格式化Java 组件。param元素可用于向Applet 或 Bean 传递参数。
    
<jsp:plugin type="applet" codebase="dirname" code="MyApplet.class"
                           width="60" height="80">
   <jsp:param name="fontcolor" value="red" />
   <jsp:param name="background" value="black" />
 
   <jsp:fallback>
      Unable to initialize Java Plugin
   </jsp:fallback>
 
</jsp:plugin>
  1. jsp:element 、 jsp:attribute、 jsp:body动作元素

jsp:element 、 jsp:attribute、 jsp:body动作元素动态定义XML元素。动态是非常重要的,这就意味着XML元素在编译时是动态生成的而非静态。

  • 案例
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
</head>
<body>
<jsp:element name="xmlElement">
<jsp:attribute name="xmlElementAttr">
   属性值
</jsp:attribute>
    <jsp:body>
        XML 元素的主体
    </jsp:body>
</jsp:element>
</body>
</html>
  1. jsp:text动作元素

元素允许在JSP页面和文档中使用写入文本的模板,语法格式如下:

<jsp:text>模板数据</jsp:text>

jsp客户端请求

https://www.runoob.com/jsp/jsp-client-request.html

jsp服务器响应

https://www.runoob.com/jsp/jsp-server-response.html

jsp的表单处理


我们在浏览网页的时候,经常需要向服务器提交信息,并让后台程序处理。浏览器中使用 GET 和 POST 方法向服务器提交数据。

  • get方法

GET方法将请求的编码信息添加在网址后面,网址与编码信息通过"?"号分隔。如下所示:

http://www.runoob.com/hello?key1=value1&key2=value2

GET方法是浏览器默认传递参数的方法,一些敏感信息,如密码等建议不使用GET方法。
用get时,传输数据的大小有限制 (注意不是参数的个数有限制),最大为1024字节。

  • post方法

一些敏感信息,如密码等我们可以通过POST方法传递,POST提交数据是隐式的。
POST提交数据是不可见的,GET是通过在url里面传递的(可以看一下你浏览器的地址栏)。
JSP使用getParameter()来获得传递的参数,getInputStream()方法用来处理客户端的二进制数据流的请求。

  • jsp读取表单的信息
  • getParameter(): 使用 request.getParameter() 方法来获取表单参数的值。
  • getParameterValues(): 获得如checkbox类(名字相同,但值有多个)的数据。 接收数组变量 ,如checkbox类型
  • getParameterNames():该方法可以取得所有变量的名称,该方法返回一个 Enumeration。
  • getInputStream():调用此方法来读取来自客户端的二进制数据流。
  • 案例
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*" %>
<html>
<head>
    <title>表单接受信息</title>
</head>
<body>
<h3>使用get方法读取表单的信息</h3>
    <ul>
        <li>
            <p>
                <b>站点名:</b>
                <%= request.getParameter("name")%>
            </p>
        </li>
        <li>
            <p>
                <b>网址:</b>
                <%= request.getParameter("url")%>
            </p>
        </li>
    </ul>

</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="11-get.jsp" method="get">
        站点名:<input type="text" name="name">
        网址名:<input type="text" name="url">
        <input type="submit" value="提交">
    </form>
</body>
</html>
  • 当访问http://localhost:8080/web_jsp/mian%E8%AE%BF%E9%97%AEget%E9%A1%B5%E9%9D%A2.html
    时,界面如下
    在这里插入图片描述
  • 当输入参数之后提交表单结果如下
    在这里插入图片描述
  • 使用表单的 POST 方法实例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <meta charset="utf-8">
</head>
<body>
<h1>使用 POST 方法读取数据</h1>
<ul>
    <li><p><b>站点名:</b>
        <%
            // 解决中文乱码的问题
            String name = new String((request.getParameter("name")).getBytes("ISO-8859-1"),"UTF-8");
        %>
        <%=name%>
    </p></li>
    <li><p><b>网址:</b>
        <%= request.getParameter("url")%>
    </p></li>
</ul>

</body>
</html>

  • post测试
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>测试post</title>
</head>
<body>

<form action="12-post.jsp" method="POST">
    站点名: <input type="text" name="name">
    <br />
    网址: <input type="text" name="url" />
    <input type="submit" value="提交" />
</form>

</body>
</html>

在这里插入图片描述

  • 传递 Checkbox 数据到JSP程序
  • html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="13-checkedPost.jsp" method="post">
        <input type="checkbox" name="google" checked="checked">google
        <input type="checkbox" name="lty">lty
        <input type="checkbox" name="zly" checked="checked">zly
        <input type="submit" value="选择">
    </form>
</body>
</html>
  • jsp页面
<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2020/12/22
  Time: 14:52
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>从复选框中选择数据</h3>
    <ul>
        <li>
            <p>
                <b>google是否选中</b>
                <%=request.getParameter("google")%>
            </p>
        </li>
        <li>
            <p>
                <b>lty是否选中</b>
                <%=request.getParameter("lty")%>
            </p>
        </li>
        <li>
            <p>
                <b>zly是否选中</b>
                <%=request.getParameter("zly")%>
            </p>
        </li>
    </ul>

</body>
</html>

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

  • 读取表单的所有数据并且遍历
<%
   Enumeration paramNames = request.getParameterNames();

   while(paramNames.hasMoreElements()) {
      String paramName = (String)paramNames.nextElement();
      out.print("<tr><td>" + paramName + "</td>\n");
      String paramValue = request.getParameter(paramName);
      out.println("<td> " + paramValue + "</td></tr>\n");
   }
%>

jsp过滤器[存在疑难问题]

在这里插入图片描述

  • javax.servlet.Filter 接口定义了三个方法:

      1. public void doFilter (ServletRequest, ServletResponse, FilterChain)
      * 该方法完成实际的过滤操作,当客户端的请求与过滤器设置的 URL 匹配时,
      * Servlet 容器将先调用过滤器的 doFilter 方法。FilterChain 用于访问后续过滤器。
      2. public void init(FilterConfig filterConfig)
      * 初始化
      3. public void destroy()
      * 删除拦截器
    

JSP Cookie 处理

Cookie 是存储在客户机的文本文件,它们保存了大量轨迹信息。在 Servlet 技术基础上,JSP 显然能够提供对 HTTP cookie 的支持

  • JSP Cookie 处理需要对中文进行编码与解码,方法如下:

String str = java.net.URLEncoder.encode(“中文”, “UTF-8”); //编码
String str = java.net.URLDecoder.decode(“编码后的字符串”,“UTF-8”); // 解码

Cookie 通常在 HTTP 信息头中设置(虽然 JavaScript 能够直接在浏览器中设置 cookie)。在 JSP 中,设置一个 cookie 需要发送如下的信息头给服务器:

	HTTP/1.1 200 OK
	Date: Fri, 04 Feb 2015 21:03:38 GMT
	Server: Apache/1.3.9 (UNIX) PHP/4.0b3
	Set-Cookie: name=runoob; expires=Friday, 04-Feb-17 22:03:38 GMT; 
	                 path=/; domain=runoob.com
	Connection: close
	Content-Type: text/html
  • 使用 JSP 设置 cookie

(1)创建一个 cookie 对象: 调用 cookie 的构造函数,使用一个 cookie 名称和值做参数,它们都是字符串。

Cookie cookie = new Cookie("key","value");
  1. 设置有效期:调用 setMaxAge() 函数表明 cookie 在多长时间(以秒为单位)内有效。下面的操作将有效期设为了 24 小时。
cookie.setMaxAge(60*60*24); 

(3) 将 cookie 发送至 HTTP 响应头中:调用 response.addCookie() 函数来向 HTTP 响应头中添加 cookie。

response.addCookie(cookie);
  • 案例
<%
   // 编码,解决中文乱码   
   String str = URLEncoder.encode(request.getParameter("name"),"utf-8");  
   // 设置 name 和 url cookie 
   Cookie name = new Cookie("name",
           str);
   Cookie url = new Cookie("url",
              request.getParameter("url"));

   // 设置cookie过期时间为24小时。
   name.setMaxAge(60*60*24); 
   url.setMaxAge(60*60*24); 

   // 在响应头部添加cookie
   response.addCookie( name );
   response.addCookie( url );
%>
  • 使用 JSP 读取 Cookie

调用 request.getCookies() 方法来获得一个 javax.servlet.http.Cookie 对象的数组,然后遍历这个数组,使用 getName() 方法和 getValue() 方法来获取每一个 cookie 的名称和值。

  • 案例
<%
   Cookie cookie = null;
   Cookie[] cookies = null;
   // 获取 cookies 的数据,是一个数组
   cookies = request.getCookies();
   if( cookies != null ){
      out.println("<h2> 查找 Cookie 名与值</h2>");
      for (int i = 0; i < cookies.length; i++){
         cookie = cookies[i];
        
         out.print("参数名 : " + cookie.getName());
         out.print("<br>");
         out.print("参数值: " + URLDecoder.decode(cookie.getValue(), "utf-8") +" <br>");
         out.print("------------------------------------<br>");
      }
  }else{
      out.println("<h2>没有发现 Cookie</h2>");
  }
%>
  • 使用 JSP 删除 cookie
  • 获取一个已经存在的 cookie 然后存储在 Cookie 对象中。
  • 将 cookie 的有效期设置为 0。
  • 将这个 cookie 重新添加进响应头中。

JSP Session


HttpSession接口来识别一个用户,存储这个用户的所有访问信息。

<%
   // 获取session创建时间
   Date createTime = new Date(session.getCreationTime());
   // 获取最后访问页面的时间
   Date lastAccessTime = new Date(session.getLastAccessedTime());

   String title = "再次访问菜鸟教程实例";
   Integer visitCount = new Integer(0);
   String visitCountKey = new String("visitCount");
   String userIDKey = new String("userID");
   String userID = new String("ABCD");

   // 检测网页是否有新的访问用户
   if (session.isNew()){
      title = "访问菜鸟教程实例";
      session.setAttribute(userIDKey, userID);
      session.setAttribute(visitCountKey,  visitCount);
   } else {
       visitCount = (Integer)session.getAttribute(visitCountKey);
       visitCount += 1;
       userID = (String)session.getAttribute(userIDKey);
       session.setAttribute(visitCountKey,  visitCount);
   }
%>
  • 删除Session数据

      移除一个特定的属性:
      调用public void removeAttribute(String name)  方法来移除指定的属性。
      
      删除整个会话:
      调用public void invalidate() 方法来使整个session无效。
    

JSP 连接数据库


  • 链接数据库
<sql:setDataSource var="snapshot" 
	 driver="com.mysql.cj.jdbc.Driver"
     url="jdbc:mysql://localhost:3306/RUNOOB?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
     user="root"  
     password="12345"/>
  • select
<sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver"
     url="jdbc:mysql://localhost:3306/RUNOOB?useUnicode=true&characterEncoding=utf-8"
     user="root"  password="123456"/>
 
<sql:query dataSource="${snapshot}" var="result">
SELECT * from websites;
</sql:query>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值