分布式总结
一、token
token的特点:
- 无状态、可扩展
- 支持移动设备
- 跨程序调用
- 安全
token原理:
- 将荷载payload以及header信息进行base64加密,形成密文payload密文,head密文。
- 将形成的密文用句号连接起来,用服务端密钥进行hs256加密,生成签名。
- 将前面的两个密文后面用句号连接签名形成最终的token返回给服务端。
token的实现:
- 用户登录校验,校验成功后就返回token给客户端
- 客户端收到数据后保存在客户端
- 客户端每次访问api是携带token到服务器端
- 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码。
token用在:登录校验。
token与session对比有更高的安全性,无状态可扩展性和多平台跨越的优点。
token可以完美解决跨站请求伪造,负载均衡,无状态可扩展性等问题。
二、敏捷开发
敏捷开发是以人为核心,迭代循序渐进的开发方法。他不是一门技术,他是一种开发方式,也就是一种软件开发流程。它采用的是迭代式开发。
三大核心角色:
产品负责人:负责确定产品功能和达到要求的标准。规定软件发布日期和交付内容,同时又权利接受拒绝开发成果。
流程管理员: 负责整个敏捷开发流程在项目中的顺利实施和进行,以及与客户沟通排除沟通障碍,使开发满足客户需求。
开发团队:负责开发工作。负责不同的技术方面,成员要求达到sprint的目标。
三个物件:
productbacklog(产品待办事项列表)、
sprint backlog(迭代列表)
燃尽图
四个会议:
sprint计划会议,每日例会
sprint评审会议,sprint回顾会议
项目前:
-
敏捷开发需求分析
2. product backlog(产品需求列表)
3. sprit计划会议
项目中:
- print backlog(迭代列表)
2. daily scrum meeting(每日立会)
3. sprint burn down(迭代周期燃尽图)
4. 版本迭代
项目后:
评审会议
总结会议
特点:
敏捷开发技术特点:
- 个体和交互胜过过程和工具
- 可以工作的软件胜过面面俱到的文档
- 客户合作胜过合同谈判
- 相应变化胜过遵循计划
优点:
用户参与其中,客户满意度高。
提高开发效率
市场快速反应能力高
缺点:
繁琐,压力大。
最小粒度:
什么是服务:服务代表一个或一组相对较小且独立的功能单元,是用户可以感知的最小功能集。登录,添加用户。。。。。。
基本服务就是最小服务,这种服务有比较高的重用性。
合成:基本服务简单组合。
组合服务:算是最大力度服务,里面基本服务关系受到工作流程控制。
粒度就是功能大小,粗粒度表示功能业务多相对重用性较低,细粒度表示功能简单重用性高。
最大粒度:在一个抽象接口封装了大块的业务逻辑和能力。
优点:减少了服务请求的交互次数,减少成本。
缺点:带来更高的复杂性,交互大量数据,不能灵活适应需求变化,重用性低。
最小粒度:相对较小的功能单元,或交互少量数据。
优点:灵活性强,重用性高
缺点,需要通过多次服务交互才能实现。
特性:重用性、灵活性、性能
解决方案:
1、设计接口和实体类
2、统一管理设计模式
3、优化组件充足业务服务。
单点登录(sso):
单点登录:就是用户只需一次登录就可以访问所有相互信任的应用系统。简单来说就是一处登录,处处登录,一处注销,处处注销。
作用:使得用户只要登录了其中一个系统,就可以访问其他相关系统,而不用进行身份验证登录。即用户只要登陆系统一次,该用户的身份信息就可以被系统中的多个主机上的应用所识别,不需要在访问每个应用时再分别进行登陆。
系统应用中的概念:
主要用于多系统的继承,即在多系统当中,用户只需要用到一个*服务器,登录一次就可以访问这些系统的任何一个,无需多次登录。目前流行的企业业务整合的解决方案之一。
单点登录的组成
单点登录(sso)体系主要有3个 :
(1)多个用户
(2)多个web应用
(3)1个sso认证中心(也就是我们的*服务器)。 其中多个用户访问不同的web应用,是否需要登 录由sso认证中心来控制。
单点登录的实现方式
1. 以cookie作为凭证媒介 ;
2. 通过jsonp实现 ;
3. 通过页面重定向的方式 ;
4.jwt+安全框架的实现方式
4. 使用独立登录系统 ;
单点登录的两种实现:
- redis实现单点登录
- cas*认证实现单点登录
redis实现单点登录 - 处理流程:
1、登录页面提交用户名密码。
2、登录成功后生成token。token相当于原来的jsessionid,字符串,可以使用uuid。
3、把用户信息保存到redis。key就是token,value就是实体类对象转换成json。
4、使用string类型保存session信息。可以使用“前缀:token”为key
5、设置key的过期时间。模拟session的过期时间。一般半个小时。
6、把token写入cookie中。
7、cookie需要跨域。
8、cookie的有效期。关闭浏览器失效。
9、登录成功。
cas*认证:cas server 和cas client
cas server负责对用户的认证工作,会为用户签发两个重要的数据,登录和服务。
cas server需要独立部署。
cas client负责处理对客户端受保护的资源的访问请求,要对请求方进行身份认证,重定向到cas server进行认证。以过滤方式保护受保护的资源。对于访问受保护资源的请求,cas client会分析请求中是否包含service ticket。
spring boot:
spring boot是一个非常好的微服务分布式开发框架,可以快速搭建一个系统。
spring 4大核心:
- 自动配置
- 起步依赖
- 命令行界面
- actuator
springapplication的实现方法:
- 如果使用的是静态run方法那么首先要创建一个springapplication对象,他会提前做下面几件事情:
根据classpath里面是否存在某个特征类来决定是否应该创建一个为web应用使用的applicationcontext。
使用springfactoriesloader在应用的classpath中查找加载所有可用的applicationcontextinitializer。
使用springfactoriesloader在应用的classpath中查找并加载所有可用applicationlistener。
推断并设置main方法定义类。
- springapplication实例初始化完成并完成设置后,就开始执行run方法的逻辑,方法执行开始,首先遍历执行所有通过springfactoriesloder可以查找到并加载的springapplicationrunlistener。调用它的started()方法,告诉springapplicationrunlistener,spring boot开始执行。
- 创建并配置当前spring boot 应用将要使用的environment。遍历调用所有apringapplicationrunlistener的environmentprepared()方法,告诉他们”当前springboot应用使用的environment准备好了”。如果springapplication的showbanner属性被设置为true。则需要打印banner。
- 根据用户是否明确设置applicationcontextclass类型以及初始化阶段的推断结果,决定改为当前springboot应用创建什么类型的applicationcontext并创建完成,然后根据条件决定是否添加shutdownhook,决定是否使用自定义的beannamegenerator,决定是否使用自定义的resourceloader,当然最重要的是将之前准备好的environment设置给创建好的applicationcontext使用。
- applicationcontext创建好之后,springapplication会再次借助spring-factoriesloader,查找并加载classpath中所有可用的applicationcontext-initialzer然后遍历调用这些applicationcontextinitializer的initialize(applicationcontext)方法来对已经创建好的applicationcontext进行进一步处理。
- 遍历所有springapplicationrunlistener的contextprepared()方法。最核心的一步,将之前通过@enableautoconfiguration获取的所有配置以及其他形式的ioc容器配置加载到已经准备完毕的applicationcontext。遍历调用所有springapplicationrunlistener的contextloaded()方法。调用applicationcontext的refresh()方法,完成ioc容器可用的最后一步,查找当前applicationcontext中是否注册有commandlinerunner,如果有遍历执行他们。
正常情况下,遍历执行springapplicationrunlistener的finished()方法,只不过这种情况会将异常信息一并传入处理。
spring boot整合redis:
创建redis.properties配置文件。
然后建一个封装redistemplate的redisutil类
最后建一个redisconf即可实现使用redis
spring boot 整合jpa:
jpa查询:基本查询分为两种,一种是spring data默认实现,一种是根据查询方法来自动解析成sql。
- 继承jparepositoy
通过继承这个类来实现最基本的增删改查。
- 自定义简单查询:
jpa这里遵循的是约定大约配置的原则,就是遵循spring以及jpql定义的方法命名。spring提供一套可以通过命名规范进行查询构建的机制,这套机制会把方法名过滤一些关键字,比如find...by、read...by,query...by和get...by。系统会根据关键字将命名解析成两个子语句,第一个by是区分这两个子语句的关键词.这个by之前的是查询子语句(知名返回要查询的对象),后面的部分是条件子语句。如果直接findby...返回的就是定义respository时指定的领域对象集合,同时jpql中也定义了丰富的关键字:and、or等等...
jpa关键注解一览:
@entity 声明类为实体或表。
@table 声明表名。
@basic 指定非约束明确的各个字段。
@embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性。
@id 指定的类的属性,用于识别(一个表中的主键)。
@generatedvalue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@column 指定持久属性栏属性。
@sequencegenerator 指定在@generatedvalue注解中指定的属性的值。它创建了一个序列。
@tablegenerator 指定在@generatedvalue批注指定属性的值发生器。它创造了的值生成的表。
@accesstype 这种类型的注释用于设置访问类型。如果设置@accesstype(field),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@accesstype(property),通过getter和setter方法访问entity的变量。
@joincolumn 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@uniqueconstraint 指定的字段和用于主要或辅助表的唯一约束。
@columnresult 参考使用select子句的sql查询中的列名。
@manytomany 定义了连接表之间的多对多一对多的关系。
@manytoone 定义了连接表之间的多对一的关系。
@onetomany 定义了连接表之间存在一个一对多的关系。
@onetoone 定义了连接表之间有一个一对一的关系。
@namedqueries 指定命名查询的列表。
@namedquery 指定使用静态名称的查询
and findbylastnameandfirstname
or findbylastnameorfirstname
is,equals findbyfirstnameis,findbyfirstnameequals
between findbystartdatebetween
lessthan findbyagelessthan
lessthanequal find byagelessthanequal
greaterthan findbyagegreaterthan
greaterthanequal findbyagegreaterthanequal
after findbystartdateafter
before findbystartdatebefore
isnull findbyageisnull
isnotnull,notnull findbyage(is)notnull
like findbyfirstnamelike
notlike findbyfirstnamenotlike
startingwith findbyfirstnamestartingwith
endingwith findbyfirstnameendingwith
containing findbyfirstnamecontaining
orderby findbyageorderbylastnamedesc
not findbylastnamenot
in findbyagein(collection ages)
notin findbyagenotin(collection age)
true findbyactivetrue()
false findbyactivefalse()
ignorecase findbyfirstnameignorecase
spring常用注解:
@configuration 等同于spring的xml配置文件;使用java代码可以检查类型安全。
@controller:用于定义控制器类,在spring 项目中由控制器负责将用户发来的url请求转发到对应的服务接口
(service层),一般这个注解在类中,通常方法需要配合注解@requestmapping
@restcontroller:用于标注控制层组件(如struts中的action),@responsebody和@controller的合集。
@requestmapping:提供路由信息,负责url到controller中的具体函数的映射。
@service:一般用于修饰service层的组件
@autowired:自动导入依赖的bean
@repository:使用@repository注解可以确保dao或者repositories提供异常转译,这个注解修饰的dao或者repositories类会被componetscan发现并配置,同时也不需要为它们提供xml配置项。
@controlleradvice:包含@component。可以被扫描到。统一处理异常。
@exceptionhandler(exception.class):用在方法上面表示遇到这个异常就执行以下方法。
定时任务:
现实生活中我们需要很多定制的任务,记住一些事情然后定时提醒我们,比如闹钟。应用开发中也经常需要一些周期性的操作,这时候就用到定时任务。
实现定时任务的集中实现方法:
- java.util.timer类
java自带的方法,允许调度一个task任务。使用这种方法可以让你程序按照一个频度执行,但不能在指定时间运行。timertask类实现由timer安排的一次或重复执行的某个人物。每个timer对象对应的是一个线程,因此计时器所执行的任务应该迅速完成不然会延迟后续的任务。
举个栗子:
timer timer=new timer();
mytask mytask=new mytask();
timer.schedule(mytask, 1000, 2000);
timertask类主要实现run()方法里的业务逻辑,用法如下:
import java.text.simpledateformat;
import java.util.date;
import java.util.timertask;
public class mytask extends timertask {
@override
public void run() {
// todo auto-generated method stub
simpledateformat simpledateformat=null;
simpledateformat=new simpledateformat("yyyy-mm-dd hh:mm:ss:sss");
system.out.println("当前的系统时间为:"+simpledateformat.format(new date()));
}
}
timer线程如何终止:
默认情况下,创建的timer线程会一直执行,所以我们有4中方法终止timer线程。
调用timer的cancle方法
把timer线程设置成daemon线程,(new timer(true)创建daemon线程),在jvm里,如果所有用户线程结束,那么守护线程也会被终止,不过这种方法一般不用。
当所有任务执行结束后,删除对应timer对象的引用,线程也会被终止。
调用system.exit方法终止程序
注意点:
每个timer仅对唯一一个线程
timer不保证任务执行的十分精确。
timer类是线程安全的。
- 连接池实现定时任务:
出现原因:
- timer之创建了一个线程,任务执行时间超过设置的时间将会出现问题。
- timer创建的线程没有处理异常,因此一旦抛出异常,该线程就立刻终止。
方法简介
scheduleatfixedrate(runnable command,
long initialdelay,
long period,
timeunit unit)1234
上面的四个参数进行讲解:
第一个command参数是任务实例,
第二个initialdelay参数是初始化延迟时间,
第三个period参数是间隔时间,
第四个unit参数是时间单元。
3.spring-task
spring自带的task实现定时任务也有两种方式,一种是xml配置的方式,一种是使用注解@scheduled,不管是那种方式,首先都需要在xml开头声明task
quartz:
quartz用一个jar文件,这个库文件包括了所有quartz核心功能。这些功能主要通过接口是scheduler接口。
quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可。
1、job
表示一个工作,要执行的具体内容。此接口中只有一个方法
void execute(jobexecutioncontext context)
2、jobdetail
jobdetail表示一个具体的可执行的调度程序,job是这个可执行程调度程序所要执行的内容,另外jobdetail还包含了这个任务调度的方案和策略。
3、trigger代表一个调度参数的配置,什么时候去调。scheduler可以将trigger绑定到某一jobdetail中,这样当trigger触发时,对应的job就被执行。一个job可以对应多个trigger,但一个trigger只能对应一个job。
4、calendar:org.quartz.calendar是一些日历特定时间点的集合, 一个trigger可以和多个calendar关联。
5.threadpool:scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率
在 quartz 中,有两类线程,scheduler 调度线程和任务执行线程,其中任务执行线程通常使用一个线程池维护一组线程
spring boot实现定时任务:
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-devtools</artifactid>
<optional>true</optional>
</dependency>
</dependencies>
然后在启动类上面加上@enablescheduling即可开启定时任务(@enablescheduling 注解,它的作用是发现注解 @scheduled的任务并由后台执行。没有它的话将无法执行定时任务)
创建定时任务实现类
安全框架shiro:
shiro是java的一个安全框架,功能强大,使用简单的java安全框架,为开发人员提供一个直观而全面的认证,授权,加密以及绘画管理解决方案。
为什么使用shiro:
- 易于使用,提供易于理解的java security api。
- 简单的身份认证,支持多数据源(ldap,jdbc,kerberos等)
- 支持一级缓存,以及提升应用程序的性能。
- shiro干净的api和设计模式使它可以方便与许多的其他框架和应用进行集成。
shiro的用途:
- 验证用户来核实他们的身份
- 对用户执行访问控制,如:判断用户是否被分配了一个确定的安全角色、判断用户是否被允许做某事。
- 在任何环境下使用sessionapi,即使没有web或ejb容器。
- 在身份验证,访问看哦内置期间或在会话的生命周期,对时间做出反应。
- 启用单点登录功能
- 数据加密,防止密码明文储存。
主要功能特点:
authentication:身份认证/登录,验证用户是不是拥有相应的身份。
authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者验证某个用户对某个资源是否具有某个权限;
session manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通javase环境的,也可以是如web环境的;
cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
web support:web支持,可以非常容易的集成到web环境;
caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
concurrency:并发,shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
testing:提供测试支持;
run as:允许一个用户假装为另一个用户(如果允许)的身份进行访问;
remember me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
总体架构:
1) subject:主体,代表了当前“用户”。这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 subject,如第三方进程,后台账户等,它仅仅意味着“当前跟软件交互的东西”。 subject在shiro中是一个接口,接口中定义了很多认证授相关的方法,外部程序通过subject进行认证授,而subject是通过securitymanager安全管理器进行认证授权 ,我们可以把 subject 认为是一个门面,securitymanager 才是实际的执行者。
2) securitymanager:安全管理器。对全部的subject进行安全管理,shiro框架的核心,即所有与安全有关的操作都会与 securitymanager 交互。通过securitymanager可以完成subject的认证、授权等,实质上securitymanager是通过authenticator进行认证,通过authorizer进行授权,通过sessionmanager进行会话管理等。 securitymanager是一个接口,继承了authenticator, authorizer, sessionmanager这三个接口
3) realm:域。shiro 从 realm 获取安全数据(如用户、角色、权限),就是说 securitymanager 要验证用户身份,那么它需要从 realm 获取相应的用户进行比较以确定用户身份是否合法,也需要从 realm 得到用户相应的角色/权限进行验证用户是否能进行操作。我们可以把 realm 看成 datasource,即安全数据源。
记住一点,shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给shiro即可。
也就是说对于我们而言,最简单的一个shiro应用:
1、应用代码通过subject来进行认证和授权,而subject又委托给securitymanager;
2、我们需要给shiro的securitymanager注入realm,从而让securitymanager能得到合法的用户及其权限进行判断。
内部结构:
1) subject:主体,可以看到主体可以是任何与应用交互的“用户”。
2) securitymanager:它是 shiro 的核心,所有具体的交互都通过 securitymanager 进行控制。它管理着所有 subject、且负责进行认证和授权、及会话、缓存的管理。
3) authenticator:认证器,负责主体认证的,认证就是核实用户身份的过程。这个过程常见的例子是“用户名/密码”组合。多数用户再登录软件系统时,通常会提供自己的用户名和密码,如果储存在系统里的密码与用户提供的匹配,他们就被认为通过认证。
4) authrizer:授权器,或者访问控制器。它用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中的哪些功能。
5) realm 可以有1个或多个realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是jdbc实现,也可以是ldap实现,或者内存实现等等;由用户提供;注意:shiro不知道你的用户/权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的realm;
6) sessionmanager:即会话管理 ,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。
7) sessiondao:用于会话的增删改查。我们可以自定义 sessiondao 的实现,控制session 存储的位置。如通过 jdbc 写到数据库或通过 jedis 写入 redis 中。另外sessiondao 中可以使用 cache 进行缓存,以提高性能。
8) cachemanager:缓存管理器。它来管理如用户、角色、权限等的缓存的。因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。
9) cryptography:密码模块,shiro 提高了一些常见的加密组件用于如密码加密/解密的。
环境配置:
<dependencies>
<dependency>
<groupid>junit</groupid>
<artifactid>junit</artifactid>
<version>4.9</version>
</dependency>
<dependency>
<groupid>commons-logging</groupid>
<artifactid>commons-logging</artifactid>
<version>1.1.3</version>
</dependency>
<dependency>
<groupid>org.apache.shiro</groupid>
<artifactid>shiro-core</artifactid>
<version>1.2.2</version>
</dependency>
</dependencies>
身份验证:
验证流程:
1、首先调用subject.login(token)进行登录,其会自动委托给security manager,调用之前必须通过securityutils. setsecuritymanager()设置;
2、securitymanager负责真正的身份验证逻辑;它会委托给authenticator进行身份验证;
3、authenticator才是真正的身份验证者,shiro api
上一篇: Linux下find命令及其参数的使用
下一篇: 女帝武则天造的“曌”字到底有何寓意呢?