quartz是window ftp服务服务框架吗

Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。它有很多特征,如:数据库支持,集群,插件,支持cron-like表达式等等以上介绍是从博客园张善友(/shanyou/archive//quartznettutorial.html)的博客摘录,可登录他博客具体了解quartz.net。&我在这里只讲具体在项目中的实现:通过Windows服务调用Quartz.net,然后Quartz.net 调用WinForm消息窗口,实现计划任务消息推送。【Windows服务】--&【Quartz.net】 --& 【Winform .exe】 --& 【程序打包】&项目解决方案,如图所示:一、创建Windows服务&1、打开vs2010--新建项目--选择"Windows服务",我这里命名为"QuartzService".%20创建好后首先映入我们眼帘的是QuartzService.cs[设计]视图,右键点设计视图选择"添加安装程序",如下图:注释:(创建一个Windows服务,仅用InstallUtil程序去安装这个服务是不够的。你必须还要把一个服务安装程序添加到你的Windows服务当中,这样便于InstallUtil或是任何别的安装程序知道应用你服务的是怎样的配置设置)2、切换到刚被添加的ProjectInstaller的设计视图,&设置serviceInstaller1组件的属性:%20StartType%20=%20Automatic;ServiceName%20=&QuartzS设置serviceProcessInstaller1组件的属性&Account%20=%20LocalSystem;&如下图:3、QuartzService中添加Quartz.dll%20,log4net.dll引用,在QuartzService.cs文件中引用命名空间%20Quartz;Quartz.I%20log4右键点击QuartzService项目,属性-目标框架%20,选择.net%20Framwork%204,如下图:4、添加app.config配置文件,具体配置如下: 1 &?xml version="1.0"?& 2 &configuration& 3
&configSections& 4
&section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c"/& 5
&section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/& 6
&sectionGroup name="common"& 7
&section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging"/& 8
&/sectionGroup& 9
&/configSections&10
&common&11
&logging&12
&factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net"&13
&arg key="configType" value="INLINE"/&14
&/factoryAdapter&15
&/logging&16
&/common&17
&log4net&18
&appender name="InfoFileAppender" type="log4net.Appender.RollingFileAppender"&19
&file value="log/" /&20
&appendToFile value="true" /&21
&param name="DatePattern" value="yyyyMMdd&.txt&" /&22
&rollingStyle value="Date" /&23
&maxSizeRollBackups value="100" /&24
&maximumFileSize value="1024KB" /&25
&staticLogFileName value="false" /&26
&Encoding value="UTF-8" /&27
&filter type="log4net.Filter.LevelRangeFilter"&28
&param name="LevelMin" value="INFO" /&29
&param name="LevelMax" value="INFO" /&30
&/filter&31
&layout type="log4net.Layout.PatternLayout"&32
&conversionPattern value="%date %-5level %logger
- %message%newline" /&33
&/layout&34
&/appender&35
&appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender"&36
&file value="log/error.txt" /&37
&appendToFile value="true" /&38
&rollingStyle value="Size" /&39
&maxSizeRollBackups value="100" /&40
&maximumFileSize value="10240KB" /&41
&staticLogFileName value="true" /&42
&Encoding value="UTF-8" /&43
&filter type="log4net.Filter.LevelRangeFilter"&44
&param name="LevelMin" value="WARN" /&45
&param name="LevelMax" value="FATAL" /&46
&/filter&47
&layout type="log4net.Layout.PatternLayout"&48
&conversionPattern value="%date %-5level %logger - %message%newline" /&49
&/layout&50
&/appender&51
&level value="INFO" /&53
&appender-ref ref="InfoFileAppender" /&54
&appender-ref ref="ErrorFileAppender" /&55
&/log4net&57 58
We use quartz.config for this server, you can always use configuration section if you want to.60
Configuration section has precedence here.
&appSettings&63
&!-- YYC.WebService URL地址 --&64
&add key="URL" value="http://localhost:43093/WebService.asmx" /&65
&/appSettings&66
&quartz &68
&/quartz&69
&startup&71
&supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/&72
&/startup&73 &/configuration&View Code二、创建Quartz.Net.JobLibrary并配置Job1、在解决方案中添加新项-选择"类库",我这里命名为Quartz.Net.JobLibrary,Quartz.Net.JobLibrary用来实现多个"作业"类。Quartz.Net.JobLibrary类库中添加Quartz.dll ,log4net.dll引用。Quartz.Net.JobLibrary类库中添加一个类Interop.cs,这个类是为了解决在Win7中出现【交互式检测】弹窗,博客园李敬然(/gnielee/archive//session0-isolation-part1.html)的博客详细谈到 穿透Session 0 隔离,具体代码如下:
2 using System.Runtime.InteropS
4 namespace Quartz.Net.JobLibrary
public class Interop
public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Z
public static void ShowMessageBox(string message, string title) 10
int resp = 0; 12
WTSSendMessage( 13
WTS_CURRENT_SERVER_HANDLE, 14
WTSGetActiveConsoleSessionId(), 15
title, title.Length, 16
message, message.Length, 17
0, 0, out resp, false); 18
[DllImport("kernel32.dll", SetLastError = true)] 20
public static extern int WTSGetActiveConsoleSessionId(); 21
[DllImport("wtsapi32.dll", SetLastError = true)] 22
public static extern bool WTSSendMessage( 23
IntPtr hServer, 24
int SessionId, 25
String pTitle, 26
int TitleLength, 27
String pMessage, 28
int MessageLength, 29
int Style, 30
int Timeout, 31
out int pResponse, 32
bool bWait); 33
public static void CreateProcess(string app, string path) 35
IntPtr hT 37
IntPtr hDupedToken = IntPtr.Z 38
PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 40
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 41
sa.Length = Marshal.SizeOf(sa); 42
STARTUPINFO si = new STARTUPINFO(); 44
si.cb = Marshal.SizeOf(si); 45
int dwSessionID = WTSGetActiveConsoleSessionId(); 47
bool result = WTSQueryUserToken(dwSessionID, out hToken); 48
if (!result) 50
ShowMessageBox("WTSQueryUserToken failed", "AlertService Message"); 52
result = DuplicateTokenEx( 55
hToken, 56
GENERIC_ALL_ACCESS, 57
ref sa, 58
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 59
(int)TOKEN_TYPE.TokenPrimary, 60
ref hDupedToken 61
if (!result) 64
ShowMessageBox("DuplicateTokenEx failed", "AlertService Message"); 66
IntPtr lpE 69
result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false); 70
if (!result) 72
ShowMessageBox("CreateEnvironmentBlock failed", "AlertService Message"); 74
result = CreateProcessAsUser( 77
hDupedToken, 78
path + app, 79
String.Empty, 80
ref sa, ref sa, 81
false, 0, IntPtr.Zero, 82
path, ref si, ref pi); 83
if (!result) 85
int error = Marshal.GetLastWin32Error(); 87
string message = String.Format("CreateProcessAsUser Error: {0}", error); 88
ShowMessageBox(message, "AlertService Message"); 89
if (pi.hProcess != IntPtr.Zero) 92
CloseHandle(pi.hProcess); 93
if (pi.hThread != IntPtr.Zero) 94
CloseHandle(pi.hThread); 95
if (hDupedToken != IntPtr.Zero) 96
CloseHandle(hDupedToken); 97
[StructLayout(LayoutKind.Sequential)]100
public struct STARTUPINFO101
public Int32103
public string lpR104
public string lpD105
public string lpT106
public Int32 dwX;107
public Int32 dwY;108
public Int32 dwXS109
public Int32 dwXCountC110
public Int32 dwYCountC111
public Int32 dwFillA112
public Int32 dwF113
public Int16 wShowW114
public Int16 cbReserved2;115
public IntPtr lpReserved2;116
public IntPtr hStdI117
public IntPtr hStdO118
public IntPtr hStdE119
[StructLayout(LayoutKind.Sequential)]122
public struct PROCESS_INFORMATION123
public IntPtr hP125
public IntPtr hT126
public Int32 dwProcessID;127
public Int32 dwThreadID;128
[StructLayout(LayoutKind.Sequential)]131
public struct SECURITY_ATTRIBUTES132
public Int32 L134
public IntPtr lpSecurityD135
public bool bInheritH136
public enum SECURITY_IMPERSONATION_LEVEL139
SecurityAnonymous,141
SecurityIdentification,142
SecurityImpersonation,143
SecurityDelegation144
public enum TOKEN_TYPE147
TokenPrimary = 1,149
TokenImpersonation150
public const int GENERIC_ALL_ACCESS = 0x;153 154
[DllImport("kernel32.dll", SetLastError = true,155
CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]156
public static extern bool CloseHandle(IntPtr handle);157 158
[DllImport("advapi32.dll", SetLastError = true,159
CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]160
public static extern bool CreateProcessAsUser(161
IntPtr hToken,162
string lpApplicationName,163
string lpCommandLine,164
ref SECURITY_ATTRIBUTES lpProcessAttributes,165
ref SECURITY_ATTRIBUTES lpThreadAttributes,166
bool bInheritHandle,167
Int32 dwCreationFlags,168
IntPtr lpEnvrionment,169
string lpCurrentDirectory,170
ref STARTUPINFO lpStartupInfo,171
ref PROCESS_INFORMATION lpProcessInformation);172 173
[DllImport("advapi32.dll", SetLastError = true)]174
public static extern bool DuplicateTokenEx(175
IntPtr hExistingToken,176
Int32 dwDesiredAccess,177
ref SECURITY_ATTRIBUTES lpThreadAttributes,178
Int32 ImpersonationLevel,179
Int32 dwTokenType,180
ref IntPtr phNewToken);181 182
[DllImport("wtsapi32.dll", SetLastError = true)]183
public static extern bool WTSQueryUserToken(184
Int32 sessionId,185
out IntPtr Token);186 187
[DllImport("userenv.dll", SetLastError = true)]188
static extern bool CreateEnvironmentBlock(189
out IntPtr lpEnvironment,190
IntPtr hToken,191
bool bInherit);192
}193 }View CodeQuartz.Net.JobLibrary类库中再分别添加两个"作业"类JobTest1.cs,JobTest2.cs:代码如下JobTest1.cs& 1 using S 2 using System.C 3 using System.R 4 using Common.L 5
6 namespace Quartz.Net.JobLibrary 7 { 8
public class JobTest1 : IJob 9
//使用Common.Logging.dll日志接口实现日志记录11
private static readonly ILog logger =12
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);13 14
private static string URL = ConfigurationManager.AppSettings["URL"];15 16
#region IJob 成员17 18
public void Execute(IJobExecutionContext context)19
("JobTest1 任务开始运行");23
//ShowMsgBox msgBox = new ShowMsgBox();24
//msgBox.ShowMsg(100, "AAAA", "计划任务提醒");25
//WebServiceSoapClient client = new WebServiceSoapClient(new BasicHttpBinding(), new EndpointAddress(URL));26
//client.Shake();27
//ShowMsg(100, "AAAA", "计划任务提醒");28
//Interop.ShowMessageBox("This a message from AlertService.",29
"AlertService Message");30
string path = System.Windows.Forms.Application.StartupP31
Interop.CreateProcess("Quartz.Net.WinForm.exe", path + "//");32
("JobTest1 任务运行结束");33
catch (Exception ex)35
logger.Error("JobTest1 运行异常", ex);37
#endregion41 42
}43 }View Code2、在Quartz.Net.JobLibrary中,添加配置文件quartz_jobs.xml,配置信息如下:
1 &?xml version="1.0" encoding="UTF-8"?&
3 &!-- This file contains job definitions in schema version 2.0 format --&
4 &job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"&
&processing-directives&
&overwrite-existing-data&true&/overwrite-existing-data&
&/processing-directives&
&schedule& 10
&!--定义JobTest1--& 11
&name&JobTest1&/name& 13
&group&JobGroup&/group& 14
&description&测试任务1&/description& 15
&job-type&Quartz.Net.JobLibrary.JobTest1,Quartz.Net.JobLibrary&/job-type& 16
&durable&true&/durable& 17
&recover&false&/recover& 18
&!--定义示JobTest2--& 21
&name&JobTest2&/name& 23
&group&JobGroup&/group& 24
&description&测试任务2&/description& 25
&job-type&Quartz.Net.JobLibrary.JobTest2,Quartz.Net.JobLibrary&/job-type& 26
&durable&true&/durable& 27
&recover&false&/recover& 28
&!--定义JobTest1 触发器 每30秒执行一次任务--& 31
&trigger& 32
&name&JobTestTrigger1&/name& 34
&group&TriggerGroup&/group& 35
&job-name&JobTest1&/job-name& 36
&job-group&JobGroup&/job-group& 37
&cron-expression&0/30 * * * * ?&/cron-expression& 38
&/cron& 39
&/trigger& 40
&!--定义JobTest2 触发器 每分钟执行一次任务--& 42
&trigger& 43
&name&JobTestTrigger2&/name& 45
&group&TriggerGroup&/group& 46
&job-name&JobTest2&/job-name& 47
&job-group&JobGroup&/job-group& 48
&cron-expression&0 * * * * ?&/cron-expression& 49
&/cron& 50
&/trigger& 51
&!--定义JobTest2 触发器 每天凌晨01:00执行一次任务--& 53
&trigger& 54
&name&JobTestTrigger3&/name& 56
&group&TriggerGroup&/group& 57
&job-name&JobTest2&/job-name& 58
&job-group&JobGroup&/job-group& 59
&cron-expression&0 0 1 * * ?&/cron-expression& 60
&/cron& 61
&/trigger& 62
&/schedule& 63
64 &!-- Cron Expressions&&Cron 表达式 65
Cron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示: 66
1. Seconds 秒 67
2. Minutes 分钟 68
3. Hours 小时 69
4. Day-of-Month 月中的天 70
5. Month 月 71
6. Day-of-Week 周中的天 72
7. Year (optional field) 年(可选的域) 73
一个cron表达式的例子字符串为"0 0 12 ? * WED",这表示&每周三的中午12:00&。 74
单个子表达式可以包含范围或者列表。例如:前面例子中的周中的天这个域(这里是"WED")可以被替换为"MON-FRI", "MON, WED, FRI"或者甚至"MON-WED,SAT"。 75
通配符('*')可以被用来表示域中&每个&可能的值。因此在"Month"域中的*表示每个月,而在Day-Of-Week域中的*则表示&周中的每一天&。 76
所有的域中的值都有特定的合法范围,这些值的合法范围相当明显,例如:秒和分域的合法值为0到59,小时的合法范围是0到23,Day-of-Month中值得合法凡范围是0到31, 77
但是需要注意不同的月份中的天数不同。月份的合法值是0到11。或者用字符串JAN,FEB MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV 及DEC来表示。 78
Days-of-Week可以用1到7来表示(1=星期日)或者用字符串SUN, MON, TUE, WED, THU, FRI 和SAT来表示. 79
'/'字符用来表示值的增量,例如, 如果分钟域中放入'0/15',它表示&每隔15分钟,从0开始&,如果在份中域中使用'3/20',则表示&小时中每隔20分钟, 80
从第3分钟开始&或者另外相同的形式就是'3,23,43'。 81
'?'字符可以用在day-of-month及day-of-week域中,它用来表示&没有指定值&。这对于需要指定一个或者两个域的值而不需要对其他域进行设置来说相当有用。 82
'L'字符可以在day-of-month及day-of-week中使用,这个字符是"last"的简写,但是在两个域中的意义不同。例如,在day-of-month域中的"L"表示这个月的最后一天, 83
即,一月的31日,非闰年的二月的28日。如果它用在day-of-week中,则表示"7"或者"SAT"。但是如果在day-of-week域中,这个字符跟在别的值后面, 84
则表示"当月的最后的周XXX"。例如:"6L" 或者 "FRIL"都表示本月的最后一个周五。当使用'L'选项时,最重要的是不要指定列表或者值范围,否则会导致混乱。 85
'W' 字符用来指定距离给定日最接近的周几(在day-of-week域中指定)。例如:如果你为day-of-month域指定为"15W",则表示&距离月中15号最近的周几&。 86
'#'表示表示月中的第几个周几。例如:day-of-week域中的"6#3" 或者 "FRI#3"表示&月中第三个周五&。 87
下面是一些表达式以及它们的含义。 88
Example Cron Expressions &&Cron表达式的例子 89
CronTrigger 90
例1 & 一个简单的每隔5分钟触发一次的表达式 91
"0 0/5 * * * ?" CronTrigger 92
例2 & 在每分钟的10秒后每隔5分钟触发一次的表达式(例如. 10:00:10 am, 10:05:10等.)。 93
"10 0/5 * * * ?" CronTrigger 94
例3 & 在每个周三和周五的10:30,11:30,12:30触发的表达式。 95
"0 30 10-13 ? * WED,FRI" CronTrigger 96
例4 & 在每个月的5号,20号的8点和10点之间每隔半个小时触发一次且不包括10点,只是8:30,9:00和9:30的表达式。 97
"0 0/30 8-9 5,20 * ?" 注意,对于单独触发器来说,有些日程需求可能过于复杂而不能用表达式表述,例如:9:00到10:00之间每隔5分钟触发一次, 98
下午1:00到10点每隔20分钟触发一次。这个解决方案就是创建两个触发器,两个触发器都运行相同的任务。 99 --&100 &/job-scheduling-data&View Code三、创建Quartz.Net.WinForm消息窗口1、在解决方案中添加新项-选择"windows 应用程序",我这里命名为Quartz.Net.WinForm,具体实现从右下角逐渐显示气泡式窗口如图所示:&点击【确定】从右下角逐渐消失通过JobTest1调用消息窗口,string path = System.Windows.Forms.Application.StartupPInterop.CreateProcess("Quartz.Net.WinForm.exe", path + "//");实现例如每一个小时检测是否有计划任务,一旦有任务,消息窗口弹出提醒!四、注册Windows服务1、cmd打开命令行工具:如果你系统是C盘,一般命令应该如下:C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/InstallUtil.exe&  "你的windows服务路径"反注册如下:C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/InstallUtil.exe& /u&"你的windows服务路径"当然也可以用sc命令sc create windows服务名称 binPath= "你的windows服务路径"删除服务sc delete windows服务名称这样注册就完了。2、打开服务:运行 下输入services.msc打开服务管理。如图:刷新,可以查看到QuartzService.如下图:3、&启动QuartzService,回到windows服务 应用程序所在目录以上四部分大体实现了类似一些新闻消息推送,下一篇讲讲具体程序打包、安装等实现过程。希望大家多多推荐一下
无相关信息iOS学习笔记之QuartzCore框架
iOS设备给用户视觉反馈其实都是通过QuartzCore框架来进行的,说白了,所有用户最终看到的显示界面都是图层合成的结果,而图层即是QuartzCore中的CALayer。 通常我们所说的视图即UIView,并不是直接显示在屏幕上,而是在创建视图对象的时候视图对象会自动创建
  iOS设备给用户视觉反馈其实都是通过QuartzCore框架来进行的,说白了,所有用户最终看到的显示界面都是图层合成的结果,而图层即是QuartzCore中的CALayer。
  通常我们所说的视图即UIView,并不是直接显示在屏幕上,而是在创建视图对象的时候视图对象会自动创建一个层,而视图对象把要显示的东西绘制在层上,待到需要显示时硬件将所有的层拷贝,然后按Z轴的高低合成最终的显示结果。
  CALayer本质上是一块包含一幅位图的缓冲区,由视图创建的层为隐式层,而手动创建的层称为显示层。
  如果要在iOS上能够有良好的用户体验,动画的过渡效果是必不可少的,而所有的动画效果都是通过CAAnimation类的子类(CAAnimation是抽象类)来完成的。CAAnimation类的子类包括了CAAnimationGroup,CAPropertyAnimation,CATransition,而CAPropertyAniamtion(同为抽象类)也衍生了CABasicAnimation和CAKeyframeAnimation。用UIView的animation实现的动画本质上也是通过CALayer来实现的,iOS系统中CALayer的很多属性都是隐含有动画效果的,如果不想要隐式动画或者想要显示动画效果,都可以通过CATransaction来设置是否显示动画效果。同时,在CATransaction内可同时修改多个属性,然后再一并同时渲染,另外CATransaction还是可嵌套的。
  CABasicAnimation是一个最多只能有两个关键帧的动画,而CAKeyframeAnimation除了可含有多个关键帧,而且还可以修改每个关键帧的速度。
  CATransition能够为层提供移出以及移入屏幕的效果。苹果提供的所有动画类型在这里有介绍,但是api只开放了其中的四种,当然你可以调用未公开的api,但是假如苹果以后出于安全还是什么原因调整接口的话,就不一定能用了,所以最好还是不要调用私有api,况且还有许多可以替代的方法,例如@"flip&,@"pageCurl&这些type是属于未公开的,一般来说不应该调用这些做动画,下面的这句
