# rookie-spring-pro **Repository Path**: wchnan/rookie-spring-pro ## Basic Information - **Project Name**: rookie-spring-pro - **Description**: b站coder1v5项目 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2024-02-20 - **Last Updated**: 2025-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 从0开始,首先进行模块设计;我要做什么,我怎么划分模块 模块的划分 parent模块,专门存放pom.xml文件 commons模块:通用包,规范:Response/Request,全局异常 网关模块: 认证中心: 用户中心:用户中心和认证中心是两回事,认证是检票,用户是游客;用户挂靠在组织下面 消息模块: 商品中心: 安全中心:大型应用,to g,to b;加解密、数据一致性校验封装成为领域服务、接口向外提供服务,而不是简单的工具类、插件。提高到服务的粒度,可以引入binlog、消息监听等手段进行监控,向外作为独立的产品提供 入口:服务编排 前台:面向的需求不一样,后台的用户可以查看所有,用户只看自己的;接口可以分开开发,也可以统一,统一则涉及权限的管理 管理员web:系统管理,服务的应用层 用户web 商品中心: 模块命名:公司域名+模块域名 com.only4play.productcenter 避免微服务扫包的冲突 模版——表单——审批表单 要素:领域服务不具备通用性,领域、领域内各要素都是唯一的;通用与否,由业务的上下文去决定;比如插排,在商城是商品,在物联网是设备;要素及其命名,由业务的上下文去决定 store:仓库 product:产品,就是spu productsku:sku goods:商品 inventory: 库存 category:分类,层级关系 为什么单独拿出来,而不是设置成Product的一个属性了 每个类都会设计有操作员、主机、操作时间的属性,这些属性从面向对象的角度思考,是否必要 attribute:一个sku有多个属性值,具化,一对多;属性可以去复用,多对多 开发流程(怎么从0到1搭建一个模块) 建包 op-product-api op-productsrv domain web infrastruture ===================视频2======建模============ 认证中心和用户中心的边界在哪里 认证中心:登录,角色的定义,以及角色拥有的资源 每个应用中心赋予用户的上下文是什么,使用户中心的回调,应用级别的 架构涉及:应用——>aware接口,应用可以获取用户的上下文 流程引擎:有自己的用户 认证中心——> inteceptor/spring filter(权限拦截器)——> 各应用中心 认证中心,存放认证信息,外围请求进入inteceptor,inteceptor中到认证中心获取token,校验是否合规;第一次登录的时候,用户中心返回token,回调token信息在认证中心中(表,redis,或者其他存放token的中间件) 用户体系——>人员的流转,三要素,组织,人员,标签(标记人员的职责、角色) 迁徙服务:数据庞大的系统,升级迭代迁移 elastic-Job:上下文的分片 ui模块:op-system-console放页面代码,静态资源,但还是打成jar,op-system-ui-server放后端的代码 op-ui-module: 前端的ui,后端的ui 如何组织代码,设计代码的结构是一个学问;模型设计,接口设计,考虑到可能的场景,留下对应的拓展点,为以后的建设留下入口 怎么搭建前端项目 笔记,要记录下思维的过程,而不是思维的结论 消息中心有什么 模版 200张表,通过表名识别业务领域 客户:cm、cb 产品:prod 订单:om 资源:res 表名设计:前缀,进行标记分组;已经划分了微服务,微服务名就是一种标记分组了,不必要再去加。但是不同领域的库、用户也要根据微服务进行对应的划分。如果prod、res、base的数据都统一放在gg库中而用户名不切分,还是要回到代码看业务领域。而业务测试很少去看代码 什么情况下要考虑什么问题,对应的解决方案是什么 很多问题不是没有能力,而是没有意识,学到一种方法之后就一只死磕,不会想着再去换一种 重复的工作,message里面的类,op-enityt敲完之后,再一个个敲包名 解决方案:live template中新增op-message-entity配置,包名固定是message包的 点出思考的维度,要从哪个方面,进行怎样的思考;商品是唯一的,规格是一类,产品是大的概况 模型,模型里面的字段,共同搭建起整个的分析框架,和成果 DirectionType:入库的方式有很多种,修理入库,借阅入库;入库的动作是一样的,但业务不一样,所处的线条,上下文也不一样 AgentStore:找到概念之间的联系,抽出来,很多问题就迎刃而解了。 调拨,从经销商的这个仓库调到经销商的那个仓库 Goods:规格之后才有库存,字段既是对象的属性,也是不同场景下,领域功能的通用点;业务不一样,但如果要用同一段代码去处理,怎么搭建起这个入口 商品——库存,小超市,门店就是库房;大公司,门店和仓库分离;抽象,必定一一对应一个能实际独立存在的概念,角色,职能 配送领域,对应配送员来说,他关心的是从哪里取货,送到哪里;对于打包员来说,关心的是物品是什么商品,商品在什么仓库。在不同的分工体系下,不同的工种,关心的对象属性不一样————在现代工业化细致的分工体系下,不同的工种,关心的只是商品中的某个字段;如果是街边的小店,什么都会关注。架构,和业务体量是分不开的。 小公司,角色和职务是一对一的;经过不断的发展,职务扮演的角色增加;对应代码中的对象类,属性也在不断地增加。这时候的重构,需要对对象进行拆分,不同的角色,角色承载的职能,独立到不同的线条去进行处理;也要设计管理类,对数据进行分流 商品和产品的差别是什么?有规格ID、唯一编码、仓库ID; 于电商,有上架的管理;有仓库,有门店,有个人,有经销商;这些角色统一收容到仓库的概念下,在storeId下面的商品,即是上架了的;屏蔽了一层业务的东西;后面经营关系变化,是否还会出现新的经营实体呢?这是拓展点,storeId屏蔽了未来变化对代码的影响,并给后续拓展留下入口 重要; 商品的入和出有一系列的事件,业务就在里面了。商品并不关心业务,关心的是库管员——出入库记录,出入库方向,一个是入(IN),一个出(OUT) InOutRecord: 仓库管理员; 重要,批次号;因为有了出入库类型,还有一个中要的概念,出入库明细,明细和数量是挂钩的;根据是否可以量化,水,和手机,明细信息还会不一样 ==================领域服务和事件的设计======================= 参数,参数的转换(req、rep)——领域服务服务的设计(领域服务层)——责任链、插件、拓展点 建模完成之后,思考接口该如何设计——商品sku设计好之后,对外的模型,应该如何暴露——sku request应该是什么 变化的代码,应该写在应用层。服务设计的一个大的原则:应用层,是永远在变化的;服务层,保证通用性,参数和逻辑,都是不会变化的,这里面的类,是模型和crud的功能类 设计的时候,变化和不变化的代码分离开来,避免外部业务的变化直接透到底层代码中 所有的驱动都是通过业务,不存在直接置状态的情况;代码生成器只能生成简单单表交互代码,业务代码是没办法生成的。今天想办法,兼容了变化点,写出了生成逻辑;明天业务变化,今天写的代码不适用,等于白干. ································································· 如果服务处理的是多个对象,涉及到具体的业务,就涉及到领域服务了。一个业务线条上的动作,只通过页面去触发吗?有流程引擎驱动的,事件监听回调的,触发的方式是多种的。但他们都在同一个业务线条下面,设计上,把这些动作都放在同一个领域服务;同时起到归类(业务性质上)的作用 领域服务,也有一个对应的模型,model 应用层,服务编排,不良数据库 constants req rep controller 入库和出库,if-else作判断出入库类型,或者针对入库设计一个线条,针对出库设计一个线条,通过签名进行区分——api的友好性。数据什么时候开始区分呢,一开始就去区分了,外部调用的url,到controller,到domainservice =============商品中心的设计============== 商品出入库 商品,商品分类,商品品牌,计量单位,建模的时候,是否需要分开单独建模呢。这些更像一些数据字典——数据字典的处理方式 普通的进销存系统,goods一层的抽象;京东的电商系统,sku---spu---goods,三层的结构 入库,入库单,仓库的概念;入库单——审批——入库流程,一条流程的入口,往往是模型中的一个属性 出库管理需要什么样的动作,选好商品、数量,提交出库单 调拨,选定起始仓库,选号商品、数量 库存预警,新增一条规则(最低数量,最高数量,对应绑定的商品),这样的规则,在出入库的流程中,由规则引擎去触发校验 商品的本质是什么,表单;(表单的抽象是什么,模板)表单是什么,对象;对象有什么,值域;值域表现在页面上是什么,下拉框、填空,单选框;前端和后端,后端之间,商品最终用json/map来传递 前端录入商品页面,和后端的代码,什么关系?前端选中商品模板ID(电视、平板、课程),后端根据模板id查询商品对应的属性,渲染到页面上,属性对应的值域,该怎么填(下拉框,选择框,填空框),数据从哪里获取,在渲染的时候完成这样的初始化工作 引出一个问题,模板如何去定义?我们希望前端定义的时候,可以随意拖动组装。这里的实现,实际是一个基本的表单系统。表单可以描述一个问卷,可以描述一个商品,甚至可以描述一个订单 订单行——订单项 商品——商品属性 资源——资源属性 用户——用户特征 都可以抽象成为模板——模板项。落到各业务中心的工作,把关系描述出来就行了 增加模型属性,没问题;改模型,说明前期的抽象和关系理解有问题 如何描述一个表单?(可以去参考tduck的设计) template templateItem: 属性值,metaData储存,实际是多个组的kv;对于固定,每个业务都会有的基础的信息(是否必填,描述,操作时间),直接放在类属性中存放即可;各个业务特有,基于业务将产生变化的,反范式地去存放在数据库中,以兼容不断的业务变化 拓展信息如何存储(模型中):获取数据的url,前端通过controller调用url获取;controller的实现方式可以是静态数据,可以去查缓存,查数据库,具体实现看业务场景;约定大于配置,字典的实现方式,就按这样去实现,不同字典,调不同的controller方法去获取;前端渲染的时候,并发加载 templateCategory: 不仅仅是商品,还可以是工作流的模板 ComponentType: 给前端看的 约定大于配置,什么是约定,就是固定的软件行为,规范文档,交互流程,加载流程,在一个节点中,上下文是固定的。我不需要去关注他之前是怎么做的,之后是怎么做的,我按照一开始的约定完成我这个节点的业务就可以了;配置就是变化,现在的软件行为满足不了我的需求,我需要进行个性化的处理 ```````````````````````什么是产品思维`````````````````````````` 基本属性,怎么做的有复用性 建设组件库 产品最终面向的是用户,市场 先创建模板,再创建商品 前端不需要知道后端的软件行为,也不需要了解后端的逻辑、流程。不止是前端,任意一个流程中的节点,它只需要去实现当前节点下的需求就行,不需要附带完成上下文的工作。否则前后节点就耦合了。后面我想去把其中一个节点拆出来,给别的流程用,就拆不动 面对产品编程,根据用户行为,拆解软件行为。产品,易用性,美观,所见即所得;后端的实现,拆解到最后,都有成熟的解决方案供选择;衔接其中的,是所谓的软件设计 功能粒度:行为 ```````````````````````认证中心和用户中心的设计````````````````````````` 不只是部门的授权,门店的授权,课程的授权,人员的授权,授权这个动作是公共的,那模块如何把他做的具备通用性。(这里的概念,设计,建设的目的,其实就是外面在搞的中台。正经的中台,应该具备这样的功能,而不是搞成一锅大杂烩) 模型: 角色通过授权的资源列表访问应用 应用 三方应用:统一的认证管理,为后面接入oos进行准备 资源 角色 用户:授权实体,和实际的用户隔离开来 微信可以登录小程序里面的商城账号,王者,吃鸡,也可以去登录各种合作商的外部应用。这里面每个系统的用户是不一样的,认证中心如何设计,以去兼容多系统的用户?认证系统中的角色,和下游系统中的用户,是一对多? 认证中心和用户中心为什么要分离, 核心是认证关系的管理,各种业务的关系(员工和组织,员工信息,用户订单)在各个业务子系统中进行管理 管理,订单管理,用户管理,账单管理,库存管理,管理的本质是什么?围绕这个本质,展开的处理流程,一套,整套的解决方案是什么?我这里说的解决方案是业务性质的,不是技术层面的。思考一下这个问题 因为授权的主体,客体是在不断地变动的,今天我要把订单查询的权限授权给一个人,明天我要把库存管理的权限授权给一个组织;这些在不断的变化过程中 认证不是授权,认证和授权还可以分开,认证解决的是你可以用什么样的方式,能不能进门;进去之后,你能进什么房间,看什么东西,这个粒度还可以进一度去划分。这个是看实际的业务上下文去决定的;这就又牵扯到一个问题,我们说建模,要考虑周全,留下接口,留下入口给后续拓展,那要留什么样的接口,做什么样的拓展,是我们想到一种就埋一条线吗?不是,实事求是,按实际情况去做。不要做无用功。 ```````````````````````认证中心和用户中心的编码````````````````````````` 发票系统的认证,订单系统的认证,互相独立,userId是唯一的,对应用户,applicationId是不一样的;怎么建立认证关系呢?前台授权,指纹/脸部识别 人——认证中心——应用,通过不同的认证关系,同一个人可以访问不同公司的不同应用。三者关系互相独立的,通过认证关系表进行绑定 钉钉登录的时候,选择公司,可以进入这个公司,说明存在授权关系。这个时候,人,公司,授权信息,是互相独立的。人脱离公司,公司解雇人,修改授权关系就行 把关系独立成一个模型进行管理的好处,这个时候就体现出现了;否则,连带关系不是在人表加campanyId,就是去公司下面新增员工列表,这些都存在耦合不好管理 人在公司业务应用的角色,职位,组织关系,有应用系统内部的上下文去决定,内部去管理,外部不需要关心或者解决他们之间的关系,解决能不鞥那进来的问题就可以了 思考的维度——独立——避免耦合 ----------------------开发规范10——应用模版化开发、打包和部署----------------------------------- service 工程模板执行 ``` mvn archetype:generate -DgroupId=com.only4play -DartifactId=op-authsrv -Dversion=4.0.0 -Dpackage=com.only4play.authcenter -DappName=auth-srv -DarchetypeArtifactId=op-service-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=4.0.0 ``` web 工程模板执行 ``` mvn archetype:generate -DgroupId=com.only4play -DartifactId=demoweb -Dversion=1.0.0-SNAPSHOT -Dpackage=com.only4play.demoweb -DappName=demo-web -DarchetypeArtifactId=op-web-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=1.0.0-SNAPSHOT ``` api 工程模板执行 ``` mvn archetype:generate -DgroupId=com.com.only4play -DartifactId=demoapi -Dversion=1.0.0-SNAPSHOT -Dpackage=com.only4play.demoapi -DarchetypeArtifactId=op-api-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=1.0.0-SNAPSHOT ``` 缺少package-info文件会导致BaseJpaAggregate的q类不生成 web层进行应用编排,srv承载具体的中心业务,api层做上层应用和底层应用的解耦 同一套代码,打包脚本不同,实现应用的隔离。实际通过服务名路由的nacos配置进行区分 域名两套:babybird——birdbaby;ngnix、nacos是一个,其他是两套隔离的环境。 ngnix babybird.geekhalo.com.conf birdbaby.geekhalo.com.conf 练习 Ptest-----Pro 61-118 centerName+_bird -------产品代码抽象编程------- 供应链网站 商品维护模块,拖动页面元素创建实例 基于模版创建商品,基于模版创建工单, 模版这一部分是通用域,类似于模版方法,抽象出来作为底层服务。 在此之外,各模块独有的元素、逻辑,是各自的个性化代码去处理 -----------------春天13_--------------------- 需求:开发一个登陆starter,校验凭证,校验逻辑暴露给下游应用继承实现 登陆的逻辑是通用的 登陆方式的差异化、登陆流程的差异、登陆凭证的差异 动态配置流程节点——服务粒度抽解的足够小,能够根据需求变化进行拆解组转 项目的定制化——登陆方式的差异化: 统一认证中心—— outh2 ca认证:涉及硬件的支撑,证书,加密机,壁垒机 ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 不只要考虑类的拓展,还要考虑包的拓展。通常根据业务大类划分 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password user auth_module代码库下 security SecurityConfig: 入口类,从这里开始看整个包的代码。在系统应用,则是服务的编排层 EnableWebSecurity——SecurityAutoConfiguration——DefaultAuthenticationEventPublisher:事件发送器的注入:错误和对应处理类的绑定 @Evenlistener,实现listener接口,等价;starter在初始化过程中可以给应用提供什么bean使用?看config自动注入类哪些 config: 和yml、nacos打交道,spring初始化过程中会使用到的配置 authentication:具体角色(管理员、代理商、用户、供销商),的校验逻辑 passencoder:密码加密,国密,加盐,或者局方、集团要求的加密逻辑 evenlistener:校验成功/失败之后的事件处理 req、rep:前端参数,可以放在外部层;token,当前用户,登陆时间 context: 用户上下文,看见代码先不急着去抄,思考,画一下,他背后构成的整个体系,或者说,这个代码是嵌入到什么体系的什么流程之中。有了这个了解之后,再去抄;Base方便强转,放通用字段;各个角色的context放个性化数据 exception: security异常处理体系的入口是AuthenticationException,业务代码继承这个类才能嵌入他的流程中; 业务异常体系的设计:业务——场景——操作——逻辑,一级一级的细化,类继承的方式去体现 entrypoint:这里是处理没进门的场景,下面是进门又被赶出来了;SecurityContextHolder存储用户登陆信息,没有的话会跑进entrypoint handler:成功失败的处理器,拒绝访问的处理器;定制,没有用security的默认类;AbstractAuthenticationProcessingFilter.class:47 默认走类页面跳转,前后端分离的项目没有页面 AdminAuthcontroller的方法都是类似的可以写一个快捷键 securityht初始化认证流程:https://www.cnblogs.com/agony-wxl/p/12486888.html AbstractAuthenticationProcessingFilter.successfulAuthentication;校验通过之后,在这里向SecurityContextHolder放入身份认证信息:如果Provider手动放入类认证信息,在successfulAuthentication则有被覆盖的风险;应当在successHandler中去处理 类的重编,maven,op-authsrv里面 PreAuthorize注解 addFilterAfter/addFilterBefore的区别 为什么没有成功失败handler呢,因为不是同一个处理体系;OncePerRequestFilter——AbstractAuthenticationProcessingFilter,token是不是直接拒之门外 怎么去把笔记做的有体系?一开始听,听完不久,还有印象,还能靠回忆补充。但是过几天再看的时候,只会感觉到零碎 ----------------------开发规范10——应用模版化开发、打包和部署----------------------------------- service 工程模板执行 ``` mvn archetype:generate -DgroupId=com.only4play -DartifactId=op-authsrv -Dversion=4.0.0 -Dpackage=com.only4play.authcenter -DappName=auth-srv -DarchetypeArtifactId=op-service-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=4.0.0 ``` web 工程模板执行 ``` mvn archetype:generate -DgroupId=com.only4play -DartifactId=demoweb -Dversion=1.0.0-SNAPSHOT -Dpackage=com.only4play.demoweb -DappName=demo-web -DarchetypeArtifactId=op-web-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=1.0.0-SNAPSHOT ``` api 工程模板执行 ``` mvn archetype:generate -DgroupId=com.com.only4play -DartifactId=demoapi -Dversion=1.0.0-SNAPSHOT -Dpackage=com.only4play.demoapi -DarchetypeArtifactId=op-api-archetype -DarchetypeGroupId=com.only4play -DarchetypeVersion=1.0.0-SNAPSHOT ``` 缺少package-info文件会导致BaseJpaAggregate的q类不生成 web层进行应用编排,srv承载具体的中心业务,api层做上层应用和底层应用的解耦 同一套代码,打包脚本不同,实现应用的隔离。实际通过服务名路由的nacos配置进行区分 域名两套:babybird——birdbaby;ngnix、nacos是一个,其他是两套隔离的环境。 ngnix babybird.geekhalo.com.conf birdbaby.geekhalo.com.conf 练习 Ptest-----Pro 61-118 centerName+_bird -------产品代码抽象编程------- 供应链网站 商品维护模块,拖动页面元素创建实例 基于模版创建商品,基于模版创建工单, 模版这一部分是通用域,类似于模版方法,抽象出来作为底层服务。 在此之外,各模块独有的元素、逻辑,是各自的个性化代码去处理 -----------------春天13_--------------------- 需求:开发一个登陆starter,校验凭证,校验逻辑暴露给下游应用继承实现 登陆的逻辑是通用的 登陆方式的差异化、登陆流程的差异、登陆凭证的差异 动态配置流程节点——服务粒度抽解的足够小,能够根据需求变化进行拆解组转 项目的定制化——登陆方式的差异化: 统一认证中心—— outh2 ca认证:涉及硬件的支撑,证书,加密机,壁垒机 ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password ```````````````security编码````````````````````` 场景,就是领域里面的一个类 UserDetailsServiceAutoConfiguration,ConfigureOnMissing,没有定义密码策略的时候,会自动给一个默认的 EnableWebSecuirty 定会自动加载HttpSecurityConfiguration.httpSecurity这个类 WebSecurityConfiguration:默认的request filter chain 配置就是配置,处理就是处理,职责单一 UserContextAware: 回调,这里是微服务,回调就补充接口返回的信息在jvm内存中 在同一个平台上面,登录方式的拓展如何解决 三个组件配置 filter provider token 在平台(京东)外部,使用第三方应用(微信、qq)登录该平台的拓展如何解决 在平台(京东)内部,接入第三方应用的拓展如何解决,外部平台的用户认证如何在认证中心进行 不只要考虑类的拓展,还要考虑包的拓展。通常根据业务大类划分 provider --这下面的是角色 admin --这下面的是认证方式的拓展 sms password user auth_module代码库下 security SecurityConfig: 入口类,从这里开始看整个包的代码。在系统应用,则是服务的编排层 EnableWebSecurity——SecurityAutoConfiguration——DefaultAuthenticationEventPublisher:事件发送器的注入:错误和对应处理类的绑定 @Evenlistener,实现listener接口,等价;starter在初始化过程中可以给应用提供什么bean使用?看config自动注入类哪些 config: 和yml、nacos打交道,spring初始化过程中会使用到的配置 authentication:具体角色(管理员、代理商、用户、供销商),的校验逻辑 passencoder:密码加密,国密,加盐,或者局方、集团要求的加密逻辑 evenlistener:校验成功/失败之后的事件处理 req、rep:前端参数,可以放在外部层;token,当前用户,登陆时间 context: 用户上下文,看见代码先不急着去抄,思考,画一下,他背后构成的整个体系,或者说,这个代码是嵌入到什么体系的什么流程之中。有了这个了解之后,再去抄;Base方便强转,放通用字段;各个角色的context放个性化数据 exception: security异常处理体系的入口是AuthenticationException,业务代码继承这个类才能嵌入他的流程中; 业务异常体系的设计:业务——场景——操作——逻辑,一级一级的细化,类继承的方式去体现 entrypoint:这里是处理没进门的场景,下面是进门又被赶出来了;SecurityContextHolder存储用户登陆信息,没有的话会跑进entrypoint handler:成功失败的处理器,拒绝访问的处理器;定制,没有用security的默认类;AbstractAuthenticationProcessingFilter.class:47 默认走类页面跳转,前后端分离的项目没有页面 AdminAuthcontroller的方法都是类似的可以写一个快捷键 securityht初始化认证流程:https://www.cnblogs.com/agony-wxl/p/12486888.html AbstractAuthenticationProcessingFilter.successfulAuthentication;校验通过之后,在这里向SecurityContextHolder放入身份认证信息:如果Provider手动放入类认证信息,在successfulAuthentication则有被覆盖的风险;应当在successHandler中去处理 类的重编,maven,op-authsrv里面 PreAuthorize注解 addFilterAfter/addFilterBefore的区别 为什么没有成功失败handler呢,因为不是同一个处理体系;OncePerRequestFilter——AbstractAuthenticationProcessingFilter,token是不是直接拒之门外 怎么去把笔记做的有体系?一开始听,听完不久,还有印象,还能靠回忆补充。但是过几天再看的时候,只会感觉到零碎 -------春天14------------ 在没有页面的情况下,怎么确定开发的主体流程?首先我们要跳出前后端交互的预置场景,想象一下如何和我们打交道的是人。相互之间需要完成什么动作,才能做完这个业务? 前提是熟悉业务,有对应的业务知识。 开发一个需求最重要的是,先把核心业务脉络梳理出来,围绕这个流程图开发接口。接口要完成的动作一开始不明确,粒度要求就不需要那么高,在后面开发的过程中再逐步细化。一个流程通常涉及到多个模块的交互,把接口摸出来,然后看流程能不能跑通。能够,再去开发其他支线的代码。 商品添加、关联属性、创建商品、入库、出库、调拨、生成订单、发票 商品模块 商品、sku crud 新建商品 属性列表查询、新属性添加、 根据商品id查询出商品组成,返回给前端 商品价格查询 资源模块 入库 商品状态校验 出库 组织间调拨、商品状态修改 模版模块 静态资源——动态资源(执行流程) 模版crud、关联模版crud 根据模版类型(商品、资源、订单)查询模版并返回 订单模块 根据业务编码查询订单模版,根据订单模版处理订单要素,生成订单报文 发票模块 订阅开票信息 开票 上层应用完成数据的组装,srv服务crud;api层处理领域相关的业务内容 这么多的bean和mapper类,是为了承载每一层业务去设计的。对应的,每一层都有一个专门处理业务的代码,写的好,就是设计模式的教学范例,写的不好,就是坑类。 不要从代码层面去理解代码,从业务层面理解代码 最小化控制单元——任务拆解——确定的任务边界,带来确定的成果预期。即使没做成,影响的范围也是固定的,有了这样的估量,我们对整体任务的进度心中有数 内容——技巧——形式 不知道页面,或者说,不清楚业务细节/规范/逻辑,可以开发程序吗? 确定输入和输出,写个空方法,继续写上下游的代码——等于一个一个业务步骤去推,用户会有什么动作,对应的就是程序中的方法。考虑到后续方法的复用,一个动作还可以拆成好几个方法组装起来去服务,粒度是实现过程中根据实际的业务需求和经验去调整的 那么,在我们一步步地推敲行为,拆解方法的过程,我们实际同步进行着任务的拆解。根据手上的开发资源和任务工期,和拆解得到的待执行列表,我们实际同步进行着计划初稿的制定;根据我们对每个人能力和习惯的了解,和我们准备分配给他们执行的任务,我们实际同步进行着能力的培养 包的划分:业务大类(领域)——业务规模 标准——规范,领域服务,通用的模型,每一个公司都能使用 jodd vtor 限流 防止重复提交 权限 校验 审计 当商品进行出入库、出售的时候,需要通用的领域服务来支撑,实现一个通用的领域服务来完成这个功能,应该如何设计 web application:数据收集、组装、调用后端product-src的goodsIn服务 product feign controller:数据转换,调用domainservice domainservice:数据校验、数据转换、商品入库 entity:发布领域事件(解耦) eventProcessor:支线任务处理 一个重要的能力,是对业务内容进行解析的能力;明白哪些业务是在同一个流程上面,哪些业务是在同一个层次上面,业务是由哪些子功能组成,功能边界是什么。把这些东西弄清楚,我们实际勾画出代码主体流程。设计合适的代码架构去承载对应的业务(设计模式、架构、使用的中间件提供的工具,如何嵌入代码流程中),设计合适的模型承载对应的数据 我们比较常做的工作是,对业务进行分类;还有一项重要的工作,对业务进行分层;怎么区分哪些内容处于同一个层次的?就考量实际的工作经验类 ## 春天15 需求:屏蔽运行环境的差异,给代码创造一个可以随时测试的环境 test container 痛点,网上有解决方案;没有——>需求——>做一个产品出来用 lego——command编程方式:mapper、feign、jpa根据方法名生成sql 确定目的,想怎么做,想要什么效果,根据你想要的效果找到对应实现的代码,根据现实生活中的流程跟踪代码的思路,一点一点地带动思维的成长找到通用的点 大数据量——spring data elastic search,滚动查询,流处理,需要时加载 行有未至,可加工力。路头一差,愈骛愈远,由入门之不正也。故曰:学其上,仅得其中;学其中,斯为下矣。也有相同的意思 spring batch——批处理,任务拆解,读,块处理 怎么用——模仿应用——模仿轮子——思想 贫血,充血,看团队成员去调整;这是一种代码的组织方式,不是固定的,看实际情况去调整。如果团队、系统简单,用普通的三层架构就能解决;如果是十几个部门合作开发的跨平台项目,就需要有足够的层次结构做改造冗余 出入通过充血模型;批次是管理概念,最终还是一对一的管理 authing application集成不同的domain有不同的功能 我们需要锻炼的是两种能力,分析业务场景,分析业务需求,抽象整体业务架构的能力,以及将其用代码实现的能力;就是说,我给你一个问题,一个场景,你通过自己的分析,提出一个或多个需求,对任务进行足够的拆解重组,知道自己每一步骤需要做什么。至于用什么样的技术去实现,是在任务明确之后,综合系统、团队、自己能力、工期、联调要求,综合进行考虑的 技术和业务的转化: 业务场景——框架:框架适用的场景,设计思路,设计原因,灵活地把它用好;当场景不合适之后,根据变更之后的场景,去找对应的处理框架,看他们是如何处理这个场景的问题;理解场景,首先思考自己的处理方式,然后去看别人的处理方式,思考一下他们为什么采用这样的处理方法,用这样的方式去学习 思考问题不够全面,了解一下别人是怎么思考的,吸收进来完善自己的分析框架 在业务逻辑、代码的易懂性、优雅、团队的开发效率之间做折衷 ## 春天16_商品入库流程 不知道怎么实现,先按猜想的流程实现一次,有所本,后续以此为基础修改;先把自己的逻辑搬出来,后面才能和别人的思想产生碰撞,发现自己的不足,修改思维模型——是看的见的修改。不然,始终是似是而非的理解,觉得自己懂了,想展开,却不知道从何说起 ### 怎么设计应用层和服务层——层次感 应用层:承载业务,屏蔽业务变化对底层方法的影响 服务层:crud,共性动作, 转运,transfer,不属于商品的属性,但是和商品相关的操作 需求:给下面三个场景写一个通用的方法 1.商品入库 2.代理商发货 3.代理商退货 拓展场景:总经销——二级经销——三级经销;消费者——退货; 供应链核心:货品在不同仓库下的流转 skuid下编码在codes中的商品,所属仓库,从inStoreId变更为outStoreId;新增对应出入库record; 针对domain层建立模型——足够通用,放在api层,直接下来 fielddesc是自己定义的,schema是swagger上面使用展示注释 非序列化商品,底层事件处理,一对一 没有实际经验的人,一开始,是没办法从上而下去设计一个通用方法来承载业务;常见的是把各个业务都实现了,然后把方法中公共的逻辑抽出来,从下而上去改造。如此反复多次,积累了实际的编程和设计的经验之后,学到的技巧,遇到类似的场景,尝试从上而下去设计。 围绕store展开,人,仓库,供应商,经销商,都收拢在store之下。不管后面业务如何拓展,只要几个核心的业务概念没有发生变化,以他们为核心建设的代码就不会发生变动 订单状态的流转: 待支付——已支付——(后面是物流的内容)——待发货——已发货——退货/确认收货 一条busi record,它的生命周期横跨多个领域,生命周期的变更,及变更所需的业务动作,它的模型如何设计,应用层如何设计,服务层如何设计? 模型: 应用层: 记录工单状态:status,orderId,operId 记录工单数据:metaData 服务层:各中心根据业务属性确定 应用层: 异步任务处理,扫描工单状态,找到对应的处理类,反射进行处理/消息监听,通过消息组件流转 模版模式,定义主体流程 规则校验,根据busiType和status联合确定规则,设计统一的接口类ICheckSV.check(Model model),按busiType+status实现不同的校验逻辑;考虑引入规则引擎 业务处理,根据busiType和status联合确定逻辑,设计统一的接口类IBusidealSV.dealbusi(Model model);根据业务处理的内容,feign调用到各业务中心进行处理 工单表状态更新/异常容错处理/处理过程记录 服务层: 原子服务 支付状态,钱,下单人——订单本质 GoodsInStoreRequest,GoodsTransferRequest属于domainservice的模型,如果设计的足够通用,能够包揽足够多的业务场景,则可以放在api层去给外部调用 ### 业务代码(应用层编写技巧) ## 春天17_spring自动装配代码思考(ImpoerSelector) 场景: 需求 ImportSelector使用场景: OAuth2ImportSelector:starter动态加载。根据@Enable***中配置的环境,动态初始化不同的程序上下文给应用使用 主要功能是分流 OAuth2ClientConfiguration:把configuration类加入到spring容器的初始化流程中,通过configuration类完成大部分上下文的初始化工作。configuration@Be类中通过@Bean完成类的初始化工作 什么时候configuration类不会被加载?没有加@Configuration注解,就没有被spring扫描到了 如何初步理解一个类的功能?类名,角色,n;方法名,动作,v;入参,出参,介宾;角色+动作+入参=出参 the selector selects the classes needed to be imported according to metadata 为什么他这样设计,解决到工作中的什么问题?为什么入参是这个,出参是那个,理解这个,就理解到这个方法的意图——机械的懂,融合实际应用场景的懂,大部分是前者 mockito @Conditional以bean为维度,ImportSelector以配置集为维度 SpringBootCondition定制举例:只有生产环境的101主机才生效 以AbstractSessionCondition为父类展开的子类体系,是另一个维度的复用,判断条件的复用 selector无法处理的场景: 复杂bean的注入 解决方案:org.springframework.context.annotation.ImportBeanDefinitionRegistrar,自定义bean的注入逻辑 描述一件事情:builder模式 通过class拿到bean 通过springboot classloader拿到class(双亲委派机制),类加载器 bean的初始化和类加载器强相关,怎么找到类,不同的打包方式,有不同的目录结构,有不同的配置方式,所以classloader有多种实现的方式 都是串起来的 configuration类import configuration类 @Enable注解import selector类,selector类在告诉spring要加载什么配置类 org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport 注入ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware就能完成这个类的工作,就是这个领域是有三个类合作输出的 建造者模式+代理类 核心流程:扫描,构建过程,注入逻辑,拓展点(后置处理,如果后面添加的拓展的逻辑大多是一个过程的内容,就把这个过程抽到主流程里面) support,抽象父类,给子类提供支持,领域内可能使用到的处理逻辑都丢在这里