最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Quartz.NET 全面解析與實(shí)戰(zhàn)指南

 更新時(shí)間:2026年05月04日 08:39:29   作者:回憶2012初秋  
文章介紹了Quartz.NET,一個(gè)功能強(qiáng)大的分布式作業(yè)調(diào)度框架,適用于.NET應(yīng)用,它支持Cron表達(dá)式、異步執(zhí)行、持久化存儲(chǔ)和集群部署等特性,提供了最佳實(shí)踐和注意事項(xiàng),感興趣的朋友一起看看吧

一、Quartz.NET 簡介

Quartz.NET 是一個(gè)功能強(qiáng)大、開源的作業(yè)調(diào)度框架,源自 OpenSymphony 的 Quartz API 的 .NET 移植版本,用 C# 改寫,適用于 Winform、ASP.NET 以及 ASP.NET Core 等各類 .NET 應(yīng)用。它的核心能力可以概括為:在指定的時(shí)間或按照指定的周期性地執(zhí)行任務(wù)——無論是每天早上 8 點(diǎn)發(fā)送一封匯總郵件、每隔 10 分鐘輪詢一次接口狀態(tài),還是在工作日的特定時(shí)段內(nèi)執(zhí)行數(shù)據(jù)同步。

Quartz.NET 的主要特性包括:

  • 支持 Cron 表達(dá)式,實(shí)現(xiàn)靈活的日歷化調(diào)度
  • 持久化任務(wù)信息到數(shù)據(jù)庫,避免應(yīng)用重啟后任務(wù)丟失
  • 分布式集群部署,支持負(fù)載均衡與故障轉(zhuǎn)移
  • 動(dòng)態(tài)管理任務(wù),支持添加、暫停、恢復(fù)、刪除作業(yè)
  • 深度集成 ASP.NET Core 依賴注入系統(tǒng)
  • 支持插件和監(jiān)聽器,可自定義調(diào)度邏輯和監(jiān)控機(jī)制

版本說明:Quartz.NET 3.0 是一個(gè)重大更新,引入了完整的 async/await 支持,并對(duì) .NET Core 提供了原生支持,NuGet 包也進(jìn)行了拆分,例如 Quartz.Jobs、Quartz.Plugins 等成為獨(dú)立的依賴項(xiàng)。

二、核心概念與架構(gòu)

核心組件

組件描述
Job(作業(yè))實(shí)現(xiàn) IJob 接口的類,包含具體要執(zhí)行的業(yè)務(wù)邏輯
Trigger(觸發(fā)器)定義任務(wù)何時(shí)執(zhí)行的規(guī)則,如時(shí)間間隔、Cron 表達(dá)式等
Scheduler(調(diào)度器)核心引擎,負(fù)責(zé)管理和協(xié)調(diào) Job 與 Trigger 的執(zhí)行
JobStore(作業(yè)存儲(chǔ))存儲(chǔ)作業(yè)和觸發(fā)器信息,支持內(nèi)存和數(shù)據(jù)庫兩種模式
ThreadPool(線程池)為任務(wù)執(zhí)行提供線程資源

基本工作流程

  1. 定義 Job(實(shí)現(xiàn) IJob 接口的類),編寫業(yè)務(wù)邏輯
  2. 創(chuàng)建 Trigger,設(shè)定觸發(fā)規(guī)則(時(shí)間間隔、Cron 表達(dá)式等)
  3. 通過 Scheduler 將 Job 和 Trigger 綁定并啟動(dòng)調(diào)度
  4. 調(diào)度器按照 Trigger 的規(guī)則,在適當(dāng)?shù)臅r(shí)機(jī)通過線程池執(zhí)行 Job

3.x 的核心變化:全面異步化

從 3.0 版本開始,Quartz.NET 全面擁抱異步編程。IJobExecute 方法現(xiàn)在返回 Task,可以輕松包含 async 代碼:

// 3.x 的 Job 定義
public class MyJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        // 異步操作示例
        await Task.Delay(1);
    }
}

如果你沒有任何異步邏輯,也可以直接返回 Task.CompletedTask

三、快速安裝與配置

1. 安裝 NuGet 包

