SpringBoot學習筆記(十五:OAuth2 )_網頁設計公司

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

@

目錄

  • 一、OAuth 簡介
    • 1、什麼是OAuth
    • 2、OAuth 角色
    • 3、OAuth 授權流程
    • 4、OAuth授權模式
      • 4.1、授權碼
      • 4.2、隱藏式
      • 4.3、密碼式
      • 4.4、憑證式
  • 二、實踐
    • 1、密碼模式
      • 1.1、授權服務器
        • 1.1.1、依賴
        • 1.1.2、授權服務器配置
        • 1.1.3、Spring Security配置
      • 1.2、資源服務器
        • 1.2.1、資源服務器配置
        • 1.2.2、資源服務接口
      • 1.3、測試
        • 1.3.1、獲取token
        • 1.3.2、使用獲取到的token訪問資源接口
    • 2、授權碼模式
      • 2.1、應用註冊
      • 2.2、具體代碼
      • 2.3、測試

一、OAuth 簡介

1、什麼是OAuth

開放授權(Open Authorization,OAuth)是一種資源提供商用於授權第三方應用代表資源所有者獲取有限訪問權限的授權機制。由於在整個授權過程中,第三方應用都無須觸及用戶的密碼就可以取得部分資源的使用權限,所以OAuth是安全開放的。

例如,用戶想通過 QQ 登錄csdn,這時csdn就是一個第三方應用,csdn要訪問用戶的一些基本信息就需要得到用戶的授權,如果用戶把自己的 QQ 用戶名和密碼告訴csdn,那麼csdn就能訪問用戶的所有數據,井且只有用戶修改密碼才能收回授權,這種授權方式安全隱患很大,如果使用 OAuth ,就能很好地解決這一問題。

OAuth第一個版本誕生於2007年12月,並於2010年4月正式被IETF作為標準發布(編號RFC 5849)。由於OAuth1.0複雜的簽名邏輯以及單一的授權流程存在較大缺陷,隨後標準工作組又推出了 OAuth2.0草案,並在2012年10月正式發布其標準(編號RFC 6749)。OAuth2.0放棄了OAuth1.0中讓開發者感到痛苦的数字簽名和加密方案,使用已經得到驗證並廣泛使用的HTTPS技術作為安全保障手 段。OAuth2.0與OAuth1.0互不兼容,由於OAuth1.0已經基本退出歷史舞台,所以下面提到的OAuth都是指OAuth2.0。

2、OAuth 角色

想要理解OAuth的運行流程,則必須要認識4個重要的角色。

  • Resource Owner:資源所有者,通常指用戶,例如每一個QQ用戶。
  • Resource Server:資源服務器,指存放用戶受保護資源的服務器,通常需要通過Access Token(訪問令牌)才能進行訪問。例如,存儲QQ用戶基本信息的服務器,充當的便是資源服務器的 角色。
  • Client:客戶端,指需要獲取用戶資源的第三方應用,如CSDN網站。
  • Authorization Server:授權服務器,用於驗證資源所有者,並在驗證成功之後向客戶端發放相關訪問令牌。

3、OAuth 授權流程

這是 個大致的流程,因為 OAuth2 中有 種不同的授權模式,每種授權模式的授權流程又會有差異,基本流程如下:

  • 客戶端(第三方應用)向資源所有者請求授權。
  • 服務端返回一個授權許可憑證給客戶端。
  • 客戶端拿着授權許可憑證去授權服務器申請令牌。
  • 授權服務器驗證信息無誤后,發放令牌給客戶端。
  • 客戶端拿着令牌去資源服務器訪問資源。
  • 資源服務器驗證令牌無誤后開放資源。

4、OAuth授權模式

OAuth 協議的授權模式共分為4種。

4.1、授權碼

授權碼(authorization code)方式,指的是第三方應用先申請一個授權碼,然後再用該碼獲取令牌。

這種方式是最常用的流程,安全性也最高,它適用於那些有後端的 Web 應用。授權碼通過前端傳送,令牌則是儲存在後端,而且所有與資源服務器的通信都在後端完成。這樣的前後端分離,可以避免令牌泄漏。

  • 第一步,A 網站提供一個鏈接,用戶點擊后就會跳轉到 B 網站,授權用戶數據給 A 網站使用。下面就是 A 網站跳轉 B 網站的一個示意鏈接。
https://b.com/oauth/authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

上面 URL 中,response_type參數表示要求返回授權碼(code),client_id參數讓 B 知道是誰在請求,redirect_uri參數是 B 接受或拒絕請求后的跳轉網址,scope參數表示要求的授權範圍(這裡是只讀)。

  • 第二步,用戶跳轉后,B 網站會要求用戶登錄,然後詢問是否同意給予 A 網站授權。用戶表示同意,這時 B 網站就會跳回redirect_uri參數指定的網址。跳轉時,會傳回一個授權碼,就像下面這樣。
https://a.com/callback?code=AUTHORIZATION_CODE

上面 URL 中,code參數就是授權碼。

  • 第三步,A 網站拿到授權碼以後,就可以在後端,向 B 網站請求令牌。
https://b.com/oauth/token?
 client_id=CLIENT_ID&
 client_secret=CLIENT_SECRET&
 grant_type=authorization_code&
 code=AUTHORIZATION_CODE&
 redirect_uri=CALLBACK_URL

上面 URL 中,client_id 參數和 client_secret 參數用來讓 B 確認 A 的身份(client_secret參數是保密的,因此只能在後端發請求),grant_type參數的值是 AUTHORIZATION_CODE,表示採用的授權方式是授權碼,code參數是上一步拿到的授權碼,redirect_uri 參數是令牌頒發后的回調網址。

  • 第四步,B 網站收到請求以後,就會頒發令牌。具體做法是向redirect_uri指定的網址,發送一段 JSON 數據。

    {    
      "access_token":"ACCESS_TOKEN",
      "token_type":"bearer",
      "expires_in":2592000,
      "refresh_token":"REFRESH_TOKEN",
      "scope":"read",
      "uid":100101,
      "info":{...}
    }

上面 JSON 數據中,access_token字段就是令牌,A 網站在後端拿到了。

4.2、隱藏式

有些 Web 應用是純前端應用,沒有後端。這時就不能用上面的方式了,必須將令牌儲存在前端。RFC 6749 就規定了第二種方式,允許直接向前端頒發令牌。這種方式沒有授權碼這个中間步驟,所以稱為(授權碼)”隱藏式”(implicit)。

  • 第一步,A 網站提供一個鏈接,要求用戶跳轉到 B 網站,授權用戶數據給 A 網站使用。
https://b.com/oauth/authorize?
  response_type=token&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read

上面 URL 中,response_type參數為token,表示要求直接返回令牌。

  • 第二步,用戶跳轉到 B 網站,登錄后同意給予 A 網站授權。這時,B 網站就會跳回redirect_uri參數指定的跳轉網址,並且把令牌作為 URL 參數,傳給 A 網站。
https://a.com/callback#token=ACCESS_TOKEN

上面 URL 中,token參數就是令牌,A 網站因此直接在前端拿到令牌。

注意,令牌的位置是 URL 錨點(fragment),而不是查詢字符串(querystring),這是因為 OAuth 2.0 允許跳轉網址是 HTTP 協議,因此存在”中間人攻擊”的風險,而瀏覽器跳轉時,錨點不會發到服務器,就減少了泄漏令牌的風險。

這種方式把令牌直接傳給前端,是很不安全的。因此,只能用於一些安全要求不高的場景,並且令牌的有效期必須非常短,通常就是會話期間(session)有效,瀏覽器關掉,令牌就失效了。

