【SSM】3. SSM项目的详细配置(使用maven工程+配置类方法)

4 篇文章 0 订阅
2 篇文章 0 订阅

1 添加依赖

  • 在项目下的pom.xml里面设置打包方式为pom
    <packaging>pom</packaging>
  • 在项目下的pom.xml里面加入需要的依赖
     <!-- ssm整合需要的所有的依赖 -->
        <properties>
            <spring.version>6.0.6</spring.version>
            <jakarta.annotation-api.version>2.1.1</jakarta.annotation-api.version>
            <jakarta.jakartaee-web-api.version>9.1.0</jakarta.jakartaee-web-api.v ersion>
            <jackson-databind.version>2.15.0</jackson-databind.version>
            <hibernate-validator.version>8.0.0.Final</hibernate-validator.version>
            <mybatis.version>3.5.11</mybatis.version>
            <mysql.version>8.0.25</mysql.version>
            <pagehelper.version>5.1.11</pagehelper.version>
            <druid.version>1.2.8</druid.version>
            <mybatis-spring.version>3.0.2</mybatis-spring.version>
            <jakarta.servlet.jsp.jstl-api.version>3.0.0</jakarta.servlet.jsp.jstl-api.version>
            <logback.version>1.2.3</logback.version>
            <lombok.version>1.18.26</lombok.version>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        <!--
           需要依赖清单分析:
              spring
                ioc/di
                  spring-context / 6.0.6
                  jakarta.annotation-api / 2.1.1  jsr250
                aop
                  spring-aspects / 6.0.6
                tx
                  spring-tx  / 6.0.6
                  spring-jdbc / 6.0.6
    
              springmvc
                 spring-webmvc 6.0.6
                 jakarta.jakartaee-web-api 9.1.0
                 jackson-databind 2.15.0
                 hibernate-validator / hibernate-validator-annotation-processor 8.0.0.Final
    
              mybatis
                 mybatis  / 3.5.11
                 mysql    / 8.0.25
                 pagehelper / 5.1.11
    
              整合需要
                 加载spring容器 spring-web / 6.0.6
                 整合mybatis   mybatis-spring x x
                 数据库连接池    druid / x
                 lombok        lombok / 1.18.26
                 logback       logback/ 1.2.3
        -->
    
        <dependencies>
            <!--spring pom.xml依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>jakarta.annotation</groupId>
                <artifactId>jakarta.annotation-api</artifactId>
                <version>${jakarta.annotation-api.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
    
            <!--
               springmvc
                   spring-webmvc 6.0.6
                   jakarta.jakartaee-web-api 9.1.0
                   jackson-databind 2.15.0
                   hibernate-validator / hibernate-validator-annotation-processor 8.0.0.Final
            -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>jakarta.platform</groupId>
                <artifactId>jakarta.jakartaee-web-api</artifactId>
                <version>${jakarta.jakartaee-web-api.version}</version>
                <scope>provided</scope>
            </dependency>
    
            <!-- jsp需要依赖! jstl-->
            <dependency>
                <groupId>jakarta.servlet.jsp.jstl</groupId>
                <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
                <version>${jakarta.servlet.jsp.jstl-api.version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson-databind.version}</version>
            </dependency>
    
    
            <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
            <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>${hibernate-validator.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
            <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator-annotation-processor</artifactId>
                <version>${hibernate-validator.version}</version>
            </dependency>
    
    
            <!--
              mybatis
                   mybatis  / 3.5.11
                   mysql    / 8.0.25
                   pagehelper / 5.1.11
            -->
            <!-- mybatis依赖 -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
    
            <!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>${pagehelper.version}</version>
            </dependency>
    
            <!-- 整合第三方特殊依赖 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>${mybatis-spring.version}</version>
            </dependency>
    
            <!-- 日志 , 会自动传递slf4j门面-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
    
        </dependencies>
    
  • 配置日志
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration debug="true">
       <!-- 指定日志输出的位置,ConsoleAppender表示输出到控制台 -->
       <appender name="STDOUT"
                 class="ch.qos.logback.core.ConsoleAppender">
           <encoder>
               <!-- 日志输出的格式 -->
               <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
               <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
               <charset>UTF-8</charset>
           </encoder>
       </appender>
    
       <!-- 设置全局日志级别。日志级别按顺序分别是:TRACE、DEBUG、INFO、WARN、ERROR -->
       <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
       <root level="DEBUG">
           <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
           <appender-ref ref="STDOUT" />
       </root>
    
       <!-- 根据特殊需求指定局部日志级别,可也是包名或全类名。 -->
       <logger name="com.example.mybatis" level="DEBUG" />
    </configuration>
    
  • 新建module,module下面的pom.xml文件里设置打包方式为war
    <packaging>war</packaging>
  • 设置webapp:在左上角project structure-> module中,选中相应的模块,点击左上角的加号,增加“web”模块
    • Web Module Deployment Descriptor添加为……\src\main\webapp\WEB-INF\web.xml
    • Web Resource Directory设置为……\src\main\webapp
      在这里插入图片描述

2 控制层配置类

控制层的配置类,需要配置controllerSpringMVC
在src文件的自己的包(如com.example)下建包config,新建WebJavaConfig.java

  • 声明@Configuration注解,代表配置类

  • 实现implements接口WebMvcConfigurer

  • 实现功能与对应方式

    实现功能方式
    controller@ComponentScan({“com.example.controller”})
    全局异常处理器@ComponentScan({“com.example.exceptionhandler”})
    handlerMapping,handlerAdapter@EnableWebMvc
    静态资源处理configurer.enable()
    视图解析器前后缀registry.jsp(“/WEB-INF/views/”,“jsp”)
    json转换器registry.addInterceptor(new XXInterceptor()).addPathPatterns(“”).excludePathPatterns(“”)
    拦截器@EnableWebMvc
  • 实现代码

    @Configuration
    @EnableWebMvc
    @ComponentScan({"com.example.controller","com.example.exceptionhandler"})
    public class WebMvcJavaConfig implements WebMvcConfigurer {
        //静态资源处理
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
        //视图解析器
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            registry.jsp("/WEB-INF/views/","jsp");
        }
        //拦截器
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    //        registry.addInterceptor(new XXInterceptor()).addPathPatterns("").excludePathPatterns("");
        }
    }
    

