在Web环境下的MyBatis项目实现和分析

后台管理系统用户数据维护平台

本文的平台使用为Windows 10、Intellij2018.3、JDK1.8、Tomcat8.5.37。本文使用的技术是HTML、CSS、Bootstrap、MySQL 5.7、Java。该项目是在Web环境中,实现mybatis,主要功能有以下6个:所有用户数据查询、单个用户查询、用户数据修改、锁定用户账号、删除用户账号、彻底删除用户账号。

基础操作——主配置解析

  • properties配置加载
  • environments环境配置
  • settings参数设置配置
  • typeAliases别名设置
  • mapper映射加载

基础操作——查询数据

  • 映射配置:sql片段
  • 映射配置:select配置
    —特殊配置:字段和属性不一致时resultMap配置

依赖导入

在mybatis-pro.xml中进行导入相关依赖,由于创建的是Web项目,因此在xml中进行配置<packing…,,在项目已开始进行部署时,使用war包形式进行部署。Servlet3.0的程序需要在Tomcat7以上才支持Java EE 6,Tomcat7需要使用JDK1.6以上的版本。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.damu.mybatis</groupId>
    <artifactId>mybatis-pro</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        
//Servlet3.0具备的注解功能,是Java EE 6规范的一部分,使得不需要在web.xml文件中进行Servlet的部署描述,简化流程开发。
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

    </dependencies>


</project>

前端 ——配置web.xml文件

在src→main→webapp→WEB-INF→web.xml进行配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
<display-name>mybatispro</display-name>

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>home.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
</welcome-file-list>

</web-app>

前端 ——编写jsp代码

index.jsp文件

1.项目中的所有内容都要放在container中,row表示拆分出一行,page-header增加一个页头。
2.bootstrap官方网站,在本次项目中,我们使用它的巨幕
在这里插入图片描述
3.增加表格,用row拆分出一行,如下效果所示。同时可以增加测试数据。

用户编号登录账号用户昵称邮箱联系方式账号创建时间最后修改时间最后登录时间用户状态备注

<%--
  Created by IntelliJ IDEA.
  User: Vivian
  Date: 2019/4/4
  Time: 14:52
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
    <title>后台用户管理中心</title>
    <link rel="stylesheet" href="lib/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="lib/2.2.4/jquery-2.2.4.min.js"></script>
    <script src="lib/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="page-header">
            <h1>后台管理系统<small>用户数据管理中心</small></h1>
        </div>
    </div>

    <div class="row">
        <div class="jumbotron">
            <h1>MyBatis基础入门课程</h1>
            <p>通过一个项目来完成基础部分的学习</p>
            <p><a class="btn btn-primary btn-lg" href="#" role="button">查看更多,请上Oracle</a></p>
        </div>
    </div>

    <div class="row">
        <table class="table table-hover table-striped">
            <tr>
                <th>用户编号</th>
                <th>登录账号</th>
                <th>用户昵称</th>
                <th>邮箱</th>
                <th>联系方式</th>
                <th>账号创建时间</th>
                <th>最后修改时间</th>
                <th>最后登录时间</th>
                <th>用户状态</th>
                <th>备注</th>
            </tr>
           <c:choose>
                <c:when test="${user.id}">
                    <tr>
                        <td>暂无信息</td>
                    </tr>
                </c:when>
                <c:otherwise>
                <!-- 要循环的对象-->
            <c:forEach var="user" items="${usersList}">
            <tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.nickname}</td>
                <td>${user.email}</td>
                <td>${user.phone}</td>
                <td>${user.createTime}</td>
                <td>${user.updateTime}</td>
                <td>${user.lastLogin}</td>
                <!--<td>${user.userStatus}</td>-->
                <c:if test="${user.userStatus == 0}">
                    <td>正常</td>
                </c:if>

                <c:if test="${user.userStatus == 1}">
                    <td>锁定</td>
                </c:if>

                <c:if test="${user.userStatus == 2}">
                    <td>删除</td>
                </c:if>

                <td>
                    <a href="${pageContext.request.contextPath}/detail?id=${user.id}">查看</a>
                    <a href="">修改</a>
                    <a href="">删除</a>
                </td>
                </c:forEach>
                </c:otherwise>
           </c:choose>

            </tr>
        </table>
    </div>
