【清晨平台记录一】平台说明、思路+代码框架

目录

1.平台说明

2.基础框架设计思路

2.1用户模块思路

2.2用户模块业务功能接口

3.基础框架研发思路

3.1基础框架思考

3.1.1技术选型

3.1.2搭建框架思路

3.2基础框架搭建

3.2.1创建基础项目

 3.2.2引入依赖

3.2.3数据库配置

3.2.4基础配置

 3.2.5仅实现用户登录和token校验接口(未连接数据库)

有几个注意点和提醒点:


本篇代码地址:  Gitee 地址 注意是 project01 分支哦

使用IDEA打开项目时,及机的使用 import ,而不是 open 哦,并且 .idea 和 .iml 文件如果存在的话记得要先删除他俩,然后再import!

1.平台说明

想自己开发一个项目,熟悉一下项目流程,打算从项目的整个流程开始分析,包括【设计】、【研发】、【测试】。

项目暂定包含几大模块,从用户使用角度:用户模块、博客模块、商品模块、交易模块。

其实就是基本实现多用户下的博客系统和商城系统。

2.基础框架设计思路

现在先从【设计】角度出发,先分析基本的需求,一个网站最重要的就是分析清楚网站的用户属性,即账号类型;然后再根据具体业务转化为具体功能。

2.1用户模块思路

那么先从网站的用户属性来分析,当用户数据逻辑清晰之后,就可以搭建最基本的用户模块。给予用户或账号信息再逐步搭建后面的模块,当然也可以先搭建业务模块,但是无论是那种先行都需要分析清楚使用的用户属性。

网上流传的商业模式都有:B2B , B2C , C2C , B2B2C ,这里就不一一介绍了,我打算使用最后一个也就是 B2B2C 模式,这个网站平台即为组织/企业提供服务,也为个人提供服务。就类似于下图:

 平台里面有多个个人帐号,多个组织以及每个组织里面包含多个子账号。

组织就是第一个B,指的是商品或服务的供应商,俗称卖方;平台就是第二个B,指的是提供卖方与买方的联系平台,也可以提供服务;个人就是C,指的是个人消费者,俗称买方。

由此我们会产生几个疑问

1.个人帐号是否能够成为组织账号?

2.如果能,那么个人账号是否可以成为多个组织的子账号?如果是,那么登陆时怎样确认当前登陆的是哪个呢?

3.由于组织账号下还会有子账号,那么子帐号又是怎样区分呢?

解答:

解答之前,我们先想一下阿里云、腾讯云是怎样的解决的?这两个云都提供了账号的注册,注册完毕后可以选择认证方式:个人认证、企业认证;无论是哪种认证方式,都可以在当前账号下创建子账号,子账号可以使用用户名的方式。账号和子账号的登录方式是不同的。

上面的是一种方式,即,每个账号之间是完全区分开的,其子账号只与当前账号有关,即便有多个子账号绑定的手机号码或者邮箱是同一个,但是登录时会判断当前登录的是账号还是某个账号的子账号,登陆成功再根据账号类型判断其余业务数据。

还有另外一种方式,我公司的哥说这种才是互联网平台的账号思维,即,用户注册账号后就拥有个人账号,他可以申请创建组织账号,申请之后会再拥有一个组织账号并成为其创建人,然后可以邀请其他账号加入组织,这个其他账号就是某个个人账号。

也就是说一个账号可以登录个人账号,也可以选择登录某个组织的账号。

上面这两种方式的唯一一个区别就是:

第一种:一个账号对应一个集合(个人或组织)信息,若想要操作多个集合信息,需要在对应的集合重新申请账号,并且如果要切换集合,只能退出重新登陆;

第二种:一个账号可以对应多个组织信息,若想要操作多个组织信息,直接加入组织就可以,只需要在登录的时候选择当前操作的是哪个组织,登录期间也可以切换组织;


按照用户操作方便来说第二种会更加简便,省去了很多使用步骤!但是,这种对用户来说又很容易产生数据错误,一旦用户忘记当前操作的组织数据,就很有可能将A组织的数据添加到B组织中,或者使用A组织的身份对B组织产生交互数据!

所以这里就采用第一种方式吧,后续看有没有时间改进成第二种方式的用户模块!

所以,我们的平台由三种用户类型组成:

1.平台管理级别用户:只能登陆平台后台管理系统,操作平台级别的业务;

2.平台使用用户:只能登陆平台前台管理系统(包括用户前台、用户后台),操作平台前台的业务,具体业务权限由平台管理级别用户管理(大部分是用户自己决定开通与否);

3.平台使用子用户:是属于平台使用用户的子用户,业务功能和平台使用用户一样,但是具体的权限由所属使用账号决定;

2.2用户模块业务功能接口

 由于正常的项目流程是需要设计师出原型图+业务描述的,然后研发人员根据原型图和业务,设计功能对应的接口。

但是画图太麻烦了,所以就先将基础的功能接口描述出来啦!

(这里仅仅只作为接口的简单描述,具体的在后面再生成接口文档。正常来说研发人员会根据原型图考虑出大概的接口)

序号接口接口描述
1注册用户名、密码、手机号码等
登录用户名密码登录、手机号码登录
账号信息获取
账号信息修改
修改密码通过原密码
找回密码通过手机号码
菜单列表获取列表
菜单列表获取一条信息
菜单列表新增一个菜单,类型:目录、菜单、按钮,目录仅表示由下一级,菜单表示有页面,按钮表示页面里的按钮;
菜单列表修改
菜单列表删除
部门列表获取列表
部门列表获取一条信息
部门列表获取树形下拉列表,单选框
部门列表新增
部门列表修改
部门列表删除
角色列表获取列表
角色列表获取一条信息
角色列表(获取菜单树形下拉框,多选框)
角色列表新增
角色列表修改
角色列表删除
角色列表(获取部门树形下拉,多选框)
角色列表修改数据权限(全部、个人、自定义部门.etc)
角色列表获取角色下的成员列表
角色列表(获取不是某角色的成员列表)
角色列表

添加成员

角色列表删除成员
用户列表获取列表
用户列表获取一条信息
用户列表(获取角色下拉列表,单选框)
用户列表(获取部门树形下拉列表,单选框)
用户列表新增
用户列表修改
用户列表删除
用户列表重置密码

大概就有这些接口,我们先将基本的用户账号完成,再完成菜单、部门、角色,和最后的用户信息。

2.3用户模块接口详细设计

正常情况下前后端分离项目,开始研发前会先设计接口的详细设计,也就是接口的入参、出参、请求方式、接口名、头部信息等的设计,出参、入参一般是根据原型图中需要的信息提取出来的,状态值一般是由后端给出的。

由于我们没有原型图,所以只设计最基本的数据就行,例如账号里面可能会有邮箱啊、地址啊等信息,但是我们可以先不加仙剑能用到的加上,比如手机号码、用户名,这些必须的字段加上。后面的设计到可以补充,当然如果后面能用到的话,也可以一开始就加上。

接口详细文档不打算写表格了,太麻烦,我直接使用 Apipost工具来保存,同时用这个工具测试后端接口,这个还挺方便的,用Postman也可以,功能差不多,都能够保存接口属性并测试接口,然后还可以将接口文档分享出来。 

3.基础框架研发思路

开发项目时了解业务之后,先不着急下手,先确定是用什么工具,然后搭建一下基本架构。

本来想用springcloud搭建分布式的,但是因为初学还不熟悉而且笔记本跑三四个项目跑不起来(唉,该也该让他休息了...),所以还是用 springboot 单项目吧,后面再拆。

3.1基础框架思考

3.1.1技术选型

项目整体是按照若依框架—(一个超棒的框架,比较适合springboot的入门思考)的逻辑搭建的,那么目前我们使用的技术和若依框架的技术是相似的:

开发工具:IDEA ,VSCode,Mysql

1、系统环境

  • Java EE 8
  • Servlet 3.0
  • Apache Maven 3

2、主框架

  • Spring Boot 2.2.x
  • Spring Framework 5.2.x
  • Spring Security 5.2.x

3、持久层

  • Apache MyBatis 3.5.x
  • Hibernate Validation 6.0.x
  • Alibaba Druid 1.2.x

4、视图层

  • Vue 2.6.x
  • Axios 0.21.x
  • Element 2.15.x

3.1.2搭建框架思路

