Home 系统架构

0 14

REST简介 – loveis715 – 博客园 (cnblogs.com)

 

大纲:

一、文章介绍

二、REST的示例

  1. REST的五大约束
    • 使用客户/服务器模型
    • 层次化的系统
    • 无状态
    • 可缓存
    • 统一的接口(其有四大子约束)
      • 每个资源都拥有一个资源标识
      • 消息的自描述性
      • 资源的自描述性
      • HATEOAS

三、REST的定义

  1. 资源识别
    • 如何抽象资源(自顶向下)
    • 判断一个资源是主资源还是子资源(看它是否能独立地表示其具体含义)
    • 如何判断为REST服务所定义的资源是否合理
      • 我们需要考虑对该资源的CRUD是否有意义,从而验证资源的定义是否合理。
      • 其次,我们需要检查资源是否需要除CRUD之外的动词来操作。
      • 除此之外,我们还需要检查这些资源是否是被整体使用,创建和删除。

四、资源的URL设计

  1. URL的组成
    • 协议
    • 主机名和断开
    • 资源的相对路径
    • 请求参数
  2. 通过URL来表示资源
  3. 资源在URL中需要由单数表示还是复数表示
  4. 相对路径 vs. 请求参数

 

五、合适的动词

  1. PUT和POST
    • POST动词会在目标URI之下创建一个新的子资源
    • PUT则是根据请求创建或修改特定位置的资源
  2. 两者都有创建的含义,但是意义却不同。在决定到底是使用PUT还是POST来创建资源的时候,软件开发人员需要考虑一系列问题
    • 首先就是资源的ID是如何生成的。
    • 另外一个需要考虑的因素则是PUT的等幂性是否对REST系统的设计有所帮助。(这在网络丢包较为严重时是一个非常好的功能。反过来,在同一个URI上调用两次POST将可能创建两个独立的子资源。
    • 除此之外,还需要考虑是否将资源的创建和更新归结为一个API可以简化用户对REST服务的使用。(用户可以通过PUT动词来同时完成创建和更新一个资源这两种不同的任务。这样的好处在于简化了REST服务所提供的接口,但是反过来也让一个API执行了两种不同的任务,在一定程度上违反了API设计时每个API都需要有明确的意义这一原则。
  3. PUT和PATCH(两者之间的不同则在于PUT是对整个资源的更新,而PATCH则是对部分资源的更新。而该动词的局限性则在于对该动词的支持程度。

 

六、使用标志的状态码

七、选择适当的表示结构

八、负载的自描述性

九、无状态约束

十、Authentication

十一、版本管理

十二、性能

0 22

https://zhuanlan.zhihu.com/p/361427612

https://www.cnblogs.com/netfocus/p/3307971.html

https://www.jianshu.com/p/42fc274ff409

 

DDD是什么?

Domain-Driven Design-Tackling Complexity in the Heart of Software,即领域驱动设计

将DDD分为两个阶段来理解

  1. 设计领域模型
  2. 实现领域模型

 

那么,什么是领域模型?

https://www.zhihu.com/question/25089273

https://blog.csdn.net/zmh458/article/details/96151607

叙述

DDD本身是一套完整、详尽的方法论,从如何需求沟通(构建领域知识),到高层设计(战略建模)、详细设计(战术建模),细致到代码的实现风格都给出了示例。

领域模型
我们从以下三个问题了解一下什么是领域模型:为什么要建模;怎么建模才合理;“领域”模型具体指什么。

 

为什么要建模

客户在专卖店买了个手机,留下了自己的名字和电话,店员做了记录。客人来时,只要店员能在记录里查到客人名字和电话的订单,就说明客人曾经买过手机。

什么人需要查看订单呢?店员A 需要查看,店员B也需要查看。客人来咨询的时候,应该能随时调取。老板也需要查看,用来汇总销售情况。大家都要看,格式就必须统一,要不然有的只记了电话,有的只记了名字,有的什么都没记,就乱套了。(我理解这里的店员可以看做微服务架构下,来调用订单这个微服务的外部调用者,比如中台和风控来调我们后端写的微服务)

大家商量之后决定:订单必须包括客户名字、电话和购买的商品。

那么就有“订单=名字+电话+商品信息”。

这是店员和老板的心智模型(mental model)。

要用一个数字系统来支持订单的管理,必须形成对应的数据模型(data model),称之为数据建模(data modeling),中文简称建模。电脑采用数字化的精确储存,所以数据的格式必须提前明确,比如名字是2-4个中文字符,电话是11位数字等等。

建模本质上是一种抽象。抽象就是归类,其目的是减轻认知的负担,避免重复的思考和工作,提升人的计算能力。所以,“通用”是建模的第一步,接下来我们还需要“复用”建好的模型。(下面的维修中心和订单复用客户这个模型)

假设手机卖出之后,客户需要维修服务。客户来到店里,询问店员,店员查询确认了订单,然后把客人引到门店旁边的维修中心。维修中心的工程师拿到订单,发现手机已经过了保修期,所以他写了一个维修单,把客户的名字、电话、手机信息、维修费用写到上面。客户交了费,拿到修好的手机,走了。

这引出一个问题。维修中心需要的客户信息,其实在店员那边有,没有必要自己再抄一遍,否则很容易出错,还会遇到信息同步的问题。那么,我们就需要再做一次建模,把客户的名字和电话从订单模型中拿出来,单独做一个客户模型。订单和维修单都复用这个客户模型。

这样,我们就得到了如下三个模型。

  • 订单=客户+商品信息
  • 维修单=客户+商品信息+维修信息
  • 客户=名字+电话

这里,维修单模型里面似乎包含了一个完整的订单(客户+商品信息),为什么不直接复用订单呢?也许是因为维修部门也负责别的地方购买的商品。另外,客户的名字和电话更新之后,是不是要直接修改已经完成的订单和维修单呢?值得商椎,已经完成的信息不应该有意料之外的变化。还有,如果客户是一个单独的模型,那么背后的团队会是怎么样呢?需要仔细考虑。
当数据模型可以完全覆盖业务需要,建模也就初步完成了。

 

那么,为什么要建模?

第一,要把心智模型提取出来,显性化,让不同的人对业务的理解达成一致;

第二,要归类复用,避免重复的工作,让人可以关注更高层面的事务。
如前面所示,即便是建立简单的模型,我们也需要诸多考虑。把这些需要考虑的点体系化,就引出了下一个问题:怎么建模才合理?

 

怎么建模才合理

判断模型好坏的重要依据是它的使用效率(扩展度、灵活度、与组织的对应度),所以建模的合理性也围绕这个来展开。

为了形成高扩展度、高灵活度并且顺应康威定律的模型,Eric Evans 汇总并命名了DDD这种方法论。它的独特之处,是它认可了“人”这种生物在做抽象过程中的一些必然缺憾,并且提出了一些解决方案。

首先,它明确指出了“自然语言”这个工具的不精确性。其次,它明确指出了人在设计和实现上的矛盾性,即:人类的预测能力很差,所以我们拥抱变化;但同时,我们不能纯寄希望于误打误撞地演化出一个好结果,应该提前深思熟虑地做好设计,再辅之以小的改进。

语言的不精确性,可以用“普通话”(Ubiquitous Language)来解决,即大家在讨论任何东西之前先规范语言,统一词汇的定义。兼顾稳固和灵活的设计,则由良好的分层来做到。

DDD把模型分成四层:

  • Ul层,负责界面展示。
  • 应用层(Application Layer),负责业务流程。
  • 领域层(Domain Layer),负责领域逻辑。
  • 基建层(Infrastructure Layer),负责提供基建。

分类的依据是:越往上,预期变动越频察;越往下,预期变动越少。
对于程序员来说,UI和基建应该很容易分清,一个只管展示,一个只管提供持续储存、网络传输等等基础设施,都没有“业务”的参与。容易混淆的是应用层和领域层,在这两层中存在的,就是应用模型和领域模型。
这就引出了下一个问题:到底什么是领域模型?

 

什么是“领域”模型

按DDD的定义,领域模型应该捕捉“业务规则”或者“领域逻辑”(business rules/domain logic),而应用模型则捕捉“应用逻辑”(application logic)。

模型属于哪一层,有个粗略的判断方式。如果是一个实体(entity)和针对实体的增删改查,就属于领域层如果是一个场景,比如出现在UI菜单上的选项,就属于应用层
比如:账单,用户,编辑商品,编辑库存,这些是领域层;“购买商品”,则是应用层。
前者是针对实体的操作。每一个实体都只有增删改查这样的操作。与之相反的是,要完整实现“购买商品”这个场景,也许需要检查库存、创建订单、创建交易等多个操作。

这样看来,领域模型就像是数据库的表。不过,除了字段定义之外,领域模型还需要有领域逻辑。关系型数据库通常可以部分实现领域逻辑,比如使用外键、自增ID等等,但是更为复杂的领域逻辑则需要用代码来实现。比如,在创建订单的时候,需要扣除相应数量的库存;当订单失效,则需要恢复库存。

我们可以从两个方面理解领域逻辑。

  1. 第一,领域逻辑就是显性的专业知识,是相对容易理解和学习的部分。买了东西要给钱,出了货要扣库存,飞机来了要腾跑道,炮弹来了要拦截,这些都是专业知识中符合逻辑,可以很容易地推导和学习。与之相对的是隐性的专业知识,或者Martin Fowler 所说的“业务非逻辑”(business illogic),指的是逻辑很难推论的软知识,与人相关的部分,与不可抗拒的、稀奇古怪的意外情况相关的部分。
  2. 第二,领域逻辑是提纯、通用的规则。不管是买手机、买房、买汽车,都会有创建订单、创建交易这样的零售领域模型,它是高度提纯、通用的。如果我们需要去修改领域模型,说明我们已经进入了另一个领域。此外,规则的存在是为了维护某个事物,这个事物,就是领域模型的正确、完整性。对领域模型的正常操作,总会给我们一个“合规”的领域。

不管我们怎么去玩弄订单、交易、商品模型,增删改查,乱搞一通,最后出来的结果都应该符合规则。创建订单的时候,订单模型会尝试减库存,成功,则创建,失败,则不允许创建,如此云云。
最后出来的结果不会有逻辑问题,比如订单上的商品不存在,或者交易对应的订单不存在。
当然,领域模型只管“合规”,但不管“合理”。大型超市里,一位收银员决定把所有货品下架,这是否合理?这个不属于领域模型关心的范围,领域模型只知道,要把货物库存的位置从货架转移到仓库,目标仓库必须有能存放这个货物的空位,转移完毕时从货架的可用空间中减去货物的大小。至于谁做,为什么做,能不能做,这么做合不合理,(通常)不在领域层的关心范围,而是放到应用层去做。

在前面的例子中,如果一个客户在黑名单中,不允许购买,那么这个检查,通常是在应用层去检查。这样,我们就可以很容易地复用领域模型或者调整应用规则,而不至于把易变的应用规则混到稳定的业务规则里去。

 

模型的设计和实现

那么,DDD的模型属于业务描述还是代码、数据库定义?作者想表达的意思很明确,二者都是。好的业务描述应该能非常好地对应到代码,代码也应该以最清晰地方式来呈现业务描述。当然,转换和适配肯定不可少,毕竟有先例摆在那。想要达到设计即代码的UML,尸体都还是温的。

设计和实现的最佳契合点,其实就在“界面”之中。“界面”这个名字本身已经体现了这层意思。所以,建好的模型,和暴露出来的界面、接口,应该有相当高(或者完全一致)的对应关系。这个界面,可能是一个类的公开成员函数,也可能是一个微服务上暴露出来的RESTful接口,或者是一个公开的普通WebAPl,都没有差,只要和设计符合就行。

最后,总结起来,就是:

  • DDD把业务分成UI、应用、领域、基建四层,其核心是高度提纯、通用、少变化的领域层,是谓“领域驱动”;
  • 领域层中包含领域模型,捕捉领域逻辑,暴露出接口用于操作领域模型,这些接口提供的操作可以确保领域是自治的;
  • 领域模型既是业务描述,又是代码实现的结构设计,二者的结合点在于公开出来的界面、接口。
    领域模型的特点
    总结一下,领域模型具有如下的特点:
  • 领域模型是业务概念的可视化描述,是需求分析的产物
  • 领域模型用于指导程序设计,但领域模型与实现方式无关,领域建模时不应该考虑如何实现
  • 领域模型需要同项目所有成员(客户、项目经理、开发、测试…)达成共识

 

如何画领域模型

(1)找出用例模型中的名词,
(2)然后识别这些名词本身的相关信息,
(3)以及名词之间的相互关联关系,
(4)用UML画出领域模型。

第一步:找出用例模型中的名词
原有用例如下,用蓝色加黑标出名词(重复的就不标了):

1)顾客携带商品到收银台;

2)收银员扫描商品条形码;

3)系统根据条形码获取并显示商品信息;

