29 项目一 单体架构开发详细流程

项目一

DB

简介

电商旅游生态系统包含旅游电商系统(广告子系统,推荐子系统,评价子系统,商品子系统,订单子系统),旅游分销系统(分销商的管理),旅游业务系统(产品研发,计调服务,系统权限管理子系统)…这里只是把电商系统的大体都列一下,我只做一个系统… --系统权限管理子系统

环境搭建

1 初始化数据库

set names gbk;
source d:/djt.sql

说明:假如在mysql客户端查询表中数据,可以先执行set names gbk,否则可能会出现乱码。
2 IDE/STS配置初始化
统一工作区编码(UTF-8)
统一JDK版本(JDK1.8)
统一MAVEN配置(3.6.3)
3 快乐的时光开始了 --开始写项目代码~~

=正式代码开始
1 创建权限管理系统,springboot项目
2 添加依赖
Spring Web
Thymeleaf
Mybatis
JDBC API
MySQL Driver
Lombok
Spring Boot Actuator
3 修改配置文件application.yml
( server的port端口 , spring的datasource数据源及mvc的thymeleaf前后缀 , mybatis的mapper-locations映射文件位置 , log日志 )

#server
server:
  port: 8800
  servlet:
    context-path: /
#spring
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/dbsys?serverTimezone=GMT%2B8&characterEncoding=utf8
    username: root
    password: root
  thymeleaf:
    prefix: classpath:/templates/pages/
    suffix: .html
