华清远见-重庆中心-Java Web/知识点梳理/个人总结

java servlet

servlet介绍

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。

servlet的使用

关于servlet的使用,我们以创建一个操作数据库的项目为例来说明

项目的创建

项目名字随便,但需要注意Archetype需选择webapp项目

在webapp\WEB-INF\ 路径下面找到web.xml文件,

需要注意系统生成的web.xml文件版本是否过低

可在File》Project Structure》Project Setting》Modules 下图位置配置

在pom.xml文件中导入依赖

在下图位置配置tomcat

点击加号找到tamcat配置

项目开发

在java文件下建立好如下各种包

entity:用来写实体类

dao:用来写操作数据库的方法(增删改查)

service:用来引用dao中的各种方法

action:引用service,跳转到指定页面,接收页面传过来的数据,进行计算处理

util:写链接数据库的方法

entity

package entity;

import java.util.Date;

public class Employee {
    private Integer eid;
    private String ename;
    private Date etime;
    private Integer esalary;
    public String ejob;
    private String edept;
    private String enote;
    private String eimg;
    private Integer did;

    public Employee() {
    }

    @Override
    public String toString() {
        return "Employee{" +
                "eid=" + eid +
                ", ename='" + ename + '\'' +
                ", etime=" + etime +
                ", esalary=" + esalary +
                ", ejob='" + ejob + '\'' +
                ", edept='" + edept + '\'' +
                ", enote='" + enote + '\'' +
                ", eimg='" + eimg + '\'' +
                ", did=" + did +
                '}';
    }

    public Integer getEid() {
        return eid;
    }

    public void setEid(Integer eid) {
        this.eid = eid;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Date getEtime() {
        return etime;
    }

    public void setEtime(Date etime) {
        this.etime = etime;
    }

    public Integer getEsalary() {
        return esalary;
    }

    public void setEsalary(Integer esalary) {
        this.esalary = esalary;
    }

    public String getEjob() {
        return ejob;
    }

    public void setEjob(String ejob) {
        this.ejob = ejob;
    }

    public String getEdept() {
        return edept;
    }

    public void setEdept(String edept) {
        this.edept = edept;
    }

    public String getEnote() {
        return enote;
    }

    public void setEnote(String enote) {
        this.enote = enote;
    }

    public String getEimg() {
        return eimg;
    }

    public void setEimg(String eimg) {
        this.eimg = eimg;
    }

    public Integer getDid() {
        return did;
    }

    public void setDid(Integer did) {
        this.did = did;
    }
}

写好各种属性,get/set方法,创建构造函数,toString方法

util

public static Connection getConnection(String db,String user,String pwd){
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return  null;
        }
        String url = "jdbc:mysql://localhost:3306/"+db+"?serverTimeZone=Asia/Shanghai";
        try {
            return DriverManager.getConnection(url,user,pwd);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static void close(ResultSet rs, PreparedStatement ps,Connection con){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (ps!=null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

提供数据库连接和关闭的方法,提供参数的不同,可以连接不同的数据库

dao

public class EmployeeDao {

    //根据用户ID查询用户,查到返回对象,查不到返回null
    public Employee selectByEmployeeId(Integer eid) {
        Connection con = JDBCUtil.getConnection("empdb", "root", "123456");
        String sql = "select * from employee where e_id = "+eid;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement(sql);
            rs = ps.executeQuery();
            if (rs.next()) {
                Employee employee = new Employee();
                employee.setEid(rs.getInt(1));
                employee.setEname(rs.getString(2));
                employee.setEtime(rs.getDate(3));
                employee.setEsalary(rs.getInt(4));
                employee.setEjob(rs.getString(5));
                employee.setEdept(rs.getString(6));
                employee.setEnote(rs.getString(7));
                employee.setEimg(rs.getString(8));
                employee.setDid(rs.getInt(9));
                return employee;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(rs, ps, con);
        }
        return null;
    }

    //增加
    public int insertEmployee(Employee employee) {
        Connection con = JDBCUtil.getConnection("empdb", "root", "123456");
        String sql = "insert into employee values(0,?,?,?,?,?,?,?,?)";
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            ps.setString(1, employee.getEname());
            ps.setDate(2, new Date(employee.getEtime().getTime()));
            ps.setInt(3, employee.getEsalary());
            ps.setString(4, employee.getEjob());
            ps.setString(5, employee.getEdept());
            ps.setString(6, employee.getEnote());
            ps.setString(7, employee.getEimg());
            ps.setInt(8, employee.getDid());
            int i = ps.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, con);
        }
        return 0;
    }

    //删除
    public Integer deleteByeid(Integer eid) {
        Connection con = JDBCUtil.getConnection("empdb", "root", "123456");
        String sql = "delete from employee where e_id =" + eid;
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            int i = ps.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, con);
        }
        return 0;
    }