</div>
</body>
</html>

home.jsp文件
<%--
  Created by IntelliJ IDEA.
  User: Vivian
  Date: 2019/4/4
  Time: 16:38
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    response.sendRedirect(request.getContextPath() +"/index");
    //return ;
%>
</body>
</html>

details.jsp
<%--
  Created by IntelliJ IDEA.
  User: Vivian
  Date: 2019/4/4
  Time: 10:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
    <title>后台用户管理中心</title>
    <link rel="stylesheet" href="lib/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="lib/2.2.4/jquery-2.2.4.min.js"></script>
    <script src="lib/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>

<div class="container">
    <div class="row">
        <div class="page-header">
            <h1>后台管理系统<small>用户数据管理中心</small></h1>
        </div>
    </div>

    <div class="row">
        <div class="jumbotron">
            <h1>MyBatis基础入门课程</h1>
            <p>通过一个项目来完成基础部分的学习</p>
            <p><a class="btn btn-primary btn-lg" href="#" role="button">查看更多,请上Oracle</a></p>
        </div>
    </div>
    <c:set var="user" value="${user}"></c:set>
    <div class="row">
        <div class=".col-md-8 .col-md-offset-2">
            <form class="form-horizontal">
                <div class="form-group">
                    <label class="col-sm-2 control-label">用户账号</label>
                    <div class="col-sm-10">
                        <p class="form-control-static">${user.username}</p>
                    </div>
                </div>

                <div class="form-group">
                    <label class="col-sm-2 control-label">登录密码</label>
                    <div class="col-sm-10">
                        <p class="form-control-static">*******</p>
                    </div>
                </div>

                <div class="form-group">
                    <label for="nickname" class="col-sm-2 control-label">昵称</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="nickname" value="${user.nickname}" name="nickname" placeholder="请输入昵称">
                    </div>
                </div>

                <div class="form-group">
                    <label for="age" class="col-sm-2 control-label">年龄</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="age" name="age" value="${user.age}" placeholder="请输入年龄">
                    </div>
                </div>

                <div class="form-group">
                    <label for="gender" class="col-sm-2 control-label">性别</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="gender" name="gender" value="${user.gender}" placeholder="请输入性别">
                    </div>
                </div>

                <div class="form-group">
                    <label for="phone" class="col-sm-2 control-label">联系方式</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="phone" value="${user.phone}" name="phone" placeholder="请输入联系方式">
                    </div>
                </div>

                <div class="form-group">
                    <label for="email" class="col-sm-2 control-label">邮箱</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="email" value="${user.email}" name="email" placeholder="请输入邮箱">
                    </div>
                </div>

                <div class="form-group">
                    <label class="col-sm-2 control-label">账号创建时间</label>
                    <div class="col-sm-10">
                        <p class="form-control-static">
                           <fmt:formatDate value="${user.createTime}" pattern="yyyy-MM-dd"></fmt:formatDate>
                        </p>
                    </div>
                </div>

                <div class="form-group">
                    <label class="col-sm-2 control-label">最后修改时间</label>
                    <div class="col-sm-10">
                        <p class="form-control-static">
                            <fmt:formatDate value="${user.updateTime}" pattern="yyyy-MM-dd"></fmt:formatDate>
                        </p>
                    </div>
                </div>

                <div class="form-group">
                    <label class="col-sm-2 control-label">最后登录时间</label>
                    <div class="col-sm-10">
                        <p class="form-control-static">
                            <fmt:formatDate value="${user.lastLogin}" pattern="yyyy-MM-dd"></fmt:formatDate>
                        </p>
                    </div>
                </div>

                <div class="form-group">
                    <label class="col-sm-2 control-label">用户状态</label>
                    <div class="col-sm-10">
                        <c:if test="${user.userStatus == 0}">
                            <p class="form-control-static">正常</p>
                        </c:if>
                        <c:if test="${user.userStatus == 1}">
                            <p class="form-control-static">锁定</p>
                        </c:if>
                        <c:if test="${user.userStatus == 2}">
                            <p class="form-control-static">删除</p>
                        </c:if>
                    </div>
                </div>

                <div class="form-group">
                    <label for="remark" class="col-sm-2 control-label">备注</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" id="remark" value="${user.remark}" name="remark" placeholder="请输入备注 ">
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>
</head>
<body>