4.3、密碼式

如果你高度信任某個應用,RFC 6749 也允許用戶把用戶名和密碼,直接告訴該應用。該應用就使用你的密碼,申請令牌,這種方式稱為”密碼式”(password)。

  • 第一步,A 網站要求用戶提供 B 網站的用戶名和密碼。拿到以後,A 就直接向 B 請求令牌。
https://oauth.b.com/token?
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID

上面 URL 中,grant_type參數是授權方式,這裏的password表示”密碼式”,username和password是 B 的用戶名和密碼。

  • 第二步,B 網站驗證身份通過後,直接給出令牌。注意,這時不需要跳轉,而是把令牌放在 JSON 數據裏面,作為 HTTP 回應,A 因此拿到令牌。

4.4、憑證式

最後一種方式是憑證式(client credentials),適用於沒有前端的命令行應用,即在命令行下請求令牌。

  • 第一步,A 應用在命令行向 B 發出請求。
https://oauth.b.com/token?
  grant_type=client_credentials&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET

上面 URL 中,grant_type參數等於client_credentials表示採用憑證式,client_id和client_secret用來讓 B 確認 A 的身份。

  • 第二步,B 網站驗證通過以後,直接返回令牌。

這種方式給出的令牌,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌。

二、實踐

1、密碼模式

如果是自建單點服務,一般都會使用密碼模式。資源服務器和授權服務器
可以是同一台服務器,也可以分開。這裏我們學習分佈式的情況。

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

授權服務器和資源服務器分開,項目結構如下:

1.1、授權服務器

授權服務器的職責:

  • 管理客戶端及其授權信息
    * 管理用戶及其授權信息
    * 管理Token的生成及其存儲
    * 管理Token的校驗及校驗Key

1.1.1、依賴

        <!--security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--oauth2-->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.6.RELEASE</version>
        </dependency>

1.1.2、授權服務器配置

授權服務器配置通過繼承AuthorizationServerConfigurerAdapter的配置類實現:

/**
 * @Author 三分惡
 * @Date 2020/5/20
 * @Description  授權服務器配置
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;//密碼模式需要注入認證管理器

    @Autowired
    public PasswordEncoder passwordEncoder;

    //配置客戶端
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client-demo")
                .secret(passwordEncoder.encode("123"))
                .authorizedGrantTypes("password") //這裏配置為密碼模式
                .scopes("read_scope");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);//密碼模式必須添加authenticationManager
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .checkTokenAccess("isAuthenticated()");
    }
}

  • 客戶端的註冊:這裏通過inMemory的方式在內存中註冊客戶端相關信息;實際項目中可以通過一些管理接口及界面動態實現客戶端的註冊
  • 校驗Token權限控制:資源服務器如果需要調用授權服務器的/oauth/check_token接口校驗token有效性,那麼需要配置checkTokenAccess(“isAuthenticated()”)
  • authenticationManager配置:需要通過endpoints.authenticationManager(authenticationManager)將Security中的authenticationManager配置到Endpoints中,否則,在Spring Security中配置的權限控制將不會在進行OAuth2相關權限控制的校驗時生效。

1.1.3、Spring Security配置

通過Spring Security來完成用戶及密碼加解密等配置:

/**
 * @Author 三分惡
 * @Date 2020/5/20
 * @Description SpringSecurity 配置
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("fighter")
                .password(passwordEncoder().encode("123"))
                .authorities(new ArrayList<>(0));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有請求必須認證
        http.authorizeRequests().anyRequest().authenticated();
    }
}

1.2、資源服務器

資源服務器的職責:

  • token的校驗
  • 給與資源

1.2.1、資源服務器配置

資源服務器依賴一樣,而配置則通過繼承自ResourceServerConfigurerAdapter的配置類來實現:

/**
 * @Author 三分惡
 * @Date 2020/5/20
 * @Description
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Bean
    public RemoteTokenServices remoteTokenServices() {
        final RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setClientId("client-demo");
        tokenServices.setClientSecret("123");
        tokenServices.setCheckTokenEndpointUrl("http://localhost:8090/oauth/check_token");
        return tokenServices;
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //session創建策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //所有請求需要認證
        http.authorizeRequests().anyRequest().authenticated();
    }
}

主要進行了如下配置:

  • TokenService配置:在不採用JWT的情況下,需要配置RemoteTokenServices來充當tokenServices,它主要完成Token的校驗等工作。因此需要指定校驗Token的授權服務器接口地址
  • 同時,由於在授權服務器中配置了/oauth/check_token需要客戶端登錄后才能訪問,因此也需要配置客戶端編號及Secret;在校驗之前先進行登錄
  • 通過ResourceServerSecurityConfigurer來配置需要訪問的資源編號及使用的TokenServices

1.2.2、資源服務接口

接口比較簡單:

/**
 * @Author 三分惡
 * @Date 2020/5/20
 * @Description
 */
@RestController
public class ResourceController {

    @GetMapping("/user/{username}")
    public String user(@PathVariable String username){
        return "Hello !"+username;
    }
}

1.3、測試

授權服務器使用8090端口啟動,資源服務器使用默認端口。

1.3.1、獲取token

訪問/oauth/token端點,獲取token:

  • url:   http://localhost:8090/oauth/token?username=fighter&password=123&scope=read_scope&grant_type=password
  • 請求頭:
  • 返回的token

1.3.2、使用獲取到的token訪問資源接口

  • 使用token調用資源,訪問http://localhost:8080/user/fighter,注意使用token添加Bearer請求頭

相當於在Headers中添加 Authorization:Bearer 4a3c351d-770d-42aa-af39-3f54b50152e9。

OK,可以看到資源正確返回。

這裏僅僅是密碼模式的精簡化配置,在實際項目中,某些部分如:

  • 資源服務訪問授權服務去校驗token這部分可能會換成Jwt、Redis等tokenStore實現,
  • 授權服務器中的用戶信息與客戶端信息生產環境從數據庫中讀取,對應Spring Security的UserDetailsService實現類或用戶信息的Provider

2、授權碼模式

很多網站登錄時,允許使用第三方網站的身份,這稱為”第三方登錄”。所謂第三方登錄,實質就是 OAuth 授權。

例如用戶想要登錄 A 網站,A 網站讓用戶提供第三方網站的數據,證明自己的身份。獲取第三方網站的身份數據,就需要 OAuth 授權。

以A網站使用GitHub第三方登錄為例,流程示意如下:

接下來,簡單地實現GitHub登錄流程。

2.1、應用註冊

在使用之前需要先註冊一個應用,讓GitHub可以識別。

  • 訪問地址:https://github.com/settings/applications/new,填寫註冊表

應用的名稱隨便填,主頁 URL 填寫http://localhost:8080,回調地址填寫 http://localhost:8080/oauth/redirect。

  • 提交表單以後,GitHub 應該會返回客戶端 ID(client ID)和客戶端密鑰(client secret),這就是應用的身份識別碼

2.2、具體代碼

  • 只需要引入web依賴:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  • GitHub相關配置
github.client.clientId=29d127aa0753c12263d7
github.client.clientSecret=f3cb9222961efe4c2adccd6d3e0df706972fa5eb
github.client.authorizeUrl=https://github.com/login/oauth/authorize
github.client.accessTokenUrl=https://github.com/login/oauth/access_token
github.client.redirectUrl=http://localhost:8080/oauth/redirect
github.client.userInfoUrl=https://api.github.com/user

  • 對應的配置類