    //修改
    public Integer updateByeid(Employee employee) {
        Connection con = JDBCUtil.getConnection("empdb", "root", "123456");
        String sql = "update employee set e_name=?,e_time=?,e_salary=?,e_job=?,e_dept=?,e_note=?,e_img=?,d_id=? where e_id=?";
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            ps.setString(1, employee.getEname());
            ps.setDate(2, new Date(employee.getEtime().getTime()));
            ps.setInt(3, employee.getEsalary());
            ps.setString(4, employee.getEjob());
            ps.setString(5, employee.getEdept());
            ps.setString(6, employee.getEnote());
            ps.setString(7, employee.getEimg());
            ps.setInt(8, employee.getDid());
            ps.setInt(9, employee.getEid());
            int i = ps.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, con);
        }
        return null;
    }

    //4.查询全部
    public List<Employee> selectAllEmployee() {
        Connection con = JDBCUtil.getConnection("empdb", "root", "123456");
        String sql = "select * from employee";
        List<Employee> employees = new ArrayList<>();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next()) {
                Employee employee = new Employee();
                employee.setEid(rs.getInt(1));
                employee.setEname(rs.getString(2));
                employee.setEtime(rs.getDate(3));
                employee.setEsalary(rs.getInt(4));
                employee.setEjob(rs.getString(5));
                employee.setEdept(rs.getString(6));
                employee.setEnote(rs.getString(7));
                employee.setEimg(rs.getString(8));
                employee.setDid(rs.getInt(9));
                employees.add(employee);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(rs, ps, con);
        }
        return employees;
    }
}

service

public class EmployeeService {
    EmployeeDao dao = new EmployeeDao();

    public Boolean register(Employee employee) {
        Integer i = dao.insertEmployee(employee);
        if (i > 0) {
            return true;
        } else {
            return false;
        }
    }

    public List<Employee> queryAll() {
        return dao.selectAllEmployee();
    }

    public Employee query(Integer eid) {
        Employee employee = dao.selectByEmployeeId(eid);
        return employee;
    }

    public Boolean update(Employee employee) {
        Integer i = dao.updateByeid(employee);
        return i == 0 || i == null ? false : true;
    }

    public Boolean delete(int eid) {
        Integer i = dao.deleteByeid(eid);
        return i == 0 || i == null ? false : true;
    }
}

换取dao中不同方法的返回值,封装成方法,方便action调用

action

