用户中心——比如:腾讯的QQ账号可以登录到很多应用当中 02

boyanx3天前技术教程2

用户中心——比如:腾讯的QQ账号可以登录到很多应用当中 02

@[toc]

前端登录注册

blankTarget 表示是一个用户点击时跳转时,是打开一个新的页面还是,在本地页面覆盖。

constants 公共常量——》整体修改,整体替换。@ 在 js 表示 str 根目录

target="_blank" 表示跳转,打开一个新页面

Shit+F6 整体重构

前端解决跨域问题

前端-正向代理

#技术分享 #掘金正向代理:替客户端向服务器发送请求

反向代理:替服务器接收请求。

怎么实现代理:

  • Nginx 服务器
  • Node.js 服务器
spring:
  server:
    servlet:
      context-path: /api

测试,测试

shifrt + F6 重构

右键查看-本地历史版本之前的

用户注销

前端用户管理页面

前端用户的权限管理

app.tsx 项目全局入口文件,定义了整个项目中都能使用的公共数据。

access.ts 控制用户的访问权限

首次访问页面(刷新页面),进入 app.tsx,执行 getInitialState ,该方法就是返回值就是全局可用的状态。

ProComponents 高级表单

  1. 通过 clumns 定义表格有哪些列
  2. columns 属性
  3. dataIndex 对应后端返回数据对象(注意一定要和后端设置的字段保持一致(后端返回给前端的字段信息保持一致))
  4. title 表格列名
  5. copyable 是否允许复制
  6. ellipsis 是否允许缩略
  7. valueType 用于声明这一列的类型,为什么样的类型(date,select<可枚举的值>)

用户注销:

package com.rainbowsea.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.rainbowsea.usercenter.common.ErrorCode; import com.rainbowsea.usercenter.exception.BusinessException; import com.rainbowsea.usercenter.model.User; import com.rainbowsea.usercenter.service.UserService; import com.rainbowsea.usercenter.mapper.UserMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils;

import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest;

import static com.rainbowsea.usercenter.contant.UserConstant.USER_LOGIN_STATE;

@Service @Slf4j public class UserServiceImpl extends ServiceImpl<UserMapper, User>

implements UserService {

private static final String SALT = "rainbowsea";

@Resource private UserMapper userMapper;

@Override public int userLogout(HttpServletRequest request) { request.getSession().removeAttribute(USER_LOGIN_STATE);

return 1; } }

用户代码优化——用户校验

仅适用于用户可信的情况。

后端优化:

  1. 通用返回对象:(BaseResponse)
  2. 目的:给对象补充一些信息,告诉前端整个请求在业务层面上是成功还是失败。
  3. 自定义错误码
  4. 返回类正常和错误信息。
{
    "name": "yupi"
}

↓

{ "code": 0 "data": { "name": "yupi" }, "message": "ok" }

{ "code": 50001 "data": null "message": "用户操作异常、xxx" }
  1. 封装全局异常处理(ErrorCode 枚举错误)
  2. 定义业务异常类
  3. 相对于 Java 的异常类,支持更多字段
  4. 自定义构造函数,更灵活/快捷的设置字段
package com.rainbowsea.usercenter.common;

import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data @NoArgsConstructor @AllArgsConstructor public class BaseResponse<T> implements Serializable { private static final long serialVersionUID = 7190730665908854521L;

private int code;

private T data;

private String message;

private String description;

public BaseResponse(int code, T data, String description) { this(code, data, "", description); }

public BaseResponse(int code, T data) { this(code, data, "", ""); }

public BaseResponse(ErrorCode errorCode) { this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription()); }

}
package com.rainbowsea.usercenter.common;

import lombok.Getter;

@Getter public enum ErrorCode {

SUCCESS(0, "ok", ""), PARAMS_ERROR(40000, "请求参数错误", ""), NULL_ERROR(40001, "请求数据为空", ""), NOT_ERROR(40100, "未登录", ""), NO_AUTH(40101, "无权限", ""), SYSTEM_ERROR(50000, "系统内部异常", "");

private final int code;

private final String message;

private final String description;

ErrorCode(int code, String message, String description) { this.code = code; this.message = message; this.description = description; }

}
package com.rainbowsea.usercenter.common;

