DDD领域驱动设计简介

  categories:资料  author:

眼下在讨论软件架构的时候,DDD、微服务架构和容器技术这三个东西经常会相伴出现。本文希望尽量用大白话给工程师们讲清楚它们之间的区别和联系。很粗浅,很粗浅,技术大牛请略过…

DDD:是Domain Driven Design(领域驱动设计)的缩写。这是一位叫Eric Evans的老兄2004年在一本同名的书中提出的。它是针对复杂系统设计的一套软件工程方法:把系统分割为一个个有边界的上下文(Bounded Context);通过实体、值对象、聚合等来处理领域的信息;通过服务和领域事件与其他领域耦合;通过上下文地图来表述系统的宏观结构;强调领域专家的作用;强调持续集成和演化…

领域驱动设计之领域模型

2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD。领域驱动设计分为两个阶段:

以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;
由领域模型驱动软件设计,用代码来实现该领域模型;

由此可见,领域驱动设计的核心是建立正确的领域模型。

为什么建立一个领域模型是重要的

领域驱动设计告诉我们,在通过软件实现一个业务系统时,建立一个领域模型是非常重要和必要的,因为领域模型具有以下特点:

  1. 领域模型是对具有某个边界的领域的一个抽象,反映了领域内用户业务需求的本质;领域模型是有边界的,只反应了我们在领域内所关注的部分;
  2. 领域模型只反映业务,和任何技术实现无关;领域模型不仅能反映领域中的一些实体概念,如货物,书本,应聘记录,地址,等;还能反映领域中的一些过程概念,如资金转账,等;
  3. 领域模型确保了我们的软件的业务逻辑都在一个模型中,都在一个地方;这样对提高软件的可维护性,业务可理解性以及可重用性方面都有很好的帮助;
  4. 领域模型能够帮助开发人员相对平滑地将领域知识转化为软件构造;
  5. 领域模型贯穿软件分析、设计,以及开发的整个过程;领域专家、设计人员、开发人员通过领域模型进行交流,彼此共享知识与信息;因为大家面向的都是同一个模型,所以可以防止需求走样,可以让软件设计开发人员做出来的软件真正满足需求;
  6. 要建立正确的领域模型并不简单,需要领域专家、设计、开发人员积极沟通共同努力,然后才能使大家对领域的认识不断深入,从而不断细化和完善领域模型;
  7. 为了让领域模型看的见,我们需要用一些方法来表示它;图是表达领域模型最常用的方式,但不是唯一的表达方式,代码或文字描述也能表达领域模型;
  8. 领域模型是整个软件的核心,是软件中最有价值和最具竞争力的部分;设计足够精良且符合业务需求的领域模型能够更快速的响应需求变化;

领域通用语言(UBIQUITOUS LANGUAGE)

我们认识到由软件专家和领域专家通力合作开发出一个领域的模型是绝对需要的,但是,那种方法通常会由于一些基础交流的障碍而存在难点。开发人员满脑 子都是类、方法、算法、模式、架构,等等,总是想将实际生活中的概念和程序工件进行对应。他们希望看到要建立哪些对象类,要如何对对象类之间的关系建模。 他们会习惯按照封装、继承、多态等面向对象编程中的概念去思考,会随时随地这样交谈,这对他们来说这太正常不过了,开发人员就是开发人员。但是领域专家通 常对这一无所知,他们对软件类库、框架、持久化甚至数据库没有什么概念。他们只了解他们特有的领域专业技能。比如,在空中交通监控样例中,领域专家知道飞 机、路线、海拔、经度、纬度,知道飞机偏离了正常路线,知道飞机的发射。他们用他们自己的术语讨论这些事情,有时这对于外行来说很难直接理解。如果一个人

阅读全文

使用Springboot搭建OAuth2.0 Server

  categories:资料  tags:  author:

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。

OAuth 简介

OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。

基于 OAuth 认证授权具有以下特点:

  • 安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
  • 开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
  • 简单。不管是消费方还是服务提供方,都很容易于理解与使用。

OAuth 的解决方案如下图所示。

图 1. OAuth Solution