1 [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:containerView cache:YES];
  同样也可实现翻转的效果。再不行的话,还可以通过设置@"transform.rotation.y"这个keypath来旋转,或者直接通过CATransform3D来设置@"transform&属性。总而言之,没必要用未公开的api,会留下隐患,而且替代的方法很多。
  变换过程中需要注意的是该CALayer的anchorPoint,也就是旋转缩放基准点,默认情况下是(0.5, 0.5)也就是在layer的中心。基准点如果变了,旋转或者缩放所得到的的结果将会不同。position和anchorPoint共同决定了CALayer的frame。
  再说说CATransform3D的一个很常用到的数值,那就是m34这个值,下面这段代码是从Xcode文档中得到的
1 CATransform3D aTransform = CATransform3DI
zDistance = 850;
4 aTransform.m34 = 1.0 / -zD
&默认情况下, m34的值为0,即zDistance为无穷大,而(0,0,zDistance)点表示照相机(透视点)所在的位置,从照相机位置看到的影像在xy平面上的投影即是我们可以在手机屏幕中所看到的影像,下面的这个链接讲的很详细很准确,有兴趣的可以去看。
  上面讲了iOS里面所有的动画,但是还有一个很重要的没有讲,,那就是动画的速度控制函数CAMediaTimingFunction。这个函数是用于描述时间和距离之间的关系,距离=toValue-fromValue, 时间=duration, 将它们标准化为1x1的,x,t取值在[0, 1]区间内。假设在时刻t(时间过去了duration*t)时,动画目标的位置应为 fromValue+x*(toValue-fromValue)。系统提供的四种函数的函数图如下,下面曲线的斜率表示动画的速率,从图中可以看出,kCAMediaTimingFunctionLinear为匀速运动,kCAMediaTimingFunctionEaseIn为加速运动,kCAMediaTimingFunctionEaseOut为减速运动,,kCAMediaTimingFunctionEaseInEaseOut为先加速后减速运动。当然,苹果也提供了可自定义速度控制函数,通过initWithControlPoints:x1:y1:x2:y2可自定义两个插值点,,然后所得的函数曲线为由(0,0),(x1,y1),(x2,y2),(1,1)这四个点为控制点的Bezier曲线。
  说了这么多,大概知晓了动画的原理,但是要做出很绚丽的动画还是需要很好地数学功底及勤加修炼的。当然很多时候我们不能为了炫而炫,毕竟很多时候用户使用应用是为了使用某个功能而不是专门来看动画的。