# 核心包
dotnet add package Quartz
# ASP.NET Core 托管集成
dotnet add package Quartz.Extensions.Hosting
# 如需持久化支持(例如 SQL Server)
dotnet add package Quartz.Plugins
dotnet add package Quartz.Serialization.Json

2. 定義 Job 類

using Quartz;
public class HelloJob : IJob
{
    private readonly ILogger<HelloJob> _logger;
    public HelloJob(ILogger<HelloJob> logger)
    {
        _logger = logger;
    }
    public Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("Hello! 當(dāng)前時(shí)間: {Time}", DateTime.Now);
        return Task.CompletedTask;
    }
}

Quartz.NET 通過 IJobExecutionContext 向作業(yè)傳遞上下文信息,其中包括 JobDataMap,可以在 Trigger 或 Scheduler 級(jí)別傳遞參數(shù)給 Job。

3. 注冊(cè) Quartz 到 DI 容器

Program.cs 中完成注冊(cè):

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddQuartz(q =>
{
    // 注冊(cè) Job
    var jobKey = new JobKey("HelloJob");
    q.AddJob<HelloJob>(opts => opts.WithIdentity(jobKey));
    // 注冊(cè)觸發(fā)器 - SimpleSchedule 方式
    q.AddTrigger(opts => opts
        .ForJob(jobKey)
        .WithIdentity("HelloJob-trigger")
        .WithSimpleSchedule(x => x.WithIntervalInSeconds(10).RepeatForever()));
});
// 添加 Quartz 托管服務(wù),隨應(yīng)用生命周期啟停
builder.Services.AddQuartzHostedService(q => q.WaitForJobsToComplete = true);
var app = builder.Build();
app.Run();

四、觸發(fā)器(Trigger)詳解

Trigger 是 Quartz.NET 中最靈活的組件之一,定義了作業(yè)何時(shí)執(zhí)行。

1. SimpleSchedule —— 簡單間隔調(diào)度

適用于"每隔 N 秒/分鐘/小時(shí)執(zhí)行一次"這類固定間隔的場景:

q.AddTrigger(opts => opts
    .ForJob("HelloJob")
    .WithIdentity("simple-trigger")
    .WithSimpleSchedule(x => x
        .WithIntervalInMinutes(30)  // 每 30 分鐘執(zhí)行
        .RepeatForever()));         // 無限重復(fù)

還可以控制重復(fù)次數(shù)、開始時(shí)間和結(jié)束時(shí)間:x.WithRepeatCount(10) 表示總共執(zhí)行 10 次后停止。

2. CronSchedule —— Cron 表達(dá)式調(diào)度

當(dāng)需要日歷化的復(fù)雜調(diào)度規(guī)則時(shí)(如"每個(gè)工作日早上 9 點(diǎn)"),使用 Cron 表達(dá)式:

q.AddTrigger(opts => opts
    .ForJob("HelloJob")
    .WithIdentity("cron-trigger")
    .WithCronSchedule("0 0 9 ? * MON-FRI")); // 工作日早上9點(diǎn)

3. Cron 表達(dá)式詳解

Quartz.NET 使用 7 字段(年可選)的 Cron 表達(dá)式:

字段是否必填允許值允許的特殊字符
0-59, - * /
0-59, - * /
小時(shí)0-23, - * /
日期1-31, - * ? / L W
月份1-12 或 JAN-DEC, - * /
星期1-7 或 SUN-SAT, - * ? / L #
空或 1970-2099, - * /

例如 0 0 12 ? * WED 表示"每周三中午 12:00 執(zhí)行"。

常用特殊字符

字符含義示例
*所有值* * * * * ? 表示每秒
?不指定值(日期和星期互斥)日期字段為 ? 時(shí)不關(guān)心具體日期
-范圍MON-FRI 表示周一至周五
,列舉MON,WED,FRI 表示周一、三、五
/增量0/15 在分鐘字段表示每 15 分鐘,從第 0 分鐘開始
L最后L 在日期字段表示當(dāng)月最后一天
#第 N 個(gè)6#3 在星期字段表示第 3 個(gè)周五

常用表達(dá)式示例