3 业务层配置类

业务层配置类:需要配置service,aop,tx
在src文件下的包(如com.example)-> config,新建ServiceJavaConfig.java

  • 声明@Configuration注解,代表配置类

  • 实现功能与对应方式

    实现功能方式
    service@ComponentScan(“com.example.service”)
    aop代理@EnableAspectJAutoProxy
    tx事务管理@EnableTransactionManagement
    指定具体的事务管理器transactionManager(DataSource dataSource)
  • 注意:其中TransactionManager(DataSource dataSource)需要注入连接池(配置mybatis的配置类后IOC可以自动注入)

  • 实现代码

    @EnableTransactionManagement
    @EnableAspectJAutoProxy
    @Configuration
    @ComponentScan("com.example.service")
    public class ServiceJavaConfig {
        
        @Bean
        public DataSourceTransactionManager transactionManager(DataSource dataSource){
            DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
            transactionManager.setDataSource(dataSource);
            return transactionManager;
        }
    }
    

4 持久层配置类

配置mapper代理对象,连接池和mybatis核心组件配置
mybatis之前自己调用官方api使用的核心方法有:

//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");

//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);

//3.创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取mapper代理对象
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//5.数据库方法调用
int rows = empMapper.deleteEmpById(1);
System.out.println("rows = " + rows);
//6.提交和回滚
sqlSession.commit();
sqlSession.close();

注意:

  • 其中事务的提交也可以使用sqlSessionFactory.openSession(true)来自动提交
  • 并不是所有的类对象都需要存储到IOC容器中,只需要:
    • SqlSessionFactory实例存储到IoC容器
    • Mapper实例存储到IoC容器

4.1 方式1

保留mybatis的外部配置文件(xml), 但是数据库连接信息交给Druid连接池配置,不使用mybatis-config.xml中自带的配置

  • 数据库连接配置文件 Resources->jdbc.properties
    jdbc.user=root 
    jdbc.password=root
    jdbc.url=jdbc:mysql:///mybatis-example
    jdbc.driver=com.mysql.cj.jdbc.Driver
    
  • mybatis核心配置文件 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>
           <!-- 开启驼峰式映射-->
           <setting name="mapUnderscoreToCamelCase" value="true"/>
           <!-- 开启logback日志输出-->
           <setting name="logImpl" value="SLF4J"/>
           <!--开启resultMap自动映射 -->
           <setting name="autoMappingBehavior" value="FULL"/>
       </settings>
    
       <typeAliases>
           <!-- 给实体类起别名 -->
           <package name="com.example.pojo"/>
       </typeAliases>
    
       <plugins>
           <plugin interceptor="com.github.pagehelper.PageInterceptor">
               <!--
                   helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。
                   你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
                   oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby
                   (完整内容看 PageAutoDialect) 特别注意:使用 SqlServer2012 数据库时,
                   https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md#%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E5%BA%93%E6%96%B9%E8%A8%80
                -->
               <property name="helperDialect" value="mysql"/>
           </plugin>
       </plugins>
    </configuration>
    
    

