【Quartz】作业调度详解及SSM整合

1.Quartz是一个完全由java编写的开源作业调度框架,Quartz的主要三个核心类为Scheduler(调度器)、Trigger(触发器)、Job(任务)。

1)Scheduler:调度器就相当于一个容器,装载着任务和触发器。该类是一个接口,代表一个Quartz的独立运行容器。Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组和名称,组及名称是Scheduler查找定位容器中某一对象的依据。Trigger的组及名称必须唯一,JobDetail的组及名称必须唯一。SchedulerFactory则是Scheduler工厂,负责生成Scheduler。
2)Trigger::负责设置调度策略,该类是一个接口,描述触发job执行的时间触发规则。最常用的是SimpleTrigger和CronTrigger。如果你需要在一个固定的时间和重复次数或一个固定的间隔时间,那么SimpleTrigger比较合适;如果你有许多复杂的作业调度,那么CronTrigger比较合适。CronTrigger和Unix的cron机制基本一致,需要的只是一个cron表达式,比如"0 0 12 * * ?"会在每天中午12点触发执行;"0 15 10 ? * 6L"会在每个月的最后一个星期五的早上10:15触发Job执行。
3)Job:定义需要执行的任务,该类是一个接口,只定义一个方法execute(JobExecutionContext context),在实现类的execute方法中编写所需要定时执行的Job,JobExecutionContext类提供了调度应用的一些信息,Job运行时的信息保存在JobDataMap中。
4)JobDetail:描述Job的实现类及其他相关的静态信息,如:Job名字,关联监听器,Quartz每次调度Job时,都重新创建一个Job。
5)ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。
6)Listener:事件和监听器体系,大部分组件都拥有事件。 下面搭建SSM框架,Quartz定时调度查询MySQL数据库中的数据。

2.Cron表达式:

'*'可以用于所有字段,在'分'字段中设为"*"表示每一分钟的含义
'?'可以用在'日'和'周几'字段,指定不明确的值
'-'被用来指定一个值的范围,如在小时字段中设为'10-12'表示10点-12点
','指定数个值,如'MON,WED,FRI'表示'the days Monday,Wednesday,and Friday'
'/'用来指定一个值的增加幅度,如在'秒'字段中设置为'0/15'表示'第0,15,30和45s'
'L'用在日和周几这两个字段,是'last'缩写,'日'字段中的'L'表示'一个月中的最后一天',在'周几'字段中,它简单的表示'7'
'W'可用于'日'字段,用来指定给定日期最近的工作日
'L'和'W'可以组合用于'日'字段表示为'LW',该月最后一个工作日
'#'可用于周几字段,表示'该月第几个周x',

"0 0 17 * * ?"              每天傍晚17点触发
"0 15 17 ? * *"             每天傍晚17点15分触发
"0 15 17 * * ?"             每天傍晚17点15分触发
"0 15 17 * * ? *"           每天傍晚17点15分触发
"0 15 17 * * ? 2017"        2017年的每天傍晚17点15分触发
"0 * 17 * * ?"              每天傍晚17点开始至17点59分每分钟触发一次
"0 0/5 17 * * ?"            每天傍晚17点开始至17点55分每隔5分钟触发一次
"0 0/5 17,19 * * ?"         每天傍晚17点开始至17点55和19点至19点55两个时间段内分每隔5分钟触发一次
"0 0-5 17 * * ?"            每天傍晚17至17点05每分钟触发一次
"0 0 17 ? * MON-FRI"        每个周一至周五的17:00:00触发
"0 0 17 15 * ?"             每月15号的17点触发
"0 0 17 L * ?"              每月的最后一天的17点触发
"0 0 17 * ? 6"              每月的最后一一个周五的17点触发
"0 0 17 ? * 6#3"            每月的第三个周五的17点触发  

以上都是Quartz作业调度框架的基础知识,作为一个开发人员,我的学习方式是以项目例子推动对所学知识的理解。下面为搭建一个SSM框架,定时触发对MySQL数据库相关数据的查询。

1)整个package结构:

这里写图片描述