public class ResultUtils {

public static <T> BaseResponse<T> success(T data) { return new BaseResponse<>(0, data, "ok"); }

public static BaseResponse error(ErrorCode errorCode) { return new BaseResponse(errorCode);

}

public static BaseResponse error(int code, String message, String description) { return new BaseResponse(code, null, message, description);

}

public static BaseResponse error(ErrorCode errorCode, String message) { return new BaseResponse(errorCode.getCode(), null, message); }

public static BaseResponse error(ErrorCode errorCode, String message, String description) { return new BaseResponse(errorCode.getCode(), null, message, description); }

}
package com.rainbowsea.usercenter.exception;

import com.rainbowsea.usercenter.common.ErrorCode; import lombok.Getter;

@Getter public class BusinessException extends RuntimeException {

private int code;

private String message;

private String description;

public BusinessException(int code, String message, String description) { super(message); this.code = code; this.message = message; this.description = description; }

public BusinessException(ErrorCode errorCode) { super(errorCode.getMessage()); this.code = errorCode.getCode(); this.description = errorCode.getDescription(); }

public BusinessException(ErrorCode errorCode,String description) { super(errorCode.getMessage()); this.code = errorCode.getCode(); this.description = description; } }
2. 编写全局异常处理器
    1. 捕获代码中所有的异常,内部消化,集中处理,让前端得到更详细的业务报错/信息。(不将 HTTP 500 这样的错误返回给前端,而是通过返回后端给出的特质信息。返回给前端,后端的报错信息给到了前端(特别人就知道我们的项目架构了))
    2. 同时屏蔽掉项目的内部状态。
    3. 集中记录日志,集中处理日志。

3. 这里利用:
    1. Spring AOP : 在调用方法前后进行额外的处理。
  1. 全局请求日志和登录校验
package com.rainbowsea.usercenter.exception;

import com.rainbowsea.usercenter.common.BaseResponse; import com.rainbowsea.usercenter.common.ErrorCode; import com.rainbowsea.usercenter.common.ResultUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice @Slf4j public class GlobalExceptionHandler {

@ExceptionHandler(BusinessException.class) public BaseResponse businessExceptionHandler(BusinessException e) { log.error("BusinessException" + e.getMessage(), e); return ResultUtils.error(e.getCode(), e.getMessage(), e.getDescription()); }

@ExceptionHandler(RuntimeException.class) public BaseResponse runtimeExceptionHandler(BusinessException e) { log.error("RuntimeException", e); return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage(), ""); } }

添加一个额外的 userRole '用户角色 0- 普通用户 1 - 管理员 2 - vip'

create table user
(
    username     varchar(256)                       null comment '用户昵称',
    id           bigint auto_increment comment 'id'
        primary key,
    userAccount  varchar(256)                       null comment '账号',
    avatarUrl    varchar(1024)                      null comment '用户头像',
    gender       tinyint                            null comment '性别',
    userPassword varchar(512)                       not null comment '密码',
    phone        varchar(128)                       null comment '电话',
    email        varchar(512)                       null comment '邮箱',
    userStatus   int      default 0                 not null comment '状态-0-正常',
    createTime   datetime default CURRENT_TIMESTAMP null comment '创建时间',
    updateTime   datetime default CURRENT_TIMESTAMP null comment '更新时间',
    isDelete     tinyint  default 0                 not null comment '是否删除 0 1(逻辑删除)',
    userRole     int      default 0                 not null comment '用户角色 0- 普通用户 1 - 管理员 2 - vip'
)
    comment '用户';

注意这里:我们修改更新了数据表,所以我们后端对应上的 Bean 对象,以及相关 MyBatis 当中 SQL 语句的映射相关的 XML 文件也是需要对应更新上的。这里我们还是使用:IDEA 当中的一个 MyBatis-x 插件自动生成对应的相关的 SQL XML 的脚本信息

