struts 2和Hibernian 整合注册的例子

开发工具:MyEclipse 6.0 Tomcat 5.5 JDK 1.5  MySQL 5.0 ;开发准备:下载Struts 2.0Hibernate 3.2,大家可StrutsHibernate的官方网站下载这两个框架。我们先来总览一下开发完成后的包类图:

首先NEW一个Web Project ,名为"LoginSystem" ,在 lib 目录下加入Struts 2.0的Jar包和Hibernate 3.2的Jar包,然后按下面的步骤来:

    1、在 src 目录下建 "hibernate.cfg.xml" 全部代码如下:

 1 <?xml version='1.0' encoding='UTF-8'?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3           "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4           "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5
 6 <!-- Generated by MyEclipse Hibernate Tools.                   -->
 7 <hibernate-configuration>
 8     <session-factory>
 9         <property name="connection.username">root</property>
10         <property name="connection.url">
11             jdbc:mysql://localhost:3306/LoginSystem
12         </property>
13         <property name="dialect">
14             org.hibernate.dialect.MySQLDialect
15         </property>
16         <property name="myeclipse.connection.profile">
17             LoginSystem
18         </property>
19         <property name="connection.password">root</property>
20         <property name="connection.driver_class">
21             com.mysql.jdbc.Driver
22         </property>
23         <property name="show_sql">true</property>
24         <!-- POJO类映射配置 -->
25         <mapping resource="com/rong/ORM/User.hbm.xml" />
26     </session-factory>
27 </hibernate-configuration>

    2、建立实体类 "User.java" 及其映射文件 "User.hbm.xml" 两者都放在 "com.rong.ORM" 包下。其中"User.java"的代码如下:

 1 package com.rong.ORM;
 2
 3 public class User {
 4     
 5     private int id;        //主键ID
 6     private String name;    //用户名
 7     private String pwd;        //密码
 8
 9     /*
10      * Getter方法与Setter方法
11      */    
12     public String getName() {
13         return name;
14     }
15     public void setName(String name) {
16         this.name = name;
17     }
18     public String getPwd() {
19         return pwd;
20     }
21     public void setPwd(String pwd) {
22         this.pwd = pwd;
23     }
24     public int getId() {
25         return id;
26     }
27     public void setId(int id) {
28         this.id = id;
29     }
30 }

    User.hbm.xml的代码如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4
 5 <hibernate-mapping>
 6     <class name="com.rong.ORM.User" table="tb_user">
 7         <id name="id">
 8             <generator class="native"/>
 9         </id>
10         <property name="name" type="java.lang.String" length="20"/>
11         <property name="pwd" type="java.lang.String" length="20"/>
12     </class>
13 </hibernate-mapping>

3、建立"ExportDB.java"工具类,我们执行如下代码,就能轻松将User类导入数据库转变成数据库中的表。不过,前提是我们已经在MySQL中建立了一个名为"LoginSystem"的数据库。

 1 package tool;
 2
 3 import org.hibernate.cfg.Configuration;
 4 import org.hibernate.tool.hbm2ddl.SchemaExport;
 5
 6 public class ExportDB {
 7     
 8     /*
 9      * 运行此类,通过POJO类和配置文件,生成数据库的表
10      */
11     public static void main(String[] args){
12         Configuration cfg = new Configuration().configure();
13         SchemaExport export = new SchemaExport(cfg);
14         export.create(truetrue);
15     }
16 }
17

    4、建立获取SessionFactory和管理Session的HibernateUtil.java类:

 1 package com.rong.hibernate;
 2
 3 import org.hibernate.HibernateException;
 4 import org.hibernate.Session;
 5 import org.hibernate.SessionFactory;
 6 import org.hibernate.cfg.Configuration;
 7
 8 public class HibernateUtil {
 9     
10     //声明Hibernate配置文件所在的路径
11     private static String configFile = "/hibernate.cfg.xml";
12     //建Configuration对象
13     private static Configuration configuration = new Configuration();
14     //建Session工厂对象
15     private static SessionFactory sessionFactory = null;
16     
17     /**
18      * 单例模式,只初始化一次,只产生一个SessionFactory对象(线程安全)
19      */
20     static {
21         try{
22             //通过hibernate.cfg.xml配置数据库连接
23             configuration.configure(configFile);
24             //建立一个Session工厂
25             sessionFactory = configuration.buildSessionFactory();
26             System.out.println("[标记]初始化SessionFactory");
27         }catch(Exception e){
28             System.out.println("[异常]创建SessionFactory时发生异常,异常原因如下:");
29             e.printStackTrace();
30         }
31     }
32     
33     /**
34      * getSession()方法
35      * @return Session对象
36      * @throws HibernateException
37      */
38     public Session getSession(){
39         Session session = null;
40         try{
41             session = sessionFactory.openSession();
42         }catch(Exception e){
43             System.out.println("[异常]开启Session时发生异常,异常原因如下:");
44             e.printStackTrace();
45         }
46         return session;
47     }
48     
49     /**
50      * closeSession()方法
51      * @param session 要关闭的Session对象
52      */
53     public void closeSession(Session session){
54         try{
55             if(null != session)
56                 session.close();
57         }catch(Exception e){
58             System.out.println("[异常]关闭Session时发生异常,异常原因如下:");
59             e.printStackTrace();
60         }
61     }
62     
63     
64     
66 }
67

   5、DAO层设计:在"com.rong.DAO" 包下建立两个类,一个是接口,一个是实现类,其中UserDao.java代码如下:

 1 package com.rong.DAO;
 2
 3 import java.util.List;
 4 import com.rong.ORM.User;
 5
 6 public interface UserDao {
 7     
 8     /**
 9      * 增加用户
10      * @param user 要增加的用户
11      */
12     public void add(User user);
13     
14     /**
15      * 登录验证
16      * @param name
17      * @param password
18      * @return -1:不存在用户名 ; -2:密码不正确 ; >0:登录成功(即返回该记录ID)
19      */
20     public int isExist(String name,String password);    
21 }

    UserDaoImpl.java的代码如下

 1 package com.rong.DAO;
 2
 3 import java.util.Iterator;
 4 import java.util.List;
 5 import org.hibernate.Query;
 6 import org.hibernate.Session;
 7 import org.hibernate.Transaction;
 8 import com.rong.ORM.User;
 9 import com.rong.hibernate.HibernateUtil;
