1 通用异常
1.1 什么是通用异常
目前的代码中如果发生系统异常,则直接会给用户抛出不友好的异常信息。
为了提高前后台用户的体验,并且系统本身很多的地方都会有一些业务相关的异常,需要统一进行捕获并进行返回给前端。springmvc为我们提供了几个注解 实现统一异常的捕获功能,根据不同的异常的类型进行不同的处理。
总结:
1.需要处理系统异常相关 未知的错误
2.需要处理自定义业务异常相关 已知的业务的错误。例如 商品获取不到,查询不到数据等。
1.2 异常配置说明
@RestControllerAdvice
控制器增强注解 添加该注解的全局异常处理类需要被spring扫描到
@ExceptionHandler
异常处理器 与上面注解一起使用,可以拦截指定的异常信息并做相关的处理
@Slf4j 日志打印,topic指定将来输出到哪个文件上
2 通用Controller的抽取
2.1 需求分析
我们还需要实现敏感词管理,还需要实现各种表对应的【简单】的CRUD的操作,这个时候单表操作简单但是开发效率不高,每次都要编写,如果超过很多张表,那么需要重复劳动很多次。由此我们想到优化解决方案,其中就可以采取类似于mybatisplus一样的效果,mybatisplus已经实现了 基本的业务层CRUD操作和持久层CRUD操作,但是没实现controller的CRUD操作。那么我们需要自定义一个核心的controller的CRUD操作。
接口与实现类的区别
简单回答:
抽象类:主要用于封装通用方法,作为工具类使用。
接口:主要用于定义规范。
完善回答:
一、抽象类与接口的相同之处
1、抽象类和接口都不能被实例化,都用于被其他类实现或继承
2、他们都可以包含抽象方法,并且在其他类继承或实现的时候都必须实现这些抽象方法
二、抽象类与接口的区别
1、抽象类是对事物属性的抽象,而接口是对行为的抽象
2、接口只能做方法的声明,而抽象类中既可以包含方法的声明,也可以包含方法的实现。
3、接口里只能定义静态常量,而不能定义成员变量,抽象类中既可以定义静态常量,也可以定义成员变量。
4、接口没有构造函数,而抽象类有构造函数。
5、java语法当中只支持类的单继承,而可以存在接口的多实现。
6、接口方法的访问权限必须是公共的,被public修饰
2.2 思路说明
如图:
我们开发的时候每一个表对应的controller都要编写一个crud相关的业务代码,进行调用实现需求,虽然技术难度不大,但是频繁的操作很麻烦。
优化之后如右侧所示:
1.扩展维护性增强
2 不需要大量的代码重复劳动,需要自己编写一个controller 继承抽象类的controller即可立即实现所有相关的CRUDP功能
3 日志
日志处理是一个正式项目必备的功能,日志要能够根据时间、类型等要素,根据指定格式来保存指定的日志,方便我们观察程序运行情况、定位程序bug
SpringBoot中推荐使用Logback日志框架。默认采用logback来实现日志处理。更多日志相关参考如下:
4 JWT介绍
4.1 token认证
随着 Restful API、微服务的兴起,基于 Token(令牌) 的认证现在已经越来越普遍。基于token的用户认证是一种服务端无状态的认证方式,所谓服务端无状态指的token本身包含登录用户所有的相关数据,而客户端在认证后的每次请求都会携带token,因此服务器端无需存放token数据。
有状态:服务端存储登录信息
缺点:用户量大时,服务端存储大理用户信息
优点:安全(金融、保险) 使用redis存放登录用户信息
无状态:服务端不存储登录信息, 登录用户信息存到token里
缺点:密钥泄露了,任意创建
优点:节省服务存储,每次请求时都得带上token
解决:分布式架构中,单点登录问题(登录后只能针对某台服务不需要登录,而其它服务都需要再次登录)
服务端有状态:用户登录成功后,服务端存储登录用户信息(session), session.getAttribute(“loginUser”)
服务端有状态:用户登录成功后,服务端不存储登录用户信息, 则无法通过session获取登录用户信息,怎么校验用户登录了呢? 客户端每次请求后端时,必须带上token(身份证), 登录用户信息存到token里了。
当用户认证后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份。
4.2 什么是JWT?
我们现在了解了基于token认证的交互机制,但令牌里面究竟是什么内容?什么格式呢?市面上基于token的认证方式大都采用的是JWT(Json Web Token)。
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递json对象(登录用户信息),传递的信息经过数字签名可以被验证和信任。
JWT令牌结构:
JWT令牌由Header、Payload、Signature三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
- Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC、SHA256或RSA)。
一个例子:
{
"alg": "HS256",
"typ": "JWT"
}
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
- Payload 载荷
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比
如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
一个例子:
{
"sub": "1234567890",
"name": "456",
"admin": true
}
最后将第二部分载荷使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。
- Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明
签名算法进行签名。
一个例子:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret(密钥))
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。