</body>
</html>

后端 ——MyBatis的配置文件

开始mybatis的配置,要在mybatis-pro.xml中增加mybatis3.4.3版本和mysql5.1.41版本依赖。
mybatis依赖
mysql依赖

properties配置

在src→resources→mybatis-config.xml下进行配置。在mybatis3.4.4的官方文档中,找到关于数据源的配置,放在mybatis-config.xml中。其中,具体的详解已经在代码中注释。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--
    properties配置,用于加载外部的properties配置文件
    -->
    <properties resource="db.properties"></properties>

    <!--
        environments 主要用于进行数据源的配置
        可以配置多个数据源~ 通过default属性来指定当前项目运行过程中使用的是哪个数据源
        development是开发环境下的数据源
     -->
    <environments default="development">

        <!--
        environment 用于配置一个具体的独立的数据源
        id属性用于给当前数据源定义一个名称,方便我们的项目指定
        -->
        <environment id="development">

            <!--
            transactionManager用于配置事务管理,默认情况下使用的是JDBC事务管理
            -->
            <transactionManager type="JDBC"/>

            <!--
             dataSource具体数据源的链接信息;type属性用于指定是否使用连接池
              -->
            <dataSource type="POOLED">
               <!-- ${}代表sql的拼接,在拼接like中的%${value}%,或者表名时候用到 -->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
<!--
生产环境数据源
-->
        <environment id="product">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
<!--
测试环境数据源
-->
     <environment id="test">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
    </environments>

在数据源部分,通过配置一个properties文件来定义,使用key-value进行存储。
在这里插入图片描述
然后在mybatis-config.xml中进行配置,加载这个外部的properties文件。引入之后,在dataSource中,使用EL表达式来使用。
在这里插入图片描述

映射文件配置

在src→resources→mapper→usersMapper.xml中进行配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper 用于定义一个映射配置文件的根节点
namespace属性用来配置命名空间,主要进行session级别的缓存管理
命名空间默认情况下,使用当前操作的实体类的全路径(接口文件的全路径)
-->
<mapper namespace="com.damu.entity.Users">

    <select id="findAll" resultType="com.damu.entity.Users">
        select * from users
    </select>

    <select id="findById" resultType="com.damu.entity.Users">
    <!-- #{}表示占位符,相当于JDBC中的?可以达到防止sql注入的危险-->
        select * from users where id = #{id}
    </select>

</mapper>

配置完成之后,将改配置增加在mybatis-pro.xml文件中:

    <!-- mappers主要用于配置我们外部的映射配置文件
     在主配置文件中需要引入加载映射配置文件
     -->
    <mappers>
        <mapper resource="mapper/usersMapper.xml"/>
    </mappers>
</configuration>

至此为止,已经将所有的mybatis支持完整的添加到项目。可以开始写代码啦~

后端 ——编写Java代码

1.创建实体类包com.damu.entity→创建用户类实体Users.java
package com.damu.entity;

import java.util.Date;

/**
 * resources:mybatis-config.xml
 * InputStream
 * SqlSessionFactory
 * SqlSession
 * 执行配置好的SQL语句
 */
public class Users {
    private Integer id;                 // 用户编号
    private String username;            // 登录账号
    private String userpass;            // 登录密码
    private String nickname;            // 用户昵称
    private Integer age;                // 用户年龄
    private String gender;              // 用户性别
    private String phone;               // 联系方式
    private String email;               // 用户邮箱
    private Date createTime;            // 创建时间
    private Date updateTime;            // 账号最后修改时间
    private Date lastLogin;             // 用户最后登录时间
    private Integer userStatus;         // 用户账号状态 0 正常 1 锁定 2 删除
    private String remark;              // 用户备注信息

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id =
                id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username =
                username;
    }

    public String getUserpass() {
        return userpass;
    }

    public void setUserpass(String userpass) {
        this.userpass =
                userpass;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname =
                nickname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age =
                age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender =
                gender;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone =
                phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email =
                email;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime =
                createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime =
                updateTime;
    }

    public Date getLastLogin() {
        return lastLogin;
    }

    public void setLastLogin(Date lastLogin) {
        this.lastLogin =
                lastLogin;
    }

    public Integer getUserStatus() {
        return userStatus;
    }

    public void setUserStatus(Integer userStatus) {
        this.userStatus =
                userStatus;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark =
                remark;
    }
}