10
11 public class UserDaoImpl implements UserDao {
12
13     HibernateUtil util = new HibernateUtil();
14     
15     /**
16      * 增加用户
17      * @param user 要增加的用户
18      */
19     public void add(User user){
20         Session session = util.getSession();
21         Transaction ts = null;
22         try{
23             ts = session.beginTransaction();
24             session.save(user);
25             ts.commit();
26         }catch(Exception e){
27             System.out.println("UserDaoImpl.add()方法发生异常:");
28             e.printStackTrace();
29         }finally{
30             util.closeSession(session);
31         }
32     }
33     
34     /**
35      * 登录验证
36      * @param name
37      * @param password
38      * @return -1:不存在用户名 ; -2:密码不正确 ; >0:登录成功(即返回该记录ID)
39      */
40     public int isExist(String name,String password){
41         //int state = 0 ;        //初始化状态变量
42         Session session = util.getSession();
43         try{
44             Query query = session.createQuery("from User u where u.name = ?");
45             query.setString(0, name);
46             List list = query.list();
47             if(null == list || 0 == list.size()){
48                 return -1 ;     //用户名不存在
49             }
50             Query query2 = session.createQuery("from User u where u.name = ? and u.pwd = ?");
51             query2.setString(0, name);
52             query2.setString(1, password);
53             List list2 = query.list();
54             if(null == list2){
55                 return -2 ;        //密码不正确
56             }
57             Iterator it = list.iterator();
58             User user = (User)it.next();
59             return user.getId();    //验证成功,取ID值
60             
61         }catch(Exception e){
62             System.out.println("UserDaoImpl.isExist()方法发生异常:");
63             e.printStackTrace();
64             return 0;    //异常时返回0
65         }finally{
66             util.closeSession(session);
67         }
68     }
69 }
70

  6、在web.xml中配置Struts 2.0支持:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 5     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 6
 7     <!-- 用过滤器配置Struts2支持 -->
 8     <filter>
 9         <filter-name>struts2</filter-name>
