到目前为止,我主要使用 Struts 2
、Spring
、JQuery
技术堆栈来构建 Web 应用程序。关键是,提到的堆栈使用服务器端 MVC
模式。 Web 浏览器的主要作用仅限于请求/响应周期(+ 客户端验证)。数据检索、业务逻辑、布线和验证是服务器端的主要职责。
我对 AngularJS 框架有几个问题,这些问题的灵感来自我读过的以下引用:
对于 Angular 应用程序,我们鼓励使用模型-视图-控制器 (MVC) 设计模式来解耦代码并分离关注点。
从 Wikipedia Model–view–controller:
模型-视图-控制器 (MVC) 是一种将信息表示与用户与之交互分离的架构。模型由应用程序数据和业务规则组成,控制器调解输入,将其转换为模型或视图的命令
AngularJS 使用客户端 MVC
模式。所以我想没有其他选择可以以某种方式在客户端也包含验证逻辑?
编写健壮的 AngularJS 应用程序的最佳方式是什么?客户端的 MVC 和服务器端的某种 MC(模型、控制器)?
这是否意味着 MODEL 和 CONTROLLER 以一种方式重复(客户端/服务器)?
我知道我的问题有点奇怪,但我认为原因是,我在某种程度上习惯了传统的服务器端 MVC 模式。我确信有人已经完成了相同的过渡。
这根本不是一个奇怪的问题——我一直在尝试将 Angular 推销给很多 Java 开发人员,他们会问这个问题。我在学习的时候自己问过(我还在学习,顺便说一句)
如果您采用您所描述的“传统”java webapp 并对其进行 Angular 化,您必须首先采用您的服务器并将其设为 RESTful API。删除 JSP 等。这实际上是 IMO 编写 Angular 应用程序的难点——正确获取 REST API。对我来说,决定哪些逻辑需要进入服务器的关键是将它视为一个纯粹的 api,而暂时忘记它会有一个前端。
这个问题真的帮助了我——如果有人试图保存给定的资源并且该资源没有有效数据,则没有前端可以告诉他们——他们直接访问 API,因此 API 需要拒绝它。因此,后端负责深度验证。这也适用于您的业务逻辑。假设有人只使用 API,那么您的服务器需要做什么就很清楚了。
服务器还需要(可能)以 json 格式出售数据(我使用 Spring MVC + Jackson),因此它负责将模型暴露给 Angular,并与数据库进行通信。
那么 Angular 方面的 MVC 是什么?
模型:来自 REST API 的数据。如果 API 正在出售 JSON,那么这些对象将已经是 1 类 javascript 对象。
视图:HTML,以及需要操作 DOM 时的指令
控制器:(以及您从控制器中提取的自定义服务。)查询 REST API 并将视图所需的内容放在 $scope 上为指令提供回调以响应可能需要回调服务器的事件.验证:通常通过对指令的回调。可能会与您已经在服务器中放置的一些验证重叠,但您不希望您的用户等待服务器验证所有内容 - 客户端应该知道一些关于验证的信息以便给用户即时反馈。业务逻辑:与验证几乎相同。
查询 REST API 并将视图所需的内容放在 $scope 上
为指令提供回调以响应可能需要回调服务器的事件。
验证:通常通过对指令的回调。可能会与您已经在服务器中放置的一些验证重叠,但您不希望您的用户等待服务器验证所有内容 - 客户端应该知道一些关于验证的信息以便给用户即时反馈。
业务逻辑:与验证几乎相同。
但是为什么在客户端和服务器中存在重复的逻辑呢?主要是因为您不是在编写一个应用程序,而是在编写两个独立的东西:
一个 REST API 需要在没有前端的情况下保持健壮和可用 一个 GUI 需要立即向用户提供反馈,而不必等待服务器。
所以,简短的回答 - 通过忘记会有一个 UI 来获得正确的 REST API,并且进入 Angular 的内容会更加清晰。
我认为术语“业务逻辑”在这里有点用词不当。客户端应用程序的“业务”是处理用户界面的业务。它不会是诸如安全规则和专有逻辑或其他敏感知识产权之类的东西。
所以在 Angular 中,划分是(通常):
控制器(controller):用于操作 UI 背后的数据(范围)。
指令:用于设置 DOM 以通过范围与控制器进行通信,以及用于操作 DOM。
模板(视图):将指令分配给 DOM 的元素。
范围(模型或视图模型):用于在系统的所有部分之间承载数据。
服务:可注入、可重用的代码。通常用于处理 Ajax、cookie 或其他 I/O 等依赖项。
它实际上几乎是 MVVM 而不是 MVC。
至于您的“业务”逻辑或规则……任何需要安全的东西都必须始终在服务器级别进行保护。
重要的是要理解,在 MVC 模式的某些版本中,数据以及操作数据的逻辑都驻留在“模型”层中(“控制器”层除了绑定什么都不做)。然而,在 AngularJS 中,数据($scope)单独驻留在“模型”层中,而操作数据的逻辑($scope)驻留在“控制器”层中。
https://i.stack.imgur.com/LBqIG.png
我喜欢@Roy TrueLove 所说的话。但是让我说这是使用 angularjs 的终极方式。当然,如果你想获得 Angular 的最大好处,你必须学会以这种方式来做你的应用程序。我祈祷有一天能在那里。
同时,在你学习的过程中,以及在你过渡到完全使用 angularjs 作为你的客户端主要做事方式的过程中,你可以开始到处使用它来完成一些小任务,并逐渐习惯它和它的方式。思维。
我鼓励逐渐拥抱它,慢慢地慢慢走,但我保证,当然。
Angularjs 旨在服务于这种方法,因为它可以处理最小的任务,也可以处理最大的任务。例如,我第一次使用 angular 只是为了在用户键入 id 时显示名称。
我同意这里的答案。还有一些评论。当您编写应用程序时,您首先需要专注于问题域。并创建一些真实业务的软件模型。例如,如果您的问题域是购物,您需要建模的一些需求可能包括:
信用卡应该是有效的。
如果您使用品牌 X 的信用卡付款,您将获得 10% 的折扣。
购物车应至少包含一项以执行结帐
商品必须有库存才能让用户将它们添加到购物车
这些需求的实现将为您的问题域建模,这是您的业务逻辑。
Angular 是一个前端框架和工具包。它是一个网络前端。如果您在 Web 前端实现此功能,您将错过从其他前端或界面(如移动或桌面应用程序)重用模型的机会。因此,理想情况下,您的业务逻辑实现需要与任何用户界面框架分离,也需要与任何持久性框架分离。然后,您将拥有将处理用户界面问题并与您的业务逻辑对象通信的界面对象。这可以是 Spring MVC 控制器,和/或 Angular 控制器或服务。
您可以查看一个 sample application,它遵循此处提到的原则。
我似乎也有这个问题,因为一些组织只是热衷于新技术——“我想要云……等等,我想要轻量级”,很难证明它是否值得转向更轻量级的框架。
我一直使用 Spring/JBoss seam/JSF 和 MVC 框架开发 Web 应用程序。大多数情况下,java 脚本将驻留在表示层验证中,而主要的操作类/实体和业务逻辑将驻留在 Java 代码中。在对 Angular 进行了一些基本的实践之后,我开始理解 MVC 的含义,因为它们在表示层上抽象了另一个层次,我们可以在前端拥有自己的视图和控制器。要回答您的问题,就像每个人的评论一样,最好的方法是将其放在表示层上。
至于安全角度,我认为繁重或敏感的业务规则应该驻留在服务器端,因为我们不想将其暴露给世界。如果业务逻辑开发不好,很容易找到我们代码的弱点并加以利用。
这是我对像 Angular 这样的框架的想法,就像一个小商店/SOHO 处理客户,他们有几个人,非常高效和快速。他们很好地满足了面临业务和高效交付/接收货物的客户(REST,JSON)。他们确实有指定的角色和任务,但有些工人执行的不仅仅是任务。这家商店也容易受到小偷或强盗的攻击,因为他们通常不强调严密的安全性。
至于像 Spring/Struts 2 这样的服务器端框架,想象一个现代公司(CMM 5 级),具有不同的管理水平并能够处理更大的业务(批处理作业、Web 服务、企业总线)。他们确实与客户打交道,但不是直接的,经常通过经纪人甚至零售店。安全方面,公司更强大,通常前门有证券,或重要信息被保护在保险箱中(加密/登录)。
我的方法始终是自下而上的方法。从数据库设计开始,在需要时使用正确构造/相关的表和存储过程,然后将实体框架添加到解决方案中,或者如果不能选择 EF,则使用 ADO.Net。然后开发业务逻辑和模型以将数据输入和输出数据库。
建立模型后,我们现在可以走两条路线:开发 MVC 控制器和/或开发 WebAPI 控制器。两个控制器都可以访问模型,这只是实例化类和调用方法的问题。
您现在可以选择设置由 MVC 控制器控制的 MVC 视图,或者完全独立的 HTML 页面集或 SPA(NodeJS 上托管的单页应用程序)。
使用完全独立的 HTML 页面集,您将需要使用 WebAPI 控制器,以及 Get、Post、Put 和 Delete 方法,并确保来回包含令牌以识别您的客户端,并启用 CORS(用于跨域请求)
使用 MVC 视图,您可以使用控制器属性和/或会话来识别您的客户端,而无需担心 CORS,如果需要,您甚至可以将视图设为强类型。不幸的是,如果您有一组 UI 开发人员,他们将不得不使用相同的 MVC 解决方案。
在这两种情况下,您都可以使用 AngularJS 在控制器之间来回传输数据。
恕我直言,AngularJS 控制器的概念与 C# MVC 或 C# WebAPI 控制器不同。 AngularJS 控制器包含所有 javascript 逻辑以及通过“ApiFactory”对端点的调用,而 C# 控制器只不过是服务器端接受和响应 UI 请求的端点。
But why the duplication of logic in the client and in the server? Mostly because you're not writing one app, you're writing two independent things: 1) a REST API that needs to be robust and usable without a front end 2) a GUI that needs to give immediate feedback to a user and not necessarily wait for a server. So, short answer - get the REST API right by forgetting that there will be a UI, and what goes into Angular will be much clearer.
谢谢!