成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

spring statemachine的企業(yè)可用級開發(fā)指南6-持久化

Jioby / 3099人閱讀

摘要:目前為止,我們都是從狀態(tài)流程的開始階段創(chuàng)建一個狀態(tài)機,然后一路走下去。然后就可以愉快的在里面看怎么用了發(fā)送事件持久化恢復(fù)狀態(tài)機后的狀態(tài)為執(zhí)行完保存后,大家可以自己在客戶端查看以下,是不是有內(nèi)容保存進(jìn)去了。

目前為止,我們都是從狀態(tài)流程的開始階段創(chuàng)建一個狀態(tài)機,然后一路走下去。但在實際業(yè)務(wù)中,狀態(tài)機可能需要在某個環(huán)節(jié)停留,等待其他業(yè)務(wù)的觸發(fā),然后再繼續(xù)下面的流程。比如訂單,可能在支付環(huán)節(jié)需要等待一個剁手的用戶隔天再下單,所以這里面涉及到一個創(chuàng)建的狀態(tài)機該何去何從的問題。在spring statemachine中,給出來的辦法就是保存起來,到需要的時候取出來用。

1、持久化到本地內(nèi)存
嚴(yán)格來說,你完全可以自己保存狀態(tài)機,比如我就自己用map保存下來了。

public class MachineMap {

public static Map> orderMap = new HashMap>();
public static Map> formMap = new HashMap>();

}
這個代碼一看就明白,我用唯一id作為key(order就是orderId,form就是formId),把狀態(tài)機保存到map表里面,在實際的業(yè)務(wù)中,自由存取

@RequestMapping("/sendEvent")

void sendEvent(String machineId,String events,String id) throws Exception{
    if(machineId.equals("form")) {
        StateMachine sm = MachineMap.formMap.get(id);
        Form form = new Form();
        form.setId(id);
        if(sm == null) {
            if(events.equals("WRITE")) {
                sm = formStateMachineBuilder.build(beanFactory);
                sm.start();
                MachineMap.formMap.put(id, sm);
            }else {
                System.out.println("該表單流程尚未開始,不能做"+events+"轉(zhuǎn)換");
                return;
            }
        }
        
        Message message = MessageBuilder.withPayload(FormEvents.valueOf(events)).setHeader("form", form).build();
        sm.sendEvent(message);
    }
    if(machineId.equals("order")) {
        StateMachine sm = MachineMap.orderMap.get(id);
        Order order = new Order();
        order.setId(id);
        if(sm == null) {
            if(events.equals("PAY")) {
                sm = orderStateMachineBuilder.build(beanFactory);
                sm.start();
                MachineMap.orderMap.put(id, sm);
            }else {
                System.out.println("該訂單流程尚未開始,不能做"+events+"轉(zhuǎn)換");
                return;
            }
            
        }
        Message message = MessageBuilder.withPayload(OrderEvents.valueOf(events)).setHeader("order", order).setHeader("test","test1").build();
        sm.sendEvent(message);
    }
}

在這段代碼里面,我根據(jù)不同種類的狀態(tài)機去map取和id對應(yīng)的狀態(tài)機,如果狀態(tài)機沒在map里面,就創(chuàng)建一個,然后塞進(jìn)map表。其實寫這個代碼,并沒有其他意思,只是為了告訴你,spring打算管理你的map表,所以出了一個接口來規(guī)范這件事:

import java.util.HashMap;
import java.util.Map;

import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.stereotype.Component;

/**

在內(nèi)存中持久化狀態(tài)機

*/
@Component
public class InMemoryStateMachinePersist implements StateMachinePersist {

private Map> map = new HashMap>();

@Override
public void write(StateMachineContext context, String contextObj) throws Exception {
    map.put(contextObj, context);
}

@Override
public StateMachineContext read(String contextObj) throws Exception {
    return map.get(contextObj);
}

}
這個接口非常簡單,就是write和read,但他保存的對象是StateMachineContext,不是StateMachine,所以我們還不能直接用它,需要配置一下。