4)收银员重复2~3步,直到所有商品扫描完毕;

5)系统计算商品总额;

。。。。。。。。。。。。。。。。。。。。

n)系统打出商品清单,完成交易。

这个用例中的名词有“顾客”、“商品”、“收银台”、“收银员”、“商品条形码”、“系统”、“商品信息”、“商品总额”、“商品清单”、“交易”。稍加整理:

1)“顾客”、“收银员”是系统的外部对象,不需要我们进行设计,但这些对象要和系统进行交互;

2)“商品”、“商品条形码”、“商品信息”、“商品总额”、“商品清单”、“交易”是领域对象,但“商品条形码”、“商品信息”可以算作“商品”的属性、“商品总额”可以算作“交易”的属性,最后从这个用例总结出来的领域对象有“商品”、“商品清单”、“交易”三个。

第二步:识别这些名词本身的相关信息
一个对象的属性可能分布在多个用例中,因此可以通过迭代不断的完善一个对象的属性,大家可以看到,我们在第一步中的样例就已经分析了一部分了:“商品条形码”、“商品信息”可以算作“商品”的属性。

对象除了属性外,还有一些约束或者限制,这些在用例中可能有,也可能没有,这就需要分析人员来发现了。比如说交易金额必须大于0.1元小于99999元这种约束,用例中不一定会体现,可能需要分析人员向客户咨询。