4.1.1 合起来配置(会出现问题)

  • 配置类文件 MapperJavaConfig.java
实现功能方式
数据库配置文件@PropertySource(“classpath:jdbc.properties”),@Value(“${jdbc.user}”)
数据库连接池配置DataSource dataSource()
数据库工厂SqlSessionFactoryBean sqlSessionFactoryBean
mapper的类与xml配置MapperScannerConfigurer mapperScannerConfigurer
  • 但是这种方式(如下)会产生问题:初始化顺序(SqlSessionFactoryBean和MapperScannerConfigurer会早于Value注解生效)可能会导致属性注入@Value读取为null,因此需要拆分配置类

出现问题: 当配置类被加载时,Spring容器会首先处理Bean的定义和初始化,其中包括sqlSessionFactoryBean和mapperScannerConfigurer的初始化。在这个过程中,如果@Value注解所在的Bean还没有被完全初始化,可能会导致注入的属性值为null
解决方法: 分开配置时,会把所有对象全都生成之后缓存起来,再统一进行互相引用。因此可以进行分开配置

@Configuration
@PropertySource("classpath:jdbc.properties")
public class MapperJavaConfig {

   @Value("${jdbc.user}")
   private String user;
   @Value("${jdbc.password}")
   private String password;
   @Value("${jdbc.url}")
   private String url;
   @Value("${jdbc.driver}")
   private String driver;


   //数据库连接池配置
   @Bean
   public DataSource dataSource(){
       DruidDataSource dataSource = new DruidDataSource();
       dataSource.setUsername(user);
       dataSource.setPassword(password);
       dataSource.setUrl(url);
       dataSource.setDriverClassName(driver);
       return dataSource;
   }

   /**
    * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
    * @param dataSource 需要注入连接池对象
    * @return 工厂Bean
    */
   @Bean
   public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
       //实例化SqlSessionFactory工厂
       SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

       //设置连接池
       sqlSessionFactoryBean.setDataSource(dataSource);

       //设置配置文件
       //包裹外部配置文件地址对象
       Resource resource = new ClassPathResource("mybatis-config.xml");
       sqlSessionFactoryBean.setConfigLocation(resource);

       return sqlSessionFactoryBean;
   }

   /**
    * 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
    * @return
    */
   @Bean
   public MapperScannerConfigurer mapperScannerConfigurer(){
       MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
       //设置mapper接口和xml文件所在的共同包
       mapperScannerConfigurer.setBasePackage("com.example.mapper");
       return mapperScannerConfigurer;
   }

}

4.1.2 分开配置

  • MapperJavaConfig.java拆分为数据库配置类DataSourceJavaConfig.java
    mybatis配置类MapperJavaConfig.java

    • 数据库配置类DataSourceJavaConfig.java
    @Configuration
    @PropertySource("classpath:jdbc.properties")
    public class DataSourceJavaConfig {
    
    
        @Value("${jdbc.user}")
        private String user;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driver}")
        private String driver;
    
    
        //数据库连接池配置
        @Bean
        public DataSource dataSource(){
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setUsername(user);
            dataSource.setPassword(password);
            dataSource.setUrl(url);
            dataSource.setDriverClassName(driver);
            return dataSource;
        }
    
    }
    
    • mybatis配置类MapperJavaConfig.java
    @Configuration
    public class MapperJavaConfig {
    
       /**
        * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
        * @param dataSource 需要注入连接池对象
        * @return 工厂Bean
        */
       @Bean
       public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
           //实例化SqlSessionFactory工厂
           SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    
           //设置连接池
           sqlSessionFactoryBean.setDataSource(dataSource);
    
           //设置配置文件
           //包裹外部配置文件地址对象
           Resource resource = new ClassPathResource("mybatis-config.xml");
           sqlSessionFactoryBean.setConfigLocation(resource);
    
           return sqlSessionFactoryBean;
       }
    
       /**
        * 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
        * @return
        */
       @Bean
       public MapperScannerConfigurer mapperScannerConfigurer(){
           MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
           //设置mapper接口和xml文件所在的共同包
           mapperScannerConfigurer.setBasePackage("com.example.mapper");
           return mapperScannerConfigurer;
       }
    
    }
    