0 0/5 * * * ?              # 每 5 分鐘執(zhí)行一次
0 0 2 * * ?                # 每天凌晨 2 點(diǎn)執(zhí)行
0 15 10 ? * MON-FRI        # 周一至周五上午 10:15 執(zhí)行
0 0 9 ? * 6L               # 每月最后一個(gè)周五上午 9 點(diǎn)
0 0/30 9-17 ? * MON-FRI    # 工作日 9:00-17:00 內(nèi)每 30 分鐘執(zhí)行

4. 其他高級(jí)觸發(fā)器

Quartz.NET 還支持 DailyTimeIntervalTrigger,可以方便地定義每日時(shí)間段內(nèi)的調(diào)度:

var trigger = TriggerBuilder.Create()
    .WithIdentity("officeHoursTrigger")
    .WithSchedule(DailyTimeIntervalScheduleBuilder.Create()
        .OnMondayThroughFriday()
        .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(9, 0))
        .EndingDailyAt(TimeOfDay.HourAndMinuteOfDay(17, 0))
        .WithIntervalInHours(2))
    .Build();

五、依賴注入與 Job 工廠

Quartz.NET 天然支持 ASP.NET Core 的依賴注入系統(tǒng)。創(chuàng)建帶依賴的 Job 非常簡單:

// 定義有依賴注入的 Job
public class EmailJob : IJob
{
    private readonly IEmailService _emailService;
    public EmailJob(IEmailService emailService)
    {
        _emailService = emailService;
    }
    public async Task Execute(IJobExecutionContext context)
    {
        await _emailService.SendAsync("定時(shí)郵件", "來自 Quartz.NET 的問候");
    }
}
// 注冊(cè)服務(wù)和 Job
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddQuartz(q =>
{
    q.UseMicrosoftDependencyInjectionJobFactory(); // 啟用 DI 工廠
    q.AddJob<EmailJob>(opts => opts.WithIdentity("EmailJob"));
});

UseMicrosoftDependencyInjectionJobFactory() 告訴 Quartz 使用 Microsoft 的 DI 容器來創(chuàng)建 Job 實(shí)例,這樣構(gòu)造函數(shù)中注入的服務(wù)就能被正確解析。

六、任務(wù)持久化(JobStore)

Quartz.NET 提供兩種存儲(chǔ)模式:

1. RAMJobStore —— 內(nèi)存存儲(chǔ)

默認(rèn)的存儲(chǔ)模式,將所有數(shù)據(jù)保存在內(nèi)存中,速度最快,但應(yīng)用停止或崩潰后任務(wù)信息會(huì)丟失。適合測試環(huán)境或不在意任務(wù)丟失的輕量場景。

2. AdoJobStore —— 數(shù)據(jù)庫持久化

將 Jobs 和 Triggers 存儲(chǔ)到關(guān)系型數(shù)據(jù)庫中,確保任務(wù)在應(yīng)用重啟后不會(huì)丟失,也是集群部署的基礎(chǔ)。

配置步驟

(1)首先創(chuàng)建數(shù)據(jù)庫表——官方提供了 SQL 建表腳本,位于 database/dbtables 目錄下,所有表默認(rèn)以 QRTZ_ 為前綴。

(2)配置連接字符串和 JobStore:

Quartz.NET 4.1 及以上版本支持使用 appsettings.json 進(jìn)行層次化 JSON 配置,更加直觀:

{
  "Quartz": {
    "Scheduler": {
      "InstanceName": "My Scheduler",
      "InstanceId": "AUTO"
    },
    "ThreadPool": {
      "MaxConcurrency": 10
    },
    "JobStore": {
      "Type": "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
      "DataSource": "default",
      "TablePrefix": "QRTZ_"
    },
    "DataSource": {
      "default": {
        "Provider": "SqlServer",
        "ConnectionString": "Server=localhost;Database=quartznet"
      }
    }
  }
}

(3)在代碼中使用 JSON 配置:

builder.Services.AddQuartz(Configuration.GetSection("Quartz"), q =>
{
    // 代碼配置可與 JSON 配置并存
});

七、監(jiān)聽器(Listeners)——AOP 式任務(wù)監(jiān)控

