Magicodes.IE在.NET Core中通過請求頭導出多種格式文件

前言

在2.2里程碑中我們增加了一些新的功能,正如標題所寫通過請求頭進行導出我們不同格式的文件.下面我們來看一下如何使用.通過這種方式無論是對我們的數據多用途,還是說對我們的數據校驗都做到了輕鬆易配。

同時我們也將在本周發布2.3版本,另外3.0版本我們將進行一次大的性能提升。3.0版本我們將對Razor引擎以及導出引擎進行更換,包括對所有代碼的重構,這是值得期待的。

上周我們發布了2.2.5版本更新如下:

  • 【Nuget】版本更新到2.2.5

  • 【Excel導出】增加分欄、分sheet、追加rows導出 #74

    - exporter.Append(list1).SeparateByColumn().Append(list2).ExportAppendData(filePath);
    - exporter.Append(list1).SeparateBySheet().Append(list2).ExportAppendData(filePath);
    - exporter.Append(list1).SeparateByRow().AppendHeaders().Append(list2).ExportAppendData(filePath);
    
  • [Excel導出】修復‘IsAllowRepeat=true’ #107

  • [Pdf導出】增加PDF擴展方法,支持通過以參數形式傳遞特性參數 #104

    - Task<byte[]> ExportListBytesByTemplate<T>(ICollection<T> data, PdfExporterAttribute pdfExporterAttribute,string temple);
    - Task<byte[]> ExportBytesByTemplate<T>(T data, PdfExporterAttribute pdfExporterAttribute,string template);
    

主要步驟

1.安裝包

Install-Package Magicodes.IE.AspNetCore

2.開始配置

Startup.cs的Configure()方法中,在UseRouting()中間件之後,註冊如下中間件

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();
    app.UseMagiCodesIE();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

上面這種以中間件形式可以為我們提供導出服務,那麼我們再看一下另一種方式如下所示:

  public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllers(options=>options.Filters.Add(typeof(MagicodesFilter)));
            }

上面兩種方式都可以為我們提供導出服務,我們只需要對我們的控制器進行配置我們的特性,在這邊呢 特性主要做的是一個標識作用,標識他的一些相關的內容數據,同時標識他可以當成文件導出。

[HttpGet("excel")]
[Magicodes(Type = typeof(ExportTestDataWithAttrs))]
public List<ExportTestDataWithAttrs> Excel()
{
    return GenFu.GenFu.ListOf<ExportTestDataWithAttrs>(100);
}

上面代碼片段中我們標識這個類允許被導出。同時我們需要通過Type指定我們被導出類的類型。

這樣填寫完后我們可以通過對該地址的調用,但是注意我們必須要添加請求頭以標識被導出的文件類型。如果不添加請求頭,那麼此處將返回的還是json格式的數據。請求頭名稱為Magicodes-Type

       /// <summary>
        ///     XLSX
        /// </summary>
        internal const string XLSXHttpContentMediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        /// <summary>
        ///     PDF
        /// </summary>
        internal const string PDFHttpContentMediaType = "application/pdf";
        /// <summary>
        ///     DOCX
        /// </summary>
        internal const string DOCXHttpContentMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        /// <summary>
        ///     HTML
        /// </summary>
        internal const string HTMLHttpContentMediaType = "text/html";

如果說是模板導出word或者pdf甚至說html文件那麼我們也是同樣的操作如下所示:

[HttpGet("Word")]
        [Magicodes(Type = typeof(ReceiptInfo), TemplatePath = ".//ExportTemplates//receipt.cshtml")]
        public ReceiptInfo Word()
        {
            return new ReceiptInfo
            {
                Amount = 22939.43M,
                Grade = "2019秋",
                IdNo = "43062619890622xxxx",
                Name = "張三",
                Payee = "湖南心萊信息科技有限公司",
                PaymentMethod = "微信支付",
                Profession = "運動訓練",
                Remark = "學費",
                TradeStatus = "已完成",
                TradeTime = DateTime.Now,
                UppercaseAmount = "貳萬貳仟玖佰叄拾玖圓肆角叄分",
                Code = "19071800001"
            };
        }

我們還是需要對其指定Type,然後通過TemplatePath進行指定模板地址即可

同樣的我們還可以通過請求頭進行標識本次請求是否是文件格式導出。


        [HttpGet("pdf")]
        [Magicodes(Type = typeof(BatchPortraitReceiptInfoInput), TemplatePath = ".//ExportTemplates//batchReceipt.cshtml")]
        public BatchPortraitReceiptInfoInput Pdf()
        {

            var input = new BatchPortraitReceiptInfoInput
            {
                Payee = "湖南心萊信息科技有限公司",
                SealUrl =
                @"data:image/jpeg;base64,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",
                LogoUrl =
                @"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAAAYCAYAAACY5PEcAAAaPUlEQVRogY15eZxdVbHuV2vt+Yzdp8f0mM4cAySBBEOAgEHCoIKggIIXZFJ5IMPjPhwAEQdUFHmAE6hccLqoQDDMDhBCCBDIBBnI2N3puU/36TPuaQ3vj+QBvuvTW7/f+mvtqlr17Vq1a39FWkv8V2EAYm+095ObZcz9+mlfOoUb2byMpqAVAEQgrkFMwHIWglgC0BMAtUDrKkqjvwSjOhj2nFShb+PN5eEDJ2iZHm+Zf9pNqZY5u7ibhqgVERaGQdwAlAaZDMw1Aa0Pn0HDTnVhaMdvMbrnj5j/oa9jZM8v4KZnoWnm1QAApSdAIBDVQ4rdEHEvwtoe2O7RsN25qJbWI6rtBVESWgE6rsKrXwEnNQ9+cSuC6hZ42WNgOtOgVQ1x1AfGOAANEAMjC1LtgqYSlAxgWatgGEcAegoAB4hBK4XYPwgR1jC+5xHUd5yMOIhR6NsCbmTQvuQSMAKY4aB3/eMoD+yHAbwXJECHjCFmkyOXrAtrG2cr0YLxA3duy3VcfZrlztgW+0N4T+cfiQYz09CxbBnb9eCG0sjBbhVm4RcHUJsondq28MxLcrOWPKKVBBH9Ezv/P/nv6BBA7J88+8/2/ju+2fuW+tdaRMD7YmVa1XBo+dAQAICp/LXPV4u/XWzZH4BptyIOB1pHdn93q1/cdqbptQF0OBv+oYMkoFVj4eATm8Nyf7fttcBwM/Dq2zA1sNuZ2LftWhHWQCAwywEzTDDDBDF+KCgiQCvYqZbDQR4KjnELjFlghvfe4SkHovpDfpkLIgYiG9zIAkiDcQ/ELDDugHEbxExwMwPAADfTIGYCZICYC25kYVit4GYruNEGbnSBsRz+Pin54SDTACUAuADUuz5ABGIGQAStFYg4DDsJslIAs0GMQ2sFg8g9bIgBAMLqroyTOPX7fmnNShGPgKETpt2CqFrG8K67n8x1XXR9tvXEu0U8CujK++A+VKa0DptKo7/fIsKgxbA7IQICtEZ1YhCtC05cP3vV5adx20NtrG9mXJ06yC071FLCztTD8hLQUoK4jdHdz19M3OlVosSVLF0ZB5ULQn/wAaWK48mGJV/hpgcRv3EF414fM+c+r8U4lIq4VpUllcKTC2T8nx8nlvohNHypfGhFgFIo59c3ivCZyznXv2Ym64UKNsbBXhn5O072Sy/cZjrN+xmXQso9s233mOtMd9lmjSKIAKWnUC7c820ZDCeA1LWmMx2J7LnQKoIS1YyW8c+0FBcQOAwrAYJCNb+fCn1vrfbSDZ+VUW3SclOgQzWdABAmDz58S2H4W9d2Ln7oA4SEGDtw5XDsByax6YAwEdZ8yMhHrvPD99V1nHONVkUYZjeIpQBY0HqqJX/wvFdr+dEuiPmQgQkR2KiMl+Fm5m6cecIVx5qZNh1MjR49vvPlE9MtPXdrJTWRgSAYQBxPgnEbpl2PTU9fp5tnnPCraXOWr+3dfO/P5xz/HRrZ98P9WvtW4/Tz2hU2I45Wa9NtedGwjjuZs7kgSqRrxaeLQXk34qAAy14AwAPgBVCcpIjsOKggqg7A9rLw6mYh07IiY3rTSyIaWxxWt14cBc99EZSHlznjHm61/VLJNT/UNNmgJAfnp98Vlnb9m1/ceCxjTYls65eQqDsP43vu+mFp+LUzlEzM5izzhpXo+rk/MboirFaPEhHSYSVoZzDHmZkZJzjVwzWdoTT26hkHNt14e6qphInBT4w0tj/V1dT9q87RfV/cFlT6Gg1jFgwzBYKNqaEnrtYY68i2nf8JYklxCPD9HVP5j78S+v3t3DoJUmiACGF1HF62e1v7UauWGV5KA8DYzr99yU40POI1dmoVB2DcRP/6P6IwuAWWlwORAYDyIL47qE6OMzMBxi1wI/GaENVlhtkAr/4GFPMHxg0zV0lmroLWPrSmKjfretxUfm5UO3iu6XR837K7/aDS/zmtlLa99vtFFDSGlYHPWV7mYdNtGLLcjmrkv4M4HAyJWJ4buQMgI0nk5rWaiKQc4JomoGIJRmVws7PPsMYaiepgOjMAACIqzIiDfJNhpSCico/hRM0aelgr2Wi5uSLjql0J1a8ln5K+HxgAh1/snfvWc+c95WVNOMlFIBrAaN8pfXVNP/9A4/TvHzW29+tb/VJvI+czQNyGYbWjkn/uLCm2TrbO/nMaAIqFGf1RBJjWKsTRoY9kWBmEk577Vq7rlGPNRKMkM43S0KbPFAc3nj3rQ9d/UoQlQCloFaF9welonbMCjNvghoOtz/V6pp0ShulCyxjEGLiZGhfxUE5rhcjfCugoL9VEKozWIa4NA9KQUXTgVmi7U0vywuquhxklKQqCIyEZqkbiVCkkTKsxFmH/bSiJraZVdwO3GIjC9jjce4ZGuYW474b+8x8znZ7H3eTdKzTFgAa0IkS1R75ARBxgqBWfheUejfruT30sUbdscX7fmjcbpp+Ws5PdkJEP0grcbcWeFx7WXQtXHCdjRLEfwAjKQ01vPv7JDUrXYCdnQasQShZhOcsGGGtMWnbXjqYZNy8eeeeb6/ypoW7DbgNA0DqEmz7pWSnyjSIcneYmr7gtjh64TchhEM1AUN6HRG7F9raFtxzHrWSgVQhAYWDzg790Us3PAxGiyigMK4lqoQ+jB14CMx0wMHDDQ1SbtEwnM8EMm2slQCBwMzUCwGWkIWUeGgJM20pLAdOaB8amgRvThmullx3DmiUSmY8wKXwdj67uATORajzzHYJNfultJcJBM1m3LM/NDNzMUSCu36gWVv8kDtdfqVWBbG/RPaZzNIMeWAE9klXKBKOe7UTuqNY6YZj1CKobUJv6C7zsKeA8F6jdj8RhdfQG4Ueb/cLQFVJgdlQL6msTAxjZ9eb+qOK/2rH0I/ca25696TfF8bezzbOOhFYhtA616SxZm2n8xhmmsdSPgtdhmB0DrbO+ctTQrns2+KXB+YKNINf9b7/Ptnz1/P6t1+xk5p/mTpu3xsg2nLRhwv/yc0FpK9zMyr0di7+zBMR9QICYi6n+x77hT2412k743v8kzmF6aRhWEkaYgtQEKEAzBiVCaJAIK+NxnE4S4xaUliCyR7QKuAbgJU6CiP9WArGclzoXSk0B2oKIDnxFisnHvWznbYbVstXLzkBU3fu0htLJ3PKLYn8AKh49PihuvprI+LZXtxDMcBCUX10UlF69n9vmLpBRkPHebzPu/SiOf3SdwlCHjAHbuuwbjNf3E7FurcvgfBqi2gg434KwPDxbxiGf7Hv5B5nW46+Jw3IAuIMy9v3MtJ7XiVgLcWPJnj//5kVj4uAbp6Qa5kArAa0DECCzTfdeQSzlx+FWcKMVcXAQjDulljk3Lhza/u29ljc3bui8+fz8wZtW1ybfmlvXHWL8wJlhwtnQkq7/+hk6WnNXc893lx4CXAIwoFWxfnjHPTdn2z+4P9E8a5eMiuCWC00adqIe3UedBcZNMG5Ca6LR3medRP30kuVmSckYh7Idk4CCBqFafg4yHq4RE8ni5DdAaIaWlKhOPvGcltbywuAvzg5rAzsY1cOwZ0yHBPYePGu7jAJYbud8Qg0T/T/pVKrvw056flWKEQJkrxLFGjNMCxBVxpsGbfOmBUrt5cqywGhmIQ5ff1LrSINMMOoCFGFs90/eLo/u+IBpz9D1PSuPb5zzmfXj76y5vZo/EM8746azwon9sDMt2PHUw2tNJ9FkJLLto0H5rWYv2wkiD0oXjFL+S8+5qQs+Ztsf3i5FHlJNAWiBlpW4bcGXF8qwMXnw7fPWaVp/vOWeDm4WoNQY3/3XG8db5l31kWnHPDQPMKF1CCITADDR/72no2ofGmdedydxBjB9uI9NYO9rD2N091o4qaZ3e/XYL6GS318xzK4McQ4iQqrxuI2Tww9BK//ibMNVD02Nvi6UHHa8xKehVQAty1pnKvmwuu9hIJlxkovSWjOEldF2ECHTfMKolgQRlfZA+yWvbmbazRyjlJiACAe0lEXNUCDD7NZaFxiRp2z3YyWlBqC1AwAUFF+sA8iua7vdIpWMwvImw071PGpY3Wv9qcErTdt6C6ihrnvln/te//xLSvDGrqXnX7zzmQd/N9m748RlV/1oljF7+dWXb332ijUiLIEoA8bqEfkv90T+jjca2pZ9kPHUViIbhtWMoLwNptteIEoXtCq3k+EC0NBaQUsNt76uzGFUdRiD7BBEaQAMgf/INcWRnx2bavpIlGyY8xsZ5aFlADCG2K8hUdeB9iM+Cm7ah36/mamrr+9EpuUDsJOuoWUErSJkWj862FjZ9GC+9+7/cNPTH1JqcgDMW0jcBnQN3JxZs5zq1UF55xPZ1s8crXUEL70U4/vuf0EDurH70g/5xS2QUehMDj76kps97ljijdqfehpx0CeIuZooZBpScd48JuIdmajw7XdA47OVMqCjGZBxDCkCROWdP0jkzrqGGUI42YVfk7Fq7nvt1qu0jrvLw+u3efVL1y06725r26NfjV795Ssfd5LT9LGXfoupuKaNho4PPtm54FOfGznw8595WQ1iGXCzEyIqOPn+q15P5a5cYXsLXyViULKC2B+Dk25F55HPTB/tveTF2tjAChENwrTqxppnn7PIMpqG/MpemDBh2guh9CvHlguX3qNEDrn2Vfc62dllEU2AWxkQNyGCMupa58OwXGitYbkZlMb2dUd+AYaZ2BeU+psifxJKBWZU3R43dF58aSIz/0FmpEHMC0S8p1HJIrTyASoh8nfdqmRhMRHAeRMIDZCi5IIMzXgLDLsTjFeYjCaWBOVdN7hM/IDzZmhbcxHubACza1qLCDpKEiUCUNutIK8RzCbwRhCrXgOVT4HkIwBQyb8OOzkLcVBdLoIJcCtTEWGM/O6nesJq+UJuJmAnDZ8Yc4a3rbuKiD9mKABdi66+P9Uy1xrff/u9IoxAVAfDakdQ6rPG+7++oaXngeOcZOcGrQRMpxkyrABMI9Vw5klx+W8vGma2zqtbeno0IYZi2glDcdhsIQL/5fmBf+ZflajBSZ6CdOsp38Xh7gTEQGSiNLoZ/tQgDDsJAHBTrdi38eEHTacO9Z0f3FebymlmuNjz2i2Rl8nCsGNheTScrD96XablultKkzd+oTr109tNe+mtWu2rrxWfuyJZd8HvLGcBDrFzMaQoziLmagCwvelQKq6lGlc+Uxx+/PuGdfqD2dbrJv3S384pT070cu5XZNx/HDGYduKjjmku/XUUrgbpNMA7IKN1VzFjKBP6L74sRkYBmUNp6Llbxvc9c3u66aS93O7cP7Ljd8mgOLJPxSaa5q76QtOs5fcPb3/5xuGtG+4DrPv4N751J0w3h3TTktdtr6NYnvzP0+wUA1gShHqoKEatsOUy05n2oum09RH3oGUVQzueQlQrIztt8X+Y7tyfmtbssjbK4LYJw2hBHA6cWhq75UUy9rgyBlJ1t97hZj+4Roo8AAmChlY+8gc2IiiNQ8YB4qCMsDqJqDpR6Fhw1h0NPSvGvOysgu01rSbooVzHhzYn6o/aaljpvbbX/kYie8HzzGj4q199/qBpzTngOMsTGuHWTNP/uI0bTWA8BYCDG+a46TT9wbQ7d2koMJ6GV7f4NyoeGfEyS3cZdldNq/Ko6XTezgx3kFvtW0xn7hrLXrTeNE8Yl/I1yHgMprEIhLhClFmrdbyR83p42ZMRVXvbSWN/x5I7LjKtXBiXDySTTQs2Nc0++cJ06/zXtdY61dS1PtnYdgcxcztprfB+xq049qMvVYr/fodhz4SKm6CFi6AyBRUzNE2//ox089nPyHAEB7c80VGe3Dy7Y9HytcxcJ0zrRFPrppxfPHhMUOy9TESvnW2lpmClNoIZPZPZ3L4ckQ+ta+/SDkQexva8iPLIHphu6l0OyJ8aQqqxC02zV6Ba2A6/2Ida6S1wM0Zjz0XwMksAGAAE/OpqlEsPwUuciWT68/Crf4aTOAEiHEdU2QniGWg5jtL4SwgqIwwQqrH7SjiZeZDhICy3AyIeRFh7C6H/JpK5s0DEAQiY5gwQ60IQ3g8tAc4XQIRvIw6noEQI05oHL7sStck3IPw8Mu3nQAsfKhhEFElE1SkooaHiGMzwoIWGEgLG+xlCrQKkcp/4Doy3ncrkQ18jnQDgwLQbEIkSxvY+8LRhTzvXyy59rGnm6ar46itfHdxx01+aZmfzYW1URBUnFxRDU4QR3KwHjV4Qc5FteOQkAgAtQXAOg2tAiQiGaSLR0AbObYAArTVkXEO67WgoGWOi7yUoXUTk964Nypv2FEdfubzjyOvh1bVAyF6Y9nwkEp9EpfBrxLUhEEuiOvlXVKdegxYGHG8hQNQVlPc9HwcTq0y3tbeafwnl8Wdhp2ZCkw+oPJQYPxsq+Clj6TatlVRyL2B2AYhgWxeAKA2/9nv45RegZT1ErQJKpaB1CICDuIHS8F9guZ2wEq3Qfh9qEwcQ12pQsQK0CcPKINncA37bbV97L9O1ABDDcpe9yHgL90svrNDKgVYuOEshDqsoja4938vOfNOrm/Wmm+5+iHPdoWnj8XE4lBSBwSGTgHZANAg7HUbZph8vI7VyMxAzaNLQHNAMxGwExUGEpYOwvTowboAZNggaIAO57uMh4wkQS6Ku/SRwbm5wktPXtc66dtJJt8OvrAPjMVzvAlj2QpTz/xu1yssQwUGE1XdA5AGagZsNsOxpLXGYv0nJ6BfNs67PG1YWfmkzQFWkch+F5R4Nratj3GhabTlzRoil3sWC8U4Q2Yd4VLEPfukv0MKEVhqW0w43cxy08KFVBUqEsFM9MN1pYKRQGd99qLxZSUAqaA3UdR3xfzNdH77ZzruZmMrecCtUysr3f+cmxlwAJkynCbE/iaEdN6/J9Xz8Ki+78CfJhusvj6MT76xOvXCLL0ZWRSEaGDemErljfl/ffuE1pd5gieVuOiPRMu8ZLYLDd4oBWiCq5aHJhBSHp1ekwYwEjex5/KFEfc8NWk86UyNv3NXe8Knz8n1PrYzDvSOZaSv3RrU9d1YKT53gpIRgzNlkmSu/yLjXwI3mLkLiEGeuTIi4BlA8TJyXZVya9OqOHjCshllj/X/8sVaRE1X6jWphw5/STR+5I/S3t8bB7gstb/pXoLXSKkCsD4AZPWBUD62nMkH51w8oOTKNoV5LEQHcvToOhrdPDT3z26g20RZVyoaM2EO5GV0/Lo/tPrvQv+16rSzGeErISJv+5CTjdt2jh2v6/yvv1fipkTvvnRj49dWcTYcSHrQ2QCiAjAkkcp1rE/XLfmB7x6/RmiGq7UdUq8Cy28ANC/k9a3/CeH13y4JLztHK9w/P+kDEQYyhOjkIKcLDA4xDXk23Hnteue8xvzI6ZbuUNN1krmXWqpX9b92xi/Hw+dY5n/lyUPlbxXCCTxtuFDAz8Zhtndztl15ZHovCT6E9QHJoxRGHAbz0wjtMu+27+b7VfbmOz3RIoX9VGnl6VbJ+3pVxPDJPxn23p5tWmoblnBn4m5/MNF9uQENqnYeiAqAJGhoieuWKuPbm/bb7hXNFOKygPTBqemGq75nLRRx8v2X+1z8RFPYsze978rrOY65zhrY+PRqWJ/7kZnuerBUmH+fM+SIzM2FtIv8j4x8g/j4RyLZcck0cFhLFobWfJWoBiIPxBLjJENX2rZDy7RVO8ldDpme8BNb5Cjd6gqD8zvLCgQ0Xc2N2pWvZjS2Mu77W1rsvk4gjDgqQcRnETbw7AAFATKOubeEvhl745pOGGWH+yV87lzEDgB4m7ozaiZluHL7Rb3tLfmemmhD5f9lrOUcuF0KsVv7Wlxg1H2IEJYEZEbiVKykZt0FFxK0cuGknuZV5wq07YrUqlFaLEOfEwRAMa3pIZA1BA0QWiNWB4EIjRhxvh4h2ZW335J3J7GWPTRy8CkAS/lQvwsrB2Vai689ajD6aaVv66NTAy2dF5T4OqFJd+/yH63tWvLR//aPDDZ1zf1Y384Ro+5oHrvsXoAeQoohUw8pLRRDo0ujWS4licPdQn82NHBgVIcXuaRRNXiDlaxeEU/PgT4Tg1oLelrmXz2HcjQ4Bbf6dZRlXwQwXzHDeG0YTgZiDkb0vfG/m0i98zrDiusmB1+5rW3DuY1F1sIlFIqdEGdCiEzA4GJdKTsxkPJtOZD5WC/23alpHYORCE0BkQEZlkOZtxM02EY5BRnEo49KHuZE8yTAb5/hy4zFuevE0sKlYRAenARJC9EOIbcdptf9S0z72Ss7blGHOrMTRpnlTI9ceUZtao1Scg5M8dY+bnd8vwuKVlfyWVcWhTYug0WYmpiklN3cpGc2QcfCSCGutSsluEVQLWorp/wJ0glYhRDSOTPOHL3OSSzdP9v/pDhGOJMEUuKkBKBC5AAFKAoCBbNuFv7SchZcp+f5xnn7XZmnkbUz0vgI70QCt35u1EuOQInJEUN2Sapj5W8aFXRzbcrRWEo09n3ocqO7mZjbUWj8CUpogwFjiN1JO7bLdpUjXfwql8UehGQc0gbEsOMtA66hgWI2/j/yDPFl/wjfjoP++6sSmu0BKeJkjX7S8OfPA4rekqP2RG21ayjFI0T8Hav9lkjd83k18Vjn2aX+YGr/841Hw+oN28gQlAgW37oirGqZ/6K6xd36xuDy++d/jqs+b51z0v9y62Yqxp/5A3NpHYDBt91FivKShA27Zv/0XoB8GXoZQqCKVO/Y+w6r/o1988xIp+1YSH5tNrFBHrK7GWKbPdhe96rmn/slyFv81KO2HEtX/YgsAiiPvYOSddXAzrX+/SwxxWIs4T1wYVcfhZRsrlps7z7KzmH7Md28GgKi6E0qEFxAZIDJALHURHe4HLGceGE9CKwFoA8xIgxt1UKo2YtqN5xMRuenZb1tey0m220pKFHUcjcByZoF4HWx3+ScBwGE2DLPxQU3yQcZsMNYEovq8l7n6VJkYTWrBCFLBsLoibraFyYZjz61O7EKibhbSLYuhlYRpJz9tWAkww4LlJD/BLAdEBiwncdn/AYw6MEDPFpZRAAAAAElFTkSuQmCC",
                ReceiptInfoInputs = new List<BatchPortraitReceiptInfoDto>()
            };

            for (var i = 0; i < 500; i++)
                input.ReceiptInfoInputs.Add(new BatchPortraitReceiptInfoDto
                {
                    Amount = 22939.43M,
                    Grade = "2019秋",
                    IdNo = "43062619890622xxxx",
                    Name = "張三",
                    PaymentMethod = "微信支付",
                    Profession = "運動訓練",
                    Remark = "學費",
                    TradeStatus = "已完成",
                    TradeTime = DateTime.Now,
                    UppercaseAmount = "貳萬貳仟玖佰叄拾玖圓肆角叄分",
                    Code = "1907180000" + i
                });
            return input;
        }


        [HttpGet("Html")]
        [Magicodes(Type = typeof(ReceiptInfo), TemplatePath = ".//ExportTemplates//receipt.cshtml")]
        public ReceiptInfo Html()
        {
            return new ReceiptInfo
            {
                Amount = 22939.43M,
                Grade = "2019秋",
                IdNo = "43062619890622xxxx",
                Name = "張三",
                Payee = "湖南心萊信息科技有限公司",
                PaymentMethod = "微信支付",
                Profession = "運動訓練",
                Remark = "學費",
                TradeStatus = "已完成",
                TradeTime = DateTime.Now,
                UppercaseAmount = "貳萬貳仟玖佰叄拾玖圓肆角叄分",
                Code = "19071800001"
            };
        }

Reference

https://github.com/dotnetcore/Magicodes.IE

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

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

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

FB行銷專家,教你從零開始的技巧

我從LongAdder中窺探到了高併發的秘籍,上面只寫了兩個字…

這是why的第 53 篇原創文章

荒腔走板

大家好,我是why。

時間過的真是快,一周又要結束了。那麼,你比上周更博學了嗎?先來一個簡短的荒腔走板,給冰冷的技術文注入一絲色彩。

上面這圖是我之前拼的一副拼圖,一共劃分了800塊,背面無提示,難度極高,我花了兩周的時間才拼完。

拼的是壇城,傳說中佛祖居住生活的地方。

第一次知道這個名詞是 2015 年,窩在寢室看紀錄片《第三極》。

其中有一個片段講的就是僧人為了某個節日用沙繪畫壇城,他們的那種專註,虔誠,真摯深深的打動了我,當宏偉的壇城畫完之後,他靜靜的等待節日的到來。

本以為節日當天眾人會對壇城頂禮膜拜,而實際情況是大家手握一炷香,看着眾僧人快速的摧毀壇城。

還沒來得及仔細欣賞那複雜的美麗的圖案,卻又用掃把掃的乾乾凈凈。

掃把掃下去的那一瞬間,我的心受到了一種強烈的撞擊:可以辛苦地拿起,也可以輕鬆地放下。

看到摧毀壇城的片段的時候,有一個彈幕是這樣說的:

一切有為法,如夢幻泡影,如露亦如電,應作如是觀。

這句話出自《金剛般若波羅蜜經》第三十二品,應化非真分。

因為之前翻閱過幾次《金剛經》,看到這句話的時候我一下就想起了它。

因為讀的時候我就覺得這句話很有哲理,但是也似懂非懂。所以印象比較深刻。

當他再次在壇城這個畫面上以彈幕的形式展現在我的眼前的時候,我一下就懂了其中的哲理,不敢說大徹大悟,至少領悟一二。

觀看摧毀壇城,這個色彩斑斕的世界變幻消失的過程,正常人的感受都是震撼,轉而覺得可惜,心裏久久不能平靜。

但是僧人卻風輕雲淡的說:一切有為法,如夢幻泡影,如露亦如電,應作如是觀。

好了,說迴文章。

先說AtomicLong

關於 AtomicLong 我就不進行詳細的介紹了。

先寫這一小節的目的是預熱一下,拋出一個問題,而這個問題是關於 CAS 操作和 volatile 關鍵字的。

我不知道源碼為什麼這樣寫,希望知道答案的朋友指點一二。

抱拳了,老鐵。

為了順利的拋出這個問題,我就得先用《Java併發編程的藝術》一書做引子,引出這個問題。

首先在書的第 2.3 章節《原子操作的實現原理》中介紹處理器是如何實現原子操作時提到了兩點:

  • 使用總線鎖保證原子性。

  • 使用緩存鎖保證原子性。

所謂總線鎖就是使用處理器提供一個提供的一個 LOCK # 信號,當一個處理器在總線上輸出此信號時,其他處理器的請求將被阻塞住,那麼該處理器可以獨佔共享內存。

總線鎖保證原子性的操作有點簡單粗暴直接了,導致總線鎖定的開銷比較大。

所以,目前處理器在某些場合下使用緩存鎖來進行優化。

緩存鎖的概念可以看一下書裏面怎麼寫的:

其中提到的圖 2-3 是這樣的:

其實關鍵 Lock 前綴指令。

被 Lock 前綴指令操作的內存區域就會加鎖,導致其他處理器不能同時訪問。

而根據 IA-32 架構軟件開發者手冊可以知道,Lock 前綴的指令在多核處理器下會引發兩件事情:

  • 將當前處理器緩存行的數據寫回系統內存。
  • 這個寫回內存的操作會使在其他 CPU 里緩存了該內存地址的數據無效。

對於 volatile 關鍵字,毫無疑問,我們是知道它是使用了 Lock 前綴指令的。

那麼問題來了,JVM 的 CAS 操作使用了 Lock 前綴指令嗎?

是的,使用了。

JVM 中的 CAS 操作使用的是處理器通過的 CMPXCHG 指令實現的。這也是一個 Lock 前綴指令。

好,接下來我們看一個方法:

java.util.concurrent.locks.AbstractQueuedLongSynchronizer#compareAndSetState

這個方法位於 AQS 包裏面,就是一個 CAS 的操作。現在只需要關心我框起來的部分。

英文部分翻譯過來是:這個操作具有 volatile 讀和寫的內存語言。

而這個操作是什麼操作?

就是 344 行 unsafe 的 compareAndSwapLong 操作,這個方法是一個 native 方法。

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

為什麼這個操作具有 volatile 讀和寫的內存語言呢?

書裏面是這樣寫的:

這個本地方法的最終實現在 openjdk 的如下位置:
openjdk-7-fcs-src-b147- 27_jun_2011\openjdk\hotspot\src\os_cpu\windows_x86\vm\atomic_windows_x86.inline.hpp(對應於Windows操作系統,X86處理器)

intel 的手冊對 Lock 前綴的說明如下。

  • 確保對內存的讀-改-寫操作原子執行。在 Pentium 及 Pentium 之前的處理器中,帶有 Lock 前綴的指令在執行期間會鎖住總線,使得其他處理器暫時無法通過總線訪問內存。很顯然,這會帶來昂貴的開銷。從Pentium 4、Intel Xeon及P6處理器開始,Intel使用緩存鎖定(Cache Locking) 來保證指令執行的原子性。緩存鎖定將大大降低lock前綴指令的執行開銷。

  • 禁止該指令,與之前和之後的讀和寫指令重排序。

  • 把寫緩衝區中的所有數據刷新到內存中。

上面的第2點和第3點所具有的內存屏障效果,足以同時實現 volatile 讀和volatile 寫的內存語義。

好,如果你說你對書上的內容存疑。那麼我帶大家再看看官方文檔:

https://docs.oracle.com/javase/8/docs/api/

我框起來的部分:

compareAndSet 和所有其他的諸如 getAndIncrement 這種讀然後更新的操作擁有和 volatile 讀、寫一樣的內存語義。

原因就是用的到了 Lock 指令。

好,到這裏我們可以得出結論了:

compareAndSet 同時具有volatile讀和volatile寫的內存語義。

那麼問題就來了!

這個操作,在 AtomicLong 裏面也有調用:

而 AtomicLong 裏面的 value 又是被 volatile 修飾了的:

請問:為什麼 compareAndSwapLong 操作已經同時具有 volatile 讀和 volatile 寫的內存語義了,其操作的 value 還需要被 volatile 修飾呢?

這個問題也是一個朋友拋出來探討的,探討的結果是,我們都不知道為什麼:

我猜測會不會是由於操作系統不同而不同。在 x86 上面運行是這樣,其他的操作系統就不一定了,但是沒有證據。

希望知道為什麼這樣做的朋友能指點一下。

好,那麼前面說到 CAS ,那麼一個經典的面試題就來了:

請問,CAS 實現原子操作有哪些問題呢?

  • ABA問題。

  • 循環時間開銷大。

  • 只能保證一個共享變量的原子操作。

如果上面這三點你不知道,或者你說不明白,那我建議你看完本文後一定去了解一下,屬於面試常問系列。

我主要說說這個循環時間開銷大的問題。自旋 CAS 如果長時間不成功,就會對 CPU 帶來比較大的執行開銷。

而回答這個問題的朋友,大多數舉例的時候都會說: “AtomicLong 就是基於自旋 CAS 做的,會帶來一定的性能問題。巴拉巴拉……”

而我作為面試官的時候只是微笑着看着你,讓你錯以為自己答的很完美。

我知道你為什麼這樣答,因為你看了幾篇博客,刷了刷常見面試題,那裡面都是這樣寫的 :AtomicLong 就是基於自旋 CAS 做的。

但是,朋友,你可以這樣說,但是回答不完美。這題得分別從 JDK 7 和 JDK 8 去答:

JDK 7 的 AtomicLong 是基於自旋 CAS 做的,比如下面這個方法:

while(true) 就是自旋,自旋裏面純粹依賴於 compareAndSet 方法:

這個方法裏面調用的 native 的 comareAndSwapLong 方法,對應的 Lock 前綴指令就是我們前面說到的 cmpxchg。

而在 JDK 8 裏面 AtomicLong 裏面的一些方法也是自旋,但是就不僅僅依賴於 cmpxchg 指令做了,比如還是上面這個方法:

可以看到這裏面還是有一個 do-while 的循環,還是調用的 compareAndSwapLong 方法:

這個方法對應的 Lock 前綴指令是我們前面提到過的 xadd 指令。

從 Java 代碼的角度來看,都是自旋,都是 compareAndSwapLong 方法。沒有什麼差異。

但是從這篇 oracle 官網的文章,我們可以窺見 JDK 8 在 x86 平台上對 compareAndSwapLong 方法做了一些操作,使用了 xadd 彙編指令代替 CAS 操作。

xadd 指令是 fetch and add。

cmpxchg 指令是 compare and swap。

xadd 指令的性能是優於 cmpxchg 指令的。

具體可以看看這篇 oracle 官網的文章:

https://blogs.oracle.com/dave/atomic-fetch-and-add-vs-compare-and-swap

文章下面的評論,可以多注意一下,我截取其中兩個,大家品一品:

然後是這個:

總之就是:這篇文章說的有道理,我們(Dave and Doug)也在思考這個問題。所以我們會在 JIT 上面搞事情,在 x86 平台上把 CAS 操作替換為 LOCK:XADD 指令。

(這個地方我之前理解的有問題,經過朋友的指正後才修改過來。)

所以,JDK 8 之後的 AtomicLong 裏面的方法都是經過改良后, xadd+cmpxchg 雙重加持的方法。

另外需要注意的是,我怕有的朋友懵逼,專門多提一嘴:CAS 是指一次比較並交換的過程,成功了就返回 true,失敗了則返回 false,強調的是一次。而自旋 CAS 是在死循環裏面進行比較並交換,只要不返回 true 就一直循環。

所以,不要一提到 CAS 就說循環時間開銷大。前面記得加上“自旋”和“競爭大”兩個條件。

至於 JDK 8 使用 xadd 彙編指令代替 CAS 操作的是否真的是性能更好了,可以看看這篇 oracle 官網的文章:

https://blogs.oracle.com/dave/atomic-fetch-and-add-vs-compare-and-swap

文章下面的評論,可以多注意一下,我截取其中一個,大家品一品:

經過我們前面的分析,AtomicLong 從 JDK 7 到 JDK 8 是有一定程度上的性能優化的,但是改動並不大。

還是存在一個問題:雖然它可以實現原子性的增減操作,但是當競爭非常大的時候,被操作的這個 value 就是一個熱點數據,所有線程都要去對其進行爭搶,導致併發修改時衝突很大。

所以,歸根到底它的主要問題還是出在共享熱點數據上。

為了解決這個問題,Doug Lea 在 JDK 8 裏面引入了 LongAdder 類。

更加牛逼的LongAdder

大家先看一下官網上的介紹:

上面的截圖一共兩段話,是對 LongAdder 的簡介,我給大家翻譯並解讀一下。

首先第一段:當有多線程競爭的情況下,有個叫做變量集合(set of variables)的東西會動態的增加,以減少競爭。sum() 方法返回的是某個時刻的這些變量的總和。

所以,我們知道了它的返回值,不論是 sum() 方法還是 longValue() 方法,都是那個時刻的,不是一個準確的值。

意思就是你拿到這個值的那一刻,這個值其實已經變了。

這點是非常重要的,為什麼會是這樣呢?

我們對比一下 AtomicLong 和 LongAdder 的自增方法就可以知道了:

AtomicLong 的自增是有返回值的,就是一個這次調用之後的準確的值,這是一個原子性的操作。

LongAdder 的自增是沒有返回值的,你要獲取當前值的時候,只能調用 sum 方法。

你想這個操作:先自增,再獲取值,這就不是原子操作了。

所以,當多線程併發調用的時候,sum 方法返回的值必定不是一個準確的值。除非你加鎖。

該方法上的說明也是這樣的:

至於為什麼不能返回一個準確的值,這就是和它的設計相關了,這點放在後面去說。

然後第二段:當在多線程的情況下對一個共享數據進行更新(寫)操作,比如實現一些統計信息類的需求,LongAdder 的表現比它的老大哥 AtomicLong 表現的更好。在併發不高的時候,兩個類都差不多。但是高併發時 LongAdder 的吞吐量明顯高一點,它也佔用更多的空間。這是一種空間換時間的思想。

這段話其實是接着第一段話在進行描述的。

因為它在多線程併發情況下,沒有一個準確的返回值,所以當你需要根據返回值去搞事情的時候,你就要仔細思考思考,這個返回值你是要精準的,還是大概的統計類的數據就行。

比如說,如果你是用來做序號生成器,所以你需要一個準確的返回值,那麼還是用 AtomicLong 更加合適

如果你是用來做計數器,這種寫多讀少的場景。比如接口訪問次數的統計類需求,不需要時時刻刻的返回一個準確的值,那就上 LongAdder 吧

總之,AtomicLong 是可以保證每次都有準確值,而 LongAdder 是可以保證最終數據是準確的。高併發的場景下 LongAdder 的寫性能比 AtomicLong 高。

接下來探討三個問題:

  • LongAdder 是怎麼解決多線程操作熱點 value 導致併發修改衝突很大這個問題的?

  • 為什麼高併發場景下 LongAdder 的 sum 方法不能返回一個準確的值?

  • 為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

先帶大家看個圖片,看不懂沒有關係,先有個大概的印象:

接下來我們就去探索源碼,源碼之下無秘密。

從源碼我們可以看到 add 方法是關鍵:

裏面有 cells 、base 這樣的變量,所以在解釋 add 方法之前,我們先看一下 這幾個成員變量。

這幾個變量是 Striped64 裏面的。

LongAdder 是 Striped64 的子類:

其中的四個變量如下:

  • NCPU:cpu 的個數,用來決定 cells 數組的大小。

  • cells:一個數組,當不為 null 的時候大小是 2 的次冪。裏面放的是 cell 對象。

  • base : 基數值,當沒有競爭的時候直接把值累加到 base 裏面。還有一個作用就是在 cells 初始化時,由於 cells 只能初始化一次,所以其他競爭初始化操作失敗線程會把值累加到 base 裏面。

  • cellsBusy:當 cells 在擴容或者初始化的時候的鎖標識。

之前,文檔裏面說的 set of variables 就是這裏的 cells。

好了,我們再回到 add 方法裏面:

cells 沒有被初始化過,說明是第一次調用或者競爭不大,導致 CAS 操作每次都是成功的。

casBase 方法就是進行 CAS 操作。

當由於競爭激烈導致 casBase 方法返回了 false 后,進入 if 分支判斷。

這個 if 分子判斷有 4 個條件,做了 3 種情況的判斷

  • 標號為 ① 的地方是再次判斷 cells 數組是否為 null 或者 size 為 0 。as 就是 cells 數組。

  • 標號為 ② 的地方是判斷當前線程對 cells 數組大小取模后的值,在 cells 數組裡面是否能取到 cell 對象。

  • 標號為 ③ 的地方是對取到的 cell 對象進行 CAS 操作是否能成功。

這三個操作的含義為:當 cells 數組裡面有東西,並且通過 getProbe() & m算出來的值,在 cells 數組裡面能取到東西(cell)時,就再次對取到的 cell 對象進行 CAS 操作。

如果不滿足上面的條件,則進入 longAccumulate 函數。

這個方法主要是對 cells 數組進行操作,你想一個數組它可以有三個狀態:未初始化、初始化中、已初始化,所以下面就是對這三種狀態的分別處理:

  • 標號為 ① 的地方是 cells 已經初始化過了,那麼這個裡面可以進行在 cell 裏面累加的操作,或者擴容的操作。

  • 標號為 ② 的地方是 cells 沒有初始化,也還沒有被加鎖,那就對 cellsBusy 標識進行 CAS 操作,嘗試加鎖。加鎖成功了就可以在這裏面進行一些初始化的事情。

  • 標號為 ③ 的地方是 cells 正在進行初始化,這個時候就在 base 基數上進行 CAS 的累加操作。

上面三步是在一個死循環裏面的。

所以如果 cells 還沒有進行初始化,由於有鎖的標誌位,所以就算併發非常大的時候一定只有一個線程去做初始化 cells 的操作,然後對 cells 進行初始化或者擴容的時候,其他線程的值就在 base 上進行累加操作。

上面就是 sum 方法的工作過程。

感受到了嗎,其實這就是一個分段操作的思想,不知道你有沒有想到 ConcurrentHashMap,也不奇怪,畢竟這兩個東西都是 Doug Lea 寫的。

然後再補充說明一下,cells 的初始化大小為 2:

cells 的最大值為 CPU 核數:

cell 是被 Contended 註解修飾了,為了解決偽共享的問題:

說起偽共享,我想起了之前的《一個困擾我122天的技術問題,我好像知道答案了》這篇文章中提到的一個猜想:

後來,我也用這個註解去解決偽共享的問題了,可惜最終的實驗結果表明不是這個原因。

那篇文章發布後有很多朋友給我反饋他們的看法,而更多的是在這條路上發現了更多更多的玄學問題,但是最終這些問題的背後都指向了同一個東西:JIT。

扯遠了,說回本文的這個 LongAdder。

總的來說,就是當沒有衝突的時候 LongAdder 表現的和 AtomicLong 一樣。當有衝突的時候,才是 LongAdder 表現的時候,然後我們再回去看這個圖,就能明白怎麼回事了:

好了,現在我們回到前面提出的三個問題:

  • LongAdder 是怎麼解決多線程操作熱點 value 導致併發修改衝突很大這個問題的?

  • 為什麼高併發場景下 LongAdder 的 sum 方法不能返回一個準確的值?

  • 為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

它們其實是一個問題。

因為 LongAdder 把熱點 value 拆分了,放到了各個 cell 裏面去操作。這樣就相當於把衝突分散到了 cell 裏面。所以解決了併發修改衝突很大這個問題。

當發生衝突時 sum= base+cells。高併發的情況下當你獲取 sum 的時候,cells 極有可能正在被其他的線程改變。一個在高併發場景下實時變化的值,你要它怎麼給你個準確值?當然,你也可以通過加鎖操作拿到當前的一個準確值,但是這種場景你還用啥 LongAdder,是 AtomicLong 不香了嗎?

為什麼高併發場景下 LongAdder 的寫性能比 AtomicLong 高?

你發動你的小腦殼想一想,朋友。

AtomicLong 不管有沒有衝突,它寫的都是一個共享的 value,有衝突的時候它就在自旋。

LongAdder 沒有衝突的時候表現的和 AtomicLong 一樣,有衝突的時候就把衝突分散到各個 cell 裏面了,衝突分散了,寫的當然更快了。

一點思考

本文的題目是《我從LongAdder中窺探到了高併發的秘籍,上面就寫了兩個字……》。

那麼這兩個字是什麼呢?

就是拆分。我淺顯的覺得分佈式、高併發都是基於拆分思想的。

本文的 LongAdder 就不說了。

微服務化、分庫分表、讀寫分離……這些東西都是在拆分,把集中的壓力分散開來。

我們常常說性能不行了,那就堆機器解決,這就是在做拆分。

當然,拆分了帶來好處的同時也是有一定的問題的。

比如老大難的分佈式事務、數據聚合查詢等需求。

舉一個我遇到過的例子吧。

在寫這篇文章之前,我看了 LongAdder 源碼,了解到它這樣的結構后,知道了它和 AtomicLong 之間的差異后,我想起了之前做過的一個需求。

就是賬戶服務,有個大商戶的賬戶是一個熱點賬戶,交易非常的頻繁。

這個賬戶上的金額就相當於是一個共享的熱點數據。

我們當時的做法是把這個賬戶拆分為多個影子賬戶,這樣就把熱點賬戶拆分成了多個影子賬戶,壓力就分攤了。

其實這個思想和 LongAdder 是一脈相承的。

這個場景下拆分帶來的問題是什麼呢?

其中一個問題就是這個賬戶的總餘額是多個影子賬戶之和,而每個影子賬戶上的餘額是時刻在變化的,所以我們不能保證餘額是一個實時準確的值。

但是商戶不關心這個呀。他只關心上日餘額是準確的,每日對賬都能對上就行了。

我們在滿足需求的同時,性能還上去了。

還有一個簡單的思考是如果我們把“實現原子操作進行加減”這句話當做一個需求。

我個人拙見是這樣的,AtomicLong 類就是實現了這個需求,交付出去后,它能用,能正常工作,而且還附送了一個功能是每次都給你返回一個準確的值。

而 LongAdder 就是更加優雅的實現了這個需求,它是在原有的基礎上進行了迭代開發,功能還是能一樣的實現,沒有附加功能,但是針對某些場景來說,更好用了。

它們傳遞給我的思想不是我們常說的:先上,能跑就行,後期再迭代。

而是:它確實能跑,但是還有更加快,更加優雅的實現方式,我們可以實現它。

這是我們需要學習的地方。

最後說兩句(求關注)

才疏學淺,難免會有紕漏,如果你發現了錯誤的地方,還請你留言指出來,我對其加以修改。

感謝您的閱讀,我堅持原創,十分歡迎並感謝您的關注。

我是 why,一個被代碼耽誤的文學創作者,不是大佬,但是喜歡分享,是一個又暖又有料的四川好男人。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

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

美國八大州擬擴建充電站等 提升電動汽車普及率

為增加電動汽車普及率,美國加州、紐約及其它6州政府昨(24) 日聯合發布聲明,將廣設充電站、修改營建法條,務求使一般市民也能輕鬆擁有、享受電動汽車。

加州、紐約、麻州、康乃狄克、馬里蘭、羅德島、佛蒙特、奧勒崗等州,合計銷售佔比已超過美國汽車市場的25%。其中,加州是美國最大的汽車銷售市場。

據紐約時報報導,到2025年,州政府希望零碳排放汽車(包含電動汽車與燃料電池汽車)銷量至少能達到330萬輛的目標。

美國電動汽車製造商特斯拉(Tesla)昨天宣布,成功挖腳蘋果產品設計副總裁Doug Field,他在蘋果公司任職時,曾是MacBook Air、MacBook Pro、與iMac等明星級產品的幕後推手。Field之前還在福特汽車任職過,未來他將領導特斯拉汽車研發部門。

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

【其他文章推薦】

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

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

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

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

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

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

戴姆勒與歐洲五集團合作 擬在德國大幅增設加氫站

戴姆勒集團日前宣佈,將與法國液化空氣集團、德國林德集團、奧地利石油天然氣集團(OMV)、荷蘭皇家殼牌集團、法國道達爾集團合作,啟動一項名為“H2 流動”的計畫,到2017年將德國現有的15座加氫站增加到100座,到2023年增加到400座。以效刺激氫燃料電池車市場。

除了在城市中心區大量設置加氫站之外,還將在德國主要高速公路沿線設置加氫站,兩座加氫站之間的距離不超過90公里。這項加氫站建設計畫耗資巨大。戴姆勒集團預計,為了修建400座加氫站,大約需要3.5億歐元。

加氫站是發展氫燃料電池車的必備條件,各國都在陸續興建,但此前一直進展緩慢,去年全球僅新增27座加氫站。根據美國能源部最新公佈的資料,目前美國境內只有10座公共加氫站。

由於氫燃料電池車實現了零排放,有利於保護環境,同時降低對石油的依賴,被稱為“終極環保車”。此外,氫燃料電池車續駛里程較長,且幾分鐘內就可以完成加氫工作。目前氫燃料電池車市場處於起步階段,大多採用租賃方式。

今年1月,戴姆勒與福特、日產簽署了戰略聯盟協定,在燃料電池車領域展開深度合作,聯合研發可以共用的燃料電池堆、燃料電池系統及其他燃料電池車部件,並計畫2017年推出各自的量產燃料電池車。

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

【其他文章推薦】

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

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

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

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

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

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

雷諾擬與LG Chem合作開發時速400公里的電動車

全球最大可充電電池製造商樂金化學公司(LG Chem),和歐洲電動車先驅雷諾汽車(Renault)聯手,希望未來幾年將電動車的最高時速加快一倍。

據韓國總統朴槿惠的首席經濟幕僚趙源東(Cho Won Dong)透露,這兩家公司正在考慮開發最快時速可達400公里的電動車。目前電動車的最高時速為每小時200公里。

為加強雙邊合作,朴槿惠4日還拜會了雷諾在巴黎南方設立的電動車測試中心。

據悉,兩家公司目前還不會簽署了解備忘錄(MOU),但原則上同意互相合作,正在協商細節上的歧異。由於要開發高速電動車,鋰電池是最重要的環節之一,因此對於雷諾來說,與樂金化學的合作十分重要。

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

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

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

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

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

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

※回頭車貨運收費標準

日產結盟三菱 衝刺北美及新興電動車市場

日產和三菱汽車周二(5)宣布策略結盟,將藉由共同開發電動車,共享工廠、產能和技術,並提升北美和新興市場汽車銷量。日產在聲明中表示,「日產已與三菱達成策略結盟,此舉將擴大雷諾與日產的盟友關係。」

三菱加入後,雷諾與日產的盟友將增加至5名,還包括德國戴姆勒和俄羅斯的AvtoVAZ,共同抵禦德國福斯和日本豐田的競爭。此外,雷諾的本國對手標緻雪鐵龍(PSA Peugeot Citroen)也與通用結盟,以節省成本。

2011年,日產和三菱成立合資公司NMKV,共同研發迷你車,本次的聲明表示,「預期現有的NMKV公司將共同研發新款小車,其中包括預計在全球銷售、特定版本的電動車。」

雷諾、日產和三菱表示,結盟後的首批新車之一,將是由雷諾子公司-雷諾三星汽車在南韓生產的大型車,該車款將掛上三菱的品牌在北美市場販售。第2款較小型的車款也是為三菱設計,係由雷諾研發,生產地點尚未決定。

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

中國高新汽車國際峰會 – 汽車行業思想領袖的國際峰會

  探索新一代節能智聯車輛的創新業務與技術戰略   第二屆中國高新汽車國際峰會由法蘭克福展覽(上海)有限公司和中國國家發展和改革委員會 國際合作中心聯合主辦,是真正國際化的行業思想領袖盛會。演講嘉賓和與會代表將相互交流,分享理念,推廣新策略、新協作、新技術、新服務與新應用。 與會代表在峰會中將獲得有關商業模式、產品和服務戰略、技術創新的寶貴新創意和洞察力, 將推動OEM廠商、供應商和服務提供商朝著更加可持續、更具盈利能力的未來繼續前進。    本屆峰會的演講和討論會將深入探索各種熱門主題,包括:    1.
中國汽車行業和相關市場實現可持續發展的政策、首要任務與積極措施演變 2.
國外經驗與案例分析:為汽車行業發展而採用的商業模式和技術創新 3.
促進中國國有和民營汽車企業的發展:朝著真正合作、技術轉讓和全球市場渠道邁進 4.
電動方程式賽車(Formula E)來臨中國 – 對電動車的研發,性能,安全性,可靠性和消費者的接受程度帶來潛在附帶利益 5.
個人交通的新方向如何與中國未來智能生態城市發展的目標接軌 6.
電動交通和電動化 – 使市場增長的關鍵步驟 7.
未來高增長售後市場的機會:實現盈利發展和客戶滿意度 8.
經銷商和分銷商將業務擴大至新維修市場的潛力 9.
將威力強大的數字營銷和社交媒體戰略用於汽車市場的發展:OEM廠商及零售商的最佳實 踐 10.
評估乘用車和商用車市場中的綜合機遇 11.
在中國的商用車輛和運輸車隊中減排,實現更清潔高效的運作 12.
汽車智聯技術創新實現遠程信息處理之外的新商機   聆聽各大OEM商、供應商和政府政策制定者的新見解,目前,來自國內外的多位高級別演講嘉賓業已確認出席:   ‧
中國國家發展和改革委員會:高級司長 ‧
中國科技部:高級司長 ‧
王成先生,中國汽車技術研究中心 (CATARC), 汽車產業發展研究所副 總工程師及清潔能源汽車生產力促進中心執行主任 ‧
呂洋先生, 中國海億汽車賽事管理(北京)有限公司副總裁及CEO ‧
Thomas Hajek先生, 德國菲亞特克萊斯勒集團董事會成員 ‧
Boriana Lambreva女士,大眾汽車(中國)公司新能源汽車集團戰略與規劃高 級經理 ‧
原誠寅博士, 北京汽車新能源汽車有限公司產品工程院副院長 ‧
Ridzuan Yusof先生, 馬來西亞Proton電動 車輛項目總監 ‧
Martin Rosell先生, 瑞典WirelessCar公司董事總經理 ‧
Christophe Aufrere先生,法國佛吉亞集團首席技術官 ‧
Christian Heep先生,德國電動交通協會(BEM)首席執行官兼營銷總監 ‧
董揚先生, 中國汽車工業協會(CAAM) 秘書長 ‧
Francois Schoentgen先生,大陸汽車集團動力總成變速箱控制董事總經理 ‧
Klaus Paur先生,中國益普索公司全球汽車業總監製 ‧
Ing Bernd Kraemmer先生, 奧地利iO Vehicles/ iO-E-Scooter公司董事總經理 ‧
Rebecca Zhu女士, 中國HTI業務發展總監(休斯通信公司) ‧
Rick Longobart先生,美國聖塔阿娜市 設施與車隊經理兼市政設備維護協會 (MEMA)主席 ‧
宋健教授,清華大學汽車技術研究院院長及汽車工程系教授 ‧
Madani Sahari先生, 馬來西亞汽車研究院(MAI)首席執行官 ‧
林程博士,北京理工大學電動車輛國家工程實驗室(NELEV)教授兼副主任   詳細內容請上 

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

【其他文章推薦】

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

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

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

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

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

全國環保盃桌球錦標賽基隆登場 41支隊伍以球會友

第一次在基隆市舉辦的「全國第32屆環保盃桌球錦標賽」,自9日起一連三天在體育館熱鬧開打,市長林右昌也以地主台北網頁設計身份歡迎全國各縣市環保單位41支隊伍、近500名桌球好手來到基隆,並期許選手們除了以球會友,也別忘了好好欣新北清潔賞基隆的山海美景。

開幕典禮由基隆市長林右昌及環保署署長張子敬到場勉勵選手,並在台上進行開iphone維修球儀式。林右昌代表基隆市民歡迎全國各縣市選手的到來,希望在大FB行銷會的妥善安排下,能讓選手賓至如歸,展現最佳實力,並提醒選台北網頁設計手們除了透過比賽相互交流切磋球技,也別忘了盡情享受基隆的在地文化。

林右昌表示,這屆的環保盃桌球錦標賽是32年貨運來首度在基隆舉行,過去由於基隆市的運動場館場地環境條件不太好,因此無租車法舉辦全國賽事,這幾年來市府把包括市立體育館的運動空間及游泳池大幅整修,讓大家享受優質的運動環境,除了比賽之外銷售文案也歡迎大家在基隆住宿,並且進行觀光遊程,𣈱遊基隆的好山好水。

環保局指出,市府如何寫文案將安排選手前往有「網頁設計台灣龍珠」美譽的基隆嶼,以及海科館、和平島等地,進行環保網頁設計公司業務交流活動,讓各地的環保夥伴能夠對基隆有更進一步的瞭解。

環保盃桌球錦標賽是從環保署成立之初就開始舉辦,每年由包裝行銷各縣市環保局輪流辦理,今年已邁入第32年,除網頁設計讓各縣市環保人員有聯誼交流機會,也鼓勵大家運動強身,發揮團隊精神,讓工作更有效率。

基市府與法院推出青少年法治教育 培育「國民法官」超前部署

為全面提升學生法治教育素養,基隆市政府與基隆地方法院特別為全市高中學生,安排專業法律素養學習與公民實踐活動,第一批八斗高中的學生11日前往地院參觀,透過真實情境與模擬法庭學習法律知識,為培育「國民法官」超前部署。

這項青少年專業法律素養學習與公民實踐活動,是由林右昌市長與基隆地院李台北網頁設計麗玲院長大力促成,以專業的角度,為本市高中833位學生精心規劃「法FB行銷院設施導覽」、「青少年版模擬法庭」及「與法官有約」等系列學習活動,透過各活動體驗傳達各項法律知識,讓原本抽象的法律用語、知識變得更親近、更有趣。

林右昌在11日下午的開幕新北清潔儀式中指出,民主政治不只是投票選舉,公民才是民iphone維修主政治的基礎,在古代也不是每個人都有網頁設計公民權,身為公民既有權利也有責任,權利與責任之間就是法治的基礎,近年來包括司台北網頁設計法體制跟法院與人民的認知比較疏遠,因此他認為應該要為學生規劃建立法治觀念,讓大家成為負責任的公民。

林右昌說,雖然在學校中有公民跟法治教育,但比較難以引起銷售文案學生的興趣,感謝李院長跟法院同仁在百忙中安排這樣的課程,透過真實情境參觀與模網頁設計公司擬法庭等,希望讓同學建立更正確的法律價值觀念。

在導覽中,學生能近距離認識投標室、公證禮堂、法貨運律服務櫃台等與生活貼近的法院場網頁設計所,更特別安排學生參觀少年法庭與收容室,導覽過程同步進行青少年犯罪防治宣導,接著進行「模擬法庭」,學生必須預先了解法院精心準備的劇本,然後在法庭分別飾演法官、檢察官、書租車記官、法警及律師等,依著劇情完成如何寫文案一次審理程序,擔任證人的同學甚至能體驗變聲設備,過程十分真實!

在最後「與法官有約」的座談中,法官除了為學生解說模擬法庭中的法律知識,更現身說法,讓學生對司法官、檢察官等司法工作有更多認識,由於「國民法官」制度即將在2023年上路,透過這一系列的活動,法院也將逐步推動本市國民參與審判準備工作。

教育處表示,法治教育是社會基礎工程,法治素養是一項重要的公民包裝行銷素養,為了深化法治教育,將持續與法院合作辦理「高中法治教育與公民實踐活動」,規劃每位高中生在畢業前均能到法院參與體驗學習,全面提升本市學生公民與法治素養。

Model S銷量不如預期 Tesla三季度財測不佳

美國電動車製造商特斯拉(Tesla Motors)於美股5日收盤後公佈的上季汽車銷量不如預期、賣給其他車商的碳權抵換交易收入下滑,加上第4季盈餘財測欠佳,導致該公司盤後股價重挫逾12%。

特斯拉表示,Q3期間電動轎車每週已可生產550台、整季出貨量達創記錄的5,500台,其中歐洲地區的出貨量超過了1,000台。不過,Model S的Q3出貨量仍不如市場樂觀的預估,市場曾預期Model S的Q3銷售量有望上升至5,850台。

展望Q4,特斯拉預估Model S的出貨量有望接近6,000台,這會讓2013年一整年的出貨量達到21,500台,而當季的本業毛利率則可望上升至25%。此外,特斯拉已在Q3開始接受來自中國大陸客戶對Model S下達的訂單,預計可在明年Q1首度交貨。

特斯拉去年的Model S出貨量僅約2,650台,不如該公司原本設定的5,000台。

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

【其他文章推薦】

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

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

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

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

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

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