10         <filter-class>
11             org.apache.struts2.dispatcher.FilterDispatcher
12         </filter-class>
13     </filter>
14     <filter-mapping>
15         <filter-name>struts2</filter-name>
16         <url-pattern>/*</url-pattern>
17     </filter-mapping>
18
19     <welcome-file-list>
20         <welcome-file>login.jsp</welcome-file>
21     </welcome-file-list>
22 </web-app>

    7、登录页面login.jsp代码如下:

 1 <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
 2 <%@ taglib prefix="s" uri="/struts-tags" %>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5     <head>
 6
 7         <title>Login Page</title>
 8     </head>
 9
10     <body>
11         <p><href="register.jsp">用户注册</a>|用户登录</p>
12                 <s:form action="loginAction" theme="simple">
13             <table>
14                 <tr>
15                     <td style="text-align:right">
16                         账号
17                     </td>
18                     <td>
19                         <s:textfield name="name" label="账号" />
20
21                     </td>
22                 </tr>
23                 <tr>
24                     <td style="text-align:right">
25                         密码
26                     </td>
27                     <td>
28                         <s:password name="pwd" label="密码" />
29                     </td>
30                 </tr>
31                 <tr>
32                     <td style="text-align:right">
33                         验证码
34                     </td>
35                     <td>
36                         <s:textfield name="inputCertCode" label="验证码" cssStyle="width:100px"/>
37                         <img src="other/makeCertPic.jsp">
38                     </td>
39                 </tr>
40                 <tr>
41                     <td style="text-align:right">
42                         <s:submit value="登录" />
43                     </td>
44                     <td style="text-align:left">
45                         <s:reset value="取消"/>
46                     </td>
47                 </tr>
48             </table>
49         </s:form>
50         <s:fielderror cssStyle="color:red"/>
51     </body>
52 </html>
53

    注册页register.jsp代码如下

 1 <%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
 2 <%@ taglib prefix="s" uri="/struts-tags"%>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5     <head>
 6
 7         <title>Register Page</title>
 8     </head>
 9
10     <body>
11         <p><href="login.jsp">用户登录</a>|用户注册</p>
12         <s:form action="registerAction" theme="simple">
13             <table>
14                 <tr>
15                     <td style="text-align:right">
16                         请输入账号
17                     </td>
18                     <td>
19                         <s:textfield name="user.name" label="账号" />
20
21                     </td>
22                 </tr>
23                 <tr>
24                     <td style="text-align:right">
25                         请输入密码
26                     </td>
27                     <td>
28                         <s:password name="user.pwd" label="密码" />
29                     </td>
30                 </tr>
31                 <tr>
32                     <td style="text-align:right">
33                         请再次输入密码
34                     </td>
35                     <td>
36                         <s:password name="repwd" label="重复密码" />
37                     </td>
38                 </tr>
39                 <tr>
40                     <td style="text-align:right">
41                         请输入验证码
42                     </td>
43                     <td>
44                         <s:textfield name="inputCertCode" label="验证码" cssStyle="width:100px"/>
45                         <img src="other/makeCertPic.jsp">
46                     </td>
47                 </tr>
48                 <tr>
49                     <td style="text-align:right">
50                         <s:submit value="注册" />
51                     </td>
52                     <td style="text-align:left">
53                         <s:reset value="取消"/>
54                     </td>
55                 </tr>
56             </table>
57         </s:form>
58         <s:fielderror cssStyle="color:red"/>
59     </body>
60 </html>
61

  8、在JSP页中所用到的验证码的生成页面makeCertPic.jsp(我们把它放在WebRoot的other目录下):

1 <%@page contentType="image/jpeg" pageEncoding="gbk"%>
2 <jsp:useBean id="image" scope="page" class="com.rong.other.makeCertPic" />
3 <%
4     String str = image.getCertPic(0,0,response.getOutputStream());
5     // 将验证码保存到Session中
6     session.setAttribute("certCode", str); 
7 %>

    其中,它调用了名为makeCertPic的Bean ,这个类主要用来生成彩色的验证图片,其代码如下:

 1 package com.rong.other;
 2 import java.awt.Color;
 3 import java.awt.Font;
 4 import java.awt.Graphics;
 5 import java.awt.image.BufferedImage;
 6 import java.io.IOException;
 7 import java.io.OutputStream;
 8 import java.util.Random;
 9 import javax.imageio.ImageIO;
10 /**
11  * 生成验证码图片
12  */
13 public class makeCertPic {
14     //验证码图片中可以出现的字符集,可根据需要修改
15     private char mapTable[]={
16             'a','b','c','d','e','f',
17             'g','h','i','j','k','l',
18             'm','n','o','p','q','r',
19             's','t','u','v','w','x',
20             'y','z','0','1','2','3',
21             '4','5','6','7','8','9'};
22     /**
23      * 功能:生成彩色验证码图片
24      * 参数width为生成的图片的宽度,参数height为生成的图片的高度,参数os为页面的输出流
25      */
26     public String getCertPic(int width, int height, OutputStream os) {
27         if(width<=0)width=60;
28         if(height<=0)height=20;    
29         BufferedImage image = new BufferedImage(width, height, 
30                                     BufferedImage.TYPE_INT_RGB); 
31         // 获取图形上下文 
32         Graphics g = image.getGraphics(); 
33         // 设定背景色 
34         g.setColor(new Color(0xDCDCDC)); 
35         g.fillRect(0, 0, width, height); 
36         //画边框 
37         g.setColor(Color.black); 
38         g.drawRect(0,0,width-1,height-1); 
39         // 取随机产生的认证码
40         String strEnsure = "";
41         // 4代表4位验证码,如果要生成更多位的认证码,则加大数值
42         for(int i=0; i<4; ++i) {
43             strEnsure += mapTable[(int)(mapTable.length*Math.random())];
44         }        
45         // 将认证码显示到图象中,如果要生成更多位的认证码,增加drawString语句
46         g.setColor(Color.black); 
47         g.setFont(new Font("Atlantic Inline",Font.PLAIN,18)); 
48         String str = strEnsure.substring(0,1); 
49         g.drawString(str,8,17);     
50         str = strEnsure.substring(1,2); 
51         g.drawString(str,20,15); 
52         str = strEnsure.substring(2,3); 
53         g.drawString(str,35,18);         
54         str = strEnsure.substring(3,4); 
55         g.drawString(str,45,15); 
56         // 随机产生10个干扰点
57         Random rand = new Random();
58         for (int i=0;i<10;i++) { 
59             int x = rand.nextInt(width); 
60             int y = rand.nextInt(height); 
61             g.drawOval(x,y,1,1); 
62         } 
63         // 释放图形上下文
64         g.dispose();         
65         try {
66             // 输出图象到页面 
67             ImageIO.write(image, "JPEG", os);
68         } catch (IOException e) {
69             return "";
70         }        
71         return strEnsure;
72     }
73 }
74

  9、此时,我们很有必要来配置一下struts.xml其全部代码如下

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE struts PUBLIC
 3         "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
 4         "http://struts.apache.org/dtds/struts-2.0.dtd">
 5
 6 <struts>
 7
 8     <package name="com.rong.action" extends="struts-default">
 9         <!-- 用户登录 -->
