项目中的实现流程图

本文详细介绍了Web应用中的用户登录、密码修改、退出功能的实现,包括后端服务、控制器和前端交互的逻辑。此外,还涉及全局异常处理、非法请求拦截、记住我功能、营销管理模块的多个子功能,如数据加载、添加、编辑、删除等操作。文章强调了数据安全、状态管理以及前后端交互的重要性,并提供了相关的代码示例和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本信息模块

一、基本信息模块------用户登录

在这里插入图片描述
后端
service层
1.用户名 非空
2.密码 非空
3.根据UserId获取User信息
4.根据User信息,判断用户名是否存在
5.将密码使用MD5加密,并与User用户中密码对比
6.返回User用户信息
controller层
1.需要返回ResultInfo对象需要有:
Object属性
code状态码
msg信息
2.需要前端给传进来的userName,passWord参数
3.调用service中验证用户信息方法
前端
若后端没有将用户存储到cookie中,则前端需要在收到code状态码为200时,将结果中的User用户数据写入cookie中,并跳转到main页面。如下:
在这里插入图片描述
小知识:前端在保存UserId时存储时,若是没有加密的UserId值会不安全。所以可以在后端查找到User用户时,将数据传递给前端之前将Id值进行Base64加密,同时若在其他情况使用cookie中UserId时,先使用Base64解密再查找User用户。
mian页面—用户登录状态实现
小知识1:内部跳转若使用转发时,转发可以用作用域传递数据。
小知识2:request作用域的特点是一次请求。当用户登录成功时,会进入main页面。而main页面有很多菜单,这些菜单一点击就会做页面跳转,页面一跳转这个信息就失效了。
小知识3:session作用域,session作用域的数据不会因为页面跳转而失效。可通过(HttpSession session)或者(HttpServletRequest request)来获取。
设置session的两种方式:
(1)session.setAttribute(“user”,user);
(2)request.getSession().setAttribute(“user”,user);

二、基础信息模块------修改密码

在这里插入图片描述
后端
service层
1.原密码 非空
2.新密码 非空
3.确认密码 非空
4.根据UserId获取User信息
5.原密码使用MD5加密后,与User用户中密码对比
6.判断新密码与确认密码是否一致
7.将新密码通过MD5加密后保存用户对象
8.根据用户ID更新用户对象数据
controller层
1.返回ReauestInfo对象
2.参数中需要(HttpServletRequest request,String userName,String password,String confirmPassword)
这里需要使用request来作用域把用户ID拿出来给Service调用
3.使用Service调用
前端
根据后端返回的Result对象来判断code状态码,若code状态码为200,则清空用户cookie,在清除时需要指定domain的作用域及项目根路径
在这里插入图片描述
上图修需要修改为在父页面进行跳转
在这里插入图片描述

三、退出功能实现

点击“退出按钮”时,前端清除cookie信息,并跳转父窗口跳转到登录页面即可。
在这里插入图片描述

四、全局异常处理

第一种:基于@ControllerAdvice注解的Controller层的全局异常统一处理
全局异常同处理统一
第二种:基于AOP也可以实现异常的全局处理

/**
 * @Author: gmy
 * @Description: 基于AOP的全局异常统一处理
 * @Date: 2018/6/1
 * @Time: 13:46
 */
@Component
@Aspect
public class ExceptionAspectController {
    public static final Logger logger = LoggerFactory.getLogger(ExceptionAspectController.class);
 
    @Pointcut("execution(* com.test.test.*.*(..))")//此处基于自身项目的路径做具体的设置
    public void pointCut(){}
 
    @Around("pointCut()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        Stopwatch stopwatch = Stopwatch.createStarted();
 
        APIResponse<?> apiResponse;
        try {
            logger.info("执行Controller开始: " + pjp.getSignature() + " 参数:" + Lists.newArrayList(pjp.getArgs()).toString());
            apiResponse = (APIResponse<?>) pjp.proceed(pjp.getArgs());
            logger.info("执行Controller结束: " + pjp.getSignature() + ", 返回值:" + apiResponse.toString());
            logger.info("耗时:" + stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) + "(毫秒).");
        } catch (Throwable throwable) {
            apiResponse = handlerException(pjp, throwable);
        }
 