#mybatis
mybatis:
  configuration:
    default-statement-timeout: 30
    map-underscore-to-camel-case: true
  mapper-locations:
    - classpath:/mapper/*/*.xml
#log
logging:
  level:
    com.cy: debug

4 初始化首页 --前端不写直接导入项目中29 项目一 单体架构开发详细流程_第1张图片
5 创建controller --作为项目入口

模块一 日志模块

分析

本模块主要是实现对用户行为日志(例如谁在什么时间点执行了什么操作,访问了哪些方法,传递的什么参数,执行时长等)进行记录、查询、删除等操作
1 表设计语句: id,登录用户名,用户执行的操作,请求方法,请求参数,执行时长,ip地址,日志记录时间
2 基于用户需求,实现静态页面(html/css/js)
3 基本业务实现
@Controller @Service @Mapper
controller 调service 调接口dao 还可以映射到Mapper.xml中执行sql语句或者直接在dao中加注解执行sql语句(后面直接使用Mybatis-plus后dao继承BaseMapper单表查询的直接在service层中直接调用dao即可!!)

具体后端业务流程:

日志管理列表页面呈现

controller层根据用户请求url响应到html列表页面,展现列表页面(数据是空的)
编辑pojo类封装数据库查询的日志记录或操作中产生的日志记录( id,登录用户名,用户执行的操作,请求方法,请求参数,执行时长,ip地址,日志记录时间)
编辑dao接口
按条件查询记录总数
按条件(哪个用户)查询数据库,查询出当前页展示的日志记录的数据
//–当DAO中方法参数多于一个时尽量使用@Param(“username”)注解进行修饰并指定名字,然后在Mapper文件中便可以通过#{username}方式进行获取
编辑Mapper文件
对应dao接口对数据库执行操作

username like concat("%",#{username},"%")

编辑Service接口及实现类
接收controller层数据,基于用户名进行总记录数的查询并校验,再基于页面上需要展示的当前页码分页页面大小进行当前页记录的查询,查询出日志数据封装为List集合再将封装了日志记录的list集合及数据总数和页码信息封装为vo对象(页面对象)返回给controller层
编辑ServiceException自定义异常处理类
继承RuntimeException异常类super()传参并构造方法创建抛出异常对象ServiceException自定义异常类对象,实际是创建的RuntimeException父类对象,只是名字是自定义异常类,方便清楚知道是哪一个类出了异常,便于后期维护
编辑vo对象类
序列化实现Serializable接口,基于此对象封装控制层响应结果(添加状态码及状态信息,封装数据对象)
编辑Controller类
@RequestMapping定义此类及方法映射路径,DI注入service层对象,调用service执行业务方法
编辑全局异常处理类
主要针对控制层出现的异常问题统一处理
添加@ControllerAdvice修饰类,方法上添加@ExceptionHandler(RuntimeException.class)指明拦截异常类型,传参(RuntimeException e)将异常类型传入后返回JsonResult(e)封装异常数据对象即可

日志删除操作

dao层mapper接口
编写删除操作的方法
(@Param(“ids”)Integer… ids)
Mapper映射文件
编写对应的sql语句执行删除操作
sql可靠性优化,添加if判断标签判断传参数据是否为空
service层
编写删除日志的方法,实现类调用dao层执行(一般每次都要首先判断传来的参数合法性是否为空)
if( ids == null || ids.length == 0 )
并对调用dao的方法后执行结果判断是否为0等
返回结果即可
controller层
接收客户端提交的参数,调用service层执行删除业务,响应给客户端JsonResult结果即可

日志添加操作

dao层接口
编写插入日志记录到数据库的方法(日志记录封装为最开始定义的日志对象)
Mapper映射文件
编写插入数据库的sql语句
service层
将日志切面中抓取到的用户行为日志信息保存到数据库
编写保存将日志记录(pojo对象)插入数据库中的方法调用dao执行保存日志的方法
并且在启动类上添加@EnableAsync 开启异步功能,插入日志的方法上添加@Async异步注解,开启异步线程,提高服务器性能
日志切面Aspect类AOP编程
抓取用户行为日志信息,封装到日志对象,传递给业务层
使用@annotation()注解实现AOP
@Around(" ")方法中首先获取目标方法对象的类型point.getTarget().getClass()及其名字.getName(),再获取方法签名对象(MethodSignature)point.getSignature(),通过方法签名对象获取方法名字.getMethod().getName()及方法上的参数类型.getMethod().getParameterTypes()
通过目标方法对象的类型获取目标方法对象,传入参数为(目标方法的名字及目标方法上的参数类型),通过目标方法对象获取方法上的注解里的值.getDeclaredAnnotation(RequiredLog.class).value() --RequiredLog是自己定义的添加为日志记录的注解
通过Shiro安全管理框架提供的SecurityUtils工具类调用API方法,获取用户名(指明封装数据的对象类型,强转) --(SysUser) SecurityUtils.getSubject().getPrincipal().getUsername(),再获取目标方法上的参数point.getArgs(),通过ObjectMapper对象将获得的参数对象转化为Json对象 --String params=new ObjectMapper().writeValueAsString(paramsObj)
最后封装为日志对象 SysLog log=new SysLog();
通过setXxx(…)方法将用户名,目标方法上的注解里的参数值,目标方法(目标方法的类型的名字.目标方法的名字),转化为Json串的目标方法上的参数对象,登录用户的ip地址(通过获取IP地址的工具类获取的),操作时间(登录执行目标方法前及执行目标方法后的时间差),日志记录时间(new Date()).全部存入日志对象中
最后再调用service层的保存日志的方法将日志插入到数据库中!!
IP地址获取的工具类(直接拿来用即可)

public class IPUtils {
        private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
public static String getIpAddr() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = null;
  try {
		ip = request.getHeader("x-forwarded-for");
		if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("Proxy-Client-IP");
	}
	if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("WL-Proxy-Client-IP");
	}
	if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("HTTP_CLIENT_IP");
	}
	if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("HTTP_X_FORWARDED_FOR");
	}
	if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getRemoteAddr();
	}
  } catch (Exception e) {
		logger.error("IPUtils ERROR ", e);
  }
	return ip;
  }
}

模块二 菜单模块

分析

菜单管理又称为资源管理,本模块主要是实现对菜单进行添加、修改、查询、删除等操作
菜单数据库表字段
资源名称,资源url,类型(菜单/按钮),排序,备注,父菜单一级菜单为0,授权标识,创建时间,修改时间,创建用户,修改用户,资源管理
菜单表与角色表是多对多的关系,角色和菜单对应的关系数据要存储到关系表中
角色id,菜单id
29 项目一 单体架构开发详细流程_第2张图片

具体业务流程

controller层
接收url请求展示菜单页面

菜单管理列表页面呈现

使用树结构,本次借助jQuery中的treeGrid插件实现(下载并引入相应的js)
dao层mapper接口
编写查询出所有菜单的的方法(List>集合)
一行记录映射为一个map对象,多行存储到list
Mapper映射文件
编写对应mapper文件查询方法的sql语句(自关联查询)
service层
编写查询菜单方法,调用dao执行查询方法
controller层
接收url请求返回响应结果

菜单管理删除

基于用户在列表页面上选择的菜单记录id,执行删除操作,并且判断当前菜单是否有子菜单,若有则不允许删除,没有则先删除菜单角色关系数据,再删除菜单自身信息
dao接口
角色菜单dao
基于id删除关系数据
菜单dao
基于菜单id查询子菜单个数的方法 --是0则删除,有则不删除
再基于菜单id删除菜单记录
Mapper映射文件
对应dao层分别编写mapper文件及对应的方法

select count(*) from sys_menus where parentId=#{id} //查询子菜单的个数

service层
编写执行删除菜单的方法,首先通过控制层传递的菜单id(校验是否为空)。然后基于菜单id 调用dao层执行统计子菜单个数方法,假如有子菜单则抛出异常,提示不允许删除。假如没有子菜单,则调用dao层执行先删除角色菜单关系数据。最后再调用dao层执行删除菜单自身记录信息后并返回业务执行结果
controller层
接收url请求调用service层执行删除菜单的方法

添加菜单业务

首先查询出上级菜单
定义封装查询到的上级菜单id,name,parentId的pojo类
dao层
定义查询上级菜单信息(id,name,parentId)的方法
mapper映射文件
对应dao层方法编写查询上级菜单信息的sql语句
service层
调dao层执行查询方法
controller层
接收用户请求,调用service层执行查询上级菜单的方法
执行菜单数据添加业务
客户端添加好数据之后,提交到服务端
定义菜单实体类SysMenu封装客户端传来的菜单信息或查询数据库菜单表封装查询出的数据
字段:菜单名称,菜单url,菜单类型,排序,备注,上级菜单,菜单对应的权限标识,创建用户,修改用户
创建时间,修改时间 --实体类都要写set和get方法并且貌似vo对象还需要写构造方法
dao层接口
定义将新增菜单pojo对象插入数据库的方法
mapper映射文件
编写对应dao接口方法的插入菜单数据的sql语句
service层
基于控制层传来参数(判断是否为null)调用dao层执行插入数据库数据的方法
controller层
接收客户端传来参数pojo菜单数据对象,调用service层执行插入方法
返回响应信息即可return new JsonResult(“save ok”);

修改菜单数据

dao层接口
添加更新修改菜单的方法,传参为菜单pojo实体类
mapper映射文件
基于dao层更新修改菜单的方法编写sql语句
service层
定义更新菜单的方法根据controller层传来的pojo菜单实体对象(验证对象是否为null),调用dao层执行更新菜单的方法
controller层
接收客户端传来修改菜单pojo实体类对象,调用service层执行修改业务

模块三 角色模块

本模块主要实现的是企业内部角色(岗位)的管理,可以在添加角色时,为角色分配菜单(资源)访问权限,最后将角色再分配给用户,这样用户就具有了对应角色可以访问哪些菜单的权限
表设计:
角色表
字段:
角色id,角色名称,备注,创建时间,修改时间,创建用户,修改用户
角色与菜单关系表
字段:
id,角色id,菜单id
角色与用户关系表
字段:
id,用户id,角色id

具体业务流程

controller层
基于url请求,响应角色列表页面

角色管理的列表的 页面展示

pojo实体类
封装数据库查询出的角色信息及其他与数据库交互的信息
dao层接口
1 定义根据用户名 查询数据库其对应角色信息总记录数的方法–mapper文件中if标签判断搜索框中name是否为空,为空直接查询出了所有角色信息展示,不为空就根据name模糊查询即可,上面有一个按名字搜索框,会根据模糊查询名字查询出角色数据及其记录总数,查询出总记录数是为了分页展示时用的
2 定义根据用户名 当前页码值 页面大小查询数据库角色信息的方法
当DAO中方法参数多于一个或参数应用在动态SQL中时尽量使用@Param注解进行修饰并指定名字,然后再Mapper文件中便可以通过类似#{username}方式进行获取
Mapper映射文件
角色mapper映射文件中
定义查询出总记录数的sql语句
定义根据搜索框输入的名字模糊查询(这里加where标签和if标签,若搜索框有名字则执行模糊查询,若没有则不执行模糊查询,就是查询出全部的角色信息)根据创建时间排序,分页展示查询出角色信息
Service接口
定义根据controller层传来参数用户名和当前页码值,查询角色信息的方法(对参数校验),调用dao执行查询总记录数的方法,根据当前页码值及总记录数计算出当前页应展示的角色信息的起始位置(startIndex=(pageCurrent-1)*pageSize),这里pageSize自己定义或根据页面传来的参数pageSize定义都行,再调用dao传参 模糊查询的用户名,页面展示的起始位置(哪一条),页面大小 执行查询角色信息展示即可
返回给controller层页面对象封装了 (当前页码值,页面大小,总记录数,封装了角色信息的list集合) 即可
Controller层
接收url请求及参数模糊查询用的用户名,当前页码值,调用service层执行查询方法即可,接收到service层返回的页面对象,封装进JsonResult对象中添加状态信息即可!!

角色管理删除业务 --先删除关系数据

角色菜单dao层
定义根据角色id删除角色菜单关系数据的方法
角色菜单mapper文件
定义根据角色id删除角色菜单关系数据的sql语句
角色用户dao层
定义根据角色id删除角色用户关系数据的方法
角色用户mapper文件
定义根据角色id删除角色用户关系数据的sql语句
角色dao层
定义根据角色id删除角色信息的方法
角色mapper文件
定义根据角色id删除角色信息的sql语句

service层 --一个即可 业务里面调用三个dao分别执行删除方法即可
定义根据角色id删除角色信息的方法(校验参数),调用三个dao分别执行删除方法即可
controller层
根据url请求及参数id调用service层删除角色信息后,返回JsonResult一个响应信息即可

角色添加业务 --js中引入zTree树状展示

角色dao层
定义根据传来的角色实体对象,插入数据库的方法
角色菜单dao层
定义根据传来参数角色id及对应的菜单ids插入数据库的方法
角色Mapper文件
定义插入新增角色的sql语句insert标签里面并指定使用生成的key及key属性(useGeneratedKeys=“true” keyProperty=“id”),这样在不使用mybatis-plus情况下可以在刚插入数据库的信息上直接获取到主键id值
角色菜单Mapper文件
定义插入的角色id及对应的菜单id关系数据(foreach循环标签一个个菜单id取出存入即可)
service层
接收controller层传来角色实体类及对应菜单ids 保存角色信息保存角色和菜单对应数据关系的信息的方法 --一个方法里面分别调用多个dao执行插入方法即可(参数校验)
controller层
接收url请求及传来角色实体类及对应菜单ids调用service层执行保存插入数据的方法
返回JsonResult的响应信息的方法

角色修改业务

定义vo对象封装从数据库查询到的角色菜单记录,方便操作 --单独将角色表中的id,name,note字段取出跟对应菜单ids封装到一个实体类中,方便后续操作
字段:
角色id,角色名称name,角色备注note,菜单ids
dao层
定义根据角色id查询角色信息的方法
Mapper文件
对应dao层根据角色id查询角色信息(id,name,note,menu_id)的方法 –resultMap属性sql语句中的用法

 <!--方案一:  从当前表中基于查询角色id查询角色表自身信息及角色菜单表的对应的菜单ids的信息(-多表关联查询) --多表关联查询就是在一个mapper文件中一条sql中直接查询出两张表中需要的信息即可-->
  <!-- collection一般应用于one2many查询 -->
   <resultMap type="com.cy.pj.sys.pojo.SysRoleMenuVo"  id="sysRoleMenu">
          <id property="id" column="id"/>
          <result property="name" column="name"/> 
          <result property="note" column="note"/> 
          <collection property="menuIds" ofType="integer"> 
                      <result column="menu_id"/>
          </collection>
   </resultMap>
   <select id="findById" 
           resultMap="sysRoleMenu">
           select r.id,r.name,r.note,rm.menu_id
           from sys_roles r left join sys_role_menus rm
           on r.id=rm.role_id
           where r.id=#{id}
   </select>
   
//==================================  二选一用

 <!--方案二:  从当前表中只基于查询角色id查询角色表自身信息(单表查询)但是在resultMap中额外添加查询对应菜单ids的字段查询(对应到角色菜单dao查询菜单ids的方法)  单表查询就在两个mapper文件中分别查询出需要的数据的操作-->
 <select id="findObjectById"  resultMap="sysRoleMenuVo">
     select  id,name,note   from sys_roles   where id=#{id}        
 </select>
 
 <resultMap type="com.cy.pj.sys.vo.SysRoleMenuVo"  id="sysRoleMenuVo">
     <id property="id" column="id"/>
     <collection property="menuIds"  select="com.cy.pj.sys.dao.SysRoleMenuDao.findMenuIdsByRoleId"  column="id">
	 </collection>
 </resultMap> 
 //=====注意以下这个sql是针对方案二的 在角色菜单mapper文件中的  根据角色id查询对应的菜单ids  column="id"貌似应该为column="menu_id"
  <select id="findMenuIdsByRoleId"  resultType="int">
	   select menu_id  from sys_role_menus  where role_id=#{id}
  </select>

service层
基于controller层传来的角色id查询出需要的 角色id,角色名称,角色备注,对应的菜单ids 的方法(参数校验) ,调用dao执行查询方法即可 --这里用的mapper中的方案一(若要用方案二需要再调用角色菜单dao查询出对应的菜单ids即可)第一种
controller层
接收url请求及参数角色id,调用service层执行查询方法 --这里只是查询出对应角色id的角色信息(包含角色对应的菜单ids)
===下面才真正的角色数据更新业务
dao层
根据传来的角色实体信息,执行更新的方法
mapper文件
对应dao层编写更新角色信息的sql语句
service层
根据控制层传来参数角色实体类及对应的菜单ids更新角色信息 的方法(验证参数)
调用角色dao执行根据传来角色实体对象,更新角色数据的方法
调用角色菜单dao执行根据角色id删除原先的角色菜单对应关系数据
调用角色菜单dao执行插入新的角色id菜单ids对应关系数据
controller层
接收请求传来的更新角色信息的实体对象及其对应的菜单ids,调用service层执行更新数据操作
返回JsonResult的响应信息即可

小结重点:
角色数据的删除时一定先删除对应的关系数据
一对多数据的保存?(保存角色的同时也要保存角色和菜单的关系数据)
一对多数据的查询映射?(基于角色id查询角色信息并将对应的菜单信息也查询出来)

模块四 用户管理模块

本模块主要是实现对用户信息的管理,包括用户查询,保存,更新(对应部门用户手机号的等用户信息),禁用启用操作
使用shiro框架对用户登录进行认证,对用户操作权限进行控制(在需要权限操作的方法上添加注解@RequiresPermissions(“sys:log:delete”)并指定权限标识,从而用户在在执行该方法时shiro框架的授权管理器会对该用户是否具有操作该方法的权限进行判断(Realm类中重写了授权方法,获取当前用户的对应角色对应菜单上的授权范围交给SecurityManager管理器中的授权管理器比对判断是否有授权))
创建用户表
字段:
id,用户名,密码,盐值,邮箱,手机号,禁用启用状态,对应部门id,创建时间,修改时间,创建用户,修改用户
创建用户与角色关系表
字段:
id,用户id,角色id
controller层
定义接收请求展示用户管理页面的方法

用户管理列表数据的展现

pojo实体类vo --貌似应该时bo
构建值对象封装从数据库查到的用户及用户对应的部门信息,一行记录映射为一个对象
属性有:
用户id,用户姓名,密码,盐值,邮箱,手机号,禁用启用状态值,部门信息对象sysDept,创建时间,修改时间,创建用户,修改用户
dao层
根据模糊查询用户名 (搜索框里的内容,为空则查询全部用户的信息) 查询用户记录总数
定义根据传来参数用户名,起始位置,页面大小查询当前页面要展示的记录数据
mapper文件
对应dao中的方法,编写sql语句
查询总记录数
根据创建时间排序,分页查询本次应展示的数据 数据库表中字段为deptId,本次需要查询的是dept部门信息对象(部门名字) 所以用resultMap来映射新的对应关系,展示在页面上

 <select id="findPageObjects" resultMap="sysUserDeptVo">
	select * from sys_users
	<where>
	    <if test="username!=null and username!=''">
		    username like concat("%",#{username},"%")
	    </if>
	</where>
		order by createdTime desc  limit #{startIndex},#{pageSize}
 </select>
 
  <resultMap type="com.cy.pj.sys.vo.SysUserDeptVo"  id="sysUserDeptVo">
  <!-- 一般应用于many2one或one2one做关联查询在当前应用是基于deptId查询部门信息并将其存储到SysUserDeptVo对象的sysDept属性中。-->
		<association property="sysDept"  column="deptId"  select="com.cy.pj.sys.dao.SysDeptDao.findById">
 		</association> 
  </resultMap>

注:
resultMap用户进行自定义结果映射。
association 元素用于定义关联数据的查询。
service层
定义接收controller传来的用户名及当前页码值,查询用户数据的方法(校验参数)
调用dao根据用户名(搜索框输入的模糊查询用户名)执行查询总记录数的方法
自己设置页面大小或从前端传来页面大小,并计算出当前页面数据的起始位置(int startIndex=(pageCurrent-1)*pageSize;)
调用dao传参用户名,当前页面起始位置,页面大小执行查询当前页应展示用户数据信息
返回封装了 (当前页码值,页面大小,总记录数,封装了用户信息的list集合) 的页面对象给controller
controller层
接收url请求及参数用户名(模糊查询用的)及当前页码值,调用service层执行查询方法
返回封装了页面对象并添加了状态信息后的JsonResult对象

用户管理禁用启用操作

基于用户在列表页面上选择的的用户记录ID,执行禁用或启用操作,后续业务中被禁用的用户不允许登陆系统
dao层
定义 基于service层传来参数用户id,当前禁用启用状态数据,修改用户执行修改禁用启用的状态 的方法
Mapper文件
对应用户dao方法,基于选中的要修改的用户的id 编写修改update更新该用户的状态信息的sql语句
service层
定义接收controller层传来的用户id及对应的状态信息,修改该用户的状态信息的方法(参数验证)
调用dao执行修改状态信息的方法
返回结果即可
controller层
接收请求传来参数 选中要修改的用户的id,状态信息 调用service层执行修改状态信息的方法
返回JsonResult信息结果即可

用户添加业务

定义vo实体类 --一般vo类就不单独创建数据库表了,只是根据已有的数据库表查询出数据封装使用即可
封装用户角色信息
封装用户对应的角色id,角色名信息
属性:
角色id,角色名称
dao层
定义查询角色id,角色name (vo实体对象) 的方法
mapper文件
对应dao层编写查询角色表查询这两个字段的sql语句即可
service层
定义查询角色id及角色name的方法
调用dao执行查询方法即可
controller层 --这就是数据回显,方便后面的修改更新的操作
定义查询方法,调用service层执行查询角色id,角色name的方法
返回给客户端封装了查询到数据的数据对象(前面定义的vo对象的list集合对象)及状态码信息的JsonResult对象

添加用户数据业务

pojo类 --对应数据库表
属性:
用户id,用户姓名,密码,盐值,邮箱,电话,状态信息(禁用启用),对应的部门id,创建时间,修改时间,创建用户,修改用户
用户dao层
定义接收service层传来的用户实体对象,插入数据库的方法
用户角色dao层
定义根据传参用户id,对应的角色ids,插入用户角色关系表中的方法
用户mapper文件
对应dao插入数据库的方法编写sql语句,并在insert标签中指明使用生成的key及key属性为id ( useGeneratedKeys=“true” keyProperty=“id” )
用户角色mapper文件
对应dao编写插入用户id及与其对应的角色ids的sql语句
service层
定义接收controller层传来用户实体对象参数,对应角色ids参数的保存信息的方法(参数校验)
通过用户实体对象获取用户输入的密码
UUID生成盐值 (UUID.randomUUID().toString()
创建使用Shiro安全框架的SimpleHash这个简单hash对象对用户输入的密码进行加密,传入参数(“MD5”,用户输入密码,盐值,加密次数)
SimpleHash sh=new SimpleHash(“MD5”,passward,salt,1);
将盐值及新生成的加密密码(sh.thHex()转化为16进制字符串存储),set设置进用户实体对象中
调用用户dao执行插入数据库的方法
调用用户角色dao执行插入用户id与对应的角色ids关系数据的数据库中
返回结果即可
注:使用SimpleHash时必须注入shiro安全框架的依赖 --这里仅仅只是用shiro中的一个对象,没有使用认证和授权,所以这里加密时只添加shiro框架依赖即可!!!
controller层
定义接收请求传参用户注册的实体对象,对应的角色ids,保存数据的方法
调用service层执行保存数据的方法
返回JsonResult响应信息即可

用户数据修改业务 (发现了吧 ~~ 修改业务一般都先查询数据回显到修改页面上,方便后面的修改业务的执行 ~ 哈哈哈)

用户dao层
定义基于用户id查询用户相关信息的方法
用户角色dao层
定义基于用户id查询角色ids的方法
用户mapper文件
对应dao编写基于用户id查询用户信息的方法
用户角色mapper文件
对应dao基于用户id查询对应角色ids的方法
service层
定义基于controller层传来参数用户id 查询用户信息及用户对应的角色信息 返回值封装到Map集合…的方法(校验参数)
调用用户dao基于用户id执行查询用户信息的方法,返回值用户信息的实体对象
调用用户角色dao 基于用户id查询用户对应角色ids的方法,返回值List < Integer >
创建Map集合封装用户对象数据及对应的菜单ids数据(创建map对象后put插入数据即可)
Map map=new HashMap<>();
map.put(“user”, user);
map.put(“roleIds”, roleIds);
return map;
返回map对象即可
controller层
定义接收请求及参数用户id,查询用户信息及对应的菜单ids的方法
调用service层执行查询方法,因为service层返回值时map对象,所以这里用map对象接收
返回值封装了map对象的JsonResult对象

====真正的用户数据更新业务
用户dao层
定义基于service层传来的用户信息实体对象,更新用户信息的方法
用户角色dao层
定义基于用户id删除关系数据的方法
用户mapper文件
对应dao编写基于用户id修改update更新用户信息的sql语句
用户角色mapper文件
定义基于用户id删除关系数据的sql语句
service层
定义接收controller层传来的用户实体对象及对应的菜单ids参数更新用户信息的方法(参数校验)
调用用户dao执行更新用户信息的方法
调用用户角色dao基于用户id删除关系数据
调用用户角色dao基于用户id及ui应的菜单ids插入新增关系数据
返回结果
controller层
定义接收请求及参数用户实体对象及对应的菜单ids的方法
调用service层执行更新用户信息及用户角色关系信息方法
返回JsonResult的响应信息即可

修改密码业务实现

dao层
定义基于service层传来参数用户id 修改 盐值,用户密码,更新密码的方法
mapper文件
对应dao编写基于用户id修改update更新用户盐值及密码的方法
service层
定义接收controller层传来参数 原密码,新密码,确认密码 修改密码的方法(参数校验)
通过shiro框架的SecurityUtils安全工具对象调用getSubject()方法获得主体对象调用getPrincipal()获得用户实体对象(强转User即可)
调用shiro的SimpleHash简单hash对象对新的参数加密(“MD5”,本次修改密码输入的原密码,数据库中盐值,加密次数) --可通过获得的用户实体对象的get方法获得
通过用户实体对象get获取数据库中原用户的密码与本次用户输入的原密码加密后的16进制字符串比较是否相等
正确则执行更新密码操作
生成新的盐值
对新密码进行加密 后 转为16进制字符串
调用用户dao基于用户id更新新密码的方法来更新密码,盐值
返回结果即可!!
controller层
定义接收请求及参数 原密码,新密码,确认密码的方法
调用service层执行更新密码操作
返回JsonResult的响应信息即可

小结:
一对多数据的保存 (保存用户信息,保存用户和角色的关系数据)
多对一数据的查询映射 (查询用户时查询用户对应的部门信息)。
用户密码的加密实现 (spring框架提供的DigestUtils工具类调用md5DigestAsHex()方法或shiro框架提供的SimpleHash对象对用户密码进行MD5盐值加密)

//通过DigestUtils这个工具类对象的API   md5DigestAsHex(password.getBytes()); //将密码转化为byte数组后通过该API将数组转化为16进制的加密字符串!!
String newPassword = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());

//或者使用shiro框架的SimpliHash对象
SimpleHash sh=new SimpleHash("MD5",passward,salt,1);
String newPassword = sh.toHex();

你可能感兴趣的:(java,项目开发,java)