@Component
@ConfigurationProperties(prefix = "github.client")
public class GithubProperties {
    private String clientId;
    private String clientSecret;
    private String authorizeUrl;
    private String redirectUrl;
    private String accessTokenUrl;
    private String userInfoUrl;
    //省略getter、setter
}    
  • index.html:首頁比較簡單,一個鏈接向後端發起登錄請求
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>網站首頁</title>
</head>
<body>
    <div style="text-align: center">
        <a href="http://localhost:8080/authorize">Login in with GitHub</a>
    </div>
</body>
</html>
  • GithubLoginController.java:
     * 使用RestTemplate發送http請求
     * 使用Jackson解析返回的json,不用引入更多依賴
     * 快捷起見,發送http請求的方法直接寫在控制器中,實際上應該將工具方法分離出去
     * 同樣是快捷起見,返回的用戶信息沒有做任何解析
@Controller
public class GithubLoginController {
    @Autowired
    GithubProperties githubProperties;


    /**
     * 登錄接口,重定向至github
     *
     * @return 跳轉url
     */
    @GetMapping("/authorize")
    public String authorize() {
        String url =githubProperties.getAuthorizeUrl() +
                "?client_id=" + githubProperties.getClientId() +
                "&redirect_uri=" + githubProperties.getRedirectUrl();
        return "redirect:" + url;
    }

    /**
     * 回調接口,用戶同意授權后,GitHub會將授權碼傳遞給此接口
     * @param code GitHub重定向時附加的授權碼,只能用一次
     * @return
     */
    @GetMapping("/oauth/redirect")
    @ResponseBody
    public String redirect(@RequestParam("code") String code) throws JsonProcessingException {
        System.out.println("code:"+code);
        // 使用code獲取token
        String accessToken = this.getAccessToken(code);
        // 使用token獲取userInfo
        String userInfo = this.getUserInfo(accessToken);
        return userInfo;
    }


    /**
     * 使用授權碼獲取token
     * @param code
     * @return
     */
    private String getAccessToken(String code) throws JsonProcessingException {
        String url = githubProperties.getAccessTokenUrl() +
                "?client_id=" + githubProperties.getClientId() +
                "&client_secret=" + githubProperties.getClientSecret() +
                "&code=" + code +
                "&grant_type=authorization_code";
        // 構建請求頭
        HttpHeaders requestHeaders = new HttpHeaders();
        // 指定響應返回json格式
        requestHeaders.add("accept", "application/json");
        // 構建請求實體
        HttpEntity<String> requestEntity = new HttpEntity<>(requestHeaders);
        RestTemplate restTemplate = new RestTemplate();
        // post 請求方式
        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
        String responseStr = response.getBody();
        // 解析響應json字符串
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(responseStr);
        String accessToken = jsonNode.get("access_token").asText();
        System.out.println("accessToken:"+accessToken);
        return accessToken;
    }

    /**
     *
     * @param accessToken 使用token獲取userInfo
     * @return
     */
    private String getUserInfo(String accessToken) {
        String url = githubProperties.getUserInfoUrl();
        // 構建請求頭
        HttpHeaders requestHeaders = new HttpHeaders();
        // 指定響應返回json格式
        requestHeaders.add("accept", "application/json");
        // AccessToken放在請求頭中
        requestHeaders.add("Authorization", "token " + accessToken);
        // 構建請求實體
        HttpEntity<String> requestEntity = new HttpEntity<>(requestHeaders);
        RestTemplate restTemplate = new RestTemplate();
        // get請求方式
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
        String userInfo = response.getBody();
        System.out.println("userInfo:"+userInfo);
        return userInfo;
    }

}

2.3、測試

  • 訪問localhost:8080,點擊鏈接,重定向至GitHub
  • 在GitHub中輸入賬號密碼,登錄
  • 登錄成功后,GitHub 就會跳轉到redirect_uri指定的跳轉網址,並且帶上授權碼
http://localhost:8080/oauth/redirect?code=d45683eded3ac7d4e6ed

OK,用戶信息也一併返回了。

本文為學習筆記類博客,學習資料見參考!

參考:

【1】:《SpringSecurity 實戰》
【2】:《SpringBoot Vue全棧開發實戰》
【3】:理解OAuth 2.0
【4】:OAuth 2.0 的一個簡單解釋
【5】:OAuth 2.0 的四種方式
【6】:這個案例寫出來,還怕跟面試官扯不明白 OAuth2 登錄流程?
【7】:做微服務繞不過的 OAuth2,松哥也來和大家扯一扯
【8】:GitHub OAuth 第三方登錄示例教程
【9】:OAuth 2.0 認證的原理與實踐
【10】:Spring Security OAuth2 Demo —— 密碼模式(Password)
【11】:Spring Security OAuth專題學習-密碼模式及客戶端模式實例
【12】:Spring Boot and OAuth2
【13】:Spring Boot+OAuth2使用GitHub登錄自己的服務

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

結合 AOP 輕鬆處理事件發布處理日誌_包裝設計

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

結合 AOP 輕鬆處理事件發布處理日誌

Intro

前段時間,實現了 EventBus 以及 EventQueue 基於 Event 的事件處理,但是沒有做日誌(EventLog)相關的部分,原本想增加兩個接口, 處理事件發布日誌和事件處理日誌,最近用了 AOP 的思想處理了 EntityFramework 的數據變更自動審計,於是想着事件日誌也用 AOP 的思想來實現,而且可能用 AOP 來處理可能會更好一些,最近自己造了一個 AOP 的輪子 —— FluentAspects,下面的示例就以它來演示了,你也可以換成自己喜歡的 AOP 組件,思想是類似的

事件日誌示例

事件發布日誌

事件發布日誌只需要攔截事件發布的方法調用即可,在發布事件時進行攔截,在攔截器中根據需要進行日誌記錄即可

事件發布者接口定義:

public interface IEventPublisher
{
    /// <summary>
    /// publish an event
    /// </summary>
    /// <typeparam name="TEvent">event type</typeparam>
    /// <param name="event">event data</param>
    /// <returns>whether the operation succeed</returns>
    bool Publish<TEvent>(TEvent @event) where TEvent : class, IEventBase;

    /// <summary>
    /// publish an event async
    /// </summary>
    /// <typeparam name="TEvent">event type</typeparam>
    /// <param name="event">event data</param>
    /// <returns>whether the operation succeed</returns>
    Task<bool> PublishAsync<TEvent>(TEvent @event) where TEvent : class, IEventBase;
}

事件發布日誌攔截器:

public class EventPublishLogInterceptor : AbstractInterceptor
{
    public override async Task Invoke(IInvocation invocation, Func<Task> next)
    {
        Console.WriteLine("-------------------------------");
        Console.WriteLine($"Event publish begin, eventData:{invocation.Arguments.ToJson()}");
        var watch = Stopwatch.StartNew();
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Event publish exception({ex})");
        }
        finally
        {
            watch.Stop();
            Console.WriteLine($"Event publish complete, elasped:{watch.ElapsedMilliseconds} ms");
        }
        Console.WriteLine("-------------------------------");
    }
}

事件處理日誌

事件處理器接口定義:

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

public interface IEventHandler
{
    Task Handle(object eventData);
}

事件處理日誌攔截器定義:

public class EventHandleLogInterceptor : IInterceptor
{
    public async Task Invoke(IInvocation invocation, Func<Task> next)
    {
        Console.WriteLine("-------------------------------");
        Console.WriteLine($"Event handle begin, eventData:{invocation.Arguments.ToJson()}");
        var watch = Stopwatch.StartNew();
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Event handle exception({ex})");
        }
        finally
        {
            watch.Stop();
            Console.WriteLine($"Event handle complete, elasped:{watch.ElapsedMilliseconds} ms");
        }
        Console.WriteLine("-------------------------------");
    }
}