第三步:识别对象间的关系
面向对象设计就是依靠对象间的互相协作来配合完成相应的功能,因此识别出对象和对象本身的属性外,还要识别对象间的关系,例如1对多、1对1、依赖等,详细的各种关系可以参考UML的标准定义。

我们以第一步识别的三个对象为例:“商品清单”包含多个“商品”、一次“交易”对应一个“商品清单”、一个“商品”只能属于一个“交易”等。

第四步:画出领域模型UML图
画出这个样例的UML领域模型图

小结
知道了理论,接下来就是去实践了。

领域模型设计实例

https://blog.csdn.net/kiwangruikyo/article/details/114526518

0 21

前言
本篇文章是基于win10系统下载安装Maven的教程。

一、 Maven介绍
1. 什么是Maven

Maven是一个跨平台的项目管理工具。作为Apache组织的一个颇为成功的开源项目,其主要服务于基于Java平台的项目创建,依赖管理和项目信息管理。maven是Apache的顶级项目,解释为“专家,内行”,它是一个项目管理的工具,maven自身是纯java开发的,可以使用maven对java项目进行构建、依赖管理。

2. Maven的作用

依赖管理
依赖指的就是是 我们项目中需要使用的第三方Jar包, 一个大一点的工程往往需要几十上百个Jar包,按照我们之前的方式,每使用一种Jar,就需要导入到工程中,还要解决各种Jar冲突的问题.
Maven可以对Jar包进行统一的管理,包括快速引入Jar包,以及对使用的 Jar包进行统一的版本控制
一键构建项目
之前我们创建项目,需要确定项目的目录结构,比如src 存放Java源码, resources存放配置文件,还要配置环境比如JDK的版本等等,如果有多个项目 那么就需要每次自己搞一套配置,十分麻烦
Maven为我们提供了一个标准化的Java项目结构,我们可以通过Maven快速创建一个标准的Java项目.