public class EmployeeServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String servletPath = req.getServletPath();
        PrintWriter writer = resp.getWriter();
        EmployeeService service = new EmployeeService();
        
        if (servletPath.equals("/add.emp")) {
            String ename = req.getParameter("ename");
            String etime = req.getParameter("etime");
            String esalary = req.getParameter("esalary");
            String ejob = req.getParameter("ejob");
            String edept = req.getParameter("edept");
            String enote = req.getParameter("enote");
            String eimg = req.getParameter("eimg");
            String did = req.getParameter("did");
            Employee employee = new Employee();
            employee.setEname(ename);
            if (etime != null) {
                employee.setEtime(Date.valueOf(etime));
            }
            if (esalary != null) {
                employee.setEsalary(Integer.valueOf(esalary));
            }
            employee.setEjob(ejob);
            employee.setEdept(edept);
            employee.setEnote(enote);
            employee.setEimg(eimg);
            if (did != null) {
                employee.setDid(Integer.valueOf(did));
            }
            Boolean aBoolean = service.register(employee);
            if (aBoolean==false){
                req.setAttribute("msg","添加失败");
                RequestDispatcher rd = req.getRequestDispatcher("./emp/info.jsp");
                rd.forward(req,resp);
            }else {
                resp.sendRedirect("list.emp");
            }
        } else if (servletPath.equals("/delete.emp")) {
            String eid = req.getParameter("eid");
            if (eid == null) {
                req.setAttribute("msg", "只能根据id删除数据");
                RequestDispatcher rd = req.getRequestDispatcher("./emp/info.jsp");
                rd.forward(req, resp);
            } else {
                Boolean aBoolean = service.delete(Integer.valueOf(eid));
                if (aBoolean == false) {
                    req.setAttribute("msg", "删除失败");
                    RequestDispatcher rd = req.getRequestDispatcher("./emp/info.jsp");
                    rd.forward(req, resp);
                } else {
                    //删除成功 转发到
                    //req.getRequestDispatcher("list.do").forward(req, resp);
                    //重定向 -- sendRedirect
                    resp.sendRedirect("list.emp");
                }
            }
        } else if (servletPath.equals("/toedit.emp")) {
            //根据bookId,查询一本书的信息,然后把书的信息转发到update.jsp页面
            String eid = req.getParameter("eid");//说明请求参数中需要传输bookId到这里
            if (eid != null) {
                Employee employee = service.query(Integer.valueOf(eid));
                if (employee == null) {
                    resp.getWriter().write("参数错误,查询不到书的信息");
                    resp.getWriter().write("<a href='list.emp'>查询员工信息</a>");
                } else {
                    //转发
                    req.setAttribute("emp", employee);//a.  把数据保存在request对象中
                    RequestDispatcher dispatcher = req.getRequestDispatcher("./emp/update.jsp");//b.获取转发对象,设置转发的路径
                    dispatcher.forward(req, resp);//c.转发
                }
            } else {
                resp.getWriter().write("参数错误");
                resp.getWriter().write("<a href='list.emp'>查询员工信息</a>");
            }

        }
        else if (servletPath.equals("/edit.emp")) {
            String eid = req.getParameter("eid");
            String ename = req.getParameter("ename");
            String etime = req.getParameter("etime");
            String esalary = req.getParameter("esalary");
            String ejob = req.getParameter("ejob");
            String edept = req.getParameter("edept");
            String enote = req.getParameter("enote");
            String eimg = req.getParameter("eimg");
            String did = req.getParameter("did");
            Employee employee = new Employee();
            if (eid != null) {
                employee.setEid(Integer.valueOf(eid));
            }
            if (ename != null) {
                employee.setEname(ename);
            }
            if (etime != null) {
                employee.setEtime(Date.valueOf(etime));
            }
            if (esalary != null) {
                employee.setEsalary(Integer.valueOf(esalary));
            }
            employee.setEjob(ejob);
            employee.setEdept(edept);
            employee.setEnote(enote);
            employee.setEimg(eimg);
            if (did != null) {
                employee.setDid(Integer.valueOf(did));
            }

            Boolean update = service.update(employee);
            //3.转发到success.jsp页面
            String msg = "";
            if (update) {
                //msg = "更新成功"; 重定向
                resp.sendRedirect("list.emp");
            } else {
                req.setAttribute("msg", "更新失败");
                RequestDispatcher rd = req.getRequestDispatcher("./emp/info.jsp");
                rd.forward(req, resp);
            }
        } else if (servletPath.equals("/list.emp")) {
            //servlet中查询数据
            List<Employee> employees = service.queryAll();
            //把数据bookInfos,转发到jsp页面,jsp页面显示数据
            //把需要转发到jsp页面上的数据,保存在request对象中
            req.setAttribute("emps", employees);
            //当前这个请求对应的路径:http://localhost:8080/employee/list.do
            RequestDispatcher dispatcher = req.getRequestDispatcher("./emp/show.jsp");
            dispatcher.forward(req, resp);// - forward
        }
         else {
            req.setAttribute("msg","输入的路径有错误!");
            RequestDispatcher rd = req.getRequestDispatcher("./emp/info.jsp");
            rd.forward(req,resp);
        }
    }
}

使用req.getServletPath()获取浏览器的url地址

通过if语句进行判断,实现不同请求的数据处理

web.xml文件配置

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>employee</servlet-name>
        <servlet-class>action.EmployeeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>employee</servlet-name>
        <url-pattern>*.emp</url-pattern>
    </servlet-mapping>