AOP 配置

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(builder =>
    {
        builder.UseStartup<Startup>();
    })
    .UseFluentAspectsServiceProviderFactory(options =>
    {
        // 攔截器配置
        
        // 攔截 `IEventPublisher` 日誌,註冊事件發布日誌攔截器
        options
            .InterceptType<IEventPublisher>()
            .With<EventPublishLogInterceptor>();

        // 攔截 `IEventHandler`,註冊事件處理日誌攔截器
        options.InterceptType<IEventHandler>()
            .With<EventHandleLogInterceptor>();
    }, builder =>
    {
        // 默認使用默認實現來生成代理,現在提供了 Castle 和 AspectCore 的擴展,也可以自己擴展實現自定義代理生成方式
        // 取消註釋使用 Castle 來生成代理
        //builder.UseCastleProxy();
    }, t => t.Namespace?.StartsWith("WeihanLi") == false // 要忽略的類型斷言
    )
    .Build()
    .Run();

More

事件發布示例,定義了一個發布事件的中間件:

// pageView middleware
app.Use((context, next) =>
{
    var eventPublisher = context.RequestServices
        .GetRequiredService<IEventPublisher>();
    eventPublisher.Publish(new PageViewEvent()
    {
        Path = context.Request.Path.Value,
    });

    return next();
});

事件處理示例是用一個消息隊列的模式來處理的,示例和前面的事件的文章類似,EventConsumer 是一個後台任務,完整代碼示例如下:

public class EventConsumer : BackgroundService
{
    private readonly IEventQueue _eventQueue;
    private readonly IEventHandlerFactory _eventHandlerFactory;

    public EventConsumer(IEventQueue eventQueue, IEventHandlerFactory eventHandlerFactory)
    {
        _eventQueue = eventQueue;
        _eventHandlerFactory = eventHandlerFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var queues = await _eventQueue.GetQueuesAsync();
            if (queues.Count > 0)
            {
                await queues.Select(async q =>
                        {
                            var @event = await _eventQueue.DequeueAsync(q);
                            if (null != @event)
                            {
                                var handlers = _eventHandlerFactory.GetHandlers(@event.GetType());
                                if (handlers.Count > 0)
                                {
                                    await handlers
                                            .Select(h => h.Handle(@event))
                                            .WhenAll()
                                        ;
                                }
                            }
                        })
                        .WhenAll()
                    ;
            }

            await Task.Delay(1000, stoppingToken);
        }
    }
}

完整的示例代碼可以從https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample 獲取

OverMore

之前在微軟的 EShopOnContainers 項目里又看到類似下面這樣的代碼,在發布事件的時候包裝一層 try … catch 來記錄事件發布日誌,相比之下,本文示例中的這種方式更為簡潔,代碼更清爽

Reference

  • https://www.cnblogs.com/weihanli/p/12941919.html
  • https://www.cnblogs.com/weihanli/p/implement-event-queue.html
  • https://github.com/WeihanLi/WeihanLi.Common
  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample/Startup.cs

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

10萬就可以輕鬆入手中型SUV 竟然還帶7座_貨運

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

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

採用全黑的內飾配色,大尺寸的中控屏非常醒目,整車質感良好,电子駐車、無鑰匙進入/啟動、車身穩定系統、倒車影像等配置比較齊全。儲物空間方面非常豐富,如中控台下方掏空的設計就非常方便放些零碎的東西,2780mm的軸距,帶來的是非常寬敞的空間感受,頭部、腿部空間都有很多餘量。

眾泰汽車-眾泰T600

指導價:7.98-14.98萬

外觀設計方面,眾泰T600給人很大氣的感覺,與途銳有着極其相似的前臉使它看起來一點都不陌生,尾部的造型圓潤不失動感,雙出的排氣管動感十足;內飾整體布局簡潔大方,仿木飾板和銀色飾條的搭配看起來很得體,6安全氣囊、胎壓監測、無鑰匙進入/啟動、自動駐車、倒車影像、自動頭燈等配置應有盡有;2807mm的軸距在同級別中佔有優勢,乘坐舒適度良好,儲物空間表現中規中矩,滿足日常使用;動力提供了1.5T(最大功率162馬力)/2.0T(最大功率190馬力)兩種車型選擇,搭配5擋手動或着6擋雙離合變速箱,動力響應足夠快,底盤的調校偏向舒適。

東風小康-東風風光580

指導價:7.29-9.99萬

風光580可謂是一款網紅級別的車型,外形設計較為動感,車身線條流暢優雅,三條鍍鉻格柵搭配大尺寸的六邊形進氣格柵,力量感十足,雙色多幅鋁合金輪轂與其時尚的外觀很般配;採用全黑的內飾配色,大尺寸的中控屏非常醒目,整車質感良好,

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

电子駐車、無鑰匙進入/啟動、車身穩定系統、倒車影像等配置比較齊全;儲物空間方面非常豐富,如中控台下方掏空的設計就非常方便放些零碎的東西,2780mm的軸距,帶來的是非常寬敞的空間感受,頭部、腿部空間都有很多餘量;1.5T發動機最大功率150馬力,搭配6擋手動或者CVT變速器,動力儲備較為充足,由於車身重心較高的原因,過一些較大顛簸路面時,晃動感會比較大。

長安汽車-長安CX70

指導價:6.89-8.49萬

長安CX70的外觀原創度還是蠻高的,車身看起來很粗獷、硬朗,但車身側面難免會給人一種麵包車的感覺,接近角23.5度,離去角25度,最小離地間隙達到190mm,通過性表現出色;內飾布局規整協調,橙黑雙色的搭配看起來很有活力,中控屏與空調控制系統集成在一起,取消了物理按鍵,非常有特斯拉大屏的那種檔次感,右側全景影像系統便利性很強;CX70的車身高度達到了1750mm,所以頭部空間非常寬敞,採用2+3+2的座椅布局,第三排座椅支持翻折,擴展性強;全系採用1.6L(最大功率117馬力)+5擋手動變速箱的動力組合,滿足日常城市道路使用,而且懸架支撐性好,期待渦輪增壓車型和自動擋的出現。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

每天跑100公里 選這些大氣B級車准沒錯!_網頁設計公司

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

同時,這款速派要喝95號汽油。話雖如此,速派的底盤濾震效果還是杠杠的,對付城區里的小顛簸總能有條不紊地過濾掉。遇到特別爛的路,則會讓你感覺一種帶有厚實感的硬度。配置上,這款速派就有不少亮點,不僅配了胎壓監測,還有自動駐車+电子手剎這對黃金組合,另外還可以選裝電動天窗和發動機啟停。

現在B級車市場的選擇琳琅滿目,為了滿足每天往返市區與郊區的路程,該如何選擇一款符合自己心意的B級車呢?下面編者我就給大家介紹幾款省心又好開的B級車。

廣汽豐田-凱美瑞

2016款 2.0E 十周年紀念精英版

指導價:18.78萬

優惠幅度:2.5萬元左右(僅供參考)

編者點評:

凱美瑞作為一款久歷沙場的車系,各項技術都比較穩定。這款2.0L車型的綜合油耗為8.7L左右,算是比較省油的。現在這款車終端也能有2.5萬元左右的優惠,讓步也夠大的。