二、Maven 的下载安装

1. Maven软件的下载

使用 Maven 管理工具,我们首先要到官网去下载它的安装软件。

http://maven.apache.org/download.cgi

目前最新版是 apache-maven-3.6.3 版本,点击进行下载即可.

为了方便,我上传到了百度网盘,也可在此链接下载。
链接:https://pan.baidu.com/s/12SuxtOXiUhNgkb0DH1eyCw
提取码:gnaf

2. Maven软件的安装

Maven 下载后,将 Maven 解压到一个没有中文没有空格的路径下,比如:F:\ 下面。 解压后目录结构如下:

  1. bin:存放了 maven 的命令
  2. boot:存放了一些 maven 本身的引导程序,如类加载器等
  3. conf:存放了 maven 的一些配置文件,如 setting.xml 文件
  4. lib:存放了 maven 本身运行所需的一些 jar 包

 

3. Maven环境变量配置

  1. 配置 MAVEN_HOME ,变量值就是你的 maven 安装的路径(bin 目录之前一级目录)

2.将MAVEN_HOME 添加到Path系统变量

4. Maven 软件版本测试

win+R 打开dos窗口,通过 mvn -v命令检查 maven 是否安装成功,看到 maven 的版本为 3.6.3 及 java 版本为 jdk-11 即为安装 成功。 打开命令行,输入 mvn –v命令,如下图:
在这里插入图片描述

 

