zoukankan      html  css  js  c++  java
  • 系统架构——前后端分离

    前后端分离大概是指是HTML和服务器代码的分离,因为浏览器中解释执行的HTML+JS+CSS代码混合着<%%>包含的内容确实是不友好,于是就有人发明了代码分离的技术,比如asp.net的基于事件的codebehind,struts的mvc方式。再后来,为了更彻底地分离,前端直接做成了独立的程序包或应用,比如基于浏览器的angular、react之类的。这种前后端分离的好处是显而易见的,即增加了代码的可读性,增加了可维护性,同时也容易分配开发任务,前后端可以并行开发,互不干扰。

    在实际开发中,新的项目,只要是正式的项目,肯定是尽量代码分离的,况且现在主流的程序框架都是MVC结构的,你不想分离都难,唯一纠结的地方就是选择服务端渲染还是客户端渲染的问题。服务端渲染和客户端渲染的比较大的差别大概有两点,一个是响应速度上,服务端渲染每次返回的一个完整的HTML代码或是部分HTML代码,而客户端渲染则所有界面逻辑都在客户端,变更界面不用每次都向服务器请求。由于客户端渲染每次操作只请求纯数据的部分,这样无论响应速度还是网络流量都会比服务端渲染好点。当然服务端渲染也有服务端渲染的好处,就是生成页面连同数据一同发过来的,不用复杂的Dom操作,这样有利于开发的效率,毕竟服务端的调试要比客户调试来得方便。

    我们可以用代码的方式来比较一下这两者的不同。假设我们要开发一个网店系统,其中有一功能就是商品的管理,商品有一个分类属性,商品和分类是从属关系,一般设计成多对一的关系。比如以下关于分类和商品实体的定义代码:

        /// <summary>
        /// 分类实体
        /// </summary>
        [Table("CategoryInfo")]
        public class CategoryInfo
        {
            public Guid Id { get; set; }
            public string Title { get; set; }
    
            public override string ToString()
            {
                return Title;
            }
        }
        
        
        /// <summary>
        /// 商品实体
        /// </summary>
        [Table("CommodityInfo")]
        public class CommodityInfo
        {
            public Guid Id { get; set; }
    
            public string Title { get; set; }
    
            public float Price { get; set; }
    
            public Guid CategoryInfoId { get; set; }
    
            public CategoryInfo Category { get; set; }
    
            public override string ToString()
            {
                return Title;
            }
        }
    
    

    然后,我们在DbContext里边加上这两行:

            public DbSet<CategoryInfo> CategoryInfos { get; set; }
    
            public DbSet<CommodityInfo> CommodityInfos { get; set; }
    
    

    因为我们只做简单的CRUD操作,所以这个示例中免去了业务层代码逻辑,我们将直接在Controller中进行Linq查询,无论是MVC项目,还是WEB API项目,查询逻辑是一样的。

    //MVC中的Action
            public IActionResult Index()
            {
                return View(dbContext.CommodityInfos.ToList());
            }
    
    //API中的查询
            [HttpGet()]
            public CommodityInfo[] All()
            {
                return dbContext.CommodityInfos.ToArray();
            }
    
    

    接下来就有区别了,MVC中我们只要定义一个View视图。

    @model List<RelationData.CommodityInfo>
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <table class="table">
        <tr><th>分类</th><th>商品名称</th></tr>
        @foreach (var p in Model)
        {
            <tr><td>@p.Category</td><td>@p</td></tr>
        }
    </table>
    

    而客户端渲染要先建一个Angular(当然也可以是其它的),我们可以在VS中创建,也可以命令行创建。为了方便,我们用DevExpress。
    HTML部分:

    <dx-data-grid id="gridContainer"
        [dataSource]="dataSource"
        [remoteOperations]="false"
        [allowColumnReordering]="true"
        [rowAlternationEnabled]="true"
        [showBorders]="true"
        (onContentReady)="contentReady($event)">
    
        <dxo-paging [pageSize]="10"></dxo-paging>
        <dxo-pager
            [showPageSizeSelector]="true"
            [allowedPageSizes]="[10, 25, 50, 100]"
        ></dxo-pager>
        <dxo-search-panel
            [visible]="true"
            [highlightCaseSensitive]="true"
        ></dxo-search-panel>
        <dxo-group-panel
            [visible]="true"
        ></dxo-group-panel>
        <dxo-grouping
            [autoExpandAll]="false"
        ></dxo-grouping>
    
        <dxi-column dataField="Category.Title" caption="分类"></dxi-column>
        <dxi-column caption="Title" dataField="商品名称"></dxi-column>
    
    </dx-data-grid>
    

    组件部分:

    import { NgModule, Component, Pipe, PipeTransform, enableProdMode } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { DxDataGridModule,
             DxBulletModule,
             DxTemplateModule } from 'devextreme-angular';
    import DataSource from 'devextreme/data/data_source';
    import { Service } from './app.service';
    
    @Component({
      selector: 'app-counter-component',
      templateUrl: './commodity.component.html'
    })
    export class CommodityComponent {
        
        dataSource: DataSource;
    
        constructor(service: Service) {
            this.dataSource = service.getDataSource();
        }
    }
    

    数据服务:

    import { Injectable } from '@angular/core';
    import 'devextreme/data/odata/store';
    import DataSource from 'devextreme/data/data_source';
    
    @Injectable()
    export class Service {
        getDataSource() {
            return new DataSource({
                store: {
                    url: 'https://localhost/api/commodity/all'
                }
            });
        }
    }
    

    相较而言,两者似乎差不多,区别是服务器端渲染是内存传递对象,而客户端渲染是通过json来传递对象。另外就是客户端增加了一个技能栈,当然你也可以不用Angular框架,而是直接用ajax的方式直接操作Dom树。

    前后端分离,我们还可以再扩展一下。现在的客户端框架,其实就是将原来的瘦端进行了富化,现在有了丰富的第三方UI组件,原来需要桌面程序才能实现的东西,现在通过纯网页也可以实现了,因而前端并不限于HTML,不包括桌面应用,手机APP、小程序等不直接处理业务逻辑的各类终端。

    Xamarin中获取Json数据:

      var uri = new Uri (string.Format ("http://localhost/api/all", string.Empty));
    
      ...
      var json = JsonConvert.SerializeObject (item);
      var content = new StringContent (json, Encoding.UTF8, "application/json");
    
      HttpResponseMessage response = null;
      if (isNewItem)
      {
        response = await _client.PostAsync (uri, content);
      }
      ...
    
      if (response.IsSuccessStatusCode)
      {
        Debug.WriteLine (@"	TodoItem successfully saved.");
    
      }
      ...
    
  • 相关阅读:
    Storm的并行度、Grouping策略以及消息可靠处理机制简介
    storm入门原理介绍
    Kafka学习笔记-Java简单操作
    批量复制word文档,并生成以日期为后缀名的批量文档攻略,批量生成word文档
    数组
    分支结构,循环结构学习整理
    java中的运算符
    Java中的变量和基本数据类型知识
    Java开发环境描述
    使用Map,统计字符串中每个字符出现的次数
  • 原文地址:https://www.cnblogs.com/icoolno1/p/12797806.html
Copyright © 2011-2022 走看看