2)applicationContext-core.xml为Spring相关配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
        http://mybatis.org/schema/mybatis-spring      
        http://mybatis.org/schema/mybatis-spring.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!-- 1.把属性资源文件的信息加载到Spring环境中进行利用 -->
    <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/db.properties</value>
                <value>classpath:config/quartz.properties</value>
            </list>
        </property>
    </bean>

    <!-- 2.创建数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${db.driver}" />
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
        <!-- 最大并发连接数 -->
        <property name="maxActive" value="10" />
        <!-- 最小空闲连接数 -->
        <property name="maxIdle" value="5" />
    </bean>

    <!-- 3.配置SqlSessionFactoryBean -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 自动扫描com.mybatis.assess.pojo, 指定包名称来为该包下的pojo类声明别名,默认的别名就是类名(首字母大小写都行) -->
        <property name="typeAliasesPackage" value="com.ssm.quartz.pojo" />
        <!-- 指定mybatis的全局配置文件的路径 -->
        <property name="mapperLocations" value="classpath:com/ssm/quartz/mybatis/*DaoMapper.xml" />
    </bean>

    <!-- 4.扫描com.mybatis.assess.dao包下接口 自动生成代理实现类 -->
    <mybatis:scan base-package="com.ssm.quartz.dao" factory-ref="sqlSessionFactory" />

    <!-- 5.事务管理 -->
    <bean name="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- 加载定时器 配置文件-->
    <import resource="spring-quartz.xml"/>

</beans>
2)applicationContext-mvc.xml为SpringMVC相关配置文件
<?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:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="   
           http://www.springframework.org/schema/beans   
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
           http://www.springframework.org/schema/context   
           http://www.springframework.org/schema/context/spring-context-3.2.xsd  
           http://www.springframework.org/schema/mvc   
           http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

    <context:component-scan base-package="com.ssm.quartz" />

    <mvc:annotation-driven />

    <!-- 配置资源映射    
            mapping:代表映射路径  
            location:代表文件路径,必须是webapp根目录下的路径才行
            cache-period:浏览器缓存时间
    -->
    <mvc:resources location="/css/" mapping="/css/**" cache-period="31536000"/>
    <mvc:resources location="/js/" mapping="/js/**" cache-period="31536000"/>
    <mvc:resources location="/image/" mapping="/image/**" cache-period="31536000"/>

    <!-- 配置视图解析器
        当Controller返回XXX字符串时,先通过拦截器,然后该类就会在jsp/目录下,
        查找XXX.jsp文件 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>
3)db.properties为数据库相关配置文件
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&amp;characterEncoding=UTF-8&useSSL=true
db.username=root
db.password=123456

#db.driver = oracle.jdbc.driver.OracleDriver
#db.url = jdbc:oracle:thin:@localhost:1521:orcl
#db.username = root
#db.password = 123456
4)quartz.properties为Cron表达式相关配置文件
#查询日期是否变化表达式意思(10/10 * * * * ?  10秒后每隔10秒运行)
qzExcutTimer=5/5 * * * * ?
#日终启动时间(0 0 18 * * ?表示每天下午6点执行)
qzRunDataTimer=0 32 11 * * ?
5)spring-quartz.xml为Quartz框架相关配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
        http://mybatis.org/schema/mybatis-spring      
        http://mybatis.org/schema/mybatis-spring.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <bean id="quartzJob" class="com.ssm.quartz.job.QuartzJob"></bean>   

    <!-- 使用MethodInvokingJobDetailFactoryBean,任务类可以不实现Job借口,通过targetMethod指定调用方法 -->
    <bean id="JobTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 要调度的对象 -->
        <property name="targetObject" ref="quartzJob" />
        <!-- 要执行的方法名称 -->
        <property name="targetMethod" value="excutor" />
        <!-- 将并发设置为false -->
        <property name="concurrent" value="false"></property>
    </bean>
    <!-- 调度触发器 -->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="JobTask" />
        <!-- 表达式 -->
        <property name="cronExpression" value="${qzExcutTimer}" />
    </bean>
    <!-- 调度工厂:如果将lazy-init="false",那么容器启动就会执行调度程序 -->
    <bean id="startQuartz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <!-- 作业调度器,list下可加入其它的调度器 -->
                <ref bean="trigger" />
            </list>
        </property>
    </bean>

</beans>    
6)web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <!-- 配置Spring上下文监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/config/applicationContext-core.xml</param-value>
    </context-param>

    <!-- 配置Log4j日志上下文监听器 -->    
    <listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <context-param>
      <param-name>log4jConfigLocation</param-name>
      <param-value>/WEB-INF/log4j.properties</param-value>
    </context-param>
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>quartz.root</param-value>
    </context-param>

    <!-- Spring编码过滤器 -->
    <filter>
      <filter-name>characterEncoding</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>
    </filter>
    <filter-mapping>
        <filter-name>characterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置前端控制器DispatcherServlet -->   
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 
            默认加载方式:默认加载文件必须规范
                文件命名:servlet-name-servlet.xml======springmvc-servlet.xml
                路径规范:必须在WEB-INF目录下面
         -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/config/applicationContext-mvc.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>