import org.springframework.statemachine.StateMachinePersist;
......
import org.springframework.statemachine.persist.StateMachinePersister;
@Configuration
public class PersistConfig {


@Autowired
private InMemoryStateMachinePersist inMemoryStateMachinePersist;

/**
 * 注入StateMachinePersister對象
 * 
 * @return
 */
@Bean(name="orderMemoryPersister")
public StateMachinePersister getPersister() {
    return new DefaultStateMachinePersister<>(inMemoryStateMachinePersist);
}

}
這里有個坑,InMemoryStateMachinePersist 實現(xiàn)的接口是

org.springframework.statemachine.StateMachinePersist
,但在PersistConfig 里面,getPersister()方法返回的值類型是StateMachinePersister類型,看著很像,但并不是上面的這個接口,而是org.springframework.statemachine.persist.StateMachinePersister接口,為了表示這個坑對我的傷害,我要強調(diào)一下兩個接口:

package org.springframework.statemachine;
public interface StateMachinePersist {

void write(StateMachineContext context, T contextObj) throws Exception;
StateMachineContext read(T contextObj) throws Exception;

}
package org.springframework.statemachine.persist;
import org.springframework.statemachine.StateMachine;
public interface StateMachinePersister {

void persist(StateMachine stateMachine, T contextObj) throws Exception;
StateMachine restore(StateMachine stateMachine, T contextObj) throws Exception;

}
這兩個接口名字很類似,很容易搞混,但下面的是有er的,包名也不同的。StateMachinePersister是可以直接保存StateMachine對象的,所以我們需要先實現(xiàn)上面的StateMachinePersist,然后再一個Config類里面轉(zhuǎn)換成下面的StateMachinePersister,轉(zhuǎn)換的代碼就在上面的PersistConfig類里。

然后我們就能在controller里面使用了

@Resource(name="orderMemoryPersister")
private StateMachinePersister orderMemorypersister;

......

//保存狀態(tài)機
@RequestMapping("/testMemoryPersister")

public void tesMemorytPersister(String id) throws Exception {
    StateMachine stateMachine = orderStateMachineBuilder.build(beanFactory);
    stateMachine.start();
    
    //發(fā)送PAY事件
    stateMachine.sendEvent(OrderEvents.PAY);
    Order order = new Order();
    order.setId(id);
    
    //持久化stateMachine
    orderMemorypersister.persist(stateMachine, order.getId());

}

//取出狀態(tài)機
@RequestMapping("/testMemoryPersisterRestore")

public void testMemoryRestore(String id) throws Exception {
    StateMachine stateMachine = orderStateMachineBuilder.build(beanFactory);
    orderMemorypersister.restore(stateMachine, id);
    System.out.println("恢復(fù)狀態(tài)機后的狀態(tài)為:" + stateMachine.getState().getId());
}

2、持久化到redis
真正的業(yè)務(wù)中,一般都是多臺機分布式運行,所以如果狀態(tài)機只能保存在本地內(nèi)容,就不能用在分布式應(yīng)用上了。spring提供了一個方便的辦法,使用redis解決這個問題。讓我們看看怎么弄。

pom文件引入spring-statemachine-redis

    
        org.springframework.statemachine
        spring-statemachine-redis
        1.2.9.RELEASE
    

在springboot配置文件里面加上redis參數(shù),我這是application.properties

REDIS (RedisProperties) Redis數(shù)據(jù)庫索引(默認(rèn)為0)

spring.redis.database=0

Redis服務(wù)器地址

spring.redis.host=localhost

Redis服務(wù)器連接端口

spring.redis.port=6379

Redis服務(wù)器連接密碼(默認(rèn)為空)

spring.redis.password=

連接池最大連接數(shù)(使用負(fù)值表示沒有限制)