三、Maven 仓库

Maven中的仓库是用来存放maven构建的项目和各种依赖的(Jar包)。

1. Maven的仓库分类

本地仓库: 位于自己计算机中的仓库, 用来存储从远程仓库或中央仓库下载的插件和 jar 包,
远程仓库: 需要联网才可以使用的仓库,阿里提供了一个免费的maven 远程仓库。
中央仓库: 在 maven 软件中内置一个远程仓库地址 http://repo1.maven.org/maven2 ,它是中 央仓库,服务于整个互联网,它是由 Maven 团队自己维护,里面存储了非常全的 jar 包,它包含了世界上大部分流行的开源项目构件

2. Maven 本地仓库的配置

maven仓库默认是在 C:\Users\breakyang\.m2 目录下,我们不要将仓库放在C盘,所以这里要重新配置一下.

在maven安装目录中,进入conf文件夹, 可以看到一个 settings.xml 文件中, 我们在这个文件中, 进行本地仓库的配置

 

在你需要存放repository仓库的地方,先创建Maven文件夹,在其下创建repo文件夹,同时复制一份settings到该文件夹下修改两个settings文档

<localRepository>填写的就是之前创建的repo文件夹的目录

自此你的Maven依赖都会下载到此文件夹中

 

3.检验下是否已经设置成功

控制台输入 mvn help:system

可观察到repo文件夹下多了许多文件!说明Maven配置成功!

0 19

 

1.SOA架构和微服务架构的区别

首先SOA和微服务架构一个层面的东西,而对于ESB和微服务网关是一个层面的东西,一个谈到是架构风格和方法,一个谈的是实现工具或组件。

1.SOA(Service Oriented Architecture)“面向服务的架构”:他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。

2.微服务架构:其实和 SOA 架构类似,微服务是在 SOA 上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。

微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想

 

2.SOA架构特点:

系统集成:站在系统的角度,解决企业系统间的通信问题,把原先散乱、无规划的系统间的网状结构,梳理成规整、可治理的系统间星形结构,这一步往往需要引入 一些产品,比如 ESB、以及技术规范、服务管理规范; 这一步解决的核心问题是【有序】

系统的服务化:站在功能的角度,把业务逻辑抽象成 可复用、可组装的服务,通过服务的编排实现业务的 快速再生,目的:把原先固有的业务功能转变为通用 的业务服务,实现业务逻辑的快速复用;这一步解决 的核心问题是【复用】

业务的服务化:站在企业的角度,把企业职能抽象成 可复用、可组装的服务;把原先职能化的企业架构转变为服务化的企业架构,进一步提升企业的对外服务能力;“前面两步都是从技术层面来解决系统调用、系统功能复用的问题”。第三步,则是以业务驱动把一个业务单元封装成一项服务。这一步解决的核心问题是【高效】

3.微服务架构特点

1.通过服务实现组件化

  • 开发者不再需要协调其它服务部署对本服务的影响。

2.按业务能力来划分服务和开发团队

  • 开发者可以自由选择开发技术,提供 API 服务

3.去中心化

  • 每个微服务有自己私有的数据库持久化业务数据
  • 每个微服务只能访问自己的数据库,而不能访问其它服务的数据库
  • 某些业务场景下,需要在一个事务中更新多个数据库。这种情况也不能直接访问其它微服务的数据库,而是通过对于微服务进行操作。
  • 数据的去中心化,进一步降低了微服务之间的耦合度,不同服务可以采用不同的数据库技术(SQL、NoSQL等)。
  • 在复杂的业务场景下,如果包含多个微服务,通常在客户端或者中间层(网关)处理。

4.基础设施自动化(devops、自动化部署)

Java EE部署架构,通过展现层打包WARs,业务层划分到JARs最后部署为EAR一个大包,而微服务则打开了这个黑盒子,把应用拆分成为一个一个的单个服务,应用Docker技术,不依赖任何服务器和数据模型,是一个全栈应用,可以通过自动化方式独立部署,每个服务运行在自己的进程中,通过轻量的通讯机制联系,经常是基于HTTP资源API,这些服务基于业务能力构建,能实现集中化管理(因为服务太多啦,不集中管理就无法DevOps啦)。

 

5.主要区别

