SSM框架整合个人博客(一)

SSM框架整合总结(一)

1.SSM:spring、springMVC、mybatis三大框架

1.1 spring:IOC、DI. aop。

1.1.1 IOC:控制翻转,将对象委托给spring进行统一管理。在application.xml文件中进行配置。或者利用@Service、@Controller等注解进行自动配置。配置过程是spring对注解进行扫描后,对扫描到的注解类进行管理。

1.1.2 DI:依赖注入:我们需要声明一个对象类型的数据,spring会通过注解或者xml配置,将对象注入到这个类型数据。

1.1.3 AOP:面向切面编程:面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。

除了类(classes)以外,AOP提供了切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。Spring的一个关键的组件就是AOP框架,可以自由选择是否使用AOP。

提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明性事务管理,这个服务建立在Spring的抽象事物管理之上。

允许用户实现自定义切面,用AOP来完善OOP的使用可以把Spring AOP看作是对Spring的一种增强。

1.2 SpringMVC:网站访问流程控制单元。针对前后端数据交互提供了方便的访问机制。原始访问需要不断的发送request请求,而springMVC封装了后台跳转控制,提供了更为简单的跳转流程。

1.3 mybatis:一个轻量级的数据访问层框架。负责后端与数据库之间的交互。

2.所需jar包

2.1 spring 、springMVC、mybatis、数据库连接池、驱动包。

2.1.1 spring jdbc、spring Aspact、springMVC。

2.1.2 mybatis

2.1.3 mybatis spring适配包

2.1.4 数据库连接池与驱动 c3p0数据库连接池。mysql connection j驱动包

2.1.5 jstl 、serverlt apiproviede已经有了、junit测试包

2.1.6. mybatis Generator core mybatis逆向工程生成支持

2.1.7 spring test spring单元测试模块

3. 配置文件:mybatis-config.xml/ applicationContext.xml/springMvc.xml/web.xml

3.1 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- @version $Id: applicationContext.xml 561608 2007-08-01 00:33:12Z vgritsenko $ -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:configurator="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd"
>
<!--  除了controller控制器不扫其他的都扫 -->
  <context:component-scan base-package="com.tree">
      <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  </context:component-scan>

  <!-- 引入数据库相关配置文件 -->
  <context:property-placeholder location="classpath:jdbc.properties"/>

  <!-- 配置数据源 -->
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}" />
    <property name="jdbcUrl" value="${jdbc.url}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />

<!--    &lt;!&ndash; 初始化连接大小 &ndash;&gt;-->
<!--    <property name="initialPoolSize" value="${initialSize}"/>-->
<!--    &lt;!&ndash; 连接池最大数量 &ndash;&gt;-->
<!--    <property name="maxPoolSize" value="${maxActive}"/>-->
<!--    &lt;!&ndash; 连接池最大空闲 &ndash;&gt;-->
<!--    <property name="maxIdleTime" value="${maxIdle}"/>-->
<!--    &lt;!&ndash; 连接池最小空闲 &ndash;&gt;-->
<!--    <property name="minPoolSize" value="${minIdle}"/>-->
<!--    &lt;!&ndash; 获取连接最大等待时间 &ndash;&gt;-->
<!--    <property name="maxIdleTimeExcessConnections" value="${maxWait}"/>-->
  </bean>