10         <action name="loginAction" class="com.rong.action.LoginAction">
11             <result name="success" type="redirect">/back/index.jsp</result>
12             <result name="input">/login.jsp</result>
13         </action>
14         <!-- 用户注册 -->
15         <action name="registerAction" class="com.rong.action.RegisterAction">
16             <result name="success" type="redirect">/login.jsp</result>
17             <result name="input">/register.jsp</result>
18         </action>
19     </package>
20 </struts>

    10、Action层设计:两个非常关键的类,其中LoginAction.java的代码如下:

 1 package com.rong.action;
 2
 3 import java.util.Map;
 4 import com.opensymphony.xwork2.ActionContext;
 5 import com.opensymphony.xwork2.ActionSupport;
 6 import com.rong.DAO.UserDao;
 7 import com.rong.DAO.UserDaoImpl;
 8 import com.rong.ORM.User;
 9
10 public class LoginAction extends ActionSupport {
11     
12     
13     private UserDao userDao = new UserDaoImpl();    //操纵数据库DAO类(Hibernate实现),通过Struts.xml注入值
14     
15     private int id;
16     private String name;    //用户名(值由struts注入)
17     private String pwd;        //密码(值由struts注入)
18     
19     private String inputCertCode;    //验证码
20
21     public int getId() {
22         return id;
23     }
24     public void setId(int id) {
25         this.id = id;
26     }
27     public String getName() {
28         return name;
29     }
30     public void setName(String name) {
31         this.name = name;
32     }
33     public String getPwd() {
34         return pwd;
35     }
36     public void setPwd(String pwd) {
37         this.pwd = pwd;
38     }
39
40     public String getInputCertCode() {
41         return inputCertCode;
42     }
43     public void setInputCertCode(String inputCertCode) {
44         this.inputCertCode = inputCertCode;
45     }
46     @Override
47     public String execute() throws Exception {
48         int state = userDao.isExist(name,pwd);
49         System.out.println("state="+state);
50         if(state == -1){
51             this.addFieldError("name", "用户名不正确,请先注册!");
52             return INPUT;
53         }else if(state == -2){
54             this.addFieldError("pwd", "密码不正确,请重新输入密码!");
55             return INPUT;
56         }else if(state > 0){
57             System.out.println("[测试]登录成功!用户ID="+state);
58             this.setId(state);
59             return SUCCESS;
60         }else{
61             this.addFieldError("name", "登录失败,请与管理员联系!");
62             return INPUT;
63         }
64     }
65     
66     public void validate() {
67         //验证码验证
68         if(null == inputCertCode || "".equals(inputCertCode)){
69             this.addFieldError("inputCertCode", "验证码不能为空!");
70         }else{
71             Map session = ActionContext.getContext().getSession();
72             String certCode = session.get("certCode").toString();
73             if( ! certCode.equals(this.inputCertCode)){
74                 this.addFieldError("inputCertCode", "验证码不正确!");
75             }
76         }
77         
78     }
79     
80     
81     
82
83 }
84

    RegisterAction.java的代码如下:

 1 package com.rong.action;
 2
 3 import java.util.Map;
 4
 5 import com.opensymphony.xwork2.ActionContext;
 6 import com.opensymphony.xwork2.ActionSupport;
 7 import com.rong.DAO.UserDao;
 8 import com.rong.DAO.UserDaoImpl;
 9 import com.rong.ORM.User;