監(jiān)聽器是 Quartz.NET 中實(shí)現(xiàn)任務(wù)監(jiān)控和橫切關(guān)注點(diǎn)(AOP)的關(guān)鍵機(jī)制。通過實(shí)現(xiàn)監(jiān)聽器接口,可以在調(diào)度生命周期中插入自定義邏輯(如日志記錄、性能監(jiān)控、告警通知等)。

1. JobListener —— 監(jiān)聽 Job 事件

接收與 Job 執(zhí)行相關(guān)的三個(gè)事件:

public class LoggingJobListener : JobListenerSupport
{
    public override string Name => "LoggingJobListener";
    public override ValueTask JobToBeExecuted(IJobExecutionContext context)
    {
        Console.WriteLine($"Job [{context.JobDetail.Key}] 即將執(zhí)行...");
        return ValueTask.CompletedTask;
    }
    public override ValueTask JobWasExecuted(IJobExecutionContext context,
        JobExecutionException? jobException)
    {
        if (jobException == null)
            Console.WriteLine($"Job [{context.JobDetail.Key}] 執(zhí)行成功");
        else
            Console.WriteLine($"Job [{context.JobDetail.Key}] 執(zhí)行失敗: {jobException.Message}");
        return ValueTask.CompletedTask;
    }
}

2. TriggerListener —— 監(jiān)聽 Trigger 事件

接收與觸發(fā)器相關(guān)的四個(gè)事件:

public class MetricsTriggerListener : TriggerListenerSupport
{
    public override string Name => "MetricsTriggerListener";
    public override ValueTask TriggerFired(ITrigger trigger, IJobExecutionContext context)
    {
        // 觸發(fā)器觸發(fā)時(shí)記錄指標(biāo)
        return ValueTask.CompletedTask;
    }
    public override ValueTask TriggerMisfired(ITrigger trigger)
    {
        // 處理錯(cuò)過觸發(fā)的情況
        Console.WriteLine($"Trigger [{trigger.Key}] 錯(cuò)過觸發(fā)!");
        return ValueTask.CompletedTask;
    }
}

> 關(guān)鍵提示

  • 異常處理:確保監(jiān)聽器內(nèi)不拋出未捕獲異常,否則可能導(dǎo)致作業(yè)卡死
  • 不持久化:監(jiān)聽器注冊(cè)在運(yùn)行時(shí),不會(huì)存入 JobStore,每次應(yīng)用啟動(dòng)都需重新注冊(cè)
  • 使用輔助基類:繼承 JobListenerSupportTriggerListenerSupport 可以只重寫感興趣的方法

3. 注冊(cè)監(jiān)聽器

監(jiān)聽器通過 ListenerManager 注冊(cè),配合 Matcher 精確控制作用范圍:

scheduler.ListenerManager.AddJobListener(
    myJobListener,
    KeyMatcher<JobKey>.KeyEquals(new JobKey("myJobName", "myJobGroup")));
// 監(jiān)聽特定組的所有 Job
scheduler.ListenerManager.AddJobListener(
    myJobListener,
    GroupMatcher<JobKey>.GroupEquals("myJobGroup"));
// 監(jiān)聽所有 Job
scheduler.ListenerManager.AddJobListener(
    myJobListener,
    GroupMatcher<JobKey>.AnyGroup());

八、高級(jí)特性詳解

1. 集群部署

Quartz.NET 支持多節(jié)點(diǎn)集群,實(shí)現(xiàn)負(fù)載均衡和故障轉(zhuǎn)移。集群模式下,所有節(jié)點(diǎn)共享同一個(gè)數(shù)據(jù)庫(通過 AdoJobStore),通過數(shù)據(jù)庫鎖機(jī)制確保同一個(gè) Job 不會(huì)被多個(gè)節(jié)點(diǎn)同時(shí)執(zhí)行。

配置要點(diǎn)

  • 所有共享同一套數(shù)據(jù)庫和表結(jié)構(gòu)
  • 設(shè)置 org.quartz.jobStore.isClustered = true
  • 各節(jié)點(diǎn)的線程池參數(shù)保持一致
  • 確保各節(jié)點(diǎn)時(shí)鐘同步