现在站在研发层面思考,先考虑,我们的开发项目需要业务模块清晰,也就是模块的代码要分开放置,这样后期我们如果要拆项目会更容易,也就是代码结构要按照模块可拆卸可装配的思路设计,那么我们可以大致分为:系统模块*1、业务模块*N。

系统模块只有一个,里面可以包含系统级别的,也就是所有模块都离不开的,例如账号信息、用户信息、日志信息等;

思考:日志信息为什么是系统模块里的呢?因为它是必须的嘛?

疑问:我感觉并不是,从代码逻辑来说,一个网站并不是必须要日志信息,但是,从网站建设层面来说,日志是必不可少的,因为会涉及到数据问题或不良操作追踪。所以一个系统往往会有添加日志信息,即便不会对用户公开,但也会保存操作等日志信息。

那么在系统模块中也更会用到日志信息来进行日志记录,所以日志信息可以归类到系统模块。当然也可以通过技术手段拆出去,但我目前没遇到过,所以不予置评,待补充

业务模块可以有多个,里面还包含了必要或不必要的业务,例如博客信息、商品信息、订单信息等;

那么我们的项目也按照这个逻辑来搭建,业务模块可以先不用考虑,后续直接建项目引入即可,先考虑系统模块。 

系统模块搭建也需要考虑几点,我们至少需要1.启动服务模块、2.核心框架模块、3.工具模块

如果不理解,可以先看后面的文件结构图!

我们从后面往前说,3.工具模块很简单,就是我们开发中常用到的工具类,例如字符串装换工具类、spring环境管理类,又或者通用常量信息类,又或者我们系统数据表的实体类(可能有业务模块会用到该实体类)等等,大致就是自己不会产生什么业务,只是给其余模块提供的类。

2.核心框架,可以理解为处理系统模块业务的类,例如security配置类、反射类,系统数据表的关联实体、持久层、业务层等;当然这里也能再进行细分。

1.启动服务模块,主要就是我们的 controller 接口和所有的系统级别配置文件application.yml

首先我们先不考虑业务模块,我们先将基础的用户账号登录、登出逻辑

既然,我们已经列好了文档结构,那么就开始写搭建框架啦!

搭建步骤:

  1. 创建对应的文件目录项目,此时 pom 文件只引入子包就可以;
  2. 引入依赖包,主要有springboot依赖包(这里面包含spring整合的context-support、security、web、aop、druid、mybatis、validation、pagehelper、redis),按照基础需要到的添加;
  3. 创建基础数据库,例如user表,这里一定要整理好数据存储思路,否则后面一旦有变动要修改数据库以及持久层代码和,很麻烦的;
  4. 工具、配置信息、基类、常量类的配置,例如 security 、 JWT、AjaxResult ;
  5. 持久层、业务层、表现层代码

3.2基础框架搭建

(在这里会先说明大致思路,再举例代码)

3.2.1创建基础项目

记录一下创建项目: 创建项目记录图 ,最终的目录结构完善成下图:

 3.2.2引入依赖

先从父项目开始,这里我要记录一下,springboot 的依赖引入有两个常用的方式,这两种方式是有些区别的:spring-boot-starter-parent 与 spring-boot-dependencies区别 ,starter 包是通过被继承引入的,dependencies 包是直接声明引入的,我们这里选择后者,(其实starter 包里面也是继承了 dependencies  包的,而 dependencies 内为我们统一管理依赖及版本号的)

具体的 pom 以来看代码

3.2.3数据库配置

我们当前先实现账号的基本登录、登出功能,然后后面加入附属信息角色、部门,系统菜单、权限配置等业务功能。

先实现账号登录登出,只需要用户表就可以,先考虑到用户表里面会不会与其他表有属性关联,用户表只与角色、部门有关,然后分析,用户与角色之间是多对多的(一个用户有多个角色,一个角色对应多个用户),用户与部门之间是多对一(一个用户对一个部门,一个部门有多个用户);

数据表构建时按照:

一对一:先考虑放到一张表里面,如有特殊情况,比如字段太多,可以创建外键,用父表主键id子表主键id关联;

例如:

(1).用户表(用户主键id,用户名,密码,用户住址,用户年龄)

(2).用户表(用户主键id,用户名,密码),用户详情(用户详情主键id,用户主键id,用户住址,用户年龄)

