日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > Java > 正文

使用Spring來創(chuàng)建一個(gè)簡單的工作流引擎

2020-01-31 16:52:30
字體:
供稿:網(wǎng)友
文章來源:matrix 作者:Steve Dodge

  摘要
   spring是支持控制反轉(zhuǎn)編程機(jī)制的一個(gè)相對新的框架。本文把spring作為簡單工作流引擎,將它用在了更加通用的地方。在對工作流簡單介紹之后,將要介紹在基本工作流場景中基于Spring的工作流API的使用。

   許多J2EE應(yīng)用程序要求在一個(gè)和主機(jī)分離的上下文中執(zhí)行處理過程。在許多情況下,這些后臺的進(jìn)程執(zhí)行多個(gè)任務(wù),一些任務(wù)依賴于以前任務(wù)的狀態(tài)。由于這些處理任務(wù)之間存在相互依賴的關(guān)系,使用一套基于過程的方法調(diào)用常常不能滿足要求。開發(fā)人員能夠利用Spring來容易地將后臺進(jìn)程分離成活動(dòng)的集合。Spring容器連接這些活動(dòng),并將它們組織成簡單的工作流。

   在本文中,簡單工作流被定義成不需要用戶干預(yù),以一定順序執(zhí)行的任意活動(dòng)的集合。然而,我們并不建議將這種方式代替存在的工作流框架。在一些場景中,需要更多的用戶交互,例如基于用戶輸入而進(jìn)行的轉(zhuǎn)向,連接或傳輸,這時(shí),比較好的方法是配用一個(gè)單獨(dú)的開源或者商業(yè)的工作流引擎。一個(gè)開源項(xiàng)目已經(jīng)成功地將更復(fù)雜的工作流設(shè)計(jì)集成到spring中。

   如果你手上的工作流任務(wù)是簡單的,那么,與功能完備的獨(dú)立工作流框架相比,簡單工作流的策略就會(huì)變得有意義,特別地,如果已經(jīng)使用了spring,這種快速實(shí)現(xiàn)可以保證時(shí)間不會(huì)變得更加漫長。此外,考慮到spring輕量級的控制反轉(zhuǎn)容器的特點(diǎn),spring在資源負(fù)載上減少了資源負(fù)載。

   這篇文章簡短地從編程主題的角度介紹工作流。通過使用工作流的概念,spring被用來作為驅(qū)動(dòng)工作流引擎的框架。然后,討論了生產(chǎn)部署選項(xiàng)。現(xiàn)在,讓我們從工作流的設(shè)計(jì)模式和相關(guān)背景信息來介紹簡單工作流的思想吧。

簡單工作流
   工作流模型是一個(gè)早在70年代就有人開始研究的主題,許多開發(fā)者都試圖創(chuàng)建工作流模型規(guī)范。W.H.M. van der Aalst等人寫了《工作流模型》白皮書(2003年7月),它成功地提煉出一組設(shè)計(jì)模式,這些設(shè)計(jì)模式準(zhǔn)確地將大多數(shù)通用的工作流場景建模。當(dāng)中,最普通的工作流模式是順序模式 (Sequence pattern)。順序工作流模式滿足了簡單工作流的設(shè)計(jì)原則,并且由一組順序執(zhí)行的活動(dòng)組成。

   UML(統(tǒng)一建模語言)活動(dòng)圖通常被用來作為一個(gè)機(jī)制對工作流建模。圖1顯示了一個(gè)基本的使用標(biāo)準(zhǔn)UML活動(dòng)圖對順序工作流過程的建模過程。

圖 1順序工作流模式

  順序工作流是一個(gè)在J2EE中流行的標(biāo)準(zhǔn)工作流模式。J2EE應(yīng)用程序在后臺線程中,通常需要一些順序發(fā)生的事件或者異步事件。圖2中的活動(dòng)圖描述了一個(gè)簡單的工作流,用來通知感興趣的旅行者,他們感興趣的目的地的機(jī)票價(jià)格已經(jīng)下降的事件。