图 1. OAuth Solution

如 … 阅读全文

Gradle常用命令

  categories:资料  author:
1、Gragle常用命令

之前接触了一些命令如

./gradlew -v

./gradlew clean

./gradlew build,

注意都是./gradlew./代表当前目录,gradlew代表 gradle wrapper,意思是gradle的一层包装,可以理解为在这个项目本地就封装了gradle,即gradle wrapper,只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

Gradle常用命令列表

gradle build

gradle test

gradle compilejava

gradle jar

gradle clean

gradle jar

gradle init

//生成wrapper包

gradle wrapper

gradle compilejava

gradle javadoc

gradle … 阅读全文

java的WeakReference弱引用概述

  categories:资料  author:

–test-2-国外一个技术面试官在面试senior java developer的时候, 问到一个weak reference相关的问题. 他没有期望有人能够完整解释清楚weak reference是什么, 怎么用, 只是期望有人能够提到这个concept和java的GC相关. 很可惜的是, 20多个拥有5年以上java开发经验的面试者中, 只有两人知道weak reference的存在, 而其中只有一人实际用到过他. 无疑, 在interviewer眼中, 对于weak reference的理解和应用在面试中给了这一个interviewee相当多的加分. 所以, 将我对于这个技术的理解和使用总结在这篇博客里, 希望读者和自己通过读和写这篇帖子, 能够在以后的工作和面试中获得加分.
在Java里, 当一个对象o被创建时, 它被放在Heap里. 当GC运行的时候, 如果发现没有任何引用指向o, o就会被回收以腾出内存空间. 或者换句话说, 一个对象被回收, 必须满足两个条件: 1)没有任何引用指向它 2)GC被运行.

在现实情况写代码的时候, 我们往往通过把所有指向某个对象的referece置空来保证这个对象在下次GC运行的时候被回收 (可以用java -verbose:gc来观察gc的行为)

Object c = … 阅读全文

ThreadLocal用法详解和原理

  categories:资料  author:

一、用法

ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。

1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。

2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。

3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。

4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回

此方法值。

package com.coshaho.reflect;