</web-app>

增加数据页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登记员工</title>
</head>
<body>
<h1>登记员工</h1>
<form action="register.emp" method="post">
    <label>请输入员工名:</label>
    <input type="text" name="ename"><br>
    <label>请输入入职时间:</label>
    <input type="text" name="etime"><br>
    <label>请输入薪资:</label>
    <input type="text" name="esalary"><br>
    <label>请输入工作岗位:</label>
    <input type="text" name="ejob"><br>
    <label>请输入所在部门:</label>
    <input type="text" name="edept"><br>
    <label>员工介绍:</label>
    <input type="text" name="enote"><br>
    <label>员工照片路径:</label>
    <input type="text" name="eimg"><br>
    <label>请输入部门ID:</label>
    <input type="text" name="did"><br>
    <input type="submit" value="注册">
    <input type="reset" value="重置">
</form>
</body>
</html>

修改数据页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登记员工</title>
    <script src="./js/jquery-3.6.3.js"></script>
</head>
<body>
<h1>登记员工</h1>
<form action="edit.emp" method="post">
    <input type="hidden" name="eid" value="1">
    <label>请输入员工名:</label>
    <input type="text" name="ename"><br>
    <label>请输入入职时间:</label>
    <input type="text" name="etime"><br>
    <label>请输入薪资:</label>
    <input type="text" name="esalary"><br>
    <label>请输入工作岗位:</label>
    <input type="text" name="ejob"><br>
    <label>请输入所在部门:</label>
    <input type="text" name="edept"><br>
    <label>员工介绍:</label>
    <input type="text" name="enote"><br>
    <label>员工照片路径:</label>
    <input type="text" name="eimg"><br>
    <label>请输入部门ID:</label>
    <input type="text" name="did"><br>
    <input type="submit" value="修改">
    <input type="reset" value="重置">
</form>
<script>
    //获取url地址,然后截取出数据,最后把数据设置到输框中
    let url = window.location.href;
    url= decodeURI(url);
    let args = url.substring(url.indexOf("?")+1,url.length);
    console.log(args)
    let arrs = args.split("&")
    $("input").eq(0).val(arrs[0].split("=")[1]);
    $("input").eq(1).val(arrs[1].split("=")[1]);
    $("input").eq(2).val(arrs[2].split("=")[1]);
    $("input").eq(3).val(arrs[3].split("=")[1]);
    $("input").eq(4).val(arrs[4].split("=")[1]);
    $("input").eq(5).val(arrs[5].split("=")[1]);
    $("input").eq(6).val(arrs[6].split("=")[1]);
    $("input").eq(7).val(arrs[7].split("=")[1]);
    $("input").eq(8).val(arrs[8].split("=")[1]);
</script>
</body>
</html>

模糊匹配

在web.xml文件配置时,url-pattern用来配置浏览器的请求路径

模糊匹配便于配置多个请求的路径

精确匹配

在 中配置的项必须与url完全精确匹配。

<filter>
        <filter-name>MyServlet</filter-name>
        <filter-class>filter.PingLunFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyServlet</filter-name>
        <url-pattern>/pinglun.emp</url-pattern>
    </filter-mapping>

必须以http://localhost:8080/employee/pinglun.emp这个路径才能访问到

其中localhost是ip地址,这里指127.0.0.1。 8080是端口号。employee是tomcat配置的Application Context

路径匹配