圖 2.機(jī)票價(jià)格下降的簡單工作流

  圖1中的航線工作流負(fù)責(zé)創(chuàng)建和發(fā)送動(dòng)態(tài)的email通知。過程中的每一步表示了一個(gè)活動(dòng)(activity)。在工作流處于活動(dòng)之前,一些額外事件必須發(fā)生。在這個(gè)例子中,事件是飛行路線費(fèi)率的減少。

   讓我們來簡要的看一下航線工作流的業(yè)務(wù)邏輯。如果第一個(gè)活動(dòng)找不到對費(fèi)率減少通知感興趣的用戶,那么整個(gè)工作流就被取消。如果發(fā)現(xiàn)了感興趣的用戶,那么接下來的活動(dòng)繼續(xù)執(zhí)行。隨后,一個(gè)XSL(擴(kuò)展樣式表)轉(zhuǎn)換生成消息內(nèi)容,之后,記錄審計(jì)信息 (audit information)。最后,工作流試圖通過SMTP服務(wù)器發(fā)送這個(gè)消息。如果這個(gè)任務(wù)沒有錯(cuò)誤地完成,便在日志中記錄成功的信息,進(jìn)程結(jié)束。但是,如果在和SMTP服務(wù)器通訊時(shí)發(fā)生了錯(cuò)誤,一個(gè)特別的錯(cuò)誤處理例程將要管理這些錯(cuò)誤。錯(cuò)誤處理代碼將會(huì)試著去重新發(fā)送消息。

   考慮這個(gè)航線的例子,一個(gè)明顯的問題是:你怎么樣有效地將順序處理過程分解為單獨(dú)的活動(dòng)?這個(gè)問題被spring巧妙的處理了。下面,讓我們快速地討論spring的反轉(zhuǎn)控制框架。
控制反轉(zhuǎn)
   Spring通過使用spring容器來負(fù)責(zé)控制對象之間的依賴關(guān)系,使得我們不再對對象之間的依賴負(fù)責(zé)。 這種依賴關(guān)系的實(shí)現(xiàn)就是大家所知道的控制反轉(zhuǎn)(IoC)或依賴注射。參見Martin Fowler's "Inversion of Control Containers and the Dependency Injection Pattern"(martinfowler.com, 2004年2月)得到關(guān)于控制反轉(zhuǎn)和依賴注射的更加深入的討論。通過管理對象之間的依賴關(guān)系,spring就不需要那些只是為了使類能夠相互協(xié)作,而將對象粘合的代碼。

作為spring beans的工作流組件
   在進(jìn)一步討論之前,現(xiàn)在是簡要介紹spring中主要概念的恰當(dāng)時(shí)候。接口ApplicationContext是從接口BeanFactory繼承的,它被用來作為在spring容器內(nèi)實(shí)際的控制實(shí)體和容器。

   ApplicationContext負(fù)責(zé)對一組作為spring beans的一組bean的初始化,配置和生命期管理。我們通過裝配在一個(gè)基于XML的配置文件中的spring beans來配置ApplicationContext。這個(gè)配置文件說明了spring beans互相協(xié)作的本質(zhì)特點(diǎn)。這樣,用spring的術(shù)語來說,與其他spring beans交互的spring beans就被叫著協(xié)作者(collaborators)。缺省情況下,spring beans是作為單例存在于ApplicationContext中的,但是,單例的屬性能夠被設(shè)置為false,從而有效地改變他們在spring中調(diào)用原型模式時(shí)的行為。

   回到我們的例子,在飛機(jī)票價(jià)下降的時(shí)候,一個(gè)SMTP發(fā)送例程的抽象就被裝配在工作流過程例子中的最后的活動(dòng)(例子代碼可以在 Resources中得到)。由于是第5個(gè)活動(dòng),我們命名它為activity5。要發(fā)送消息,activity5就要求一個(gè)代理協(xié)作者和一個(gè)錯(cuò)位處理句柄。

<bean id="activity5" class="org.iocworkflow.test.sequence.ratedrop.SendMessage"> <property name="delegate"> <ref bean="smtpSenderDelegate"></ref> </property> <property name="errorHandler"> <ref bean="mailErrorHandler"/> </property> </bean>


   將工作流組件實(shí)施成spring beans產(chǎn)生了兩個(gè)令人喜悅的結(jié)果,就是容易進(jìn)行單元測試和很大程度上可重用能力。IoC容器的特點(diǎn)明顯地提供了有效的單元測試。使用像spring這樣的Ioc容器,在測試期間,協(xié)作者之間的依賴能夠容易的用假的替代者替代。在這個(gè)航線的例子中,能夠容易地從唯一的測試ApplicationContext中檢索出像activity5活動(dòng)這樣的spring bean。用一個(gè)假的SMTP代理SMTP服務(wù)器,就有可能單獨(dú)地測試activity5。

   第二個(gè)意外的結(jié)果,可重用能力是通過像XSL轉(zhuǎn)換這樣的工作流活動(dòng)實(shí)現(xiàn)的。一個(gè)被抽象成工作流活動(dòng)的XSL轉(zhuǎn)換現(xiàn)在能夠被任何處理XSL轉(zhuǎn)換的工作流所重用。