用户详情表里的用户主键id 只会对应一个 用户详情主键id ;

查询时,根据用户主键id查询用户详情;

一对多:创建外键,用父表主键id,子表主键id关联;如有特殊情况,比如不想改动一的数据表字段,也可以创建关联表,看下方多对多。

例如:

部门表(部门主键id,部门名称,部门编码)

用户表(用户主键id,部门主键id,用户名,密码)

用户表里的部门主键id 会对应多个 用户主键id ;

查询时根据部门主键id查询用户;

 多对多:创建关联表,关联两个表的主键id;

例如:

用户表(用户主键id,部门主键id,用户名,密码)

角色表(角色主键id,角色名称,角色编码)

用户_角色_关联表(主键id,用户主键id,角色主键id)

用户表、角色表不添加字段,新创建一个关联表,里面保存两张表的主键id;

查询时,join 关联表一起查询,【例如查询用户及角色时,from 用户表并且 left join 用户_角色_关联表 on 用户主键id = 用户主键id left join 角色表 on 角色主键id = 角色主键id】

所以用户表里面可以提前保存一个部门id,当然也可以不添加,后续创建部门时创建对应关联表也可以,一般来说能不创建就不创建,否则数据表会太多影响使用。

数据表如下,有些字段现阶段不会使用,如登录IP,性别等:

CREATE TABLE `sys_user` (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
  `user_name` varchar(30) NOT NULL COMMENT '用户账号',
  `nick_name` varchar(30) NOT NULL COMMENT '用户昵称',
  `user_type` varchar(2) DEFAULT '00' COMMENT '用户类型(00后台用户,01前台用户)',
  `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
  `phonenumber` varchar(11) DEFAULT '' COMMENT '手机号码',
  `sex` char(1) DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
  `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
  `password` varchar(100) DEFAULT '' COMMENT '密码',
  `status` char(1) DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)',
  `login_ip` varchar(128) DEFAULT '' COMMENT '最后登录IP',
  `login_date` datetime DEFAULT NULL COMMENT '最后登录时间',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8 COMMENT='用户信息表';

3.2.4基础配置

基础配置信息可以说是核心部分,在这里将会考虑到后端返回格式、controller或实体或异常基类、常量类、security配置等信息。

我们先将关联程度低的添加进去,例如后端返回格式、controller或实体或异常基类、常量类,先将基础的加进入,同时如果里面有用到工具类啥的,也就一并引入其相关依赖,(记得做好说明为啥引入依赖,哪里用到了,小心前面写后面忘),

基础的配置好后,就配置耦合度高的security ,这个相关的地方太多了,还可能会和controller啥的相关联,就按照实际使用一步步添加吧。


 3.2.5仅实现用户登录和token校验接口(未连接数据库)

 1.先将 common 模块的基本信息补充完整,下面的图片记录一下补充的类,具体的看代码:


2.准备 framework 模块的内容,为什么不先准备 system 模块呢?由于 system 模块主要是系统的mapper +service 操作,主要是系统模块的业务,所以我们可以最后再慢慢加。

现在主要解决登录业务的配置!

列一下大概需要什么配置:

  1. 首先是 security 配置类,里面要配置黑白名单、jwt过滤器、认证失败和无权限处理器、用户验证类、security加密类等啥的
  2. security框架的配置类又涉及到,我们可以实现 UserDetailsService 写一个自定义用户校验接口,其中会涉及到用户实体类等bean类;UserDetailsService 接口里面会使用到 mapper 文件操作数据库,我们可以先 new User 来代替;
  3. jwt过滤器,处理token数据并判断是否有效
  4. jwt过滤器里面涉及到token就需要添加 TokenService 类,具体方法有创建、更新、获取token等;
  5. tokenService 类既然生成 token ,就需要进行缓存保存token以及token对应的用户信息,否则我们通过请求对象获取到 token 后无法验证用户身份,这里我们可以用 spring-redis 来实现缓存,那么就需要配置 spring-redis ,为了方便使用可以创建一个 redis 操作的工具类
  6. 最后我们添加 controller 类,来验证一下登录业务!

大概就是这些,感觉不多,但是配置起来可头疼了!!! 

具体的包对应,以及相关报错、缺包啥的就记录一下:

1.security配置
	配置类:com.qingchen.framework.config.SecurityConfig
		里面主要涉及到:HttpSecurity、BCryptPasswordEncoder、AuthenticationManager、AuthenticationManagerBuilder ,具体看代码,已加好注释

2.登录用户的校验相关类
	用户校验类:com.qingchen.framework.web.service.UserDetailsServiceImpl  implements UserDetailsService 
	用户entity类:com.qingchen.common.core.domain.entity.SysUser extends BaseEntity 
	登录用户身份权限model类:com.qingchen.common.core.domain.model.LoginUser implements UserDetails {
		注意哦,我们这里实现 UserDetails 接口时,一定要给 getPassword() 、getUsername() 返回我们定义的值,否则在 AuthenticationProvider 里面校验密码时是会获取不到的哦
	用户登录model类:com.qingchen.common.core.domain.model.LoginBody
	
3.JWT过滤器
	过滤器类:com.qingchen.framework.security.filter.JwtAuthenticationTokenFilter   extends OncePerRequestFilter
		这里会使用到doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain),需要导入 javax.servlet-api.jar 包
		
4.token处理
	JWTtoken验证处理类:com.qingchen.framework.web.service.JwtTokenService
		注意,这里会用到  @Value 注解,会去 yml 文件中获取配置字段,注意要添加哦

5.springredis配置
	注意,这里需要到 yml 文件中配置 redis 链接信息,如果没有添加是不会报错的,但是如果代码使用了 RedisTemplate ,就会报 ConnectException 异常
	springredis工具类:com.qingchen.common.core.redis.SpringRedisCache
		这里可能会疑惑,为什么我们没有创建 RedisTemplate Bean 但是却能在这个类里面注入呢?因为 spring-boot-autoconfigure 包里面有个 spring.factories 文件里面会帮助我们自动创建一些 Bean ,哇塞!
	redis配置类:com.qingchen.framework.config.RedisConfig
		这里又会疑惑,已经有 RedisTemplate Bean 有为什么还要创建呢?原因在于redis转存获取会进行序列化,这也是为了对象能够跨平台存储查询,而实现这些就需要进行序列化;为了保证各个系统能够正确拿到数据,我们就需要统一序列化方式!
	FastJson序列化类:com.qingchen.common.utils.serializer.FastJson2JsonRedisSerializer
	
6.接口类
	登录接口类:com.qingchen.controller.system.SysLoginController
		可以在里面添加两个黑白名单接口,用来测试 jwttoken 拦截是否有效
	登录业务类:com.qingchen.framework.web.service.SysLoginService
		注意,这里直接用authenticationManager.authenticate(*)方法来校验用户信息

有几个注意点和提醒点:

1.如果启动时报下面的错误,说明咱们依赖了数据库相关包,但是并没有配置数据库链接的数据。

所以,要么:1.注释掉相关包,例如:mybatis-spring-boot-starter、druid-spring-boot-starter;

要么:2.在启动类中排除掉数据库连接的连接配置文件;要么:3.在 yml 配置文件中添加连接数据;

方法一好说直接去 common 模块 pom 包中注释掉;

方法二已经写在启动类里面了;

方法三在后面连接数据库中会写在 yml 中;  


***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

2.redis 一定要启动好,再启动程序

3.由于我们创建的时父子项目,所以记住启动类一定要在其他所有 bean 类包的上面级别,否则会扫描不到!!!(像现在的目录结构,启动类一定要在顶级!),比如现在启动类包就是 com.qingchen.QingChenApplication ,而其他的类都在 com.qingchen.common/system/framework 包下面,这样就会被扫描到了!

由于我之前将启动类放到了 com.qingchen.admin 下面,导致 security 配置未生效,瞎找了老半天呢!!! 

4.如果我们需要生成一个账号和密码,可以直接创建一个 main 主方法,用.encode("admin123")生成密码,可以见com.qingchen.BCryptPasswordEncoderUtil 类;

5.如果我们想要查看一下当前程序里面所有的 bean ,或者说想看一下某些bean有没有被创建,可以创建 CommandLineRunner 来查看,具体看:com.qingchen.config.TestRunBeanConfig

到目前为止代码可以看 Gitee 地址 注意是 project01 分支哦


下一篇,开始连接数据库,并且实现上述用户模块的基本功能接口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值