&启动页面,添加一个UIImageView,设置image为启动屏图片,然后对UIImageView进行动画即可。
用UIView的animation就可以实现图片切换动画,以及歌词平缓过渡动画。
先对下一个controller进行截图,然后进行动画,动画结束后显示下一个controller即可。
通过CATransition设置type,subtype即可实现层的各种切换。
你最喜欢的  你曾经需要应用执行一个任务吗?这个任务天天或每周星期二晚上11:30,或许仅仅每个月的最后一天执行。一个
自动执行而无须干预的任务在执行过程中假如发生一个严重错误,应用能够知到其执行失败并尝试重新执行吗?你和你的团队是用Java编程吗?假如这些问题中
任何一个你回答是,那么你应该使用Quartz调度器。    旁注:Matrix目前就大量使用到了Quartz。比如,排名统计功能的实现,在Jmatrix里通过Quartz定义了一个定时调度作业,在天天凌晨一点,作业开始工作,重新统计大家的Karma和排名等。    还有,文件的生成,也是通过Quartz定义作业,每隔半个小时生成一次RSS 文件。    所以Quartz使用的地方很多,本文无疑是一篇很好的入门和进阶的文章,在此,感谢David w Johnson的努力!    Quartz让作业调度简单   
 Quartz是一个完全由java编写的开源作业调度框架。不要让作业调度这个术语吓着你。尽管Quartz框架整合了许多额外功能,