裝配工作流
   在提供的API中(從Resources下載),spring控制了一些操作者以一種工作流的方式交互。關(guān)鍵接口如下:

   Activity: 封裝了工作流中一個(gè)單步業(yè)務(wù)邏輯

   ProcessContext:在工作流活動(dòng)之間傳遞具有ProcessContext類型的對象。實(shí)現(xiàn)了這個(gè)接口的對象負(fù)責(zé)維護(hù)對象在工作流轉(zhuǎn)換中從一個(gè)活動(dòng)轉(zhuǎn)換到另一個(gè)活動(dòng)的狀態(tài)。

   ErrorHandler: 提供錯(cuò)誤處理的回調(diào)方法。

   Processor: 描述一個(gè)作為主工作流線程的執(zhí)行者的bean。

   下面從例子源碼中摘錄的代碼是將航線例子裝配為簡單工作流過程的spring bean的配置。

<!-- Airline rate drop as a simple sequence workflow process -->
<bean id="rateDropProcessor" class="org.iocworkflow.SequenceProcessor" >
<property name="activities">
<list>
<ref bean="activity1"/><!--Build recipients-->
<ref bean="activity2"/><!--Construct DOM tree-->
<ref bean="activity3"/><!--Apply XSL Transform-->
<ref bean="activity4"/><!--Write Audit Data-->
<ref bean="activity5"/><!--Attempt to send message-->
</list>
</property>
<property name="defaultErrorHandler">
<ref bean="defaultErrorHandler"></ref>
</property>
<property name="processContextClass">
<value>org.iocworkflow.test.sequence.ratedrop.RateDropContext</value>
</property>
</bean>


   SequenceProcessor類是一個(gè)對順序模式建模的具體子類。有5個(gè)活動(dòng)被連接到工作流處理器,工作流處理器將順序執(zhí)行這5個(gè)活動(dòng)。

   與大多數(shù)過程式后臺進(jìn)程相比,工作流的解決方案真正的突出了高度強(qiáng)壯的錯(cuò)誤處理。錯(cuò)誤處理句柄可以單獨(dú)地處理每個(gè)活動(dòng)。這種類型的句柄在單一活動(dòng)級別提供了細(xì)致的錯(cuò)誤處理。如果沒有單獨(dú)處理單個(gè)活動(dòng)的錯(cuò)誤處理句柄,那么全局工作流處理器的錯(cuò)誤處理句柄將會(huì)處理出現(xiàn)的問題。例如,如果在工作流處理過程中的任意時(shí)刻,一個(gè)沒有被處理的錯(cuò)誤出現(xiàn)了,那么它將會(huì)向外傳播,被使用defaultErrorHandler屬性裝配的ErrorHandler Bean處理。

   更復(fù)雜的工作流框架將工作流轉(zhuǎn)換之間的狀態(tài)持久化存儲到數(shù)據(jù)庫中。在這篇文章中,我們僅僅對狀態(tài)轉(zhuǎn)換是自動(dòng)完成的工作流感興趣。狀態(tài)信息僅僅在實(shí)際工作流運(yùn)行時(shí)在ProcessContext中得到。在ProcessContext中,你僅僅能看到ProcessContext的接口的兩個(gè)方法:

public interface ProcessContext extends Serializable
{
public boolean stopProcess();
public void setSeedData(Object seedObject);
}


   用于航線例子工作流的具體的ProcessContext類是RateDropContext類。RateDropContext類封裝了用于執(zhí)行航線費(fèi)率降低工作流必須的數(shù)據(jù)。

   到現(xiàn)在為止,經(jīng)由缺省的ApplicationContext的作用,所有bean實(shí)例都已經(jīng)成了單例。但是,對于每一個(gè)航線工作流的調(diào)用,我們必須創(chuàng)建一個(gè)新的RateDropContext類的實(shí)例。為了處理這種需求,需要配置SequenceProcessor,采用全限定類名作為processContextClass屬性的值。對于每個(gè)工作流的執(zhí)行,SequenceProcessor使用指定的類名從spring檢索ProcessorContext類的一個(gè)新的實(shí)例。為了使這種機(jī)制能夠起作用,非單件的spring bean或者類型org.iocworkflow.test.sequence.simple.SimpleContext的原型必須存在于ApplicationContext中。

播種工作流
   既然我們知道怎樣使用spring來組裝一個(gè)簡單的工作流,就讓我們集中精力使用種子數(shù)據(jù)(seed data)示例工作流的過程。要明白怎樣開始工作流,看一看在實(shí)際接口Processor上表現(xiàn)的方法:

public interface Processor
{
public boolean supports(Activity activity);
public void doActivities();
public void doActivities(Object seedData);
public void setActivities(List activities);
public void setDefaultErrorHandler(ErrorHandler defaultErrorHandler);
}


   大多數(shù)情況下,工作流需要一些初始化激活才能開始。開始一個(gè)處理過程有兩個(gè)選項(xiàng):doActivities(ObjectseedData)方法或者無參數(shù)的doActivities()。下面的代碼列表是包含在樣例代碼中為SequenceProcessor而實(shí)現(xiàn)的doActivities():

public void doActivities(Object seedData)
{
//Retrieve injected by Spring
List activities = getActivities();
//Retrieve a new instance of the Workflow ProcessContext
ProcessContext context = createContext();
if (seedData != null)
context.setSeedData(seedData);
//Execute each activity in sequential order
for (Iterator it = activities.iterator(); it.hasNext();)
{
Activity activity = (Activity) it.next();
try {
context = activity.execute(context);
}
catch (Throwable th) {
//Determine if an error handler is available at the activity level
ErrorHandler errorHandler = activity.getErrorHandler();
if (errorHandler == null) {
getDefaultErrorHandler().handleError(context, th);
break;
}
else {
//Handle error using default handler
errorHandler.handleError(context, th);
}
}
//Ensure it's ok to continue the process
if (processShouldStop(context, activity))
break;
}
}


   在這個(gè)航空費(fèi)用減少的例子中,工作流過程的種子數(shù)據(jù)包括航線信息和費(fèi)率減少的信息。使用容易測試的航線工作流例子,通過doActivities(Object seedData)方法發(fā)出種子數(shù)據(jù)并激活一個(gè)單一的工作流過程是簡單的:

BaseProcessor processor = (BaseProcessor)context.getBean("rateDropProcessor");
processor.doActivities(createSeedData());


   這些代碼是從包含在這篇文章中的測試?yán)又姓浀摹ateDropProcessor Bean是從ApplicationContext中檢索來的。rateDropProcessor實(shí)際上是裝配成SequenceProcessor的實(shí)例來處理順序執(zhí)行。createSeedData()方法實(shí)例化一個(gè)對象,這個(gè)對象封裝了初始化航線工作流所需要的所有種子數(shù)據(jù)。

Processor選項(xiàng)
  雖然包含在源代碼中的Processor具體的子類僅僅是SequenceProcessor,但是,許多Processor接口的實(shí)現(xiàn)也是可以想象得到的。可以開發(fā)其他工作流處理過程子類來控制不同的工作流類型,例如,另一種像并行切割模式那樣有著變化的執(zhí)行路徑的工作流。對于簡單工作流來說,因?yàn)榛顒?dòng)的順序是預(yù)先決定了的,所以SequenceProcessor是好的選擇。盡管沒有被包括進(jìn)來,對于使用基于spring的簡單工作流的實(shí)現(xiàn)來說,排他選擇模式是另一個(gè)好的選擇。當(dāng)使用排他選擇模式時(shí),在每個(gè)活動(dòng)執(zhí)行之后,Processor具體類就會(huì)訊問ProcessorContext,接下來將要執(zhí)行哪一個(gè)活動(dòng)。

   注:有關(guān)并行切割,排他選擇和其他工作流模式的更多信息,請參看W.M.P. van der Aalst等人寫的《工作流模式》一書。

啟動(dòng)工作流
   考慮到工作流過程常常需要異步執(zhí)行的特點(diǎn),使用分離的執(zhí)行線程來啟動(dòng)工作流就變得有意義了。對于工作流的異步啟動(dòng)而言,有好幾個(gè)選項(xiàng);我們主要集中在其中的兩個(gè):積極地檢測(actively polling)一個(gè)隊(duì)列來啟動(dòng)工作流,或者使用通過ESB(enterprise service bus, 企業(yè)服務(wù)總線)的事件驅(qū)動(dòng)方式來啟動(dòng)工作流,而Mule就是ESB的一個(gè)開源項(xiàng)目。

   圖3和圖4描繪了兩種啟動(dòng)策略。圖3中,積極檢測在工作流中第一個(gè)活動(dòng)經(jīng)常檢查資源的情形下發(fā)生,比如數(shù)據(jù)源或POP3郵件帳戶。如果圖3中的積極檢測發(fā)現(xiàn)有任務(wù)等待處理,那么啟動(dòng)就會(huì)開始。

圖 3. 通過積極檢測來啟動(dòng)工作流

  另一方面,圖4表示了使用JMS(JAVA消息服務(wù))的J2EE應(yīng)用程序把事件放到隊(duì)列上的情形。一個(gè)通過ESB配置的事件監(jiān)聽器收到圖4中的事件,并且開始工作流,這樣,啟動(dòng)工作流過程。