一直以來,凱美瑞給人的感覺就是中庸,無論是外觀,還是內飾設計,都給人一種四平八穩,缺乏亮點的感覺。不過,也正是這樣的設計,得到了不少成熟人士的認可。

動力總成上,2.0L自然吸氣發動機配6擋手自一體變速箱,最大輸出167馬力和199牛米。實際動力表現不錯,換擋平順度高,發動機的運轉聲音優雅。但是,在全負荷運轉下,發動機會有點吃力。底盤可過濾大部分路面的顛簸,但是遇到大坑窪時,還是容易露餡。

保養方面,由於官方在6萬公里內免費為車主進行基礎保養,所以最後的保養也僅為3594元。作為一輛B級車來說,這個價格完全可以接受。

上汽大眾斯柯達-速派

2016款 280TSI DSG前行版

指導價:17.98萬

優惠幅度:2.5萬元左右(僅供參考)

編者點評:

雖然斯柯達是大眾的小弟,但是大眾最近把不少新技術都下放給了這位小弟。所以,鍾愛德系的人不妨選一輛斯柯達,畢竟斯柯達的品牌溢價也沒有大眾那麼高。

動力總成上,1.4T的EA211發動機+7速DCT,最大輸出150馬力和250牛米。不過,最大扭矩到3000轉就開始衰減,明顯偏早,

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

而且發動機的噪音偏大,影響乘車質感。同時,這款速派要喝95號汽油。

話雖如此,速派的底盤濾震效果還是杠杠的,對付城區里的小顛簸總能有條不紊地過濾掉。遇到特別爛的路,則會讓你感覺一種帶有厚實感的硬度。

配置上,這款速派就有不少亮點,不僅配了胎壓監測,還有自動駐車+电子手剎這對黃金組合,另外還可以選裝電動天窗和發動機啟停。除此以外,還有氙氣大燈,8-9個喇叭的揚聲器,行車電腦显示屏和后駐車雷達。

東風悅達起亞-起亞K5

2016款 2.0L 自動LUX

指導價:17.58萬

優惠幅度:3.5萬左右(僅供參考)

編者點評:

K5的設計可以說越來越前衛,也越來越能吸引年輕消費者,同時優惠幅度又足夠大。油耗上,這款2.0L車型的百公里綜合油耗為8.9L,算是比較不錯的。

K5搭載了2.0L自然吸氣發動機+6擋手自一體變速箱,最大輸出161馬力和193牛米,這個數據也只能說是中規中矩,開起來平順,輸出線性。K5的底盤濾震比較有韌性,可以帶給駕駛員良好的操控性。

配置上也頗有亮點,首先是18寸的輪胎規格加上全尺寸備胎足夠厚道。除此,還有無鑰匙進入與啟動,感應後備廂,倒車視頻影像和后視鏡電動摺疊。如此豐富的配置才對得上韓系車的名號。

編者總結:

這三款車都是有各自顯著特點的車。首先,凱美瑞雖然是一款偏中庸的車,但是如果一台車各方面都中庸的話,那中庸就是它的特點。凱美瑞應該是屬於那種久處不厭的車子,就算開久了,也不會有什麼大的問題煩擾你。

速派是德系的代表,我覺得它能代表大眾的一部分特性,但是品牌溢價又不會有大眾那麼高。這對於那些純粹想體會一下德系車品質的消費者來說,是個很好的選擇。況且,速派亦是MQB平台的產物,跟邁騰和帕薩特品質不會差太遠,差的只是一個標誌。

K5則在大打配置牌,再配合上那運動的外觀確實能吸引不少年輕消費者的目光。同時,K5也是這幾款車中優惠最大的。誠然,K5在机械質感上與日系和德系的對手比還略遜一籌,不過,它也似乎找到了彎道超車的可能。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

有了新E級就沒必要買S級?試完S級后感嘆有錢真好_包裝設計

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

後排幾乎聽不到什麼噪音,這種十分寧靜的乘坐環境,再加上都被過濾掉的路面震動,這種級別的舒適一年都享受不到幾回。我這個X裝的您給幾分。有錢人真好。4。0升V8雙渦輪增壓發動機,應該會送給那些搭載2。0T引擎的對手一個不屑的笑容。

作為梅賽德斯奔馳的旗艦,每一代S級轎車身上,都會有些引領整個行業的東西,絕門的技術、先進的科技或者無與倫比設計。眼前的這台S500就是你在中國能買到的S級轎車的頂配,他能夠給你想要的一切。但是,如果你沒有強大的氣勢或是很好的衣品,那還可以帶一個粗大的黃金鏈子做一下偽裝。因為,這台S500的氣場不是誰都能駕馭,一般人看着就像司機了。

相比起外觀的見仁見智,這一代奔馳S級轎車的內飾設計幾乎是得到了一致的好評,奔馳對豪華的理解果然有一套,這種設計,讓全球各地的消費者都非常認可,同級別豪華轎車內飾的全新典範應該不會有異議。

兩個碩大的12.3英寸液晶显示屏以及幾個圓形的空調出風口,就大致構成了整个中控台的設計。看起來相當的簡約,但卻又透露着濃濃的豪華尊貴和典雅的風範。車內的皮革、金屬等等所有的用料和做工都對得起他近200萬的身價,單就這一個內飾,S500L就已經甩開了對手好幾條街。

坐在後座,我心裏只發出一個感嘆,那就是有錢人,真好。座椅寬大而又舒適,並且放下腿托和腳踏板,就能形成一個近乎平躺的坐姿。而且坐墊比國際航班頭等艙上還要柔軟。打開遮陽簾,形成一個很好的私密環境,再從車載冰箱里拿出一瓶上好的紅酒,看一部好萊塢大片,

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

真正感受什麼叫坐奔馳。後排幾乎聽不到什麼噪音,這種十分寧靜的乘坐環境,再加上都被過濾掉的路面震動,這種級別的舒適一年都享受不到幾回。我這個X裝的您給幾分?有錢人真好!

4.0升V8雙渦輪增壓發動機,應該會送給那些搭載2.0T引擎的對手一個不屑的笑容。掛上D擋,鬆開剎車,車是原地不動的,你必須去踩下油門,車輛才會緩慢的前行,而油門的感覺會比整輛車的外觀看起來還要沉穩。一切都是那麼不慌不忙,或者換句話說,這輛車要的就是這種從容的風範。當你駕駛着車輛S500行駛在路上的時候,你會明顯感覺到這是一台很大的車,將近5米3長的車以及修長的車頭都讓你的駕駛非常的小心。但是車輛的轉向卻出乎意料的輕盈,而且無論在任何時候,豎立在車頭的奔馳三叉星logo提醒着你,駕駛這輛車似乎也成了一種很有儀式感的事情。

S500的運動模式有兩個按鍵,第一個是懸挂的運動模式S500的運動模式有兩個按鍵,第一個是懸挂的運動模式按下之後,你會發覺車輛和舒適模式沒有什麼明顯的區別,給我的感覺,他是我開過的最不運動的運動模式。按下第二個發動機的運動模式之後,此時此刻這才是真正的擁有421馬力該有的樣子,油門稍微一點車輛就迫不及待地往前躥,這個大傢伙就像在籠子里被關了很久的猛獸一樣,暴躁又狂野。但是,如果後排有人,你就完蛋了!

這就是S500L,用他的氣場,豪華和舒適,再一次“發明”汽車。

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

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

市北區第二屆“時尚+體育”_貨運

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

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