但就其简易形式看,你会发现它易用得简直让人受不了!。简单地创建一个实现org.quartz.Job接口的java类。Job接口包含唯一的方法:    public void execute(JobExecutionContext context)  throws JobExecutionE   
 在你的Job接口实现类里面,添加一些逻辑到execute()方法。一旦你配置好Job实现类并设定好调度时间表,Quartz将密切注重剩余时间。
当调度程序确定该是通知你的作业的时候,Quartz框架将调用你Job实现类(作业类)上的execute()方法并答应做它该做的事情。无需报告任何
东西给调度器或调用任何特定的东西。仅仅执行任务和结束任务即可。假如配置你的作业在随后再次被调用,Quartz框架将在恰当的时间再次调用它。   
 假如你使用了其它流行的开源框架象struts,你会对Quartz的设计和部件感到舒适。虽然两个开源工程是解决完全不同的问题,还是有很多相似的之
处,就是开源软件用户天天感觉很舒适。Quartz能用在单机J2SE应用中,作为一个RMI服务器,也可以用在web应用中,甚至也可以用在J2EE应
用服务器中。    Quartz的发展史    尽管Quartz今年开始受到人们注重,但还是暂时流
行。Quartz由James
House创建并最初于2001年春天被加入sourceforge工程。接下来的几年里,有许多新特征和版本出现,但是直到项目迁移到新的站点并成为
OpenSymphony项目家族的一员,才开始真正启动并受到应有的关注。    James House仍然和几个协助他的业余开发者参与大量开发工作。Quartz开发团队今年能发布几个新版本,包括当前正处在候选发布阶段的1.5版。    上手Quartz    Quartz工程驻留在OpenSymphony站点上。在Quartz站点上可以找到许多有用的资源:JavaDocs,包含指南的文档,CVS访问,用户和开发者论坛的连接,当然也有下载。   
 从下载连接取得Quartz的发布版本,并且解压到到本地目录。这个下载文件包含了一个预先构建好的Quartz二进制文件(quartz.jar),