圖 4. 通過ESB事件來啟動(dòng)工作流

  使用所提供樣例的代碼,讓我們更詳細(xì)的看看主動(dòng)選擇啟動(dòng)方式與事件驅(qū)動(dòng)的啟動(dòng)方式。


積極檢測
   積極檢測是一種花費(fèi)較少的啟動(dòng)工作流過程的方案。SequenceProcessor足夠靈活,以使得能夠通過平滑的選擇工作來進(jìn)行啟動(dòng)過程。盡管并不令人滿意,在沒有時(shí)間進(jìn)行事件驅(qū)動(dòng)子系統(tǒng)的配置和部署的許多情景中,積極檢測是明智的選擇。

   使用Spring的ScheduledTimerTask,檢測模式就能夠容易地裝配。缺點(diǎn)就是必須創(chuàng)建額外的活動(dòng)來進(jìn)行檢測。這個(gè)檢測活動(dòng)必須被設(shè)計(jì)來訊問某些實(shí)體,如數(shù)據(jù)庫表,pop郵件帳戶,或者Web服務(wù),然后決定新的工作是否等待參與到工作流中。

   在所提供的例子中,PollingTestCase類實(shí)例化一個(gè)基于檢測的工作流過程。使用一個(gè)有著積極檢測處理過程與事件驅(qū)動(dòng)的啟動(dòng)過程的不同之處在于,spring支持doActivities()方法的無參數(shù)版本。相反地,在事件驅(qū)動(dòng)的啟動(dòng)中,啟動(dòng)處理過程的實(shí)體通過doActivities(Object seedData)方法提供了種子數(shù)據(jù)來啟動(dòng)工作流。檢測方法的另一個(gè)缺點(diǎn)是:資源不一定能夠被重復(fù)地使用。依賴于應(yīng)用程序環(huán)境,這種資源的消耗是不可接受的。

   下面代碼例子演示了使用積極檢測來控制工作流啟動(dòng)的一個(gè)活動(dòng):

public class PollForWork implements Activity
{
public ProcessContext execute(ProcessContext context) throws Exception
{
//First check if work needs to be done
boolean workIsReady = lookIntoDatabaseForWork();
if (workIsReady)
{
//The Polling Action must also load any seed data
((MyContext) context).setSeedData(createSeedData());
}
else
{
//Nothing to do, terminate the workflow process for this iteration
((MyContext) context).setStopEntireProcess(true);
}
return context;
}
}


   此外,包含在例子代碼的單元測試中的PollRates類提供了一個(gè)主動(dòng)選舉啟動(dòng)的可以運(yùn)行的例子。PollRates模擬了對于航線費(fèi)率下降的重復(fù)檢查。

通過ESB的事件驅(qū)動(dòng)啟動(dòng)工作流
   理想地,一個(gè)包含了適當(dāng)?shù)姆N子數(shù)據(jù)的線程能夠異步地啟動(dòng)工作流。這種情況的一個(gè)例子是收到從JAVA消息服務(wù)隊(duì)列的消息。一個(gè)監(jiān)聽JMS隊(duì)列或者主題的客戶會(huì)收到通知,這個(gè)通知告知處理應(yīng)該在onMessage()方法中開始工作流。然后,通過使用Spring和doActivities(Object seedData)方法就能夠獲得工作流處理器Bean。

   使用ESB,實(shí)際用于發(fā)送啟動(dòng)事件的機(jī)制能夠恰當(dāng)?shù)貜墓ぷ髁魈幚砥髦蟹蛛x出來。開源項(xiàng)目Mule ESB有緊湊地和Spring相集成的好處。任意傳送機(jī)制,比如JMS,JVM,或者POP3郵箱都能夠發(fā)起事件的傳播。

工作流的連續(xù)運(yùn)行
   工作流引擎后臺進(jìn)程應(yīng)該能夠沒有干擾地連續(xù)運(yùn)行。對于正在運(yùn)行的基于spring的工作流單一進(jìn)程來說好,有幾個(gè)選項(xiàng)。一個(gè)有著main()方法的簡單Java類就足夠演示與這篇文章伴隨著的單元測試中的例子了。一個(gè)更加可靠的用于部署的機(jī)制是嵌入工作流到某種形式的J2EE組件中。Spring很好地支持和J2EE兼容的web應(yīng)用程序歸檔或者war文件的集成。基于Java管理附件(JMX)服務(wù)歸檔和JBoss應(yīng)用服務(wù)器(更多信息,參見JBoss homepage)支持的sar文件是更加合適的可部署組件,這種更合適的可部署組件也能夠被用來將部署歸檔。在JBoss 4.0中,sar文件已經(jīng)被大家所知道的deployer的格式所取代了。