spring.redis.pool.max-active=8

連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)

spring.redis.pool.max-wait=-1

連接池中的最大空閑連接

spring.redis.pool.max-idle=8

連接池中的最小空閑連接

spring.redis.pool.min-idle=0

連接超時時間(毫秒)

spring.redis.timeout=0
保證配置的redis開啟并能用,我們繼續(xù)。回到我們熟悉的PersistConfig

@Configuration
public class PersistConfig {

@Autowired
private RedisConnectionFactory redisConnectionFactory;


/**
 * 注入RedisStateMachinePersister對象
 * 
 * @return
 */
@Bean(name = "orderRedisPersister")
public RedisStateMachinePersister redisPersister() {
    return new RedisStateMachinePersister<>(redisPersist());
}

/**
 * 通過redisConnectionFactory創(chuàng)建StateMachinePersist
 * 
 * @return
 */
public StateMachinePersist redisPersist() {
    RedisStateMachineContextRepository repository = new RedisStateMachineContextRepository<>(redisConnectionFactory);
    return new RepositoryStateMachinePersist<>(repository);
}

}
這個套路和上面保存到本地內(nèi)存是一樣一樣的,先生成一個StateMachinePersist,這里是通過RedisConnectionFactory生成RepositoryStateMachinePersist,然后再包裝輸出StateMachinePersister,這里是RedisStateMachinePersister。然后就可以愉快的在controller里面看怎么用了

@Resource(name="orderRedisPersister")
private StateMachinePersister orderRedisPersister;

......

@RequestMapping("/testRedisPersister")

public void testRedisPersister(String id) throws Exception {
    StateMachine stateMachine = orderStateMachineBuilder.build(beanFactory);
    stateMachine.start();
    Order order = new Order();
    order.setId(id);
    //發(fā)送PAY事件
    Message message = MessageBuilder.withPayload(OrderEvents.PAY).setHeader("order", order).build();
    stateMachine.sendEvent(message);
    //持久化stateMachine
    orderRedisPersister.persist(stateMachine, order.getId());
}

@RequestMapping("/testRedisPersisterRestore")
public void testRestore(String id) throws Exception {
    StateMachine stateMachine = orderStateMachineBuilder.build(beanFactory);
    orderRedisPersister.restore(stateMachine, id);
    System.out.println("恢復(fù)狀態(tài)機后的狀態(tài)為:" + stateMachine.getState().getId());
}

執(zhí)行完redis保存statemachine后,大家可以自己在redis客戶端查看以下,是不是有內(nèi)容保存進(jìn)去了。

3、下期預(yù)告
無論是本地內(nèi)存還是分布式緩存,似乎都不是很可靠的持久化,但下一章會告訴大家,保不保存也就那么點大的事,沒保存我們就再創(chuàng)建一個就好了。但另外一個問題就浮出水面了,狀態(tài)機執(zhí)行到中間的時候創(chuàng)建狀態(tài)機,怎么在中間繼續(xù)執(zhí)行,之前的可都是從頭開始執(zhí)行的,這個問題,下一章解決。

碼云配套代碼地址

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74992.html