/**
* ThreadLocal用法
* @author coshaho
*
*/
public class MyThreadLocal
{
private static final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>(){
/**
* ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值
*/
@Override
protected 

阅读全文

深入剖析ThreadLocal

  categories:资料  author:

要了解ThreadLocal,首先搞清楚ThreadLocal 是什么?是用来解决什么问题的?

ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问, 通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联

我们知道有时候一个对象的变量会被多个线程所访问,这时就会有线程安全问题,当然我们可以使用synchorinized 关键字来为此变量加锁,进行同步处理,从而限制只能有一个线程来使用此变量,但是加锁会大大影响程序执行效率,此外我们还可以使用ThreadLocal来解决对某一个变量的访问冲突问题。

当使用ThreadLocal维护变量的时候 为每一个使用该变量的线程提供一个独立的变量副本,即每个线程内部都会有一个该变量,这样同时多个线程访问该变量并不会彼此相互影响,因此他们使用的都是自己从内存中拷贝过来的变量的副本, 这样就不存在线程安全问题,也不会影响程序的执行性能。

但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。

以下是本文目录大纲:

一.对ThreadLocal的理解

二.深入解析ThreadLocal类

三.ThreadLocal的应用场景

若有不正之处请多多谅解,并欢迎批评指正。

一.对ThreadLocal的理解

ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

这句话从字面上看起来很容易理解,但是真正理解并不是那么容易。

我们还是先来看一个例子:
class ConnectionManager {

private static Connection connect = null;

public static Connection

阅读全文

Java多线程之Callable接口

  categories:资料  author:

Callable和Runnbale一样代表着任务,区别在于Callable有返回值并且可以抛出异常。

1. 创建线程的三种方式:

  • 继承Thread,重写run方法
  • 实现Runnable接口,重新run方法
  • 实现Callable接口,重写call方法

2. Callable接口实际上是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但提供了比Runnable更加强大的功能。

  • Callable可以在任务结束的时候提供一个返回值,Runnable无法提供这个功能
  • Callable的call方法分可以抛出异常,而Runnable的run方法不能抛出异常。

Callable和Future出现的原因

创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。
这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。
如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。

而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

Callable和Future介绍

Callable接口代表一段可以调用并返回结果的代码;Future接口表示异步任务,是还没有完成的任务给出的未来结果。所以说Callable用于产生结果,Future用于获取结果。

Callable接口使用泛型去定义它的返回类型。Executors类提供了一些有用的方法在线程池中执行Callable内的任务。由于Callable任务是并行的(并行就是整体看上去是并行的,其实在某个时间点只有一个线程在执行),我们必须等待它返回的结果。
java.util.concurrent.Future对象为我们解决了这个问题。在线程池提交Callable任务后返回了一个Future对象,使用它可以知道Callable任务的状态和得到Callable返回的执行结果。Future提供了get()方法让我们可以等待Callable结束并获取它的执行结果。

package cn.iigrowing.threads.study.Callable;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/*
* 一、创建执行线程的方式三:实现 Callable 接口。 相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
*
* 二、执行 Callable 方式,需要 FutureTask … 阅读全文

什么是JWT(JSON WEB TOKEN)

  categories:资料  tags:  author:

     Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

  起源

说起JWT,我们应该来谈一谈基于token的认证和传统的Session认证的区别。

  传统的session认证

我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发送的请求,所以为了让我们的应用能识别是哪个用户发出的,我们只能在服务器存储一份用户登陆的信息,这份登陆信息会在响应时传递给服务器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的英哟个就能识别请求来自哪个用户了,这就是传统的基于sessino认证

但是这种基于session的认证使应用本身很难得扩展,随着不用客户端的增加,独立的服务器已无法承载更多的用户,而这个时候基于session认证应用的问题就会暴露出来

  基于session认证所显露的问题

Session:每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大

扩展性:用户认证之后,服务端做认证记录,如果认证的记录被保存在内存的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,响应的限制了负载均衡器的能力,也意味着限制了应用的扩展性

CSRF:因为是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或会话信息。这也就意味着机遇tokent认证机制的应用不需要去考虑用户在哪一台服务器登陆了,这就为应用的扩展提供了便利

流程是这样的

  • 用户使用用户名密码请求服务器
  • 服务器进行验证用户信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附加这个token值
  • 服务器验证token,并返回数据

这个token必须要在每次请求时发送给服务器,它应该保存在请求头中,另外,服务器要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了 Access-Control-Allow-Origin:*

JWT的构成

JWT是由三部分构成,将这三段信息文本用链接构成了JWT字符串。就像这样

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U

第一部分我们称它为头部(header)第二部分我们称其为载荷(payload,类似于飞机上承载的物品),第三部分是签证(signature)

   header

JWT的头部承载的两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法,通常直接使用HMAC SHA256

完整的头部就像下面这样的JSON

{
     'typ':'JWT',
     'alg':'HS256'  
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
阅读全文

JSON Web Token 入门教程

  categories:资料  author:

作者: 阮一峰

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法。

一、跨域认证的问题

互联网服务离不开用户认证。一般流程是下面这样。

1、用户向服务器发送用户名和密码。

2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入用户的 Cookie。

4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。

举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

二、JWT 的原理

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。

阅读全文

CAS 跨域原理

  categories:资料  tags:,   author:

CAS(Central Authentication Service) 是 Yale 大学发起的一个开源项目,据统计,大概每 10 个采用开源构建 Web SSO 的 Java 项目,就有 8 个使用 CAS 。对这些统计,我虽然不以为然,但有一点可以肯定的是, CAS 是我认为最简单实效,而且足够安全的 SSO 选择。

本节主要分析 CAS 的安全性,以及为什么 CAS 被这样设计,带着少许密码学的基础知识,我希望有助于读者对 CAS 的协议有更深层次的理解。
从结构体系看, CAS 包含两部分:
l         CAS Server
CAS Server 负责完成对用户的认证工作, CAS Server 需要独立部署,有不止一种
阅读全文


快乐成长 每天进步一点点      京ICP备18032580号-1