        return apiResponse;
    }
 
    private APIResponse<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
        APIResponse<?> apiResponse = null;
        if(e.getClass().isAssignableFrom(MessageCenterException.class) ){
            MessageCenterException messageCenterException = (MessageCenterException)e;
            logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + messageCenterException.getException().getMessage() + "}", e);
            apiResponse = messageCenterException.getApiResponse();
        } else if (e instanceof RuntimeException) {
            logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
            apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
        } else {
            logger.error("异常{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
            apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
        }
 
        return apiResponse;
    }
}

Springboot项目全局异常统一处理(例子参考)
Springboot项目全局异常统一处理

五、非法请求拦截

非法请求拦截

六、记住我功能

1.判断前端状态码code是否为200。
2.判断rememberMe是否为checked状态。
3.为checked状态,将用户信息保存到cookie中并设置失效时间。
4.不为checked状态,用户信息保存到cookie中即可。

在这里插入图片描述

七、营销管理模块

在这里插入图片描述
营销管理计划表 和 客户开发计划表 关联关系
在这里插入图片描述
营销管理计划表-----加载数据表格
分析:展示为列表,并分页
service层
1.根据前端需要的数据格式进行返回数据,这里使用Map<String,Object>的返回数据。
2.查询数据库,将营销管理计划数据查找出来
3.由于字段assign_man使用的是逻辑关联,该字段绑定的是分配人的id值。所以在查询表中数据时需要将该字段信息转换为分配人的名字才行。
此时需要两张表做关联进行查询。表关联查询的全部字段要和实体类bean中需要的字段一致。此时若实体bean缺少的字段可以自行添加。
4.做到关联表中查询字段数据要和实体bean一致
5.将前端需要的数据进行封装并放入map中
controller层
1.定义返回结果对象
2.调用service返回数据
3.将数据返回给前端
营销管理计划表-----添加数据
在这里插入图片描述

思路:
1.点击“添加”按钮,触发事件跳转到添加页面
2.在添加页面中点击“确认”按钮,则将表中数据保存至数据库
后端
service层
1.参数非空校验 。客户名称,联系人,联系号码非空
2.设置相关参数的默认值
创建人 当前登录用户名
指派人
如果没有设置指派人state(0=未分配(默认),1=已分配)
如果设置了指派人state 1=已分配
指派时间 设置为null
开发状态 (0=未开发(默认),1=开发中,2=开发成功,3=开发失败)
是否有效 (0=无效,1=有效)
创建时间 默认当前时间
更新时间 默认当前时间
3.执行添加操作,判断受影响行数
controller层
1.设置返回参数类型
2.参数设置(若有需要用户ID,可以从HttpServletRequest request中获取进行传递)
3.调用service层数据
前端:
判断后端传递数据的状态码若为200,则保存成功。保存成功后需要重新加载数据进行展示。
在这里插入图片描述

八、营销管理模块-----指派人

在这里插入图片描述
关于点击编辑,指派人没有显示问题处理。
需求: 在点击编辑页面时把指派人信息也从数据库中查询出来。
分析: 当点击编辑页面时通过ajax请求查询指派人数据库信息,并把数据设置成下拉框需要的格式添加到指定下拉框的ID中。如下:
在这里插入图片描述
分析: User表 和 Role表 有一个中间表,该中间表为 User_Role表,我们需要找出两张表关联的用户为“销售”的人的“ID”和“名字”,返回给前端使用。查询语句如下:
在这里插入图片描述

service层
1.根据UserRole表查找User表和Role表相关联的职业为“销售”的“ID”和“名字”的数据给前端
2.将数据返回
controller层
1.设置返回数据类型
2.调用service层并返回数据

九、营销管理模块-----修改时指派人回显

在这里插入图片描述