<!--   配置mybatis的整合 sqlSessionFactory 工厂-->
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--    指定mybatis全局配置文件位置-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--    指定数据源配置-->
    <property name="dataSource" ref="dataSource" />
    <!-- 指定mybatis mappers.xml文件位置 -->
    <property name="mapperLocations">
      <list>
        <value>classpath*:mappers/*.xml</value>
      </list>
    </property>
  </bean>
<!-- 配置扫描器,将mybatis接口的实现加入到IOC容器中 -->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--    扫描所有dao接口的实现加入到IOC容器中 -->
    <property name="basePackage" value="com.tree.dao" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  </bean>

  <!--  配置一个可以执行批量执行sqlSession-->
  <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
    <constructor-arg name="executorType" value="BATCH"/>
  </bean>



  <!-- 配置事务管理 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 控制数据源 -->
    <property name="dataSource" ref="dataSource" />
  </bean>
<!--开启基于注解的事物管理或者xml管理的事务管理,比较重要的就是使用配置形式-->
  <aop:config>
<!--    切入点表达式 -->
    <aop:pointcut id="txPoint"  expression="execution(* com.tree.service..*(..))" />
<!--    配置事务增强 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint" />
  </aop:config>
  <!-- 配置事务通知 -->
  <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 定义事务传播属性 -->
    <tx:attributes>
      <tx:method name="insert*" propagation="REQUIRED" />
      <tx:method name="update*" propagation="REQUIRED" />
      <tx:method name="edit*" propagation="REQUIRED" />
      <tx:method name="save*" propagation="REQUIRED" />
      <tx:method name="add*" propagation="REQUIRED" />
      <tx:method name="new*" propagation="REQUIRED" />
      <tx:method name="set*" propagation="REQUIRED" />
      <tx:method name="remove*" propagation="REQUIRED" />
      <tx:method name="delete*" propagation="REQUIRED" />
      <tx:method name="change*" propagation="REQUIRED" />
      <tx:method name="check*" propagation="REQUIRED" />
      <tx:method name="get*" propagation="REQUIRED" read-only="true" />
      <tx:method name="find*" propagation="REQUIRED" read-only="true" />
      <tx:method name="load*" propagation="REQUIRED" read-only="true" />
      <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" rollback-for="java.lang.Exception" read-only="true" />
    </tx:attributes>
  </tx:advice>
</beans>

3.2 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>
    <!-- 配置全局属性 -->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />

        <!-- 使用列别名替换列名 -->
        <!-- <setting name="useColumnLabel" value="true"/> -->

        <!-- 开启驼峰命名转换(userId === user_id) -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>

    <!-- 取别名,比如一个方法中返回值类型是User,
             配置了这个在 parameterType属性中就不用写User的全类名,
            直接写User即可,可以在这里配置,也可以再spring配置文件中配置 -->
    <!-- <typeAliases> <package name="com.zhu.smm.entity"/> </typeAliases> -->
    <typeAliases><package name="com.tree.model"/></typeAliases>
    
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>

<!--    <typeAlias</typeAliases>-->
</configuration>

3.3 springmvc-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc   http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!--  扫描包配置,只扫描控制器-->
    <context:component-scan base-package="com.tree" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>



    <!-- 同时开启json格式的支持 -->
    <mvc:annotation-driven/>

    <!-- 静态资源放行 -->
<!--    <mvc:resources mapping="/css/**" location="/static/login/css"/>-->
<!--    <mvc:resources mapping="/img/**" location="/static/login/img"/>-->
<!--    <mvc:resources mapping="/js/**" location="/static/login/js"/>-->
    <mvc:default-servlet-handler/>
    <mvc:resources mapping="/static/**" location="/static/"></mvc:resources>

<!--    <mvc:resources mapping="/css/**" location="/static/blog/css"/>-->



    <!-- 视图解析器 -->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="WEB-INF/" />
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 两个标准 -->
    <!-- 将springMVC不能处理的的请求交给tomcat   -->
    <mvc:default-servlet-handler/>
    <!-- 能支持springMVC更高级的功能,JSR303校验,快捷ajax请求,映射动态请求   -->
    <mvc:annotation-driven/>
<!--文件上传解析器-->
    <bean id="multiparResolver" class="org.springframework.web.multipart.commons.CommonsFileUploadSupport"
          abstract="true">
        <property name="maxUploadSize" value="2097152"/>
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="uploadTempDir" value="classpath:uploadFile"/>
<!--        <property name=""-->
    </bean>
<!--    <bean class="org.springframework.web.servlet.view.">-->


</beans>

3.4 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
version="4.0"
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">

<display-name>Archetype Created Web Application</display-name>
    <!-- 启动spring容器-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- 项目启动监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <!-- 字符编码过滤器 -->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <!--    <servlet-name>springmvc</servlet-name>-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <!-- springMVC前端控制器,拦截所有请求 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--    / 拦截所有请求,包括静态资源请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--  使用Rest风格的URI  将页面普通的post或者get请求转换为delete 、put请求 -->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
<!--    对静态资源进行放行 -->
<!--    <servlet-mapping>-->
<!--        <servlet-name>default</servlet-name>-->
<!--        <url-pattern>*.js</url-pattern>-->
<!--        <url-pattern>*.css</url-pattern>-->
<!--        <url-pattern>*.jpg</url-pattern>-->
<!--    </servlet-mapping>-->

    <welcome-file-list>
        <welcome-file>/WEB-INF/index.html</welcome-file>
        <welcome-file>/WEB-INF/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
4. 遇到的问题:

4.1 jdbc加载时区问题解决办法:

 connectionURL="jdbc:mysql://localhost:3306/AtCrowdfunding?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"

4.2 springmvc 加载不到静态资源的问题:

解决:在springMVC配置文件当中添加:

  <mvc:default-servlet-handler/>
    <mvc:resources mapping="/static/**" location="/static/"></mvc:resources>

此配置的目的是放行webapp目录下,static文件下的所有文件。

<link rel="stylesheet" type="text/css" href="static/login/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet" type="text/css" href="static/login/css/my-login.css"/>

此配置是在前端页面中使用的路径格式。

4.3 页面访问地址设置:

遇到问题:在页面当中,通过以下访问控制器时,在地址栏中会报404错误,此时需要设置动态访问

/loginSubmit
${pageContext.request.contextPath}/loginSubmit

通过${pageContext.request.contextPath}/loginSubmit进行访问后,就会在地址栏出现项目名称。

4.4

Parameter 'useranme' not found. Available parameters are [arg1, arg0, param1, param2]

解决办法:

int findUserByNameAndPwd(@Param("username")String username,@Param("password")String password);

@Param参数解释:在Dao层Mapper接口中,如果参数是1个mybatis会自动匹配参数,如果参数超过1个,则需要对参数进行@Param("") 标识,以供mybatis进行参数识别。

4.5 关于mybatis参数传递的可能性分析。

整合了SSM框架之后,需要获取到前台数据。根据代码可以看出,我直接从参数中获取到了前台页面中提交的数据。所以,我猜测springMVC对前台表单或者任何方式提交的数据都进行了封装,只需要从封装过的数据集合当中获取数据即可。

 @RequestMapping("/loginSubmit")
    public String loginSubmit(String username,String password){
        System.out.println(username);
        System.out.println(password);

这段代码会在控制台输出用户名和密码。已经得到密码。

4.6 在SSM中利用HttpSession域进行数据存取:

  @RequestMapping("/ajaxLogin")
    public Object ajaxLogin(User user, Model model, HttpSession session){
       int result= loginService.findUserByNameAndPassword(user.getUsername(),user.getPassword());
        AjaxMessage ajaxMessage=new AjaxMessage();
//        System.out.println(result);
       if(result>0){
        ajaxMessage.setLoginMessage(true);
        session.setAttribute("username",user.getUsername());
       }else{

4.7

关于加载文本编辑器插件遇到的问题:因为将调用放置在引入之前,倒置js加载错误。迟迟加载不到编辑器。

4.8. SSM框架获取地址栏传输数据:

<a href="${pageContext.request.contextPath}/blogById?id=${blog.blogId}">

控制层获取数据:

    @RequestMapping("/blogById")
    public String blogJump(Model model,Integer id){
        Blog blog=blogService.selectByPrimaryKey(id);
        model.addAttribute("blogByID",blog);
        return "blog/blog";
    }

以上可见SSM框架数据传输进后台封装的严密性。

4.9 Ajax传输数据前端发送与后端接收

  function doLogin() {
        var loadingIndex = null;
        var username = $("#email").val();
        var password = $("#password").val();
        $.ajax({
            type: 'POST',
            url: 'ajaxLogin',
            data: {
                "username": username,
                "password": password
            },
            beforeSend: function () {
                loadingIndex = layer.msg("处理中", {icon: 16})
            },
            success: function (result) {
                // alert(result);  这里用返回对象直接调用对象的属性进行验证
                // alert(result.loginMessage);
                if (result.loginMessage) {
                    layer.close(loadingIndex);
                    window.location.href = "${pageContext.request.contextPath}/backstage_index";
                } else {
                    layer.msg("用户名或者密码错误,请重新输入", {time:1000,icon: 16}, function () {

                    })
                }
            }
        });
    }

后端接收:

  @ResponseBody
    @RequestMapping("/ajaxLogin")
    public Object ajaxLogin(User user, Model model, HttpSession session){
//        String username=user.getUsername();
//        String password=user.getPassword();
//        System.out.println(username+password);
       int result= loginService.findUserByNameAndPassword(user.getUsername(),user.getPassword());
        AjaxMessage ajaxMessage=new AjaxMessage();
//        System.out.println(result);
       if(result>0){
        ajaxMessage.setLoginMessage(true);
        session.setAttribute("username",user.getUsername());
       }else{
           ajaxMessage.setLoginMessage(false);
       }
        return ajaxMessage;

    }
}

5.0 mybatis逆向工程:

<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <context id="simple" targetRuntime="MyBatis3Simple">

        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
<!--        配置数据库连接信息-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/blog?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=UTF-8"
                        userId="root" password="123456"
        />
<!--    指定javaBean生成的位置 -->
        <javaModelGenerator targetPackage="com.tree.model" targetProject="./src/main/java"/>
<!--指定sql映射文件生成位置 -->
        <sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources"/>
<!-- 指定dao接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.tree.dao" targetProject="src/main/java"/>
<!--指定每个表的生成策略-->
<!--        <table tableName="t_user" domainObjectName="User" />-->
<!--        <table tableName="t_blog" domainObjectName="Blog"/>-->
<!--        <table tableName="t_img" domainObjectName="img"/>-->
        <table tableName="t_blog_classify" domainObjectName="Classify"/>

    </context>
</generatorConfiguration>
package com.tree.test;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MBGTest {
    public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("mbg.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

导包:

    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.4.0</version>
    </dependency>
5. 没能解决的问题以及可能的问题分析

5.1 页面跳转过慢问题。可能性分析:页面跳转是通过springMVC DispatcherServlet进行流程控制,当页面发送一个请求时,经过SpringMVC进行转发至后台Controller控制器进行跳转控制。每当发生一次跳转请求,都会在后台进行跳转控制,跳转到前台页面时,浏览器会加载前台资源。这里不能对前台资源加载或者后台跳转延迟进行时间测量,否则将会得到跳转缓慢是发生在前台或者后台。此为待解决问题。

此问题在过去几天莫名其妙结束了

5.2 每次重启tomcat时,如果不设置欢迎页面,那么网页就没有去处。如果设置成index.html/index.jsp那么服务器好像会直接访问index.jsp静态页面,不会通过springMVC进行后台跳转控制,如果不进行后台跳转那前台就接收不到后台发送的数据,此问题如何解决??

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值