以“/”字符开头,并以“/*”结尾的字符串用于路径匹配

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/emp/*</url-pattern>
</servlet-mapping>

路径以/emp/开始,后面的路径可以任意。比如下面的url都会被匹配。

扩展名匹配

以“*.”开头的字符串被用于扩展名匹配

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>*.jsp</url-pattern>
</servlet-mapping>

任何后缀为.jsp的都能匹配到

缺省匹配

任意路径都可以匹配

匹配优先级

精确 》 路径 》 拓展名 》缺省

先找精确匹配,如果找不到在找路径匹配,在找不到就找扩展名匹配。

以上三种匹配方式都找不到,才会使用缺省匹配

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 根据所提供的华清远见-c0rtexas9资料路径,在实验中涉及到了Linux系统标准IO的应用实验。Linux系统标准IO是指Linux操作系统提供的一套标准化的IO库,可以用于操作文件、输入输出等。以下是对该实验的简单描述: 这个实验主要是关于Linux系统标准IO的应用实验。在该实验中,我们可以找到程序的源代码,该源代码是用Linux应用程序的方式编写的。通过这个实验,我们可以了解和学习Linux系统标准IO的基本操作和使用方法。 Linux系统标准IO是一套非常强大和灵活的IO库,提供了一系列的函数和方法来操作文件和进行输入输出。在实验源码中,我们可以看到一些常见的标准IO函数,比如fopen、fclose、fprintf和fscanf等。 通过这些函数,我们可以打开和关闭文件,从文件读取数据或向文件写入数据。实验源码中包含了一些常见的操作,比如读取文件、写入文件、复制文件和查找文件等。通过实验,我们可以了解到如何使用这些函数来完成不同的操作。 此外,在实验源码中可能还会涉及到一些其他的Linux系统标准IO相关的知识点,比如文件指针、文件描述符和文件流等。这些知识点对于理解和使用Linux系统标准IO函数非常重要。 通过实验中提供的源代码,我们可以进行相应的实验操作,从而更好地理解和学习Linux系统标准IO的使用。同时,我们也可以通过对实验源码的分析和调试,更深入地了解Linux系统标准IO的内部工作原理。 总之,通过这个实验,我们可以掌握Linux系统标准IO的基本操作和使用方法,从而提高我们在Linux系统中进行文件操作和输入输出的能力。 ### 回答2: 华清远见(英文名称为Far Infrared Technologies International Limited)是一家专注于红外光学技术研发及应用的企业。该公司的产品主要应用于安防监控、无人机、机器人、智能家居等领域。 关于"06. linux系统标准io实验"的实验资料包括了程序源码。在Linux操作系统中,标准I/O(Input/Output)库是用于进行文件读写和输入输出操作的一套API(Application Programming Interface)。标准I/O库提供了一系列函数,包括文件打开、读取、写入、关闭等操作,方便开发人员进行文件操作和输入输出。 这份实验资料中的源码,应该是用于展示和实践Linux系统标准I/O库的使用方法和技巧。通过编译和运行这些源码,可以了解如何使用标准I/O库来进行文件的读写和输入输出操作,包括打开文件、读取文件内容、写入文件等。 这些实验源码可以作为学习和实践Linux系统标准I/O库的参考资料。通过实际操作,可以加深对标准I/O库的理解和掌握,提高在Linux环境下进行文件操作和输入输出的能力。 总之,"06. linux系统标准io实验"的实验资料中的程序源码是用于学习和实践Linux系统标准I/O库的使用方法,通过编译和运行这些源码,可以加深对标准I/O库的理解和掌握,提高在Linux环境下进行文件操作和输入输出的能力。 ### 回答3: 华清远见-c0rtexa9资料中的程序源码目录为\linux应用实验源码\06. linux系统标准io实验\。这个实验中包含了一些关于Linux系统标准输入输出的代码示例。 在Linux中,标准输入输出是三个预先定义好的文件描述符,分别是0(stdin),1(stdout),2(stderr)。这些文件描述符与输入输出设备关联,比如键盘和屏幕。使用标准输入输出可以实现用户与程序之间的交互以及程序的输出显示。 在实验源码中,我们可以看到许多用于标准输入输出的函数,包括printf、scanf、getchar、putchar等。这些函数可以帮助我们进行输入输出操作。 在实验中,我们可以通过这些代码示例学习如何从标准输入读取用户输入,如何向标准输出显示结果。例如,可以使用scanf函数读取用户输入的数据,使用printf函数将处理结果输出显示。 通过实验中的代码示例,我们可以学习到如何处理标准输入输出的错误,如何进行格式化输入输出,如何使用缓冲区进行高效的输入输出等。 总之,华清远见-c0rtexa9资料中的\linux应用实验源码\06. linux系统标准io实验\中包含了一些关于Linux系统标准输入输出的代码示例,通过这些示例我们可以学习到如何进行标准输入输出操作,以及一些与之相关的技巧和注意事项。这对于学习Linux系统编程和开发应用程序非常有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值