功能 SOA 微服务
组件大小 大块业务逻辑 单独任务或小块业务逻辑
耦合 通常松耦合 总是松耦合
公司架构 任何类型 小型、专注于功能交叉团队
管理 着重中央管理 着重分散管理
目标 确保应用能够交互操作 执行新功能、快速拓展开发团队

 

https://blog.csdn.net/zpoison/article/details/80729052

0 26

原文链接:

https://blog.csdn.net/sj349781478/article/details/84224440

 

个人总结:

模块说明:

首先 LAMP是一种架构,表示 Linux + Apache + Mariadb / MySQL+ PhP,针对这四个东西解析:

L:Linux操作系统,是架构基础,无需多言

A:此处代指 Apache 服务器,它是Apache软件基金会管理下的一个开放源代码的服务器软件,可以理解为电脑上的一个应用程序。简单地说它的作用就是将你的电脑变成一台服务器,让你的电脑开放特定的网络端口,用以接收来自网络上发送到这台机器的HTTP请求,对请求的内容进行处理并作出相应的响应

M:表示数据库,多数采用mysql或mariadb(mariadb是mysql的一个分支)https://www.zhihu.com/question/41832866

P:PHP(PHP: Hypertext Preprocessor)即“超文本预处理器”,是在服务器端执行的脚本语言,尤其适用于Web开发并可嵌入HTML中。PHP语法利用了CJavaPerl,该语言的主要目标是允许web开发人员快速编写动态网页

流程说明:

处理一次动态页面请求,服务器主要经历:Apache处理请求——通过CGI接口访问PHP的的应用程序——PHP应用程序调用PHP解释器执行PHP代码——PHP程序访问调用数据库——最后给客户做反馈。

故在LAMP的环境机构中,apache、mariadb和php的主要功能分别如下。

 

apache主要实现如下功能:

第一:处理http的请求、构建响应报文等自身服务;

第二:配置让Apache支持PHP程序的响应(通过PHP模块或FPM);

第三:配置Apache具体处理php程序的方法,如通过反向代理将php程序交给fcgi处理。

mariadb主要实现如下功能:

第一:提供PHP程序对数据的存储;

第二:提供PHP程序对数据的读取(通常情况下从性能的角度考虑,尽量实现数据库的读写分离)。

php主要实现如下功能:

第一:提供apache的访问接口,即CGI或Fast CGI(FPM);

第二:提供PHP程序的解释器;

第三:提供mairadb数据库的连接函数的基本环境。

由此可知,要实现LAMP在配置每一个服务时,安装功能需求进行配置,即可实现LAMP的架构,当然apache、mariadb和php服务都可配置为独立服务,安装在不同服务器之上。

补充:常见的三种 web 服务器及其区别  https://www.zhihu.com/question/32212996/answer/226688632

1.Apache

Apache HTTP服务器是一个模块化的服务器,可以运行在几乎所有广泛使用的计算机平台上。其属于应用服务器。Apache支持支持模块多,性能稳定,Apache本身是静态解析,适合静态HTML、图片等,但可以通过扩展脚本、模块等支持动态页面等。

(Apche可以支持PHPcgiperl,但是要使用Java的话,你需要Tomcat在Apache后台支撑,将Java请求由Apache转发给Tomcat处理。)

缺点:配置相对复杂,自身不支持动态页面。

2. Tomcat

Tomcat是应用(Java)服务器,它只是一个Servlet(JSP也翻译成Servlet)容器,可以认为是Apache的扩展,但是可以独立于Apache运行。

3. Nginx

Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”,是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器。

 

 

0 13

RESTful架构

一、背景

Roy Thomas Fielding在他2000年的博士论文中提出 Rest 这个词,他说,我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。

 

二、名称

Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。我对这个词组的翻译是”表现层状态转化”。

如果一个架构符合REST原则,就称它为RESTful架构。

要理解RESTful架构,最好的方法就是去理解Representational State Transfer这个词组到底是什么意思,它的每一个词代表了什么涵义。如果你把这个名称搞懂了,也就不难体会REST是一种什么样的设计。

 