適用場景:集群特性最適用于將長時(shí)間運(yùn)行的計(jì)算密集型任務(wù)分布到多個(gè)節(jié)點(diǎn)執(zhí)行,實(shí)現(xiàn)負(fù)載分擔(dān)。

2. 多調(diào)度器(Multiple Schedulers)

從 Quartz.NET 4.x 開始,可以通過 AddQuartz(string name, ...) 創(chuàng)建命名調(diào)度器,實(shí)現(xiàn)工作負(fù)載隔離:

// 快速的內(nèi)存調(diào)度器(用于高頻輕量任務(wù))
builder.Services.AddQuartz("FastScheduler", q =>
{
    q.UseInMemoryStore();
    q.UseDefaultThreadPool(tp => tp.MaxConcurrency = 5);
    q.ScheduleJob<NotificationJob>(trigger => trigger
        .WithSimpleSchedule(x => x.WithIntervalInSeconds(30).RepeatForever()));
});
// 持久化的數(shù)據(jù)庫調(diào)度器(用于關(guān)鍵業(yè)務(wù)任務(wù))
builder.Services.AddQuartz("DurableScheduler", q =>
{
    q.UsePersistentStore(s =>
    {
        s.UseSqlServer(sql => sql.ConnectionString = "your connection string");
    });
    q.ScheduleJob<ReportJob>(trigger => trigger
        .WithCronSchedule("0 0 2 * * ?"));
});
// 單次調(diào)用啟動(dòng)所有命名調(diào)度器
builder.Services.AddQuartzHostedService(options =>
{
    options.WaitForJobsToComplete = true;
});

這種做法可以讓不同的調(diào)度器使用不同的存儲(chǔ)策略、線程池和配置,彼此完全隔離。

3. 動(dòng)態(tài)作業(yè)管理

通過 IScheduler 接口可以在運(yùn)行時(shí)動(dòng)態(tài)管理任務(wù):

// 動(dòng)態(tài)添加作業(yè)
await scheduler.ScheduleJob(jobDetail, trigger);
// 暫停作業(yè)
await scheduler.PauseJob(jobKey);
// 恢復(fù)作業(yè)
await scheduler.ResumeJob(jobKey);
// 刪除作業(yè)
await scheduler.DeleteJob(jobKey);
// 檢查作業(yè)是否存在
bool exists = await scheduler.CheckExists(jobKey);

4. 傳遞參數(shù) —— JobDataMap

JobDataMap 是 Quartz.NET 中向 Job 傳遞參數(shù)的機(jī)制,可以在 Trigger 定義時(shí)或 Scheduler 級(jí)別設(shè)置鍵值對(duì):

// 在 Trigger 定義時(shí)傳遞參數(shù)(示例)
q.AddTrigger(opts => opts
    .ForJob("HelloJob")
    .UsingJobData("RetryCount", "3")
    .UsingJobData("TimeoutSeconds", "30")
    .WithCronSchedule("0 0/10 * * * ?"));

生產(chǎn)建議:CronTrigger 應(yīng)顯式設(shè)置時(shí)區(qū),參數(shù)通過 JobDataMap 傳遞,任務(wù)依賴需手動(dòng)觸發(fā)或使用監(jiān)聽器實(shí)現(xiàn)。

九、Quartz.NET vs Hangfire:如何選型?

兩個(gè)框架都能實(shí)現(xiàn)定時(shí)任務(wù),但定位和適用場景有明顯差異:

維度Quartz.NETHangfire
核心定位企業(yè)級(jí)調(diào)度引擎通用后臺(tái)任務(wù)處理框架
調(diào)度能力復(fù)雜 Cron、日歷調(diào)度、時(shí)間段約束基本 Cron 表達(dá)式
持久化可選(RAM / 數(shù)據(jù)庫)默認(rèn)依賴數(shù)據(jù)庫持久化
可視化面板無(需第三方如 Quartzmin)內(nèi)置 Dashboard
集群支持原生數(shù)據(jù)庫鎖機(jī)制基于持久化存儲(chǔ)的任務(wù)分發(fā)
學(xué)習(xí)曲線較陡峭較平緩
執(zhí)行精度毫秒級(jí)秒級(jí)
最佳場景復(fù)雜調(diào)度策略、金融系統(tǒng)、企業(yè)批處理可靠任務(wù)執(zhí)行、可觀測性要求高的場景