10
11 public class RegisterAction extends ActionSupport {
12
13     private UserDao userDao = new UserDaoImpl();
14
15     private User user;    //注册提交的用户对象
16     
17     private String repwd;    //重复密码
18     
19     private String inputCertCode;    //验证码
20
21     public User getUser() {
22         return user;
23     }
24
25     public void setUser(User user) {
26         this.user = user;
27     }
28
29     public String getRepwd() {
30         return repwd;
31     }
32
33     public void setRepwd(String repwd) {
34         this.repwd = repwd;
35     }
36
37     public String getInputCertCode() {
38         return inputCertCode;
39     }
40
41     public void setInputCertCode(String inputCertCode) {
42         this.inputCertCode = inputCertCode;
43     }
44
45     @Override
46     public String execute() throws Exception {
47         User user = new User();
48         userDao.add(user);        //保存注册的user对象
49         return SUCCESS;
50     }
51
52     @Override
53     public void validate() {
54         //验证码验证
55         if(null == inputCertCode || "".equals(inputCertCode)){
56             this.addFieldError("inputCertCode", "验证码不能为空!");
57         }else{
58             Map session = ActionContext.getContext().getSession();
59             String certCode = session.get("certCode").toString();
60             if( ! certCode.equals(this.inputCertCode)){
61                 this.addFieldError("inputCertCode", "验证码不正确!");
62             }
63         }
64         
65     }
66         
67 }
68

  11、不要忘记配置校验框架,与上面两个Action同一个目录下。LoginAction-validation.xml代码如下:

 1 <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
 2     "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
 3
 4 <validators>
 5     <!-- 用户名验证 -->
 6     <field name="name">
 7         <field-validator type="requiredstring">
 8             <param name="trim">true</param>
 9             <message>用户名不能为空!</message>
10         </field-validator>
11         <field-validator type="regex">
12             <param name="expression"><![CDATA[(/w{4,8})]]></param>
13             <message>账号必须是长度为4-8的数字或字母!</message>
14         </field-validator>
15     </field>
16     <!-- 密码验证 -->
17     <field name="pwd">
18         <field-validator type="requiredstring">
19             <param name="trim">true</param>
20             <message>密码不能为空!</message>
21         </field-validator>
22         <field-validator type="regex">
23             <param name="expression"><![CDATA[(/w{4,8})]]></param>
24             <message>密码必须长度为4-8的数字或字母!</message>
25         </field-validator>
26     </field>
27
28 </validators>

    RegisterAction-validation.xml代码如下:

 1 <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
 2     "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
 3
 4 <validators>
 5
 6     <!-- 用户名验证 -->
 7     <field name="user.name">
 8         <field-validator type="requiredstring">
 9             <param name="trim">true</param>
10             <message>用户名不能为空!</message>
11         </field-validator>
12         <field-validator type="regex">
13             <param name="expression"><![CDATA[(/w{4,8})]]></param>
14             <message>账号必须是长度为4-8的数字或字母!</message>
15         </field-validator>
16     </field>
17     
18     <!-- 密码验证 -->
19     <field name="user.pwd">
20         <field-validator type="requiredstring">
21             <param name="trim">true</param>
22             <message>密码不能为空!</message>
23         </field-validator>
24         <field-validator type="regex">
25             <param name="expression"><![CDATA[(/w{4,8})]]></param>
26             <message>密码必须长度为4-8的数字或字母!</message>
27         </field-validator>
28     </field>
29     
30     <field name="repwd">
31         <field-validator type="requiredstring" short-circuit="true">
32             <param name="trim">true</param>
33             <message>重复密码不能为空!</message>
34         </field-validator>
35         <field-validator type="fieldexpression">
36             <param name="expression"><![CDATA[(repwd==user.pwd)]]></param>
37             <message>两次输入的密码要一致!</message>
38         </field-validator>
39     </field>
40     
41 </validators>

    到这里,我们的项目也差不多完成了,大家自己也尝试一下,开发出自己的J2EE系统。

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值