市北區第二屆“時尚+體育”

       10月17日晚,市北區第二屆全民健身周開幕式在郵輪母港廣場盛大啟幕。本屆全民健身周由市北區教育和體育局主辦,以“啟航市北,時尚健身季”為主線,旨在引導廣大市民把健身活動作為新時尚,在運動中增強體質、傳播快樂、成就夢想、健康生活。

  市北區大力推進全民健身事業,創新發展體育服務產業,高配套迭代健身設施,舉辦多項最具動感、最適合各年齡段群眾的健身活動活動,讓“時尚+體育、科技+健身、互聯網+運動”多種業態覆蓋轄區,為建設國際航運貿易金融創新中心核心區增添新活力。

  時尚體育盛會,開啟時尚體育新發展

  開幕式展播了市北區全民健身活動的快閃視頻,內容涵蓋涵蓋學校體育、全民健身活動、體育場館,彰顯市北的運動活力。

  各類異彩紛呈的群體體育活動也在開幕式上演。活力四射的摩登街舞,充滿青春動感的啦啦操、拳擊操、青春健身操,力量十足的鴛鴦門武術套路、跆拳道表演,為島城市民帶來一場運動魅力的饕餮盛宴。

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

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

  本屆全民健身周活動中還將組織全民健身項目展示和群眾互動活動,舉辦太極功夫扇比賽、“勝道-市北杯”乒乓球聯賽等豐富多彩的賽事。

  運動釋放生命活力,助力美好夜經濟運動生活

  開幕式結束后,“時尚夜光秀”熒光跑活動接着在郵輪母港舉行。在2公里左右的路程中共設置了6個點標,500餘名參賽选手要在1個小時的時間內完成相應任務。

  在“照亮七十載”任務點標,參賽隊伍成員需要齊心協力共同點亮70周年裝置;在“發現新時代”任務點標,1名成員需要在互動屏前做出動作,其他成員在互動屏上找出指定關鍵詞;在“逐夢綠茵場”任務點標,參賽隊伍中成員輪流在指定位置踢球射門;在“我是追夢人”任務點標,參賽隊伍需要在霓虹燈拍照牆前喊出口號,拍攝集體照片;在“分類新時尚”任務點標,參賽隊伍需要在指定時間內將垃圾圖卡投入指定垃圾桶中;在“中國最動聽”任務點標,參賽者需要使用擺在地上的琴譜,用腳彈奏出“我和我的祖國”第一句。每個點標任務完成后,參賽者將會獲得一枚大會專用章,在時限內完成所有任務抵達終點的选手將每人獲得一枚獎牌和抽獎券,有機會獲得豐厚的獎品。

  在熒光跑活動途中,主辦方還將設置自我彩繪、塗鴉、熒光網紅牆打卡、主題燈光秀等群眾互動活動,在增加活動趣味性的同時,彰顯市民個性與活力。

  2019“時尚+體育”全民健身周將為市北的市民乃至島城市民帶來一場生動有趣、形式多樣的體育運動大餐,進一步推動全民健身戰略的發展,助力國際航運貿易金融創新中心核心區建設。

網站內容來源http://www.online.jx.cn/

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

時尚達人都在打卡的小狐狸咖啡_網頁設計公司

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

時尚達人都在打卡的小狐狸咖啡

 

 

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

法國時尚品牌Maison Kitsuné大陸首家旗艦店將於10月底在魔都新天地開業,隨之帶來的,還有Maison Kitsuné的子品牌咖啡館Café Kitsuné。Maison Kitsuné的創始人分別是法國人和日本人,日法混血的品牌基因也讓Café Kitsuné別有風情,在空間打造方面,每間分店都具有強烈的品牌特色。

01

帶有法日混血基因的多元化經營品牌這是一間讓全世界的時尚icon都為它打卡的潮流咖啡廳,身上流着的血液,便和其他的咖啡館不同。

 

Café Kitsuné的母公司Maison Kitsuné是一個時尚、电子音樂、咖啡等混合的時尚生活方式品牌,自2002年誕生於法國,在歐美地區一直擁有極高的人氣。Maison Kitsuné最開始的業務分為兩個支線,由之前是建築師的日本人 Masaya Kuroki 負責時尚品牌,法國电子組合 Daft Punk 經理人 Gildas Loac 負責音樂廠牌,從最開始便是平行運作多個領域。音樂讓 Maison Kitsuné 的時尚之路走得更順暢,服裝佔據企業 80% 的利潤。產生開咖啡館的主意,是因為Masaya Kuroki在日本街頭看到許多混血的咖啡館,他們將咖啡與時尚結合,產生一個新的生活方式空間,服裝也得到更好的展示。借用這一概念,Maison Kitsuné2013年在日本青山區推出了第一間Café Kitsuné概念店。品牌的日本創始人Masaya Kuroki堅持門店應該體現當地的文化,而不是刻意營造時尚先鋒感。Café Kitsuné日本店選擇的是香柏木地板,榻榻米和傳統印花壁紙。其中手沖架為純天然木質品且印有日本傳統繪畫。在裝潢設計也完全運用日本傳統室內空間的元素,竹支圍繞的庭院中種植的植物能隨季節變化樣貌和狀態,營造一處東方禪意空間,裝潢帶着濃厚的江戶川風情。Café Kitsuné提供意式濃縮咖啡、瑪奇朵、美式咖啡、拿鐵、卡布奇諾等多種選擇,其中拿鐵是其招牌產品。除了咖啡和特調飲品,Café Kitsuné還有各式甜點和鹹食,包括經典的法式麵包三明治、海綿蛋糕、小狐狸形狀脆餅等等。隨後Maison Kitsuné在巴黎、韓國首爾等時尚地標開設立第二、第三家店,迅速風靡Ins。位於上海新天地的第四家店將於今年10月底開業,目前已圍擋。

02

結合地方特色打造複合型咖啡館Café Kitsuné 在不同城市的店鋪皆別具一格,每間店鋪都會在模式上有所創新。例如巴黎店為咖啡+酒吧,韓國店則加入了服飾、和精品零售。Café Kitsuné 主要針對20~35歲,精通網絡、國際化社區的一群人,所以選址也別有用心。Café Kitsuné巴黎店是首間將咖啡與酒吧結合的空間,店鋪選址盧浮宮最繁華的地段,將門店嵌入了具有400年歷史的巴黎皇家大王宮內。和日本以“茶室”為主題的空間不同,它是典型的法式風情裝飾。除了咖啡,餐廳還提供茶、雞尾酒、午餐及晚餐,營業時間也延長至深夜,覆蓋人們日常的休閑娛樂時間。首爾旗艦店定位在著名的畫廊、咖啡館、攝影工作室、精品店聚集的“藝術街”新沙洞,將服飾、和精品零售加入到了咖啡館內。Café Kitsuné在美妝、音樂、香氛等都有跨界,在韓國店中,潮品的佔用空間進一步加大,門店涵蓋的品類更全,服裝展示成為了重中之重。品牌方稱,最新的上海店或將複製韓國旗艦店的模式,以咖啡+精品店的模式運行。上海店並不是Maison Kitsuné首次進入中國市場,在2015年,Maison Kitsuné在香港銅鑼灣Fashion Walk名店坊開設了中國首家門店,吹響進入中國的號角。一年前, Maison Kitsuné宣布策略,表示將在當地合作夥伴的幫助下探索“尚未開發的亞洲市場”。Maison Kitsuné 已與中國公司 JoeOne 簽署了一項 50/50 的合資企業,以便在大中華區開展業務。▲Maison Kitsuné香港店Maison Kitsuné更透露,未來計劃在中國開設3家門店,分別位於香港、上海和成都,其中上海店10底開業。根據選址的不同,將把服裝店、咖啡館、酒吧、精品店複合打造概念商店。截止目前,Maison Kitsuné在全球市場共有16家直營店,Café Kitsuné已開業的有3家。網站內容來源http://www.online.jx.cn/

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