選型建議

  • Hangfire 更適合快速集成、注重任務(wù)可觀測性、需要內(nèi)置 Dashboard 的場景——集成簡單,自帶監(jiān)控面板
  • Quartz.NET 更適合需要精確、復(fù)雜調(diào)度策略的企業(yè)級(jí)系統(tǒng)——支持豐富 Cron 表達(dá)式、日歷間隔等高級(jí)調(diào)度規(guī)則,在復(fù)雜調(diào)度場景下更為靈活

十、最佳實(shí)踐與注意事項(xiàng)

1. Job 設(shè)計(jì)原則

  • 冪等性:Job 邏輯應(yīng)設(shè)計(jì)為可安全重復(fù)執(zhí)行的,避免集群或重試場景下產(chǎn)生重復(fù)數(shù)據(jù)。集群模式下,重復(fù)執(zhí)行需正確配置并保障冪等性
  • 輕量化:Job 的 Execute 方法應(yīng)盡快完成,耗時(shí)長的工作應(yīng)拆分到子任務(wù)或消息隊(duì)列中異步處理
  • 異常處理:在 Execute 方法中妥善處理異常,返回適當(dāng)?shù)?JobExecutionException 以控制重試行為
  • 避免線程阻塞:充分利用 async/await 避免阻塞調(diào)度線程

2. 配置建議

  • 生產(chǎn)環(huán)境必須使用 AdoJobStore,避免應(yīng)用重啟導(dǎo)致任務(wù)丟失
  • 合理設(shè)置線程池大小:MaxConcurrency 應(yīng)根據(jù)任務(wù)特點(diǎn)和服務(wù)器資源調(diào)整,默認(rèn)為 10
  • 配置 WaitForJobsToComplete:優(yōu)雅關(guān)閉時(shí)等待正在執(zhí)行的任務(wù)完成

3. 調(diào)試與排查

  • 利用 LoggingJobHistoryPlugin 記錄每次作業(yè)執(zhí)行歷史
  • 監(jiān)聽器實(shí)現(xiàn)自定義日志和告警
  • 第三方工具如 QuartzminQuartz.NetUI(基于 Vue 的定時(shí)任務(wù)管理系統(tǒng))提供可視化任務(wù)管理

4. 動(dòng)態(tài)作業(yè)管理

  • 將作業(yè)配置存儲(chǔ)在數(shù)據(jù)庫或配置中心,通過代碼動(dòng)態(tài)注冊(cè)而非硬編碼
  • 利用 IScheduler 接口實(shí)現(xiàn)運(yùn)行時(shí)的暫停/恢復(fù)/刪除
  • 慎用 StartNow() 方法,避免應(yīng)用啟動(dòng)時(shí)大量任務(wù)同時(shí)執(zhí)行

十一、資源與擴(kuò)展

  • 官網(wǎng):https://www.quartz-scheduler.net
  • GitHub:https://github.com/quartznet/quartznet
  • 文檔:https://www.quartz-scheduler.net/documentation
  • 擴(kuò)展包:
    Quartz.Extensions.Hosting:ASP.NET Core 托管服務(wù)。
    Quartz.Serialization.SystemTextJson:JSON 序列化支持。
    Quartz.Plugins:提供日志、異常處理等插件。

到此這篇關(guān)于Quartz.NET 全面解析與實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Quartz.NET全面介紹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

广昌县| 库伦旗| 资中县| 沙洋县| 青铜峡市| 剑河县| 西乌珠穆沁旗| 博白县| 大宁县| 孝义市| 榆中县| 上杭县| 七台河市| 白城市| 土默特左旗| 河池市| 全椒县| 洮南市| 北辰区| 社旗县| 金阳县| 嘉兴市| 井陉县| 佛山市| 金昌市| 怀仁县| 天柱县| 蒙自县| 田阳县| 包头市| 莱州市| 梓潼县| 陆丰市| 长武县| 侯马市| 谷城县| 诸暨市| 塔河县| 南陵县| 台南县| 眉山市|