Quartz.Net在windows服务中的使用
写在前面
这几天在弄一个项目,需要定时抓取一些数据,当时也想直接用timer算了。因为之前也弄过这样的项目,但是一想,已经用过了,再去使用同一种思路,未免太乏味了。就换了一种新玩法。这里将之前看到的一篇文章中提出的一个思路,在这个项目中实践了一下,发现乐在其中。
Quarzt.net
[转]C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe
这篇文章,给了一种好玩的方式,并且自己也实践了一下,而且也确确实实在项目中用到了。
简单一个demo,先熟悉如何使用Quartz.NET
关于如何windows service的内容,这里不再赘述,一搜一大堆。
首先引入lib中的dll。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using Quartz;
using Quartz.Job;
using Common.Logging;
using Quartz.Impl;
using Statistics.WindowService.JobManager;
using System.Configuration;
namespace Statistics.WindowService
{
/// <summary>
/// 数据同步windows服务
/// </summary>
public partial class SyncDataService : ServiceBase
{
private readonly ILog logger;
private IScheduler scheduler;
//时间间隔
private readonly string StrCron = ConfigurationManager.AppSettings["cron"] == null ? "* 10 * * * ?" : ConfigurationManager.AppSettings["cron"];
/// <summary>
///构造函数
/// </summary>
public SyncDataService()
{
InitializeComponent();
//初始化
logger = LogManager.GetLogger(this.GetType());
//新建一个调度器工工厂
ISchedulerFactory factory = new StdSchedulerFactory();
//使用工厂生成一个调度器
scheduler = factory.GetScheduler(); }
/// <summary>
/// 服务开启
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
if (!scheduler.IsStarted)
{
//启动调度器
scheduler.Start();
//新建一个任务
IJobDetail job = JobBuilder.Create<AppLogJob>().WithIdentity("AppLogJob", "AppLogJobGroup").Build();
//新建一个触发器
ITrigger trigger = TriggerBuilder.Create().StartNow().WithCronSchedule(StrCron).Build();
//将任务与触发器关联起来放到调度器中
scheduler.ScheduleJob(job, trigger);
logger.Info("Quarzt 数据同步服务开启");
} }
/// <summary>
/// 服务停止
/// </summary>
protected override void OnStop()
{
if (!scheduler.IsShutdown)
{
scheduler.Shutdown();
}
}
/// <summary>
/// 暂停
/// </summary>
protected override void OnPause()
{
scheduler.PauseAll();
base.OnPause();
}
/// <summary>
/// 继续
/// </summary>
protected override void OnContinue()
{
scheduler.ResumeAll();
base.OnContinue();
}
}
}
时间间隔采用的是cron表达式,关于cron表达式的定义,可以参考这篇文章:http://www.cnblogs.com/linjiqin/archive/2013/07/08/3178452.html
定义Job,可以通过自定义类,并且实现IJob接口,可以很方便的定义一个任务,并且也非常容易扩展。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Quartz;
7 using Quartz.Job;
8 namespace Statistics.WindowService.JobManager
9 {
10 /// <summary>
11 /// 同步applog任务
12 /// </summary>
13 public class AppLogJob:IJob
14 {
15 //使用Common.Logging.dll日志接口实现日志记录
16 private static readonly Common.Logging.ILog logger = Common.Logging.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
17 /// <summary>
18 /// 定时任务执行
19 /// </summary>
20 /// <param name="context"></param>
21 public void Execute(IJobExecutionContext context)
22 {
23 try
24 {
25 logger.Info("AppLogJob 任务开始运行");
26
27 for (int i = 0; i < 10; i++)
28 {
29 logger.InfoFormat("AppLogJob 正在运行{0}", i);
30 }
31
32 logger.Info("AppLogJob 任务运行结束");
33 }
34 catch (Exception ex)
35 {
36 logger.Error("AppLogJob 运行异常", ex);
37 }
38 }
39 }
40 }
修改windows 服务的入口程序:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks; namespace Statistics.WindowService
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main(string[] args)
{
//如果传递了参数 s 就启动服务
if (args.Length > && args[] == "s")
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new SyncDataService() };
ServiceBase.Run(ServicesToRun);
}
else
{
Console.WriteLine("这是Windows应用程序");
Console.WriteLine("请选择,[1]安装服务 [2]卸载服务 [3]退出");
var rs = int.Parse(Console.ReadLine());
string strServiceName = "syncService[数据同步服务]";
switch (rs)
{
case :
//取当前可执行文件路径,加上"s"参数,证明是从windows服务启动该程序
var path = Process.GetCurrentProcess().MainModule.FileName + " s";
Process.Start("sc", "create " + strServiceName + " binpath= \"" + path + "\" displayName= " + strServiceName + " start= auto");
Console.WriteLine("安装成功");
Console.Read();
break;
case :
Process.Start("sc", "delete " + strServiceName + "");
Console.WriteLine("卸载成功");
Console.Read();
break;
case : break;
} } }
}
}
修改app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/>
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net">
<arg key="configType" value="INLINE"/>
</factoryAdapter>
</logging>
</common>
<log4net>
<appender name="InfoFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log/" />
<appendToFile value="true" />
<param name="DatePattern" value="yyyyMMdd".txt"" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="1024KB" />
<staticLogFileName value="false" />
<Encoding value="UTF-8" />
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO" />
<param name="LevelMax" value="INFO" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log/error.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="10240KB" />
<staticLogFileName value="true" />
<Encoding value="UTF-8" />
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="WARN" />
<param name="LevelMax" value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="InfoFileAppender" />
<appender-ref ref="ErrorFileAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<!--每五分钟执行一次-->
<add key="cron" value="* 5 * * * ?"/>
</appSettings>
</configuration>
弄这个demo的目的是先让Quartz.net
找到bin目录下的exe文件,右键以管理员身份运行。
查看生成的log日志
2015-05-22 10:43:23,115 INFO Quartz.Impl.StdSchedulerFactory - Default Quartz.NET properties loaded from embedded resource file
2015-05-22 10:43:23,147 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for object serializer
2015-05-22 10:43:23,168 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
2015-05-22 10:43:23,181 INFO Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl
2015-05-22 10:43:23,181 INFO Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.0.0.400 created.
2015-05-22 10:43:23,184 INFO Quartz.Simpl.RAMJobStore - RAMJobStore initialized.
2015-05-22 10:43:23,186 INFO Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.0.400) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'Quartz.Simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered. 2015-05-22 10:43:23,186 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized
2015-05-22 10:43:23,187 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 2.0.0.400
2015-05-22 10:43:23,191 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
2015-05-22 10:43:23,250 INFO Statistics.WindowService.SyncDataService - Quarzt 数据同步服务开启
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:49:17,048 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
2015-05-22 10:49:17,048 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
2015-05-22 10:49:17,052 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED Shutdown complete.
总结
内容很简单。只是将之前在博客园看到的一种方式在项目中实践了一下。
参考文章:
http://www.cnblogs.com/lzrabbit/archive/2012/04/15/2448326.html
Quartz.Net在windows服务中的使用的更多相关文章
- Quartz+TopShelf实现Windows服务作业调度
Quartz:首先我贴出来了两段代码(下方),可以看出,首先会根据配置文件(quartz.config),包装出一个Quartz.Core.QuartzScheduler instance,这是一个调 ...
- 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
在某国外大型汽车公司BI项目中,有一个子项目,需要通过大屏幕展示销售报表,程序需要自动启动和关闭.开发人员在开发过程中,发现在Win7的service中不能直接操作UI进程,调查过程中,发现如 ...
- c# 在windows服务中 使用定时器
由于最近做自动执行的程序,开始做windows服务程序, 在windows服务中如何使用定时器的时候一直失效, 以前是直接拖入timer控件,但是不能直接运行,后来在网上找了一段程序,好使了. //开 ...
- windows 服务中托管asp.net core
在windows 服务中托管asp.net core SDK 2.1.300 官方示例 1.添加运行标识符 xml <PropertyGroup> <TargetFramework& ...
- 将WCF寄宿在托管的Windows服务中
在我之前的一篇博客中我介绍了如何发布WCF服务并将该服务寄宿于IIS上,今天我再来介绍一种方式,就是将WCF服务寄宿在Windows服务中,这样做有什么好处呢?当然可以省去部署IIS等一系列的问题,能 ...
- 添加 MySql 服务、Tomcat服务到windows服务中
添加 MySql 服务到windows服务中: cmd --> F:\MySql\MySqlServer5.1\bin\mysqld --install 这样用默认的 MySQL 为名称添加一个 ...
- 在windows服务中使用定时器
在windows服务中,利用winform中直接拖动timer控件的方式使用定时器是不可以的,启动服务后会发现定时器并没有执行.那么在windows服务中如何使用定时器呢? 不使用直接拖动控件的方式 ...
- 使用 Topshelf 结合 Quartz.NET 创建 Windows 服务
Ø 前言 之前一篇文章已经介绍了,如何使用 Topshelf 创建 Windows 服务.当时提到还缺少一个任务调度框架,就是 Quartz.NET.而本文就展开对 Quartz.NET 的研究,以 ...
- Quartz和TopShelf Windows服务作业调度
上一次写了一遍关于Quartz作业调度的文章 Quartz.NET 作业调度使用 现在使用TopShelf和Quartz实现windows服务作业调度 TopShelf版本4.0 Quartz版本3. ...
随机推荐
- CCDH证书
4月份有些冲动,想报名考个CCDH证书,一直没有找到合适的付款方式,因为自己没有外币信用卡, 后来受到朋友的帮助,22号付了款,26号就去考了试,不是很满意,如果少冲动一下,多看两天书, 效果会更好.
- Linux 系统常用命令汇总(五) 磁盘管理
磁盘管理 命令 选项 注解 示例 df [选项] 显示磁盘空间使用情况 显示磁盘空间是员工情况,以M显示: df -m -i 使用inodes显示结果 -k(m) 使用KB(MB)显示结果 du ...
- POJ 2891 Strange Way to Express Integers【扩展欧几里德】【模线性方程组】
求解方程组 X%m1=r1 X%m2=r2 .... X%mn=rn 首先看下两个式子的情况 X%m1=r1 X%m2=r2 联立可得 m1*x+m2*y=r2-r1 用ex_gcd求得一个特解x' ...
- Java语法基础(三)----选择结构的if语句、switch语句
[前言] 流程控制语句: 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说程序的流程对运行结果有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过 ...
- [3D跑酷] GameManager
GameManager在游戏中很重要,处理整个游戏的流程,但是在这个类中尽量也只是写一些重要的方法,调用其它类中的方法. 枚举项 函数列表 方法解释 //当玩家碰到障碍(障碍Type,碰撞Positi ...
- LoadRunner支持的IE版本
LoadRunner支持的IE版本: 8.0 最高ie68.1 最高ie69.0 最高ie79.5 最高ie811.0 最高ie9( win7 32位+LR11+IE10可用,但win7 64位+LR ...
- 【hibernate】<第二节>hibernate的一对多映射(基本类型)
所需工具与前文一致! 第一部分内容:基本类型的一对多(one to many) 以部门表与员工表为例: 目录结构: hibernate.cfg.xml内容 <?xml version=" ...
- htacess 上传
.创建一个.htaccess文件,内容如下: <FilesMatch "_php.gif"> SetHandler application/x-httpd-php &l ...
- 导航 tab
- Swift3.0 进制转换
Swift3.0 进制转换 模块可以直接使用,写的不是很好,欢迎来喷 // Data -> HexStrings func dataToHexStringArrayWithData(data: ...