趙麗穎產後恢復得真好!修身西裝未見絲毫贅肉_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

趙麗穎產後恢復得真好!修身西裝未見絲毫贅肉

不覺間,又迎來了趙麗穎的生日。產後剛復工的她,這次也是難得高調慶祝自己32歲生日。但素有拚命三娘之稱的她,即使是生日也沒有停下工作。在鮮花和蛋糕的圍繞下匆忙慶生,就趕往片場拍戲了。而這次的生日造型,也讓大家有種很新鮮亮眼的感覺了。和以往完全不同的復古攻氣西裝造型,與她甜美的長相來了個大碰撞。#誰的外套更好看#

 

趙麗穎雖然是剛復工不久,但是她整個人的狀態還是非常值得肯定的。不僅沒有圓潤變形,甚至還有種愈發少女的感覺呢。和她獨有的那種甜蜜感混搭在一起,就更是靚麗惹眼如青春美少女了。能夠有勇氣在產後迅速復工,可見趙麗穎本身也是對自己的自我管理有很大的信心啦。看着讓人一點挑不出毛病,真是想不服氣都不行呢。

 

而一貫較常走甜美路線的她,這次也是難得嘗試起了復古攻氣的造型。華麗的頭飾襯得她臉型和五官愈發精緻,看着吸睛有魅力。而身上的則是條紋西裝和白襯衫,給人種很華麗颯爽的感覺。或許是因為她是小圓臉,所以就這麼一看會覺得有點不和諧。特別是這樣的半身照,加上臉上的甜笑就更是俏麗了。和身上霸氣的西裝有點格格不入,氣場還沒能散發出來。

 

但其實別看這樣的造型沒有太多色彩就以為很好駕馭,其實光是髮型就已經非常考驗人了。整齊服帖地盤起頭髮,這對臉型是個極大的挑戰。如果臉型稍微有點缺陷,都會被無情地暴露出來。但穎寶倒是一點都沒有壓力,即使是這樣油光鋥亮的髮型也一樣輕鬆駕馭。臉部線條柔和而精緻,絲毫沒有因為髮型而崩塌半分。

 

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

身上的造型也是如此,從設計到細節都在考驗着她的身材和氣質。網紗拼接的襯衫,即使單穿都已經非常華麗高調。而這還不夠,還要搭配黑色細條紋的西裝套裝。強強聯合卻也依舊給人種和諧感,不得不感嘆趙麗穎的時尚消化力了。雖然長得可愛稚嫩,卻一點沒有被這華麗造型搶去風頭。反倒是越看越有韻味,漸漸都不會覺得突兀不搭了呢。

 

不僅穿搭很用心,當日慶生現場的布置也一點都不含糊。看着這精美的布景,不就是每個女生心中標準的慶生現場嗎!鮮花氣球的簇擁圍繞,還要有貌美華麗的三層大蛋糕。在祝福中開心許願,狂拍美照。難怪連趙麗穎都難得在社交平台上連刷一堆美照了,畢竟這個場面可真是美得讓人感覺怎麼拍都不夠。

 

不僅穿搭很用心,當日慶生現場的布置也一點都不含糊。看着這精美的布景,不就是每個女生心中標準的慶生現場嗎!鮮花氣球的簇擁圍繞,還要有貌美華麗的三層大蛋糕。在祝福中開心許願,狂拍美照。難怪連趙麗穎都難得在社交平台上連刷一堆美照了,畢竟這個場面可真是美得讓人感覺怎麼拍都不夠。

 

或許就是因為甜蜜溫馨的布景,大家才會覺得穎寶和這一身造型不搭。但一旦換上布景之後,是不是覺得整個人氣質都變得颯爽不少了呢。超修身的西裝太凸顯好身材,絲毫不見一絲多餘贅肉。視覺上優化身材好比例,讓穎寶在帥氣中又隱藏了幾分性感撩人。沒有多餘的裝飾都覺得看點滿滿,其實這風格的轉換也還是蠻成功的。

 

別說產後能夠恢復成這樣的好狀態了,即使是未生產過的少女都未必能keep出這般好身材呢。腰是腰腿是腿的,可真是太絕啦。看着從甜美小公主轉變為辣媽的穎寶,真是太為她的改變而感到驚喜~

網站內容來源http://www.online.jx.cn/

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

這些高配置的七座SUV,不足10萬就可以落地!_貨運

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

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

內飾整體還是保持長安的的風格,對稱式的布局,使用起來比較方便。CX70的車身尺寸為:4680*1800*1750mm,軸距:2780mm,並且車身設計較長,這讓CX70車內的縱向空間有了一定的布局基礎,所以,CX70的第三排乘坐空間還算可以,正常身高(175左右)乘坐,比較不先的那麼局促,舒適性相比這個價位的七座車,較高一些。

其實生不生二胎對於買不買七座SUV來說並沒有太大的影響,就好像買漢蘭達一樣,多數人都是買的七座,但並不是每個用戶都是二胎家庭。而七座的最大好處就是,在人多的時候,可以載上七個人,雖然第三排的空間有些狹小,但至少可以把人給人運走,像五座車怎麼也就只能坐五個(別說後備箱坐人什麼的)。即使平日里不用第三排的座椅,也可以放倒,這樣後備箱的空間也大。所以差不多的價格,何不選七座車型呢。

當然,按照如今的消費水平,漢蘭達這種車並不是每個家庭都可以買得起,8-15萬之間是普遍家庭的預算資金範圍,而如今,在10萬內可以落地的七座車也有不少,例如下面這三款。

眾泰汽車-大邁X5

指導價:6.99-12.39萬

大邁X5雖然不能說和某一款車型極其相似,但是拆開各個部分來看,會找不少成熟車型的影子,不過,好看就行,管他呢。中控較為簡潔,規規整整,視覺上的效果還算有質感,但是觸感就暴露一切了。大邁X5是在五座的基礎上增加了第三排座椅,布局為2+3+2,相較之下比較緊湊,第三排的的乘坐空間不算太理想,成年人會感到辛苦。第三排座椅可以按照50/50比例放倒,放倒之後,和五座車型一樣。

眾泰一向以豐富配置為賣點之一,大邁X5也不例外,有1.5T和1.6L兩種動力選擇,1.5T車型選擇較多,整體的配置都比較平均,低配和次低配沒有配備牽引力控制和ESp,舒適性上的配置也較少,往上的車型都有配備,並且舒適性的上的配置也算豐富,頂配和次頂配車型多了電動天窗,全景天窗等的配置,車型之間的價格區間較少,都在2000-4000之間,所以選擇起來會比較理想化。如果日常使用的話,建議選擇中配車型即可滿足日常需求了。

長安汽車-長安CX70

指導價:6.89-8.49萬

CX70整體設計的比較硬朗,車身看上較長,不過這麼大車型,配個17寸的輪胎看起來確實有點不搭調。內飾整體還是保持長安的的風格,對稱式的布局,使用起來比較方便。CX70的車身尺寸為:4680*1800*1750mm,軸距:2780mm,並且車身設計較長,這讓CX70車內的縱向空間有了一定的布局基礎,所以,CX70的第三排乘坐空間還算可以,正常身高(175左右)乘坐,

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

比較不先的那麼局促,舒適性相比這個價位的七座車,較高一些。

