傳小米電動車已進入量產 售價新台幣 20 萬有找

小米在智慧型手機及資訊領域攻城掠地後,顯然創辦人雷軍並未因此滿足,打從更早之前就一直有傳聞小米想要打造車子,而且還是高技術門檻的電動車,如今又有進一步消息指稱,小米電動車已經進入量產階段。   身為 Tesla 在中國市場的第一批車主,雷軍也曾多次親自拜訪 Tesla 的執行長 Elon Musk,交流許多關於電動車的未來、以及對智慧車輛的看法,近期中國網路上盛傳,內部代號「米斯拉」的小米牌電動車已經開始量產,甚至連其代工合作夥伴為比亞迪等資訊都被揭露。   消息也指出,米斯拉除了會是台電動車外,還會搭載小米自家的 MIUI 系統,將擁有豐富的智慧聯網功能;更驚人的是,這樣的一台高科技智慧電動車,售價僅要 39,999 人民幣,折合新台幣不過 20 萬有找,若此消息為真,小米將會在車界掀起另一波破壞巨浪。    

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

油價大跌 陸新能源汽車銷售目標恐難達成

國際原油每桶已跌破 55 美元,這對大陸正在推動新能源汽車恐怕將踢到鐵板,尤其是明年銷售 50 萬輛的目標很難達陣。大陸正致力推動的新能源政策,也將出現減速的阻力,包括太陽能等替代能源產業,都在這次國際油價重跌後,面臨無以為繼的結果。   《南方周末》報導,國際油價下跌,新能源汽車首當其衝,其中以中國電動車龍頭企業比亞迪受傷最重,原本就賣不動的電動車,在油價直直落後,不少消費者根本對電動車無感。   據悉,工信部副部長蘇波除到比亞迪考察新能源汽車發展和推廣情況外,更召集相關部會舉行節能與新能源汽車產業發展部際聯席會議聯絡員會議,除了發改委、科技部、財政部等 18 個部際聯席會議成員單位,還邀請國管局、國土資源部參加,規模空前,顯見中國政府也預見新能源汽車受油價影響,政府訂定的銷售目標恐難以達陣。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

硬件對同步的支持-TAS和CAS指令

目錄

  • Test and Set
  • Compare and Swap
    • 使用CAS實現線程安全的數據結構。

現在主流的多處理器架構都在硬件水平上提供了對併發同步的支持。
今天我們討論兩個很重要的硬件同步指令:Test-and-Set和Compare-and-Swap

Test and Set

一個Test-and-Set(TAS)指令包括兩個子步驟,把給定的內存地址設置為1,然後返回之前的舊值。
這兩個子步驟在硬件上實現為一個原子操作,執行期間不會被其他處理器打斷。
(一個CPU可以使用諸如Dual-port RAM电子原件提供的TAS指令,此外,CPU自身也可以提供CAS指令)
值得注意的是,TAS指令是在單個內存word(或字節)上實現,這限制了變量非0即1,並且TAS總是把變量設置為1。
可見,TAS生而為自旋鎖,下面是使用TAS實現自旋鎖的偽代碼[2]:

lock = 0 //shared state
while(test_and_set(lock)==0){ //try lock
       //do nothing   
}
// 臨界區代碼
lock = 0   //release 

當第一個線程執行這段代碼時,TAS指令會立即把lock設置為1,並返回0 ,線程退出while循環進入臨界區。
如果另一個線程嘗試進入臨界區,TAS會把lock設置為1,但是也會返回1(由第一個線程的TAS指令設置為1),
此時第二個線程會一直while循環(忙等待),直到第一個線程退出臨界區代碼,執行了lock=0,即釋放了鎖。
這種通過while-loop等待獲取鎖的實現稱為自旋鎖(spin lock)。

Compare and Swap

compare-and-swap(CAS)指令和TAS指令類似,但是比TAS要更複雜。
與TAS只有一個參數不同,CAS指令需要三個參數,一個內存位置(V)、一個期望舊值(A)、一個新值(B)。
CAS指令的執行過程:

1.比較內存V的值是否與A相等?
2.如果相等,則用新值B替換內存位置V的舊值
3.如果不相等,不做任何操作。
4.無論哪個情況,CAS都會把內存V原來的值返回。

偽代碼:

int CAS(int *ptr,int oldvalue,int newvalue)
{
   int temp = *ptr;
   if(*ptr == oldvalue)
       *ptr = newvalue
   return temp;
}

以上過程在CAS指令中是原子操作。
CAS支持32bit/64bit的數據類型,這使得CAS能夠實現一些更複雜的自旋鎖。

使用CAS實現線程安全的數據結構。

我們使用CAS實現一個併發的平衡二叉搜索樹。[1]
基本思路是,所有的更新操作都要在二叉樹的副本上進行,更新完成后,使用CAS指令把新的根節點引用替換舊的引用。

//共享變量
  root = pointer to the root of the tree
//插入操作
do
  old_root = root
  new_root = new Tree
  # copy old_root into new_root
  # do insertion into new_root
until compare_and_swap (root, old_root, new_root) == old_root
平衡操作:
do
  old_root = root
  new_root = balanced_copy_of (old_root)
until compare_and_swap (root, old_root, new_root) == old_root

如果并行的執行平衡操作和插入操作,插入操作完成後會把二叉樹的根節點指向新的引用。
等到平衡操作完成后,compare_and_swap將會失敗,因為此時根節點指向了插入操作產生的新地址,不再等於old_root,
平衡操作會重複循環執行,直到成功更新根節點。
同樣的,如果平衡操作先於插入操作完成,插入操作的CAS指令也會失敗(根節點已指向平衡操作產生的新地址),然後插入操作重複循環,直到成功。

基於CAS指令可以實現基礎的信號量、互斥量之外,還可以實現更複雜的lock-free和wait-free算法。

延伸閱讀:

1.康奈爾大學操作系統課件:Architectural support for synchronization
2.wiki:Test-and-Set指令
3.wiki:Compare-and-swap指令
4.TAS vs CAS

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

akka-typed(8) – CQRS讀寫分離模式

 前面介紹了事件源(EventSource)和集群(cluster),現在到了討論CQRS的時候了。CQRS即讀寫分離模式,由獨立的寫方程序和讀方程序組成,具體原理在以前的博客里介紹過了。akka-typed應該自然支持CQRS模式,最起碼本身提供了對寫方編程的支持,這點從EventSourcedBehavior 可以知道。akka-typed提供了新的EventSourcedBehavior-Actor,極大方便了對persistentActor的應用開發,但同時也給編程者造成了一些限制。如手工改變狀態會更困難了、EventSourcedBehavior不支持多層式的persist,也就是說通過persist某些特定的event然後在event-handler程序里進行狀態處理是不可能的了。我這裡有個例子,是個購物車應用:當完成支付后需要取個快照(snapshot),下面是這個snapshot的代碼:

 snapshotWhen { (state,evt,seqNr) => CommandHandler.takeSnapshot(state,evt,seqNr) } ... def takeSnapshot(state: Voucher, evt: Events.Action, lstSeqNr: Long)(implicit pid: PID) = { if (evt.isInstanceOf[Events.PaymentMade] || evt.isInstanceOf[Events.VoidVoucher.type] || evt.isInstanceOf[Events.SuspVoucher.type]) if (state.items.isEmpty) { log.step(s"#${state.header.num} taking snapshot at [$lstSeqNr] ...") true } else
        false
    else
      false

}

判斷event類型是沒有問題的,因為正是當前的事件,但另一個條件是購物車必須是清空了的。這個有點為難,因為這個狀態要依賴這幾個event運算的結果才能確定,也就是下一步,但確定結果又需要對購物車內容進行計算,好像是個死循環。在akka-classic里我們可以在判斷了event運算結果后,如果需要改變狀態就再persist一個特殊的event,然後在這個event的handler進行狀態處理。沒辦法,EventSourcedBehavior不支持多層persist,只有這樣做:

 

      case PaymentMade(acct, dpt, num, ref,amount) => ... writerInternal.lastVoucher = Voucher(vchs, vItems) endVoucher(Voucher(vchs,vItems),TXNTYPE.sales) Voucher(vchs.nextVoucher, List()) ...  

 