,同时还有一个脱敏处理的位置上,我们需要 set 设置一个 userRole 字段信息


  • 优化将用户常量都封装到一个包当中,定义到为常量类,这里我们是一个接口,常量
package com.rainbowsea.usercenter.contant;

public interface UserConstant {

public static final String USER_LOGIN_STATE = "userLoginState";

int DEFAULT_ROLE = 0;

int ADMIN_ROLE = 1; }

  • 将重复出现多次的代码片段,提取处理作为一个方法,进行一个复用使用,提高其复用性

后端优化:将脱敏操作,提取处理,因为有很多地方需要用到这个脱敏的操作,这里我们将脱敏操作方法,定义到 serivce 接口当中,然后在实现该接口的方法

对应前端返回的,这里我们的 search 查询接口,也是需要,将其脱敏的。不可以将,查询的信息,都返回给前端,需要脱敏(这里我们使用 Java Lambda 表达式进行一个过滤)

@GetMapping("/search")
    public List<User> searchUsers(@RequestBody String username, HttpServletRequest request) {

        if (!isAdmin(request)) {
            return new ArrayList<>();
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNoneBlank(username)) {
            queryWrapper.like("username", username);
        }

List<User> userList = userService.list(queryWrapper); return userList.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList()); }

前端优化

  1. 对接后端的错误信息。

补充:中途遇到的错误异常

Spring Boot 启动失败:Failed to start bean ‘documentationPluginsBootstrapper’ 解决方案

友情链接:

Spring Boot 启动失败:Failed to start bean ‘
documentationPluginsBootstrapper’ 解决方案_failed to start bean ’
documentationpluginsbootstra-CSDN 博客

Failed to start bean ‘documentationPluginsBootstrapper‘; nested exception is java.lang.NullPointerException
spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

符号: 方法 setUserAccount(java.lang.String) 位置: 类型为com.rainbowsea.userc

原因是:lombok 版本问题对应不上。也有可能是你的 IDEA 没有安装上 lombok 插件

这里的解决方式是:修改 Spring Boot 的版本,让其依赖的 Lombok 对应上。

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.7.0</version>

<relativePath/>

</parent>

todo 表示后续完成

to do 表示这里,后续优化,完善。这样标记之后,我们可以通过搜索工具,后续搜索进行完善。

密码统一都是:12345678

最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

标签: todomvc

相关文章

SpringMVC学习--参数绑定(springmvc参数绑定支持的类型有哪些)

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controll...

SpringBoot 自动装配原理详解(spring boot的自动装配原理)

前言使用过 Spring 的小伙伴,一定有被 XML 配置统治的恐惧。即使 Spring 后面引入了基于注解的配置,我们在开启某些 Spring 特性或者引入第三方依赖的时候,还是需要用 XML 或...

MVC之Struts2框架--你并不了解的高级应用

《“爱读书”--给你讲技术》,我来看书,你来进步,让我们开始吧!本书简介书名为《轻量级JavaEE企业应用实战》,是本人在学习JavaEE框架的时候阅读的第一本书,本书对于框架及相关基础知识讲述的比较...

探索 Swift 中的 MVC-N 模式(mvc模式是什么)

作者:Marcus Zarra(twitter:@mzarra)Marcus 将会为大家介绍一种设计模式,他曾经在那些需要从互联网进行大量频繁数据请求的 iOS 应用当中使用此设计模式。这个设计采用了...

Java单元测试浅析(JUnit+Mockito)

作者:京东物流 秦彪1. 什么是单元测试(1)单元测试环节:测试过程按照阶段划分分为:单元测试、集成测试、系统测试、验收测试等。相关含义如下:1) 单元测试: 针对计算机程序模块进行输出正确性检验工作...

angular.js之路由的选择(angular router)

在一个单页面中,我们可以添加多个模块,使得网页只在需要的时候加载这个模块。模块的切换大致上可以代替网页的切换,于是,我们便可以通过模块的切换实现网页的切换,这个切换是按需加载的。乍一看非常普通的东西,...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。