需求:当点击编辑时,若数据库中指派人不为空则要回显指派人信息
思路:当点击编辑时,通过ajax请求找到指定ID对应的营销机会客户信息(该ID在input隐藏于中可以获取)。得到的客户信息中会有一个指派人的id数字。可以通过指派人的id数字将指派人的标签设置selected选中状态即可。如下:在这里插入图片描述
总结:当点击“编辑”时,通过该营销客户的ID进行查找营销客户信息并显示form表单中。但是form表单中需要有一个指派人信息,我们查找的营销客户信息中存在的指派人是以数字绑定的信息,而我们需要的是一个指派人名字。
此时需要在点击“编辑”时,通过ajax请求进行查找营销客户之外,还需要通过ajax请求查找指派人对应的指派人名称并显示出来,该指派人信息需要User表、Role表和中间表UserRole表进行关联查询,查询出角色为“销售”人员的“名字”和“ID”。
在下拉框选项中需要通过指派人的“ID”和“名字”进行显示即可。
点击“编辑”时,需要显示选中的指派人如何实现?
点击“编辑”时,需要通过隐藏域中的营销客户ID来查找客户信息,可以客户信息中仅仅存在指派人对应的id数字,我们需要的是该id数字对应的名字是selected选中状态。所以可以通过遍历时进行比较,如果指派人对应的id数字与查询出来的指派人id相同则将其设置为selected选中状态即可。
关于“添加”和“编辑”页面显示几乎一致,前端该如何处理?
对于“添加”按钮,直接点击即跳转至添加页面中,填写数据即可。对于编辑,则需要加载响应客户的信息并回显在form表单中。两个操作使用的页面大致相同,操作的数据库一个是添加,一个是修改。
前端可以通过获取Id来判断该方法是“添加”还是“编辑”,如果有id则为编辑,没有则为添加。根据不同的操作跳转不同的url操作。

十、营销管理模块-----删除

关于批量删除 和 单个删除
前端通过行工具栏删除获取行数据中的id,并把数据传递给后端,通过后端进行删除操作
在这里插入图片描述
前端头工具栏批量删除操作
在这里插入图片描述
以上头工具栏批量删除行工具栏删除操作使用后端的url路径都是一样的。不同的是他们获取的ids的方式不同,行工具栏删除需要获取行ID进行来传参,头工具栏批量删除需要通过遍历拼接ids信息进行删除。
dao层
1.定义动态sql语句,通过ids数组进行遍历,进行is_volid设置为0即可,这里的删除是更新操作。动态sql如下:
在这里插入图片描述
service层
1.调用dao
controller层
1.调用service层

十一、当查询条件和查询结果大多一致时

当查询条件和查询结果差不多一致时,可以根据查询条件的字段进行补充,对于mapper接口也可以动态添加,service层调用mapper层,controller层可以传参来进行区分。

十二、营销管理模块-----计划项数据开发

不同按钮的实现
在这里插入图片描述
需求: 点击”客户开发计划“时,加载所有开发计划的数据并以列表形式展示,根据开发状态显示操作状态(”详情“,”开发“)
分析: 当点击”客户开发计划“时,后端从数据库中查询所有”客户开发计划“数据并返回给前端table表格显示,根据开发状态的不同,使用if标签判断开发状态来显示操作的不同按钮。
需求: 根据客户名、创建人、开发状态搜索查询结果
分析: 当点击”搜索“按钮时,前端获取三个input框中的值,并使用ajax把input框数据传递给后台,后台根据动态sql实现查找的结果返回给前端用来展示。

十三、营销管理模块-----详情和开发页面展示不同的处理

在这里插入图片描述
在这里插入图片描述
需求: 第一张图,当点击”开发“按钮时,跳转的页面中有三个按钮。第二张图,当点击”详情“按钮时,跳转的页面只显示查询的结果,不显示按钮的实现。
分析: 根据不同的开发状态显示不同的显示结果,前端当点击按钮跳转页面时使用if标签根据不同的开发状态来决定是否显示三个按钮的存在。

十四、营销管理模块-----多页面获取ID的方法

在这里插入图片描述
需求: 上图是一个多页面打开的操作,从点击”开发“----->”添加计划项“----->”确认“的实现中,在保存数据时,如何根据ID进行保存呢?
解答: 当点击”确认“时,后端执行保存操作,在保存计划项时,需要根据客户的ID才能进行保存。ID的获取也是我们需要注意的。此时的ID可以从我们点击”添加计划项“按钮要跳转页面时传递进来。可以在跳转页面时,将ID在后端的controller层获取ID参数,获取的ID参数可以通过作用域进行存储。有两种方式可以保存作用域数据,第一种:使用(HttpServletRequest request)的方式将数据以request.setAttribute(…)的方式传递。第二种:使用(Model model)的方式将数据以model.addAttribute(…)的方式传递。
如下代码:
在点击”添加计划项“时就获取当前的ID,在url中进行传递
在这里插入图片描述
在点击”添加计划项“跳转页面时,获取ID并保存在作用域中。
在这里插入图片描述

十五、权限管理模块------用户角色分配回显问题

需求:关于角色的选择可以从数据库中查询出来把数据给前端即可。若在编辑页面,若用户之前已经存在的角色该如何显示呢?
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值