你可以将它放进自己的应用中。Quartz框架只需要少数的第三方库,并且这些三方库是必需的,你很可能已经在使用这些库了。    你
要把Quartz的安装目录的&quartz- install&/lib/core 和
&quartz-install&/lib/optional目录中的第三方库加进你自己的工程中。大多数第三方库是我们所熟知和喜欢的标准
Jakarta Commons库,像Commons Logging, Commons BeantUtils等等。    quartz.properties文件   
 Quartz有一个叫做quartz.properties的配置文件,它答应你修改框架运行时环境。缺省是使用Quartz.jar里面的
quartz.properties文件。当然,你应该创建一个quartz.properties文件的副本并且把它放入你工程的classes目录中
以便类装载器找到它。quartz.properties样本文件如例1所示。    例1.quartz.properties文件答应修改Quartz运行环境:    #===============================================================  # Configure Main Scheduler Properties  #===============================================================  org.quartz.scheduler.instanceName = QuartzSchedulerorg.quartz.scheduler.instanceId = AUTO  #===============================================================  # Configure ThreadPool  #=============================================================== 
 org.quartz.threadPool.class =
org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount
= 5org.quartz.threadPool.threadPriority = 5  #===============================================================  # Configure JobStore  #===============================================================  org.quartz.jobStore.misfireThreshold = 60000org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore    一旦将Quartz.jar文件和第三方库加到自己的工程里面并且quartz.properties文件在工程的classes目录中,就可以创建作业了。然而,在做这之前,我们暂且回避一下先简短讨论一下Quartz架构。    Quartz内部架构   
 在规模方面,Quartz跟大多数开源框架类似。大约有300个java类和接口,并被组织到12个包中。这可以和Apache