CX70隻有1.6L一種動力可選,並且只有手動擋,低配和次低配沒有剎車輔助,牽引力控制,ESp,低配的舒適性上的配置少的可憐,但次低配車型以上就比較齊全一些,日常代步上也足夠。而中配的兩個車型,有些奇怪,價格低的有配備剎車輔助,牽引力控制,ESp,反而價格高的沒有配備,但是多了電動天窗,日間行車燈,其他都基本一致。而頂配車型則是多了定速巡航, 主駕駛位座椅電動調節,后視鏡加熱等一些配置。建議選擇中配車型較低價格的運動型版本,7.59萬元七個座位,加上不錯的配置,性價比較高。

力帆汽車-邁威

指導價:5.78-7.68萬

邁威整體的造型比較渾厚,帶了點一些硬派的風格,畢竟車身比較大,也不太設計走圓潤的路線。內飾視覺上的質感還算不錯,看起來上檔次,布局較為規整,對稱式布局,上手容易。邁威的車身尺寸為:4440*1760*1730mm,軸距:2720mm,七座布局為2+3+2,以尺寸而言,邁威在這個級別七座SUV中沒有什麼優勢,但車內空間還算比較充裕,頭部空間和腿部空間還算充裕,稱不上局促。第三排成年人乘坐會顯得較為局促,並且使用第三排之後,後備箱的空間變得很可憐。

邁威只有1.5L一種動力可選擇,配置上比較單薄,最低配車型的配置面板可以用可憐來形容,在往上的車型(除了頂配)雖然沒有配備剎車輔助,牽引力控制,車身穩定控制,但是可以選裝,算下來也比較划算,舒適性上的配置也夠日常使用,因為中配車型的裸車價比較低。而頂配車型有配備剎車輔助,牽引力控制,車身穩定控制,舒適性上的配置和中配車型相差不大。建議選擇中配車型,裸車價在6.68萬,算上選裝最多也就7萬多一些,相比之下,性價比還是不低的。

總結:雖然第三排座椅使用的幾率不大,但是有就好過沒有,畢竟有時候真的需要,而以上的三款車型,大邁X5雖然配置較高,但是在做工用料上有待提升,邁威價格雖然低,但是配置也較低,所以三款車型中比較推薦長安CX70,無論是在做工,價格,配置,空間,整體都比較均衡,要說不足的就是外觀的車身造型不太協調的樣子。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

眾泰:我抄你全家!比亞迪:我挖你牆腳!_網頁設計公司

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

但是一直為人詬病的,就是不夠出眾的外形和毫無設計的LOGO。就在本月4號,有消息稱,前奧迪集團設計總監沃爾夫岡·艾格,將加盟比亞迪擔任設計總監。(比亞迪和奧迪聯合成為“比奧迪”BAD。)名字沒聽過不要緊,其代表作有Q7,R8以及延續到現在的大嘴進氣格柵,就在前幾年,曾任奧迪和大眾首席設計師的彼得希瑞爾加入了韓國起亞,效果確實立竿見影,而且還造就了現在起亞機具辨識度的虎嘯式設計。

1.奔馳幹完寶馬乾破鞋

早些年保時捷推出卡宴的時候業界一片罵聲,後來的市場卻證明了德國人是對的,現在panamera的成功也讓確實讓對手眼紅,近日有報導稱奔馳AMG品牌將於2018年發布一款代號為GT4 的四門跑車,直接對標panamera,新車可能基於下一代奔馳cls開發,外觀設計融入AMG GT 車型運動元素,跑車式的外觀確實很驚艷,不過買卡宴和panamera的人,有多少是衝著保時捷的標去的,而且你這四門四座溜背,CLS準備打醬油?

2.豐田新策略?致炫三廂

有消息稱,新款致炫三廂版將會在廣州車展正式發布,外形採用了與兩廂版車型相似的前臉設計,仍搭載1.3L和1.5L發動機。從此前公布的工信部申報圖可以看到,新款致炫三廂版與一汽豐田威馳一脈相承,前臉設計雖然延續了新款致炫兩廂版的造型,但整體風格和色彩運用更加沉穩,在早些年因為國內的“屁股”情懷,兩廂車很不受待見,所以當年風靡歐洲的標緻307來到國內,也要硬生生的加個屁股上去,此次新款致炫三廂版的側面輪廓和尾部造型與威馳非常接近,難道只是為了豐田在華的新產品策略嗎?

3.抄完破鞋抄大眾 眾泰大邁X7

儘管眾泰SR9的上市迎來了一片罵聲,但是據說到目前為止銷量還不錯,這一次眾泰又給我們帶來了大邁(大賣)X7。光聽這名字就知道眾泰對這款車期望有多高了,外形上則是借鑒了大眾cross coupe GTE概念車的造型,

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

所以現在其他汽車品牌,都是家族式的設計,眾泰呢,則是別人家的設計,配置也是一如眾泰統統都有,甚至有傳言還會加入無人駕駛。

4.自主汽車顏值有救?

比亞迪近幾年的表現算是自主汽車品牌里很不錯的了,從新能源汽車的研發到賣到國外的電動大巴。但是一直為人詬病的,就是不夠出眾的外形和毫無設計的LOGO。就在本月4號,有消息稱,前奧迪集團設計總監沃爾夫岡·艾格,將加盟比亞迪擔任設計總監。(比亞迪和奧迪聯合成為“比奧迪”BAD?)名字沒聽過不要緊,其代表作有Q7,R8以及延續到現在的大嘴進氣格柵,就在前幾年,曾任奧迪和大眾首席設計師的彼得希瑞爾加入了韓國起亞,效果確實立竿見影,而且還造就了現在起亞機具辨識度的虎嘯式設計。先不管為何奧迪設計師頻頻跳槽,要是真的有如此大神的加盟,總覺得自主品牌的外形設計是有救了。

5.開車摸腿違法

這两天的朋友圈被一條違章信息刷屏了,據說一男子開車時因將手放在副駕駛女子腿部,涉嫌危險駕駛被執法設備拍攝,還將面臨罰款200元,記3分處罰,事後相關交警部門表示這條短信中的內容、落款、電話號碼均不屬實,屬於謠言,但是有一點卻應該引起大家注意,根據《道路交通安全法實施條例》第六十二條規定,駕駛員在駕車時有撥打接聽手持電話、觀看電視等妨礙安全駕駛的行為均屬於妨礙安全駕駛的行為,因此上述的開車摸大腿,依然是屬於妨礙安全駕駛的行為範疇,依照法規是可以對此違法行為進行處罰的。在這裏奔馳車主表示,開車要是不摸大腿可是會超速的。

6.廣州電動車禁令再次延期

11月2日,廣州市政府官網發布通告,電動車禁行通告再延期5年!除了電動自行車諸如電動平衡車、獨輪車也被明令禁止,駕駛電動獨輪車、電動平衡車以及其他滑行工具上道路行駛的,由公安機關交通管理部門對駕駛人處50元罰款;駕駛人拒絕接受罰款處罰的,可以扣留電動獨輪車、電動平衡車或者其他滑行工具。不過快遞等行業可以使用符合國家標準的快遞專用電動三輪車在規定區域內從事社區配送服務。實行統一車身標識、安裝車載定位系統終端監控設備、配額備案管理等管理措施,在規定的區域、線路、時間上道路行駛。所以朋友們,如果你還想騎電動車上下班請加入快遞行業,要不然就好好賺錢,努力買車吧。(說得好像買得起車就搖得到號一樣,更何況還買不起車。)本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。