我只能先吧當前狀態保存下來、進行結單運算、然後清空購物車,這樣snapshot就可以順利進行了。

好了,akka的讀方編程是通過PersistentQuery實現的。reader的作用就是把event從數據庫讀出來后再恢復成具體的數據格式。我們從reader的調用了解一下這個應用里reader的實現細節:

 

    val readerShard = writerInternal.optSharding.get val readerRef = readerShard.entityRefFor(POSReader.EntityKey, s"$pid.shopId:$pid.posId") readerRef ! Messages.PerformRead(pid.shopid, pid.posid,writerInternal.lastVoucher.header.num,writerInternal.lastVoucher.header.opr,bseq,eseq,txntype,writerInternal.expurl,writerInternal.expacct,writerInternal.exppass)

可以看到這個reader是一個集群分片,sharding-entity。想法是每單完成購買后發個消息給一個entity、這個entity再完成reader功能后自動終止,立即釋放出佔用的資源。reader-actor的定義如下:

object POSReader extends LogSupport { val EntityKey: EntityTypeKey[Command] = EntityTypeKey[Command]("POSReader") def apply(nodeAddress: String, trace: Boolean): Behavior[Command] = { log.stepOn = trace implicit var pid: PID = PID("","") Behaviors.supervise( Behaviors.setup[Command] { ctx => Behaviors.withTimers { timer =>
          implicit val ec = ctx.executionContext Behaviors.receiveMessage { case PerformRead(shopid, posid, vchnum, opr, bseq, eseq, txntype, xurl, xacct, xpass) => pid = PID(shopid, posid) log.step(s"POSReader: PerformRead($shopid,$posid,$vchnum,$opr,$bseq,$eseq,$txntype,$xurl,$xacct,$xpass)")(PID(shopid, posid)) val futReadSaveNExport = for { txnitems <- ActionReader.readActions(ctx, vchnum, opr, bseq, eseq, trace, nodeAddress, shopid, posid, txntype) _ <- ExportTxns.exportTxns(xurl, xacct, xpass, vchnum, txntype == Events.TXNTYPE.suspend, { if(txntype == Events.TXNTYPE.voidall) txnitems.map (_.copy(txntype=Events.TXNTYPE.voidall)) else txnitems }, trace)(ctx.system.toClassic, pid) } yield () ctx.pipeToSelf(futReadSaveNExport) { case Success(_) => { timer.startSingleTimer(ReaderFinish(shopid, posid, vchnum), readInterval.seconds) StopReader } case Failure(err) => log.error(s"POSReader: Error: ${err.getMessage}") timer.startSingleTimer(ReaderFinish(shopid, posid, vchnum), readInterval.seconds) StopReader } Behaviors.same case StopReader => Behaviors.same case ReaderFinish(shopid, posid, vchnum) => Behaviors.stopped( () => log.step(s"POSReader: {$shopid,$posid} finish reading voucher#$vchnum and stopped")(PID(shopid, posid)) ) } } } ).onFailure(SupervisorStrategy.restart) }

reader就是一個普通的actor。值得注意的是讀方程序可能是一個龐大複雜的程序,肯定需要分割成多個模塊,所以我們可以按照流程順序進行模塊功能切分:這樣下面的模塊可能會需要上面模塊產生的結果才能繼續。記住,在actor中絕對避免阻塞線程,所有的模塊都返回Future, 然後用for-yield串起來。上面我們用了ctx.pipeToSelf 在Future運算完成后發送ReaderFinish消息給自己,通知自己停止。

在這個例子里我們把reader任務分成:

1、從數據庫讀取事件

2、事件重演一次產生狀態數據(購物車內容)

3、將形成的購物車內容作為交易單據項目存入數據庫

4、向用戶提供的restapi輸出交易數據

event讀取是通過cassandra-persistence-plugin實現的:

    val query = PersistenceQuery(classicSystem).readJournalFor[CassandraReadJournal](CassandraReadJournal.Identifier) // issue query to journal
    val source: Source[EventEnvelope, NotUsed] = query.currentEventsByPersistenceId(s"${pid.shopid}:${pid.posid}", startSeq, endSeq) // materialize stream, consuming events
    val readActions: Future[List[Any]] = source.runFold(List[Any]()) { (lstAny, evl) => evl.event :: lstAny }

這部分比較簡單:定義一個PersistenceQuery,用它產生一個Source,然後run這個Source獲取Future[List[Any]]。

重演事件產生交易數據:

    def buildVoucher(actions: List[Any]): List[TxnItem] = { log.step(s"POSReader: read actions: $actions") val (voidtxns,onlytxns) = actions.asInstanceOf[Seq[Action]].pickOut(_.isInstanceOf[Voided]) val listOfActions = onlytxns.reverse zip (LazyList from 1)   //zipWithIndex
      listOfActions.foreach { case (txn,idx) => txn.asInstanceOf[Action] match { case Voided(_) =>
          case ti@_ => curTxnItem = EventHandlers.buildTxnItem(ti.asInstanceOf[Action],vchState).copy(opr=cshr) if(voidtxns.exists(a => a.asInstanceOf[Voided].seq == idx)) { curTxnItem = curTxnItem.copy(txntype = TXNTYPE.voided, opr=cshr) log.step(s"POSReader: voided txnitem: $curTxnItem") } val vch = EventHandlers.updateState(ti.asInstanceOf[Action],vchState,vchItems,curTxnItem,true) vchState = vch.header vchItems = vch.txnItems log.step(s"POSReader: built txnitem: ${vchItems.txnitems.head}") } } log.step(s"POSReader: voucher built with state: $vchState, items: ${vchItems.txnitems}") vchItems.txnitems }

重演List[Event],產生了List[TxnItem]。

向數據庫里寫List[TxnItem]:

 

 def writeTxnsToDB(vchnum: Int, txntype: Int, bseq: Long, eseq: Long, txns: List[TxnItem])( implicit system: akka.actor.ActorSystem, session: CassandraSession, pid: PID): Future[Seq[TxnItem]] = ???

注意返回結果類型Future[Seq[TxnItem]]。我們用for-yield把這幾個動作串起來:

  val txnitems: Future[List[Events.TxnItem]] = for { lst1 <- readActions    //read list from Source
      lstTxns <- if (lst1.length < (endSeq -startSeq))    //if imcomplete list read again
 readActions else FastFuture.successful(lst1) items <- FastFuture.successful( buildVoucher(lstTxns) ) _ <- JournalTxns.writeTxnsToDB(vchnum,txntype,startSeq,endSeq,items) _ <- session.close(ec) } yield items

注意返回結果類型Future[Seq[TxnItem]]。我們用for-yield把這幾個動作串起來:

  val txnitems: Future[List[Events.TxnItem]] = for { lst1 <- readActions    //read list from Source
      lstTxns <- if (lst1.length < (endSeq -startSeq))    //if imcomplete list read again
 readActions else FastFuture.successful(lst1) items <- FastFuture.successful( buildVoucher(lstTxns) ) _ <- JournalTxns.writeTxnsToDB(vchnum,txntype,startSeq,endSeq,items) _ <- session.close(ec) } yield items

注意:這個for返回的Future[List[TxnItem]],是提供給restapi輸出功能的。在那裡List[TxnItem]會被轉換成json作為post的包嵌數據。

現在所有子任務的返回結果類型都是Future了。我們可以再用for來把它們串起來:

             val futReadSaveNExport = for { txnitems <- ActionReader.readActions(ctx, vchnum, opr, bseq, eseq, trace, nodeAddress, shopid, posid, txntype) _ <- ExportTxns.exportTxns(xurl, xacct, xpass, vchnum, txntype == Events.TXNTYPE.suspend, { if(txntype == Events.TXNTYPE.voidall) txnitems.map (_.copy(txntype=Events.TXNTYPE.voidall)) else txnitems }, trace)(ctx.system.toClassic, pid) } yield ()

說到EventSourcedBehavior,因為用了cassandra-plugin,忽然想起配置文件里新舊有很大區別。現在這個application.conf是這樣的: 

akka { loglevel = INFO actor { provider = cluster serialization-bindings { "com.datatech.pos.cloud.CborSerializable" = jackson-cbor } } remote { artery { canonical.hostname = "192.168.11.189" canonical.port = 0 } } cluster { seed-nodes = [ "akka://cloud-pos-server@192.168.11.189:2551"] sharding { passivate-idle-entity-after = 5 m } } # use Cassandra to store both snapshots and the events of the persistent actors persistence { journal.plugin = "akka.persistence.cassandra.journal" snapshot-store.plugin = "akka.persistence.cassandra.snapshot" } } akka.persistence.cassandra { # don't use autocreate in production
  journal.keyspace = "poc2g" journal.keyspace-autocreate = on journal.tables-autocreate = on snapshot.keyspace = "poc2g_snapshot" snapshot.keyspace-autocreate = on snapshot.tables-autocreate = on } datastax-java-driver { basic.contact-points = ["192.168.11.189:9042"] basic.load-balancing-policy.local-datacenter = "datacenter1" }

akka.persitence.cassandra段落里可以定義keyspace名稱,這樣新舊版本應用可以共用一個cassandra,同時在線。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

Spring Security 之 rememberMe 自動登錄

自動登錄是將用戶的登錄信息保存在用戶瀏覽器的cookie中,當用戶下次訪問時,自動實現校驗並建立登錄態的一種機制。
Spring Security提供了兩種非常好的令牌:

  • 散列算法加密用戶必要的登錄信息並生成令牌
  • 數據庫等持久性數據存儲機制用的持久化令牌

散列加密方案

在Spring Security中加入自動登錄的功能非常簡單:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/user/**").hasRole("user")  //user 角色訪問/api/user/開頭的路由
                .antMatchers("/api/admin/**").hasRole("admin") //admin 角色訪問/api/admin/開頭的路由
                .antMatchers("/api/public/**").permitAll()                 //允許所有可以訪問/api/public/開頭的路由
                .and()
                .formLogin()
                .and()
                .rememberMe().userDetailsService(userDetailsService());      //記住密碼
    }


重啟服務后訪問受限 API,這次在表單登錄頁中多了一個可選框:

勾選“Remember me on this computer”可選框(簡寫為Remember-me),按照正常的流程登錄,並在開發者工具中查看瀏覽器cookie,可以看到除JSESSIONID外多了一個值:

這是Spring Security默認自動登錄的cookie字段。在不配置的情況下,過期時間是兩個星期:

Spring Security會在每次表單登錄成功之後更新此令牌,具體處理方式在源碼中:

RememberConfigurer:

持久化令牌方案

在持久化令牌方案中,最核心的是series和token兩個值,它們都是用MD5散列過的隨機字符串。不同的是,series僅在用戶使用密碼重新登錄時更新,而token會在每一個新的session中都重新生成。
解決了散列加密方案中一個令牌可以同時在多端登錄的問題。每個會話都會引發token的更
新,即每個token僅支持單實例登錄。
自動登錄不會導致series變更,而每次自動登錄都需要同時驗證series和token兩個值,當該
令牌還未使用過自動登錄就被盜取時,系統會在非法用戶驗證通過後刷新 token 值,此時在合法用戶
的瀏覽器中,該token值已經失效。當合法用戶使用自動登錄時,由於該series對應的 token 不同,系統
可以推斷該令牌可能已被盜用,從而做一些處理。例如,清理該用戶的所有自動登錄令牌,並通知該
用戶可能已被盜號等
Spring Security使用PersistentRememberMeToken來表明一個驗證實體:

public class PersistentRememberMeToken {
    private final String username;
    private final String series;
    private final String tokenValue;
    private final Date date;

    public PersistentRememberMeToken(String username, String series, String tokenValue, Date date) {
        this.username = username;
        this.series = series;
        this.tokenValue = tokenValue;
        this.date = date;
    }

    public String getUsername() {
        return this.username;
    }

    public String getSeries() {
        return this.series;
    }

    public String getTokenValue() {
        return this.tokenValue;
    }

    public Date getDate() {
        return this.date;
    }
}

需要使用持久化令牌方案,需要傳入PersistentTokenRepository的實例:

PersistentTokenRepository接口主要涉及token的增刪查改四個接口:

MyPersistentTokenRepositoryImpl使我們實現PersistentTokenRepository接口:

@Service
public class MyPersistentTokenRepositoryImpl implements PersistentTokenRepository {

    @Autowired
    private JPAPersistentTokenRepository  repository;

    @Override
    public void createNewToken(PersistentRememberMeToken persistentRememberMeToken) {
        MyPersistentToken myPersistentToken = new MyPersistentToken();
        myPersistentToken.setSeries(persistentRememberMeToken.getSeries());
        myPersistentToken.setUsername(persistentRememberMeToken.getUsername());
        myPersistentToken.setTokenValue(persistentRememberMeToken.getTokenValue());
        myPersistentToken.setUser_last(persistentRememberMeToken.getDate());
        repository.save(myPersistentToken);
    }

    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed) {
        MyPersistentToken myPersistentToken = repository.findBySeries(series);
        myPersistentToken.setUser_last(lastUsed);
        myPersistentToken.setTokenValue(tokenValue);
        repository.save(myPersistentToken);
    }

    @Override
    public PersistentRememberMeToken getTokenForSeries(String series) {
        MyPersistentToken myPersistentToken = repository.findBySeries(series);
        PersistentRememberMeToken persistentRememberMeToken = new PersistentRememberMeToken(myPersistentToken.getUsername(), myPersistentToken.getSeries(), myPersistentToken.getTokenValue(), myPersistentToken.getUser_last());
        return persistentRememberMeToken;
    }

    @Override
    @Transactional
    public void removeUserTokens(String username) {
        repository.deleteByUsername(username);
    }
}
public interface JPAPersistentTokenRepository extends JpaRepository<MyPersistentToken,Long> {
    MyPersistentToken findBySeries(String series);
    void deleteByUsername(String username);
}
@Entity
@Table(name = "persistent_token")
public class MyPersistentToken {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private  String username;
    @Column(unique = true)
    private  String series;
    private  String tokenValue;
    private  Date user_last;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSeries() {
        return series;
    }

    public void setSeries(String series) {
        this.series = series;
    }

    public String getTokenValue() {
        return tokenValue;
    }

    public void setTokenValue(String tokenValue) {
        this.tokenValue = tokenValue;
    }

    public Date getUser_last() {
        return user_last;
    }

    public void setUser_last(Date user_last) {
        this.user_last = user_last;
    }
}

當自動登錄認證時,Spring Security 通過series獲取用戶名、token以及上一次自動登錄時間三個信息,通過用戶名確認該令牌的身份,通過對比 token 獲知該令牌是否有效,通過上一次自動登錄時間獲知該令牌是否已過期,並在完整校驗通過之後生成新的token。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

人類的「故鄉」找到了! 20萬年前誕生於非洲波札那

摘錄自2019年10月29日中央社報導

科學家29日表示,人類祖先是在距今20萬年前誕生於非洲的波札那北部,當地現遍布沙漠和鹽地,但20萬年前卻是廣大的湖泊溼地,生機盎然。

科學期刊「自然」(Nature)刊出由澳洲雪梨大學(University of Sydney)和嘉文醫學研究所(Garvan Institute of Medical Research and University of Sydney)遺傳學家海斯(Vanessa Hayes)所率研究團隊做的這份研究。

法新社報導,現居南非與納米比亞的科伊桑人(Khoisan)是一支古老種族,他們體內有高比例的線粒體DNA支系L0,國際研究團隊從200名科伊桑人身上採集DNA樣本,和地理分布、考古、氣候變遷資料相比對。

在涵蓋現今波札那北部、納米比亞、辛巴威的地區,20萬年前有一個相當於目前維多利亞湖(Lake Victoria,面積約6.8萬平方公里)兩倍的大湖破裂後,形成廣袤的溼地,人類的祖先就誕生於此。

海斯說:「我們談的是構造上的現代人種,即現今的人類。現今人類事實上最老就是回溯到L0支系,這個支系全回溯到這個起源地。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

皮草業者毫無改善 芬蘭組織最新調查 「怪物狐狸」慘況依舊

環境資訊中心記者 鄒敏惠 報導

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

歐洲電動自行車熱銷 美利達搶攻市場

歐洲人一向喜歡騎自行車旅遊、運動,看中銀髮族人數增加,讓退休老年人也能享受騎車樂趣的電動自行車,也成為最夯運動商品,各大車廠積極搶攻電動自行車市場。 比利時最大的自行車展於本周在庫特萊 (Kortrijk) 舉行,吸引超過 10 萬人次參觀。台灣自行車廠商美利達也從荷蘭前來參展。   看中銀髮商機,這幾年各大車廠都把焦點放到電動自行車領域,從一開始以通勤用為主,到現在不少車廠都針對高單價的公路車、登山車,推出電動車款,讓銀髮族也能輕鬆和朋友騎自行車出遊。   美利達荷蘭分公司總經理柯柏芮德表示,電動自行車將是未來歐洲自行車市場的一大主流商品,成長速度也相當快。歐洲 1 年的電動自行車銷售量達 20 萬輛,他樂觀預估市場至少可以擴大到數百萬輛。美利達也於 2 年前在德國生產基地擴充電動自行車生產線,搶攻歐洲電動自行車市場。        

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

中國工業設計「奧斯卡獎」由陽光電源電動車控制器摘取

2014年12月12日,中國工業設計最高榮譽、被媲美為中國工業設計界之「奧斯卡獎」的中國創新設計紅星獎頒獎典禮在北京舉行。陽光電源電動車控制器產品從全球千餘家企業、6000多件參評作品中脫穎而出,獲得紅星獎,也是唯一獲得該獎項的電動車控制器類產品。  

  陽光電源自主研發的電動車控制器系列產品,結合了陽光電源近20年電力電子領域的技術研發和產業應用經驗,相比同類產品,該型號體積更小、重量更輕,適應範圍更廣也更環保。它採用模組化設計功能完善、能耗低、續駛里程長、可靠性高,目前成功應用於合肥、大連、舒城等多個城市電動公車。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

TUV萊茵移駕深圳 設電動車電池實驗室

德國萊茵TUV集團19日宣佈其位於深圳的全新電動車電池實驗室正式啟動。該實驗室新增設備涵蓋大尺寸電動車電池測試和更多認證服務,可依據 UN/ECE R100標準提供全尺寸電動汽車電池和非可擕式電池的測試服務,也可按照企業需求定製檢測方案,已獲 CNAS、DAkkS、CBTL、NRTL、CATL、CTIA 等多項國際認可和授權。   TUV萊茵的深圳電池實驗室除了提供動力電池相關測試外,還可為客戶提供歐洲、北美、日本、韓國、俄羅斯、巴西等國際市場准入服務。其先進的電池性能和安全測試設備,以及來自世界各國的資深專家團隊,可根據歐盟、美國等主要國家與地區的相關標準和要求,對原電池、鉛酸蓄電池、二次鋰離子電池、鎳鎘電池、鎳氫電池、輕型電動自行車電池等產品提供檢測認證服務,以保證電池符合安全、性能、儲存、運輸、化學及電磁相容等各項要求。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準