Struts把大约325个类和接口以及组织到11个包中相比。尽管规模几乎不会用来作为衡量框架质量的一个特性,但这里的要害是quarts内含很多功
能,这些功能和特性集是否成为、或者应该成为评判一个开源或非开源框架质量的因素。    Quartz调度器   
 Quartz框架的核心是调度器。调度器负责治理Quartz应用运行时环境。调度器不是靠自己做所有的工作,而是依靠框架内一些非常重要的部件。
Quartz不仅仅是线程和线程治理。为确保可伸缩性,Quartz采用了基于多线程的架构。启动时,框架初始化一套worker线程,这套线程被调度器
用来执行预定的作业。这就是Quartz怎样能并发运行多个作业的原理。Quartz依靠一套松耦合的线程池治理部件来治理线程环境。本片文障中,我们会
多次提到线程池治理,但Quartz里面的每个对象是可配置的或者是可定制的。所以,例如,假如你想要插进自己线程池治理设施,我猜你一定能!    作业   
 用Quartz的行话讲,作业是一个执行任务的简单java类。任务可以是任何java代码。只需你实现org.quartz.Job接口并且在出现严
重错误情况下抛出JobExecutionException异常即可。Job接口包含唯一的一个方法execute(),作业从这里开始执行。一旦实现
了Job接口和execute()方法,当Quartz确定该是作业运行的时候,它将调用你的作业。Execute()方法内就完全是你要做的事情。下面
有一些你要在作业里面做事情的例子:    · 用JavaMail(或者用其他的像Commons Net一样的邮件框架)发送邮件  · 创建远程接口并且调用在EJB上的方法  · 获取Hibernate ,查询和更新关系里的数据  · 使用OSWorkflow并且从作业调用一个工作流  · 使用FTP和到处移动文件  · 调用Ant构建脚本开始预定构建    这种可能性是无穷的,正事这种无限可能性使得框架功能如此强大。Quartz给你提供了一个机制来建立具有不同粒度的、可重复的调度表,于是,你只需创建一个java类,这个类被调用而执行任务。    作业治理和存储   
 作业一旦被调度,调度器需要记住并且跟踪作业和它们的执行次数。假如你的作业是30分钟后或每30秒调用,这不是很有用。事实上,作业执行需要非常准确
和即时调用在被调度作业上的execute()方法。Quartz通过一个称之为作业存储(JobStore)的概念来做作业存储和治理。    有效作业存储   
 Quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,它利用通常的内存来持久化调度程序信息。这种作业存储类型最轻易配置、
构造和运行。对许多应用来说,这种作业存储已经足够了。然而,因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度
信息将被丢失。假如你需要在重新启动之间持久化调度信息,则将需要第二种类型的作业存储。    第二种类型的作业存储实际上提供两种不
同的实现,但两种实现一般都称为JDBC作业存储。两种JDBC作业存储都需要JDBC驱动程序和后台数据库来持久化调度程序信息。这两种类型的不同在于
你是否想要控制数据库事务或这释放控制给应用服务器例如BEA's
WebLogic或Jboss。(这类似于J2EE领域中,Bean治理的事务和和容器治理事务之间的区别)    这两种JDBC作业存储是:    ·JobStoreTX:当你想要控制事务或工作在非应用服务器环境中是使用  ·JobStoreCMT:当你工作在应用服务器环境中和想要容器控制事务时使用。    JDBC作业存储为需要调度程序维护调度信息的用户而设计。    作业和触发器   
 Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个