三、资源(Resources

REST的名称”表现层状态转化”中,省略了主语。”表现层”其实指的是”资源”(Resources)的”表现层”。

所谓”资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。

所谓”上网”,就是与互联网上一系列的”资源”互动,调用它的URI

补充:URI和URL的区别

URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL = Universal Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。

四、表现层(Representation)

“资源”是一种信息实体,它可以有多种外在表现形式。我们把”资源”具体呈现出来的形式,叫做它的”表现层”(Representation)。

比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。

URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的”.html”后缀名是不必要的,因为这个后缀名表示格式,属于”表现层”范畴,而URI应该只代表”资源”的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对”表现层”的描述。

五、状态转化(State Transfer)

访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生”状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是”表现层状态转化”。

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

 

六、综述

综合上面的解释,我们总结一下什么是RESTful架构:

         (1)每一个URI代表一种资源;

  (2)客户端和服务器之间,传递这种资源的某种表现层;

  (3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”。

 

七、误区(1.URI含动词 2.URI加版本号)

RESTful架构有一些典型的设计误区。

最常见的一种设计错误,就是URI包含动词。因为”资源”表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中。

举例来说,某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示show。

如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:

  POST /accounts/1/transfer/500/to/2

正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:

  POST /transaction HTTP/1.1
  Host: 127.0.0.1
  
  from=1&to=2&amount=500.00

另一个设计误区,就是在URI中加入版本号

http://www.example.com/app/1.0/foo

http://www.example.com/app/1.1/foo

http://www.example.com/app/2.0/foo

因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分(参见Versioning REST Services):

Accept: vnd.example-com.foo+json; version=1.0

Accept: vnd.example-com.foo+json; version=1.1

Accept: vnd.example-com.foo+json; version=2.0

 

传统方式操作资源

方式:

问题所在:

  • 之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了queryUser,新增的时候用了saveUser ,修改的时候用了updateUser,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,PUT就是修改,delete就是删除,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.

请求方式

定义:可以通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。其中,GET 用于查询资源,POST 用于创建资源,PUT 用于更新服务端的资源的全部信息,PATCH 用于更新服务端的资源的部分信息,DELETE 用于删除服务端的资源。

这里使用“用户”的案例进行回顾通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。

使用RestFul操作资源

  • 【GET】 /users # 查询用户信息列表
  • 【GET】 /users/1001 # 查看某个用户信息
  • 【POST】 /users # 新建用户信息
  • 【PUT】 /users/1001 # 更新用户信息(全部字段)
  • 【PATCH】 /users/1001 # 更新用户信息(部分字段)
  • 【DELETE】 /users/1001 # 删除用户信息

API设计风格基本规则

1.使用名词而不是动词

2.Get方法和查询参数不应该涉及状态改变

  • 使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变:

3.使用复数名词

  • 不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。

4. 使用子资源表达关系

  • 如果一个资源与另外一个资源有关系,使用子资源:

GET /cars/711/drivers/ 返回 car 711的所有司机 GET /cars/711/drivers/4 返回 car 711的4号司机

5.使用Http头声明序列化格式

  • 在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定

Content-Type 定义请求格式

Accept 定义系列可接受的响应格式

6.为集合提供过滤 排序 选择和分页等功能

  • Filtering过滤:

使用唯一的查询参数进行过滤:

GET /cars?color=red 返回红色的cars GET /cars?seats<=2 返回小于两座位的cars集合

7.版本化你的API

  • 使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.

一般在Url后面使用?v

/blog/api/v1

8. 使用Http状态码处理错误

9.允许覆盖http方法

  • 一些代理只支持POST 和 GET方法, 为了使用这些有限方法支持RESTful API,需要一种办法覆盖http原来的方法。

使用订制的HTTP头 X-HTTP-Method-Override 来覆盖POST 方法.

 

 

个人对RESTFul架构的理解:首先要清楚,RESTFul架构不是一种标准,而是一种风格(也就是可以使用RESTFul风格,也可以使用其他风格),那怎么鉴别是否是RESTFul风格呢?

很简单,遵循REST原则的,就是RESTFul风格。那么什么是REST原则呢?

1.每一个URI代表一种资源;(注意区别URI和URL)

2.应用于客户端和服务器(C/S)之间的交互,并且体现在表现层(资源的呈现形式)

3.客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”(GET,PUT,POST,DELETE)

知道了RESTFul风格的特点,那么我们如何去实现RESTFul风格的编程?即怎么遵循RESTFul的API规范

1.URI中无动词,使用名词

2.GET不改变状态

3.名词区分单复数

4.子资源

5.使用Http头声明序列化格式

思考:文中提到HTTP是无状态的,怎么理解无状态?

理解HTTP的无状态 – Our home (yangbili.co)