例子代碼
   打包成zip格式的例程代碼最好是用Apache Maven來使用它們。你能夠在主源代碼目錄src/java找到API。src/java目錄中有三個(gè)單元測試,包括:SimpleSequenceTestCase,RateDropTestCase和PoolingTestCase。要運(yùn)行所有這些測試,在命令行shell中鍵入maven test,然后在編譯和運(yùn)行之前,Maven將會(huì)下載所有必需的jar文件。實(shí)際的XSL轉(zhuǎn)換將會(huì)發(fā)生在兩個(gè)測試中,它們的結(jié)果被管道輸出到控制臺。鍵入maven test:ui來拉出圖形化的測試運(yùn)行器,然后選擇你想要運(yùn)行的測試,并且觀察控制臺的結(jié)果。

結(jié)論
   在這篇文章中你已經(jīng)通過設(shè)計(jì)模式看到了工作流過程種類,在這些模式中,我們主要集中介紹了順序模式。通過使用接口,我們來對基本工作流組件建模。通過裝配多個(gè)接口實(shí)現(xiàn)到Spring,實(shí)現(xiàn)一個(gè)順序工作流。最后還討論了啟動(dòng)和部署工作流的不同選項(xiàng)。

   這里所提出的簡單工作流技術(shù)肯定不是最終的和革命性的。但是,使用Spring來實(shí)現(xiàn)像工作流這樣的通用任務(wù)是一個(gè)通過使用IoC容器而獲得的效率的好的示例。由于減少了粘合性代碼的需要,Spring在保持面向?qū)ο蟮募s束同時(shí),減少面向?qū)ο蟛僮髀闊┑某潭取?
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
亚洲中文字幕一区| 欧美三级精品| 伊人网站在线| 国产欧美日韩不卡| 99久久久精品免费观看国产| 日韩亚洲一区中文字幕| 亚洲尤物av| 国产欧美日韩在线看| 免费高清视频日韩| 日韩欧美国产高清| 一区二区不卡在线| 中文字幕线观看| 精品亚洲永久免费| 国产免费久久| a视频免费在线观看| 亚洲一区不卡在线| 国产在线高潮| 在线不卡日本| 国产精久久久久| 午夜亚洲一区| a在线观看免费视频| 久久精品一级爱片| 亚洲三级免费看| 日韩欧美在线视频| 老司机久久99久久精品播放免费| 欧美日韩在线播放三区四区| 欧美日韩一级视频| 日韩美女中文字幕| 国产专区中文字幕| 久久婷婷中文字幕| 999精品在线| 日本黄色一区二区| 欧美一级免费观看| 亚洲久草视频| 欧美日韩在线视频首页| 亚洲日本欧美日韩高观看| 中文亚洲欧美| 中文字幕第一页在线播放| 国产中文在线| 中文字幕在线看视频国产欧美| 国产视频中文字幕| 欧美中文字幕视频在线观看| 日韩视频在线一区| 亚洲图片小说综合| 精品九九久久| 欧美日韩中文精品| 红桃视频亚洲| 欧美日韩性视频一区二区三区| 91久久精品国产| 日韩欧美综合在线| 精品久久久三级| 韩日中文字幕第一页| 91精品国产调教在线观看| 91精品国产91久久久久久不卡| 国产欧美久久久精品免费| 精品国产乱码久久久久久牛牛| 中文字幕亚洲二区 | 国产一级片网站| 亚洲va久久久噜噜噜久久| 欧美亚洲国产日韩2020| 69堂精品视频在线播放| 亚洲视频一二三四| 欧美日韩在线播放视频| 一区二区三区精品在线| 亚洲影视资源网| 欧美国产综合在线V| 欧美中文字幕视频在线观看| 欧美日韩在线精品一区二区三区激情综| 91精品国产网站| 樱花草www在线| 免费视频久久| 日韩免费不卡avV| 日韩在线精品视频| 在线观看区一区二| 99国产成 人 综合 亚洲欧美 | 日韩视频国产视频| 欧美一级搡bbbb搡bbbb| 欧美一级日韩一级| 91色在线看| av手机天堂| 中文字幕在线视频第一页| 91九色在线播放| 午夜高潮免费视频| 91精品国产免费久久综合| 中文字幕高清在线播放| 日韩国产欧美在线视频| 久久精品欧美日韩精品| 中文字幕亚洲一区在线观看| 日韩 欧美 中文| 99久久久精品免费观看国产| 婷婷久久综合九色国产成人| 国产v日产∨综合v精品视频| 日韩中文字幕亚洲| 日韩精品免费观看视频| 欧美国产中文| 欧美中文字幕精品| 精品国产91| 精品日韩av一区二区| 久久在线91| 粉嫩喷白浆久久| 午夜国产福利一区二区| 中文字幕日韩第一页| 九色蝌蚪视频在线| 高清不卡一区二区| 欧美日韩高清不卡| 蜜桃久久av一区| 在线视频亚洲| 久久91精品久久久久久秒播| 欧美久久综合性欧美| 日韩av一区二区在线观看| 麻豆精品99| 欧美久久久网站| 91www成人久久| 日本亚洲视频在线| 日韩av综合在线观看| 欧美日韩激情一区二区三区| 欧美午夜精品在线| 日韩欧美中文第一页| 成人禁用看黄a在线| 欧美在线亚洲一区| 91吃瓜在线观看| 国产在线不卡av| 欧美国产一区视频在线观看| av一区二区高清| 国产永久在线观看| 色www精品视频在线观看| 日韩中文在线字幕| 日韩中文字幕国产| 中文欧美字幕免费| 精品久久久精品| 国产丝袜一区| 国产69精品久久久久孕妇国产69久久 | 日韩在线视频在线观看| 在线欧美一级视频| 国产福利第一页| 国产福利一区二区精品秒拍| 成片免费观看| 天天摸日日摸狠狠添| 欧美中日韩在线| 尤物av一区二区| 久久激情中文| 黄色一级大片在线免费看国产一| 天天在线视频色| 日韩精品丝袜在线| 中文字幕日韩在线视频| 中文字幕在线播放一区| 亚洲第一视频在线观看| 精品播放一区二区| 日韩精品一区二区三区视频播放| 国产午夜精品全部视频播放| 日韩美女视频一区二区在线观看| 午夜一区二区三区| 91精品国产高清久久久久久| 中文欧美字幕免费| 日韩精品一页| 欧美亚洲国产免费| 午夜黄色小视频| 国产视频1区2区| 一区二区视频在线观看免费的| 在线观看一区| 51精品免费网站| 日韩欧美在线网址| 亚洲欧美小说国产图片| 在线观看国产一级片| 久久精品视频免费看| 亚洲专区一区| 91精品国产色综合久久不卡蜜臀| 亚洲男女av一区二区| 色欧美日韩亚洲| 日韩专区视频网站| 国产拍揄自揄精品视频麻豆| 欧美一卡2卡三卡4卡5免费| 精品国产999| www高清在线视频日韩欧美| 国产在线www| 久久av免费| 黄色欧美日韩| 日韩在线三区| 国产三级免费观看| 91精品国产自产在线观看永久∴| 91www成人久久| 亚洲福利精品| 亚洲综合视频一区| 国产在线观看精品| 999精品在线| 欧美久久一二三四区| 日本精品在线播放| 欧美日韩在线精品成人综合网| 日韩中文字幕综合| 在线黄色国产电影| 午夜av一区二区| 日韩精品在线私人| xxxcom在线观看| 精品在线一区二区三区| 一二三区精品福利视频| 久久久久久久久99精品| 欧美日韩夫妻久久| 一区三区视频| 91极品视频在线观看| 日韩美女视频一区二区在线观看| 不卡福利视频| 久久久久久久久99精品| √新版天堂资源在线资源| 国产在线导航| 中文天堂在线一区| 中文字幕久久av| 日韩欧美三级在线| 国产最顶级的黄色片在线免费观看| 日韩欧美在线视频日韩欧美在线视频| 日韩三级在线播放| 92久久精品| 日韩不卡一二区| 不卡在线视频| 精品在线一区二区| 午夜国产福利一区二区| 中文字幕在线观看网址| 国产高清大尺度一区二区不卡| 精品久久久精品| 黄色精品在线观看| 欧美三级视频在线| 国产999在线观看| 1区2区3区在线视频| 樱花草www在线| 国产综合成人久久大片91| 久精品在线观看| 欧美国产日韩在线播放| 日韩视频在线一区二区三区| 尤物av一区二区| 日韩欧美综合| 91国内在线| 国产在线视频不卡| 日韩欧美中文| 国产一级片播放| 久久婷婷亚洲| 亚洲制服丝袜一区| 国产日韩在线视频| 999在线视频| 日本亚洲欧美| 99精品999| 亚洲国产福利视频| 精品欧美日韩| 日韩在线视频免费观看| 中文字幕在线视频久| 亚洲成a人片在线www| 国产乱国产乱老熟300部视频| 欧美日韩国产大片| 日韩午夜中文字幕| 中文字幕在线观看网址| 国产无遮挡在线视频免费观看| 婷婷精品进入| 日韩中文字幕视频网| 99视频精品全国免费| 精品久久久精品| av中文在线播放| 国产三级中文字幕| 亚洲成av人片一区二区密柚| 国产日韩av一区| 欧美三级在线看| 日本熟女一区二区| 欧美三级免费观看| 国产在线黄色| 中文字幕亚洲欧美| 色综合天天综合网天天狠天天| 视频一区不卡| www.狠狠干| 黄色片网站在线| 久久精品国产成人一区二区三区| 欧美日韩第一| 91精品电影| 精品国产网站在线观看| 国产乱国产乱老熟300| 亚洲三级免费看| 精品国产不卡一区二区| 一区二区在线观看不卡| 国产日韩av一区| 黄色一区二区在线| 97视频在线| 日韩一级精品| 国产欧美日韩不卡免费| 国产日韩亚洲欧美| 不卡av免费在线| www.xxxx精品| 激情国产在线| 日韩欧美国产成人精品免费| 蜜桃视频中文字幕| 欧美日韩国产中文精品字幕自在自线| 色99中文字幕| 欧美日韩免费视频| 国产最新在线| 亚洲va久久久噜噜噜久久| 欧美三级中文字幕在线观看| 欧美日韩在线不卡视频| 天堂精品高清1区2区3区| 国产一区不卡精品| 99精品一级欧美片免费播放| 国产一级在线| 樱花草www在线| 中文字幕精品视频在线| 亚洲欧美日本另类| 一区二区三区精品在线| 午夜亚洲福利| 日韩国产亚洲欧美| 色猫猫国产区一区二在线视频| 日韩午夜中文字幕| 精品欧美日韩| 欧美日韩精品三区| 亚洲人线精品午夜| 一区二区91| av中文资源在线| 99久热re在线精彩视频| 在线视频色在线| av一区在线观看| 婷婷中文字幕一区三区| 国产免费一级片| 日韩中文字幕久久| 久草中文在线观看| 日韩欧美专区在线| 中文字幕亚洲一区在线观看| 91精品国产免费| 日韩欧美三级在线| 91欧美在线视频| 亚洲欧洲在线观看av| 欧美国产综合视频| 91麻豆免费视频网站| 日韩精品在线观看网站| 国产视频二区| 91精品无人成人www| 婷婷中文字幕综合| 日韩在线视频免费观看| 亚洲综合日韩| 精品国产99| 91精品在线国产| 91精品国产免费| 午夜亚洲一区| 国产在线拍偷自揄拍精品| 国产天堂素人系列在线视频| 顶级网黄在线播放| 国产欧美日韩中文| 91精品视频播放| 91精品国产99| 欧美日韩日本视频| 粉嫩粉嫩芽的虎白女18在线视频| www.尤物.com| 亚洲福利视频专区| 日韩欧美中文免费| 中文字幕在线观看网址| 国产不卡视频在线| 亚洲一区精品在线| www.狠狠| 日韩免费不卡avV| 日韩欧美国产网站| 91蜜桃在线视频| 中文在线一区二区| 中文精品在线观看| 国产一区久久| 国产福利不卡| 亚州黄色一级| 天堂中文在线视频| 国产亚洲污的网站| 亚洲欧洲精品在线| 国产一区二中文字幕在线看| 91久久久久久久久| 欧美日韩久久不卡| 欧美乱大交xxxxx免费| 日韩精品三级| 最近中文av字幕在线中文| 综合图区亚洲白拍在线| 91精品国产综合久久久久久| 国产福利在线看| 精品国产免费视频| 欧美日韩综合高清一区二区 | 午夜国产在线| av免费在线观看网址| 亚洲福利在线视频| 91精品国产入口| 日韩欧美在线视频日韩欧美在线视频| 亚洲三级国产| 欧美sm一区| 最新中文字幕在线| 精品亚洲永久免费| 欧美亚洲天堂| 国产黄色在线网站| 欧美日韩综合在线观看| 国产小视频在线观看| 樱花草www在线观看| 欧美日韩中文| 国产一区深夜福利| 日韩欧美国产三级| 国产手机视频一区二区| 99热最新网址| 国产免费不卡av| 欧美日韩国产一二| 91精品视频国产| 日韩在线视频免费观看| 国产精久久久久| 国产欧美日韩成人| 日韩免费久久| 在线国产一级| 欧美日韩国产综合网| 日韩精品在线视频|