最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,假如你需要在给定的时间
和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,假如你有许多复杂的作业调度,那么或许需要
CronTrigger。    CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的天天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。    作为一个例子,下面的Quartz克隆表达式将在星期一到星期五的天天上午10点15分执行一个作业。    0 15 10 ? * MON-FRI    下面的表达式    0 15 10 ? * 6L     将在2002年到2005年的每个月的最后一个星期五上午10点15分执行作业。    你不可能用SimpleTrigger来做这些事情。你可以用两者之中的任何一个,但哪个跟合适则取决于你的调度需要。    调度一个作业   
 让我们通过看一个例子来进入实际讨论。现假定你治理一个部门,无论何时候客户在它的FTP服务器上存储一个文件,都得用电子邮件通知它。我们的作业将用
FTP登陆到远程服务器并下载所有找到的文件。然后,它将发送一封含有找到和下载的文件数量的电子邮件。这个作业很轻易就帮助人们整天从手工执行这个任务
中解脱出来,甚至连晚上都无须考虑。我们可以设置作业循环不断地每60秒检查一次,而且工作在7×24模式下。这就是Quartz框架完全的用途。    首先创建一个Job类,将执行FTP和Email逻辑。下例展示了Quartz的Job类,它实现了org.quartz.Job接口。    例2.从FTP站点下载文件和发送email的Quartz作业    public class ScanFTPSiteJob implements Job {  private static Log logger = LogFactory.getLog(ScanFTPSiteJob.class);  /*  * Called the scheduler framework at the right time  */  public void execute(JobExecutionContext context)  throws JobExecutionException {  JobDataMap jobDataMap = context.getJobDataMap();  try {  // Check the ftp site for files  File[] files = JobUtil.checkForFiles(jobDataMap);  JobUtil.sendEmail(jobDataMap, files);  } catch (Exception ex) {  throw new JobExecutionException(ex.getMessage());  }  }}   
 我们故意让ScanFTPSiteJob保持很简单。我们为这个例子创建了一个叫做JobUtil的实用类。它不是Quartz的组成部分,但对构建各
种作业能重用的实用程序库来说是有意义的。我们可以轻易将那种代码组织进作业类中,quarts
调度器一样好用,因为我们一直在使用quarts,所以那些代码可继续重用。    JobUtil.checkForFiles() and JobUtil.sendEmail()方法使用的参数是Quartz创建的JobDataMap的实例。实例为每个作业的执行而创建,它是向作业类传递配置参数的方法。    这里并没有展示JobUtil的实现,但我们能用Jakarta上的Commons Net轻易地实现FTP和Email功能。    用调度器调用作业    首先创建一个作业,但为使作业能被调度器调用,你得向调度程序说明你的作业的调用时间和频率。这个事情由与作业相关的触发器来完成。因为我们仅仅对大约每60秒循环调用作业感爱好,所以打算使用SimpleTrigger。    作业和触发器通过Quartz调度器接口而被调度。我们需要从调度器工厂类取得一个调度器的实例。最轻易的办法是调用StdSchedulerFactory这个类上的静态方法getDefaultScheduler()。    使用Quartz框架,你需要调用start()方法来启动调度器。例3的代码遵循了大多数Quartz应用的一般模式:创建一个或多个作业,创建和设置触发器,用调度器调度作业和触发器,启动调度器。    例3.Quartz作业通过Quartz调度器而被调度    public class MyQuartzServer {  public static void main(String[] args) {  MyQuartzServer server = new MyQuartzServer();  try {  server.startScheduler();  } catch (SchedulerException ex) {  ex.printStackTrace();  }  }  protected void startScheduler() throws SchedulerException {  // Use the factory to create a Scheduler instance  Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();  // JobDetail holds the definition for Jobs  JobDetail jobDetail = new JobDetail("ScanFTPJob", Scheduler.DEFAULT_GROUP, 
 ScanFTPSiteJob.class);// Store job parameters to be used within
execute()jobDetail.getJobDataMap().put("FTP_HOST",
"//home//cavaness//inbound");  // Other neccessary Job parameters here  // Create a Trigger that fires every 60 seconds  Trigger trigger = TriggerUtils.makeSecondlyTrigger(60);  // Setup the Job and Trigger with the Scheduler  scheduler.scheduleJob(jobDetail, trigger );  // Start the Scheduler running  scheduler.start();  }}    编程调度同声明性调度    例3中,我们通过编程的方法调度我们的ScanFTPSiteJob作业。就是说,我们用java代码来设置作业和触发器。Quartz框架也支持在xml文件里面申明性的设置作业调度。申明性方法答应我们更快速地修改哪个作业什么时候被执行。   
 Quartz框架有一个插件,这个插件负责读取xml配置文件。xml配置文件包含了关于启动Quartz应用的作业和触发器信息。所有xml文件中的
作业连同相关的触发器都被加进调度器。你仍然需要编写作业类,但配置那些作业类的调度器则非常动态化。例4展示了一个用申明性方式执行与例3代码相同的逻
辑的xml配置文件。    例4.能使用xml文件调度的作业    &?xml version='1.0' encoding='utf-8'?&&quartz&  &job&  &job-detail&  &name&ScanFTPSiteJob&/name&  &group&DEFAULT&/group&  &description&  A job that scans an ftp site for files  &/description&  &job-class&ScanFTPSiteJob&/job-class&  &job-data-map allows-transient-data="true"&  &entry&  &key&FTP_HOST&/key&  &value&/home/cavaness/inbound&/value&  &/entry&  &!-- Other neccessary Job parameters here --&  &/job-data-map&  &/job-detail&  &trigger&  &simple&  &name&ScanFTPSiteJoBTrigger&/name&  &group&DEFAULT&/group&  &job-name&ScanFTPSiteJob&/job-name&  &job-group&DEFAULT&/job-group&  &start-time& 6:10:00 PM&/start-time&  &!-- repeat indefinitely every 60 seconds --&  &repeat-count&-1&/repeat-count&  &repeat-interval&60000&/repeat-interval&  &/simple&  &/trigger&  &/job&&/quartz&    你可以将xml文件中的元素跟例3代码作个比较,它们从概念上来看是相同的。使用例4式的申明性方法的好处是维护变得极其简单,只需改变xml配置文件和重新启动Quartz应用即可。无须修改代码,无须重新编译,无须重新部署。    有状态和无状态作业    在本文中你所看到的作业到是无状态的。这意味着在两次作业执行之间,不会去维护作业执行时JobDataMap的状态改变。假如你需要能增、删,改JobDataMap的值,而且能让作业在下次执行时能看到这个状态改变,则需要用Quartz有状态作业。   
 假如你是一个有经验的EJB开发者的话,深信你会立即退缩,因为有状态带有负面含义。这主要是由于EJB带来的伸缩性问题。Quartz有状态作业实现
了org.quartz.StatefulJob接口。无状态和有状态作业的要害不同是有状态作业在每次执行时只有一个实例。大多数情况下,有状态的作业
不回带来大的问题。然而,假如你有一个需要频繁执行的作业或者需要很长时间才能完成的作业,那么有状态作业可能给你带来伸缩性问题。    Quartz框架的其他特征    Quartz框架有一个丰富的特征集。事实上,quarts有太多特性以致不能在一种情况中全部领会,下面列出了一些有意思的特征,但没时间在此具体讨论。    监听器和插件   
 每个人都喜欢监听和插件。今天,几乎下载任何开源框架,你必定会发现支持这两个概念。监听是你创建的java类,当要害事件发生时会收到框架的回调。例
如,当一个作业被调度、没有调度或触发器终止和不再打火时,这些都可以通过设置来来通知你的监听器。Quartz框架包含了调度器监听、作业和触发器监
听。你可以配置作业和触发器监听为全局监听或者是特定于作业和触发器的监听。    一旦你的一个具体监听被调用,你就能使用这个技术来
做一些你想要在监听类里面做的事情。例如,你假如想要在每次作业完成时发送一个电子邮件,你可以将这个逻辑写进作业里面,也可以JobListener里
面。写进JobListener的方式强制使用松耦合有利于设计上做到更好。    Quartz插件是一个新的功能特性,无须修改Quartz便可被创建和添加进Quartz框架。他为想要扩展Quartz框架又没有时间提交改变给Quartz开发团队和等待新版本的开发人员而设计。假如你熟悉Struts插件的话,那么完全可以理解Quartz插件的使用。    与其Quartz提供一个不能满足你需要的有限扩展点,还不如通过使用插件来拥有可修整的扩展点。    集群Quartz应用    Quartz应用能被集群,是水平集群还是垂直集群取决于你自己的需要。集群提供以下好处:    ·伸缩性  ·搞可用性  ·负载均衡    目前,Quartz只能借助关系数据库和JDBC作业存储支持集群。将来的版本这个制约将消失并且用RAMJobStore集群将是可能的而且将不需要数据库的支持。    Quartz web应用   
 使用框架几个星期或几个月后,Quartz用户所显示的需求之一是需要集成Quartz到图形用户界面中。目前Quartz框架已经有一些工具答应你使
servlet来初始化和启动Quartz。一旦你可以访问调度器实例,你就可以把它存储在web容器的servlet上下文中
(ServletContext中)并且可以通过调度器接口治理调度环境。    幸运的是一些开发者已正影响着单机Quartz web应用,它用来更好地治理调度器环境。构建在若干个流行开源框架如Struts和Spring之上的图形用户界面支持很多功能,这些功能都被包装进一个简单接口。GUI的一个画面如图1所示:     图1.Quartz Web应用答应比较轻易地治理Quartz环境。    Quartz的下一步计划    Quartz是一个活动中的工程。Quartz开发团队明确表示不会停留在已有的荣誉上。Quartz下一个主要版本已经在启动中。你可以在OpenSymphony的 wiki上体验一下Quartz 2.0的设计和特征。    总之,Quartz用户天天都自由地添加特性建议和设计创意以便能被核心框架考虑(看重)。    了解更多Quartz特征   
 当你开始使用Quartz框架的更多特性时,User and Developer
Forum论坛变成一个回答问题和跟其他Quartz用户沟通的极其有用的资源。经常去逛逛这个论坛时很有好处的,你也可以依靠James
House来共享与你的需要相关的知识和意见。    这个论坛时免费的,你不必登陆便可以查找和查看归档文件。然而,假如你觉得这个论坛比较好而且需要向某人回复问题时,你必须得申请一个免费帐号并用该帐号登陆。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1185103次
积分:13943
积分:13943
排名:第276名
原创:461篇
转载:166篇
译文:14篇
评论:2165条
(1)(1)(5)(3)(3)(7)(7)(5)(10)(7)(6)(7)(8)(9)(8)(6)(3)(4)(7)(8)(9)(10)(20)(18)(29)(18)(28)(38)(43)(35)(35)(18)(24)(32)(18)(25)(6)(9)(19)(15)(19)(55)(2)(1)

我要回帖

更多关于 window 服务 的文章

 

随机推荐