</web-app>
7)log4j.properties配置文件
#全局日志配置  
#log4j.appender.syslog.encoding=UTF-8
log4j.rootLogger=info, stdout, R
#包下所有类的日志级别 

#日志输出到控制台  
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
#log4j.appender.stdout.encoding=UTF-8
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.sss} [%-5p] %c [%t] - %m%n

#日志输出到文件
log4j.appender.R=org.apache.log4j.RollingFileAppender
#log4j.appender.R.encoding=UTF-8
log4j.appender.R.File=${quartz.root}/logs/server.log
log4j.appender.R.MaxFileSize=2048KB
log4j.appender.R.MaxBackupIndex=50
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.sss} [%-5p] %c [%t]- %m%n

#关闭Spring日志  
log4j.category.org.springframework =OFF 
8)pom.xml配置文件
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.quartz.test</groupId>
  <artifactId>quartz</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <url>http://maven.apache.org</url>
  <properties>
    <!-- spring版本号 -->
    <spring.version>3.2.0.RELEASE</spring.version>
    <!-- mybatis版本号 -->
    <mybatis.version>3.2.7</mybatis.version>
    <!-- log4j日志文件管理包版本 -->
    <log4j.version>1.2.17</log4j.version>
  </properties>

  <dependencies>
    <!-- spring所需jar -->
    <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-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</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-expression</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>   
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- mybatis所需jar -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.42</version>
    </dependency>

    <!-- 定时器Quartz -->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>1.8.6</version>
    </dependency>

    <!-- log4j日志 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>   
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.0-rc1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.0-rc1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
        <scope>test</scope>
    </dependency>   

    <!-- commons依赖包 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>commons-pool</groupId>
        <artifactId>commons-pool</artifactId>
        <version>1.3</version>
    </dependency>

    <dependency>
        <groupId>asm</groupId>
        <artifactId>asm</artifactId>
        <version>3.3.1</version>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.17.1-GA</version>
    </dependency>   
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency> 

  </dependencies>

</project>
9)数据访问层DAO,作业调度Job及Mybatis的Mapper代理代码如下
@Repository("userDao")
public interface IUserDao {

    List<User> queryAllUser() throws Exception;

}

public class QuartzJob implements IQuartz {
    private Logger logger = Logger.getLogger(QuartzJob.class);

    @Resource(name="userDao")
    private IUserDao userDao;

    public void excutor() {
        List<User> list = null;
        String date = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date = sdf.format(new Date());
            list = userDao.queryAllUser();
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.info(date + "定时触发查询:" + list);
    }

}

<?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="com.ssm.quartz.dao.IUserDao">
    <resultMap type="User" id="userMap">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="birthday" property="birthday"/>
        <result column="address" property="address"/>
    </resultMap>

    <select id="queryAllUser" resultMap="userMap">
        select * from user
    </select>

</mapper>

这个例子希望大家能够受益,项目例子最终运行效果为:
这里写图片描述

学习Quartz作业调度框架遇见的问题:

1)java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class
异常原因:Spring 3.0版本中内置的Quartz版本是<2.0的,在使用最新的Quartz包(>2.0)之后,接口不兼容。
2)java.lang.ClassNotFoundException:org.springframework.web.util.Log4jConfigListener
异常分析:ContextLoaderListener类位于spring-web-3.2.0.RELEASE.jar包中。检查了maven的pom.xml,依赖引入正常。在工程Maven Dependencies视图中也能看到spring-web-3.1.0.RELEASE.jar包被正常引入进来了。
异常原因:进入到tomcat的部署路径.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\下检查了一下,发现工程部署后在WEB-INF文件夹下没有生成lib目录,正常情况下,会生成lib目录并把工程的所有依赖jar包都部署到该目录下。
解决方法:1.右键点击项目--选择Properties,选择Deployment Assembly,在右边点击Add按钮,在弹出的窗口中选择Java Build Path Entries。2.点击Next,选择Maven Dependencies。3.点击Finish,然后可以看到已经把Maven Dependencies添加到Web应用结构中了。
以上分析和解决方法参照http://blog.sina.com.cn/s/blog_7fb5109d0101o48g.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值