4.2 方式2

不使用mybatis-config.xml配置文件,全部使用配置类。可以避免xml文件解析效率低的问题

  • 数据库连接池配置类如上节DataSourceJavaConfig.java
    @Configuration
    @PropertySource("classpath:jdbc.properties")
    public class DataSourceJavaConfig {
    
    
        @Value("${jdbc.user}")
        private String user;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driver}")
        private String driver;
    
    
        //数据库连接池配置
        @Bean
        public DataSource dataSource(){
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setUsername(user);
            dataSource.setPassword(password);
            dataSource.setUrl(url);
            dataSource.setDriverClassName(driver);
            return dataSource;
        }
    
    }
    
  • 创建文件config->MapperJavaConfig.java(与上节不同)
    @Configuration
    public class MapperJavaConfigNew {
    
        /**
         * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
         * @param dataSource 需要注入连接池对象
         * @return 工厂Bean
         */
        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
            //实例化SqlSessionFactory工厂
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    
            //设置连接池
            sqlSessionFactoryBean.setDataSource(dataSource);
    
            //TODO: 替代xml文件的java配置
            /*
    
                <settings>
                    <!-- 开启驼峰式映射-->
                    <setting name="mapUnderscoreToCamelCase" value="true"/>
                    <!-- 开启logback日志输出-->
                    <setting name="logImpl" value="SLF4J"/>
                    <!--开启resultMap自动映射 -->
                    <setting name="autoMappingBehavior" value="FULL"/>
                </settings>
    
                <typeAliases>
                    <!-- 给实体类起别名 -->
                    <package name="com.example.pojo"/>
                </typeAliases>
    
                <plugins>
                    <plugin interceptor="com.github.pagehelper.PageInterceptor">
                        <!--
                            helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。
                            你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
                            oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby
                            (完整内容看 PageAutoDialect) 特别注意:使用 SqlServer2012 数据库时,
                            https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md#%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E5%BA%93%E6%96%B9%E8%A8%80
                         -->
                        <property name="helperDialect" value="mysql"/>
                    </plugin>
                </plugins>
    
             */
    
            //settings [包裹到一个configuration对象,切记别倒错包]
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setMapUnderscoreToCamelCase(true);
            configuration.setLogImpl(Slf4jImpl.class);
            configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
            sqlSessionFactoryBean.setConfiguration(configuration);
    
            //typeAliases
            sqlSessionFactoryBean.setTypeAliasesPackage("com.example.pojo");
    
            //分页插件配置
            PageInterceptor pageInterceptor = new PageInterceptor();
    
            Properties properties = new Properties();
            properties.setProperty("helperDialect","mysql");
            pageInterceptor.setProperties(properties);
            sqlSessionFactoryBean.addPlugins(pageInterceptor);
    
            return sqlSessionFactoryBean;
        }
    
        /**
         * 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
         * @return
         */
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            //设置mapper接口和xml文件所在的共同包
            mapperScannerConfigurer.setBasePackage("com.example.mapper");
            return mapperScannerConfigurer;
        }
    
    }
    

    5 配置类的初始化

    • Spring的初始化类:将上述所有配置类进行初始化
    • config->SpringIoCInit.java
    • 继承AbstractAnnotationConfigDispatcherServletInitializer,需要实现三个方法
    public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
     //指定root容器对应的配置类
     @Override
     protected Class<?>[] getRootConfigClasses() {
       return new Class<?>[] {MapperJavaConfig.class, ServiceJavaConfig.class, DataSourceJavaConfig.class };
     }
     
     //指定web容器对应的配置类
     @Override
     protected Class<?>[] getServletConfigClasses() {
       return new Class<?>[] { WebJavaConfig.class };
     }
     
     //指定dispatcherServlet处理路径,通常为 / 
     @Override
     protected String[] getServletMappings() {
       return new String[] { "/" };
     }
    }
    

6 实际测试

下一节:【SSM】4. SSM项目的配置测试demo用一个简单的小demo来测试整个配置,附上所有的代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值