2.创建utils包用来管理SqlSessionFactory→创建SqlSessionFactoryUtils.java

1.SqlSessionFactoryUtils实现的功能有实现SqlSessionFactory的初始化,获取SqlSessionFactory以及关闭SqlSession。
2.由于是Web项目,因此将获取到的SqlSession放在ThreadLocalSqlSession中进行管理。属性有:private static String RESOURCE;private static SqlSessionFactory;
3.创建一个初始化SqlSessionFactory的方法。private static void initSqlSessionFactory

- 1.根据文件配置路径获得输入流,InputStream is = Resources.getResourceAsStream(RESOURCE);
- 2.使用try...catch进行异常处理。
- 3.初始化SqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

4.获取工厂对象SqlSessionFactory的方法,public static SqlSessionFactory getSqlSessionFactory;

package com.damu.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Vivian on 2019/4/4.
 */
public class SqlSessionFactoryUtils {

    private static String RESOURCE = "mybatis-config.xml";

    private static SqlSessionFactory sqlSessionFactory;

    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();

    /**
     * 创建一个初始化SqlSessionFactory的方法
     */
    public static void initSqlSessionFactory() {
        try {
            InputStream is = Resources.getResourceAsStream(RESOURCE);

            sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取工厂对象的方法
     * @return
     */
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

    /**
     * 关闭SqlSession的方法
     */
    public static void close(){
        SqlSession session = threadLocal.get();
        if(session != null) {
            session.close();
            threadLocal.set(null);
        }
    }
}

3.创建监听器包com.damu.listener→创建InitSqlSessionListener.java

编写好的listener文件中,使用标注Annotation来告知Web容器,哪些listener会提供服务以及额外的信息;

package com.damu.listener;

import com.damu.utils.SqlSessionFactoryUtils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * Created by Vivian on 2019/4/4.
 */
@WebListener
public class InitSqlSessionListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("容器加载中...");
        // 初始化我们的SqlSesionFactory对象
        SqlSessionFactoryUtils.initSqlSessionFactory();
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("容器销毁中...");
        // 关闭SqlSession对象
        SqlSessionFactoryUtils.close();
    }
}

4.创建包com.damu.dao来访问查询数据→创建UsersDAO.java
package com.damu.dao;

import com.damu.entity.Users;
import com.damu.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

/**
 * Created by Vivian on 2019/4/4.
 */
public class UsersDAO {
    private SqlSession sqlSession;
    private List<Users> list;
    private Users user;

    private SqlSession getSession() {
        sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
        return sqlSession;
    }

    /**
     * 查询全部用户
     * @return
     */
    public List<Users> findAll() {
        try {
            list = getSession().selectList("findAll");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return list;
    }

    /**
     *查询单个用户
     */
    public Users findById(Integer id) {
        try {
            user = getSession().selectOne("findById",id);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return user;

    }
}

5.创建servlet包来调用dao→创建UsersFindServlet.java

在实现所有用户的查询中,创建接口层的数据查询接口功能类文件:UsersFindServlet.class。编写好的servlet文件中,使用标注Annotation来告知Web容器,哪些servlet会提供服务以及额外的信息;在客户端进行请求的时候,如果是/index,那么就会有UsersFindServlet的servlet来处理。

package com.damu.servlet;

import com.damu.dao.UsersDAO;
import com.damu.entity.Users;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * Created by Vivian on 2019/4/4.
 */
@WebServlet("/index")
public class UsersFindServlet extends HttpServlet {

    private UsersDAO
            usersDAO = new UsersDAO();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<Users> list = usersDAO.findAll();
        System.out.println(list);
        req.setAttribute("usersList",list);
        req.getRequestDispatcher("index.jsp").forward(req,resp);
    }
}

工程目录

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值