相關(guān)文章

  • spring statemachine企業(yè)可用開發(fā)指南7-偽久化和中間段狀態(tài)機

    摘要:在實際的企業(yè)開發(fā)中,不可能所有情況都是從頭到尾的按狀態(tài)流程來,會有很多意外,比如歷史數(shù)據(jù),故障重啟后的遺留流程,所以這種可以任意調(diào)節(jié)狀態(tài)的才是我們需要的狀態(tài)機。 1、偽持久化和中間段的狀態(tài)機我們設(shè)想一個業(yè)務(wù)場景,就比如訂單吧,我們一般的設(shè)計都會把訂單狀態(tài)存到訂單表里面,其他的業(yè)務(wù)信息也都有表保存,而狀態(tài)機的主要作用其實是規(guī)范整個訂單業(yè)務(wù)流程的狀態(tài)和事件,所以狀態(tài)機要不要保存真的不重要,...

    shiyang6017 評論0 收藏0
  • spring statemachine企業(yè)可用開發(fā)指南5-傳遞參數(shù)message

    摘要:創(chuàng)建了后,狀態(tài)機就可以不只是傳一個,可以組合和數(shù)據(jù)內(nèi)容一起發(fā)送給狀態(tài)機變化的處理類了。到這里為止,狀態(tài)機通過對象就和其他的業(yè)務(wù)代碼做到了數(shù)據(jù)連接。 在企業(yè)開發(fā)中,數(shù)據(jù)在不同的業(yè)務(wù)間傳輸是最常見的工作,所以雖然我們的主架構(gòu)是用的狀態(tài)機,也就是從流程狀態(tài)的角度來看待這個項目,但在具體業(yè)務(wù)中,每個狀態(tài)的轉(zhuǎn)變中會牽涉到各類業(yè)務(wù),這些業(yè)務(wù)有些需要收到狀態(tài)機變化的通知,需要把狀態(tài)值傳遞給業(yè)務(wù)類和業(yè)...

    YacaToy 評論0 收藏0
  • spring statemachine企業(yè)可用開發(fā)指南3-多個狀態(tài)機共存

    摘要:雖然多個狀態(tài)機的問題解決了,但是對于實際的企業(yè)應(yīng)用而言,還是有問題。這個問題就用到了狀態(tài)機的持久化,我們下一章就談?wù)劤志没瘑栴}。 1、多個狀態(tài)機的搞法在實際的企業(yè)應(yīng)用中,基本不可能只有一個狀態(tài)機流程在跑,比如訂單,肯定是很多個訂單在運行,每個訂單都有自己的訂單狀態(tài)機流程,但上一章的例子,大家可以試一下,當(dāng)執(zhí)行到一個狀態(tài)時,再次刷新頁面,不會有任何日志出現(xiàn),當(dāng)一個狀態(tài)流程執(zhí)行到某個狀態(tài),...

    zhongmeizhi 評論0 收藏0
  • spring statemachine企業(yè)可用開發(fā)指南1-說些廢話

    摘要:讓我們先看下狀態(tài)機的概念。下面是狀態(tài)機模型中的個要素,即現(xiàn)態(tài)條件動作次態(tài)。因為訂單和審批公文都有很多的流程,每個流程都會產(chǎn)生狀態(tài)的變化,而且流程是這種業(yè)務(wù)的主軸,其他都是圍繞這個流程和狀態(tài)變化來考慮的,所以看起來蠻適合用狀態(tài)機來做。 1、背景在我打算學(xué)習(xí)spring statemachine的時候,我?guī)缀蹩催^了所有網(wǎng)上的中文教程,基本上都處于淺嘗輒止的階段,有幾篇講的比較深入的,都只是...

    BakerJ 評論0 收藏0
  • spring statemachine企業(yè)可用開發(fā)指南4-多種狀態(tài)機共存

    摘要:目前為止,多個狀態(tài)機和多種狀態(tài)機都可以在里面實現(xiàn)了,下一章我們來解決下狀態(tài)機和實際業(yè)務(wù)間的數(shù)據(jù)傳輸問題,畢竟我們不是為了讓狀態(tài)機自個獨自玩耍,和業(yè)務(wù)數(shù)據(jù)互通有無才是企業(yè)開發(fā)的正道。 在上一章的例子中,我們實現(xiàn)了多個狀態(tài)機并存執(zhí)行,不同的訂單有各自的狀態(tài)機運行,但只有一種狀態(tài)機,這顯然不能滿足實際業(yè)務(wù)的要求,比如我就遇到了訂單流程和公文審批流程在同一個項目的情況,所以我們這一章講怎么讓多...

    boredream 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<