springboot集成sa-token来实现登录鉴权(一)

springboot集成sa-token来实现登录鉴权(一)sa-token简介spirngboot集成sa-token代码实现maven依赖配置文件全局异常处理登录相关接口controller层service层接口中的参数类返回数据封装全局变量类和枚举类验证码图片工具类redis工具类

测试演示首先获取一个临时token然后获取验证码图片其次是真正的登录接口调用其他接口,调用的时候会校验是否登录

springboot集成sa-token来实现登录鉴权(一)

这篇文章,我们将学习怎样初步集成sa-token来实现基本的登录认证和权限校验,并初步看下底层的源码实现。

sa-token简介

sa-token是一个轻量级的登录鉴权框架,比之前的shiro和springsecurity都要轻量,一行代码就可以实现登录功能。具体文档可以看:sa-token官网。这里我们不再赘述。直接来看具体实现代码。

spirngboot集成sa-token代码实现

点击看项目源码

maven依赖

cn.dev33

sa-token-spring-boot-starter

1.34.0

cn.dev33

sa-token-dao-redis-jackson

1.34.0

org.apache.commons

commons-pool2

其中,如果是springboot3.x版本的话,上面的sa-token-spring-boot-starter依赖要换成sa-token-spring-boot3-starter

配置文件

@Configuration

public class SaTokenConfigure implements WebMvcConfigurer {

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new SaInterceptor(handler -> {

SaRouter.match("/**", StpUtil::checkLogin)

.notMatch(SaTokenConstant.excludePathPatterns);

// 这里可以给每个接口地址的路径鉴权,当然,也可以用注解在每个接口上鉴权

})).addPathPatterns(SaTokenConstant.allRouters)

.excludePathPatterns(SaTokenConstant.excludePathPatterns);

}

@Bean

@Primary

public SaTokenConfig getSaTokenConfigPrimary(){

SaTokenConfig config = new SaTokenConfig();

// token名称

config.setTokenName(SaTokenConstant.TOKEN_NAME);

// token有效期,单位 秒,默认是30天

config.setTimeout(30 * 24 * 60 * 60);

// token无操作存活时间(指定时间内无操作就视为token过期) 单位:秒

config.setActivityTimeout(SaTokenConstant.ACTIVITY_TIMEOUT);

// 是否允许同一账号并发登录,true是允许多个同一账号一起登录,false时同一账号新登录的会挤掉旧登录的

config.setIsConcurrent(false);

// 在多人登录同一账号时,是否共用一个token

config.setIsShare(true);

// token风格

config.setTokenStyle(TokenStyleEnum.SIMPLE_UUID.getTokenStyle());

// 是否输出操作日志

config.setIsLog(false);

/*

是否尝试从 cookie 里读取 Token,此值为 false 后,StpUtil.login(id) 登录时也不会再往前端注入Cookie,

false时,可以返回给前端token,然后让前端在每次请求时header里携带返回的token,

这样可以用于不能使用cookie的设备端,不在局限于web浏览器端

*/

config.setIsReadCookie(false);

return config;

}

}

全局异常处理

/**

* 全局异常处理

*/

@RestControllerAdvice

@Slf4j

public class GlobalExceptionHandler {

/**

* 全局登录异常处理

* @param exception 登录抛出的异常

* @return 提示信息

*/

@ExceptionHandler(NotLoginException.class)

public BaseResult handlerNotLoginException(NotLoginException exception) {

// 打印日志

log.error(exception.getMessage(), exception);

// 判断登录异常的场景,定制化返回提示

String type = exception.getType();

switch (type){

case NotLoginException.INVALID_TOKEN:

case NotLoginException.TOKEN_TIMEOUT:

return BaseResult.fail(520, SaTokenConstant.TOKEN_OVERDUE);

case NotLoginException.BE_REPLACED:

case NotLoginException.KICK_OUT:

return BaseResult.fail(520, SaTokenConstant.LOGIN_REPLACE);

default:

return BaseResult.fail(520, SaTokenConstant.NOT_TOKEN);

}

}

/**

* 全局权限校验异常处理

* @param exception 权限校验异常

* @return

*/

@ExceptionHandler(NotPermissionException.class)

public BaseResult handlerNotPermissionException(NotPermissionException exception){

// 打印日志

log.error(exception.getMessage(), exception);

return BaseResult.fail(520, SaTokenConstant.PERMISSION_ERROR);

}

}

登录相关接口

这里我们模拟下真实的登录场景: 用户在登录页一般会看到三个输入框,分别是:账号、密码和验证码图片。那么我们首先要在登录页面获取到验证码图片,并在登录接口中传入验证码并进行校验,那么后端就必须要存下返回给前端的验证码,那么我们需要先返回前端一个临时token,然后前端拿着这个临时token来请求获取验证码的接口,后端拿到这个临时token后,生成验证码,并将这个临时token作为缓存的key,验证码内容作为value存入缓存中。等到前端调用真正的登录接口时,需要传入 账号、密码、验证码和临时token,在这个接口中,我们通过临时token,去缓存中拿到验证码,和前端传入的验证码进行比对,然后再校验账号和密码。

controller层

@RestController

@Slf4j

public class LoginController {

@Resource

private VerifyImgUtil verifyImgUtil;

@Resource

private LoginService loginService;

/**

* 在获取验证码接口和登录接口前,先调用,获取一个临时token,用来作为验证码的key

*

* @return

*/

@GetMapping("tempToken")

public BaseResult getTempToken(@RequestParam("tokenKey") String tokenKey) {

log.info("开始获取临时token------>" + tokenKey);

String token = SaTempUtil.createToken(tokenKey, 5 * 60);

loginService.saveTempToken(token);

return BaseResult.success(token, null);

}

/**

* 获取图片验证码

*

* @param tempToken 获取到的临时token

* @param response

*/

@GetMapping("getVerifyImg")

public BaseResult getVerifyImg(@RequestParam("tempToken") String tempToken, HttpServletResponse response) throws IOException {

log.info("开始获取图片验证码------>" + tempToken);

if (!loginService.checkTempToken(tempToken)) {

return BaseResult.fail(530, LoginConstant.TOKEN_EMPTY);

}

response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片

response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容

response.setHeader("Cache-Control", "no-cache");

response.setDateHeader("Expires", 0);

OutputStream os = response.getOutputStream();

verifyImgUtil.lineCaptcha(os, tempToken);

try {

os.flush();

} finally {

os.close();

}

return null;

}

/**

* 模拟登录接口,真实场景中,可以先提供一个接口,返回一个临时token,

* 然后再提供一个获取验证码的接口,里面需要传入刚才返回的临时token,生成验证码后,以临时token作为key,验证码作为value放入缓存,

* 然后再来调用这个正式登录接口,里面需要传验证码和临时token以及用户的账号密码,先根据临时token从缓存中获取验证码来比对,

* 然后再比对账号密码,比对成功后,删除缓存中对应临时token的验证码数据,并删除临时token

*

* @param dto 登录数据

* @return

*/

@PostMapping("/login")

public BaseResult login(@RequestBody LoginDto dto) {

log.info("开始登录------>" + JSON.toJSONString(dto));

BaseResult result = loginService.checkLogin(dto);

if (!result.isState()) {

return result;

}

loginService.deleteTempToken(dto.getTempToken());// 校验成功后移除临时token

// 登录

StpUtil.login("10001");

// 将用户的数据放入上下文session中

StpUtil.getSession().set(LoginConstant.LOGIN_NAME, "admin");

StpUtil.getSession().set(LoginConstant.REAL_NAME, "管理员");

StpUtil.getSession().set(LoginConstant.USER_ID, "10001");

return BaseResult.success(StpUtil.getTokenValue(), "登录成功");

}

/**

* 注销登录接口

*/

@PostMapping("logout")

public void logout(){

StpUtil.logout();

}

}

service层

public interface LoginService {

/**

* 登录校验

* @param dto

* @return

*/

BaseResult checkLogin(LoginDto dto);

/**

* 存放临时token

* @param tempToken 临时token

*/

void saveTempToken(String tempToken);

/**

* 删除临时token

* @param tempToken 临时token

*/

void deleteTempToken(String tempToken);

/**

* 校验临时token是否有效

* @param tempToken 临时token

* @return

*/

boolean checkTempToken(String tempToken);

}

@Service

public class LoginServiceImpl implements LoginService {

@Resource

private RedisUtil redisUtil;

private static final String tempTokenPre = "tempToken";

@Override

public BaseResult checkLogin(LoginDto dto) {

if (StringUtils.isBlank(dto.getTempToken())) {

return BaseResult.fail(530, LoginConstant.TOKEN_EMPTY);

}

if (StringUtils.isBlank(dto.getVerifyCode())) {

return BaseResult.fail(530, LoginConstant.VERIFY_CODE_EMPTY);

}

if (StringUtils.isBlank(dto.getLoginName())) {

return BaseResult.fail(530, LoginConstant.LOGIN_NAME_EMPTY);

}

if (StringUtils.isBlank(dto.getPassword())) {

return BaseResult.fail(530, LoginConstant.PASSWORD_EMPTY);

}

// 校验

Object verifyCode = redisUtil.get(dto.getTempToken());

if (verifyCode == null) {

return BaseResult.fail(530, LoginConstant.VERIFY_OVERDUE);

}

if (!dto.getVerifyCode().equalsIgnoreCase(verifyCode.toString())) {

return BaseResult.fail(530, LoginConstant.VERIFY_CODE_ERROR);

}

if (!"admin".equals(dto.getLoginName())) {

return BaseResult.fail(530, LoginConstant.LOGIN_NAME_ERROR);

}

if (!"123".equals(dto.getPassword())) {

return BaseResult.fail(530, LoginConstant.PASSWORD_ERROR);

}

// 校验成功后,移除redis

redisUtil.delete(dto.getTempToken());

return BaseResult.success(null, null);

}

@Override

public void saveTempToken(String tempToken) {

redisUtil.set(tempTokenPre + tempToken, "1", 300);

}

@Override

public void deleteTempToken(String tempToken) {

redisUtil.delete(tempTokenPre + tempToken);

}

@Override

public boolean checkTempToken(String tempToken) {

Object o = redisUtil.get(tempTokenPre + tempToken);

return o != null;

}

}

接口中的参数类

@Data

public class LoginDto implements Serializable {

/**

* 账号

*/

private String loginName;

/**

* 密码

*/

private String password;

/**

* 验证码

*/

private String verifyCode;

/**

* 临时token,用来校验验证码

*/

private String tempToken;

}

返回数据封装

@Data

public class BaseResult implements Serializable {

/**

* 返回数据

*/

private T data;

/**

* 提示信息

*/

private String message;

/**

* 状态码

*/

private int code;

/**

* 状态

*/

private boolean state = true;

public static BaseResult result(int code, String message, boolean state) {

BaseResult result = new BaseResult<>();

result.setCode(code);

result.setMessage(message);

result.setState(state);

return result;

}

/**

* 返回信息

*

* @param code 状态码

* @param message 信息

* @param t 数据

* @param T

* @return ResultVo

*/

public static BaseResult result(int code, String message, T t, boolean state) {

BaseResult r = new BaseResult<>();

r.setCode(code);

r.setMessage(message);

r.setData(t);

r.setState(state);

return r;

}

/**

* 返回成功

*

* @param data data

* @param T

* @return ResultVo

*/

public static BaseResult success(T data, String message) {

return result(HttpStatus.OK.value(), message, data, true);

}

/**

* 返回失败

*

* @param code code

* @param T

* @return ResultVo

*/

public static BaseResult fail(int code, String message) {

return result(code, message, null, false);

}

}

全局变量类和枚举类

/**

* 要排除登录校验的接口地址枚举类

*/

@Getter

public enum ExcludePathEnum {

TEMP_TOKEN("/tempToken", "获取临时token的接口"),

VERIFY_IMG("/getVerifyImg", "获取验证码图片的接口"),

LOGIN("/login", "登录接口"),

LOGOUT("/logout", "注销登录接口");

private final String path;

private final String remark;

ExcludePathEnum(String path, String remark) {

this.path = path;

this.remark = remark;

}

}

public class LoginConstant {

public static final String TOKEN_EMPTY = "token不能为空!";

public static final String LOGIN_NAME_EMPTY = "请输入账号!";

public static final String PASSWORD_EMPTY = "请输入密码!";

public static final String LOGIN_NAME_ERROR = "账号不存在!";

public static final String PASSWORD_ERROR = "密码错误,请重新输入!";

public static final String VERIFY_CODE_EMPTY = "验证码不能为空!";

public static final String VERIFY_CODE_ERROR = "验证码错误,请重新输入!";

public static final String VERIFY_OVERDUE = "验证码已过期,请重新登录!";

public static final String LOGIN_NAME = "loginName";

public static final String REAL_NAME = "userName";

public static final String USER_ID = "userId";

}

public class SaTokenConstant {

/**

* token的字段名

*/

public static final String TOKEN_NAME = "token";

/**

* token无操作存活时间(指定时间内无操作就视为token过期) 单位:秒

*/

public static final long ACTIVITY_TIMEOUT = 24 * 60 * 60;

public static final List allRouters = Collections.singletonList("/**");

public static final List excludePathPatterns = Arrays.asList(

"/test/**",

"/file/upload/img/head/**",

"/swagger-resources/**",

"/webjars/**",

"/v2/**",

"/doc.html",

"**/swagger-ui.html",

"/swagger-ui.html/**",

"/img/head/**",

ExcludePathEnum.TEMP_TOKEN.getPath(),

ExcludePathEnum.VERIFY_IMG.getPath(),

ExcludePathEnum.LOGIN.getPath(),

ExcludePathEnum.LOGOUT.getPath()

);

public static final String NOT_TOKEN = "您未登录,请登录!";

public static final String TOKEN_OVERDUE = "登录已失效,请重新登录!";

public static final String LOGIN_REPLACE = "您的账号已在别处登录!";

public static final String PERMISSION_ERROR = "您没有权限!";

}

@Getter

public enum TokenStyleEnum {

/**

* 一般的uuid风格

*/

UUID("uuid"),

/**

* uuid风格,只不过去掉了中划线

*/

SIMPLE_UUID("simple-uuid"),

/**

* 随机32位字符串

*/

RANDOM_32("random-32"),

/**

* 随机64位字符串

*/

RANDOM_64("random-64"),

/**

* 随机128位字符串

*/

RANDOM_128("random-128"),

/**

* tik风格,gr_SwoIN0MC1ewxHX_vfCW3BothWDZMMtx__

*/

TIK("tik");

private final String tokenStyle;

TokenStyleEnum(String tokenStyle) {

this.tokenStyle = tokenStyle;

}

}

验证码图片工具类

这里的验证码图片生成用的是hultool包的工具类,需要先导入hultool包 maven:

cn.hutool

hutool-all

5.8.15

封装的工具类:

@Component

public class VerifyImgUtil {

@Resource

private RedisUtil redisUtil;

/**

* 生成验证码的字符,去掉了0、1、I、O这样容易混淆的字符

*/

public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

/**

* 生成线段干扰的验证码

*

* @param os 输出流

* @param tempToken 临时token,作为验证码写入缓存的key

*/

public void lineCaptcha(OutputStream os, String tempToken) {

//定义图形验证码的长和宽

LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);

// 自定义纯数字的验证码(随机4位字符,可重复)

RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);

captcha.setGenerator(randomGenerator);

putVerifyCode(tempToken, captcha.getCode());

captcha.write(os);

}

/**

* 生成圆圈干扰的验证码

*

* @param os 输出流

* @param tempToken 临时token,作为验证码写入缓存的key

*/

public void circleCaptcha(OutputStream os, String tempToken) {

//定义图形验证码的长、宽、验证码字符数、干扰元素个数

CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);

// 自定义纯数字的验证码(随机4位字符,可重复)

RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);

captcha.setGenerator(randomGenerator);

putVerifyCode(tempToken, captcha.getCode());

captcha.write(os);

}

/**

* 生成扭曲干扰的验证码

*

* @param os 输出流

* @param tempToken 临时token,作为验证码写入缓存的key

*/

public void shearCaptcha(OutputStream os, String tempToken) {

//定义图形验证码的长、宽、验证码字符数、干扰线宽度

ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);

// 自定义纯数字的验证码(随机4位字符,可重复)

RandomGenerator randomGenerator = new RandomGenerator(VERIFY_CODES, 4);

captcha.setGenerator(randomGenerator);

putVerifyCode(tempToken, captcha.getCode());

captcha.write(os);

}

/**

* 将验证码放到缓存里

*

* @param tempToken 临时token,作为验证码写入缓存的key

* @param verifyCode 验证码

*/

private void putVerifyCode(String tempToken, String verifyCode) {

redisUtil.set(tempToken, verifyCode, 40);

}

}

redis工具类

@Component

public class RedisUtil {

@Resource

private RedisTemplate redisTemplate;

/**

* 获取符合要求的所有key

* @param patternKey 指定要求的key

* @return 获取符合要求的所有key集合

*/

public Set getAllKey(String patternKey){

return redisTemplate.keys(patternKey);

}

/**

* 清空所有的redis数据库

*/

public void flushAll(){

redisTemplate.getConnectionFactory().getConnection().flushAll();

}

/**

* 清空当前数据库

*/

public void flushDB(){

redisTemplate.getConnectionFactory().getConnection().flushDb();

}

/**

* 指定缓存的有效期

* @param key 缓存key

* @param time 有效时间,已秒为单位

* @return

*/

public Boolean expire(String key, long time){

if (time > 0){

return redisTemplate.expire(key, time, TimeUnit.SECONDS);

}

return true;

}

/**

* 获取指定key的过期时间,返回0表示永久有效

* @param key 缓存key

* @return 过期时间

*/

public Long getExpire(String key){

return redisTemplate.getExpire(key);

}

/**

* 判断指定的缓存key是否存在

* @param key 缓存key

* @return

*/

public Boolean hasKey(String key){

return redisTemplate.hasKey(key);

}

/**

* 删除指定的key,可以传入一个String数组,批量删除

* @param key 缓存key数组

*/

public void delete(String... key){

if (key == null || key.length < 1){

return;

}

if (key.length == 1){

redisTemplate.delete(key[0]);

} else {

redisTemplate.delete(Arrays.asList(key));

}

}

/**

* String类型的添加缓存数据

* @param key 缓存key

* @param value 缓存value

*/

public void set(String key, Object value){

redisTemplate.opsForValue().set(key, value);

}

/**

* String类型的添加缓存数据,并设置过期时间,单位为秒

* @param key 缓存key

* @param value 缓存value

* @param time 过期时间

*/

public void set(String key, Object value, long time){

redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);

}

/**

* 获取指定key的缓存数据

* @param key 缓存key

* @return

*/

public Object get(String key){

return key == null ? null : redisTemplate.opsForValue().get(key);

}

/**

* 指定key的值递增

* @param key 缓存key

* @param delta 递增因子,即每次递增加几

* @return

*/

public Long incr(String key, long delta){

if (delta < 0){

throw new RuntimeException("递增因子要大于0");

}

return redisTemplate.opsForValue().increment(key, delta);

}

/**

* 指定key的值递减

* @param key 缓存key

* @param delta 递减因子,即每次递减减几

* @return

*/

public Long decr(String key, long delta){

if (delta < 0){

throw new RuntimeException("递减因子要大于0");

}

return redisTemplate.opsForValue().decrement(key, delta);

}

/**

*

Hash类型

* 获取指定key的指定键值对的值

* @param key 缓存key

* @param hashKey hash类型的键值对的key

* @return

*/

public Object hget(String key, String hashKey){

return redisTemplate.opsForHash().get(key, hashKey);

}

/**

*

Hash类型

* 获取指定key的所有键值对的值

* @param key 缓存key

* @return

*/

public Map hmget(String key){

return redisTemplate.opsForHash().entries(key);

}

/**

*

Hash类型

* 添加指定缓存key的多个键值对

* @param key 缓存key

* @param map 对应的多个键值对

*/

public void hmset(String key, Map map){

redisTemplate.opsForHash().putAll(key, map);

}

/**

*

Hash类型

* 添加指定缓存key的多个键值对,并设置过期时间,以秒为单位

* @param key 缓存key

* @param map 对应的多个键值对

* @param time 过期时间

*/

public void hmset(String key, Map map, long time){

redisTemplate.opsForHash().putAll(key, map);

expire(key, time);

}

/**

*

Hash类型

* 添加指定缓存key的一个键值对

* @param key 换存key

* @param hashKey 对应的键值对的key

* @param value 对应的键值对的value

*/

public void hSet(String key, String hashKey, Object value){

redisTemplate.opsForHash().put(key, hashKey, value);

}

/**

*

Hash类型

* 添加指定缓存key的一个键值对,并设置过期时间,以秒为单位

* @param key 缓存key

* @param hashKey 对应的键值对的key

* @param value 对应的键值对的value

* @param time 过期时间

*/

public void hSet(String key, String hashKey, Object value, long time){

hSet(key, hashKey, value);

expire(key, time);

}

/**

*

Hash类型

* 删除指定key的指定键值对

* @param key 缓存key

* @param hashKey 要删除的键值对的key

*/

public void hDelete(String key, Object... hashKey){

redisTemplate.opsForHash().delete(key, hashKey);

}

/**

*

Hash类型

* 判断缓存中是否有指定key的指定键值对

* @param key 缓存key

* @param hashKey 对应键值对的key

* @return

*/

public Boolean hHashKey(String key, Object hashKey){

return redisTemplate.opsForHash().hasKey(key, hashKey);

}

/**

*

Hash类型

* 递增指定key的指定键值对的值,如果不存在,则会创建,并且返回新增后的值

* @param key 缓存key

* @param hashKey 指定键值对的key

* @param delta 递增因子,即要加几

* @return

*/

public double hIncr(String key, String hashKey, long delta) {

return redisTemplate.opsForHash().increment(key, hashKey, delta);

}

/**

*

Hash类型

* 递减指定key的指定键值对的值,如果不存在,则会创建,并且返回新增后的值

* @param key 缓存key

* @param hashKey 指定键值对的key

* @param delta 递减因子,即要减几

* @return

*/

public double hDecr(String key, String hashKey, long delta) {

return redisTemplate.opsForHash().increment(key, hashKey, -delta);

}

//================================Set===========================

/**

*

Set类型

* 根据key获取Set中的所有值

* @param key 缓存key

* @return

*/

public Set sGet(String key) {

return redisTemplate.opsForSet().members(key);

}

/**

*

Set类型

* 查询指定的key中指定的value是否存在

* @param key 缓存key

* @param value Set中的指定元素

* @return

*/

public Boolean sHasKey(String key, Object value) {

return redisTemplate.opsForSet().isMember(key, value);

}

/**

*

Set类型

* 将缓存数据放入指定的key中

* @param key 缓存key

* @param values Set集合

* @return

*/

public Long sSet(String key, Object... values) {

return redisTemplate.opsForSet().add(key, values);

}

/**

*

Set类型

* 将缓存数据放入指定的key中,并设置过期时间,单位为秒

* @param key 缓存key

* @param time 过期时间

* @param values 要放入缓存的数据

* @return

*/

public Long sSet(String key, long time, Object... values) {

Long l = sSet(key, values);

expire(key, time);

return l;

}

/**

*

Set类型

* 获取指定的key中Set的长度

* @param key 缓存key

* @return

*/

public Long sGetSetLength(String key) {

Long l = redisTemplate.opsForSet().size(key);

return l == null ? 0 : l;

}

/**

*

Set类型

* 移除指定的key中指定的value

* @param key 缓存key

* @param values 指定要移除的value

* @return

*/

public long sRemove(String key, Object... values) {

Long l = redisTemplate.opsForSet().remove(key, values);

return l == null ? 0 : l;

}

//==========================List=======================

/**

*

List类型

* 获取指定的key中的list集合内容,根据起始下标获取

* @param key 缓存key

* @param start 集合的开始下标,包含在内

* @param end 集合的截止下标,也包含在内

* @return

*/

public List lGet(String key, long start, long end) {

try {

return redisTemplate.opsForList().range(key, start, end);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

*

List类型

* 根据key获取list集合的长度

* @param key 缓存key

* @return

*/

public long lGetLength(String key) {

Long l = redisTemplate.opsForList().size(key);

return l == null ? 0 : l;

}

/**

*

List类型

* 获取指定key的指定下标的元素

* @param key 缓存key

* @param index 指定的list集合下标

* @return

*/

public Object lGetByIndex(String key, long index) {

try {

return redisTemplate.opsForList().index(key, index);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

*

List类型

* 将值从左侧放入List类型的缓存中,头插法

* @param key 缓存key

* @param value 要放入缓存的值

* @return

*/

public void lSet(String key, Object value) {

redisTemplate.opsForList().leftPush(key, value);

}

/**

*

List类型

* 将值从右侧放入List类型的缓存中,尾插法

* @param key 缓存key

* @param value 要放入缓存的值

*/

public void rSet(String key, Object value) {

redisTemplate.opsForList().rightPush(key, value);

}

/**

*

List类型

* 将值从左侧放入List类型的缓存中,头插法,并设置过期时间,单位为秒

* @param key 缓存key

* @param value 要放入缓存的值

* @param time 过期时间

* @return

*/

public void lSet(String key, Object value, long time) {

redisTemplate.opsForList().leftPush(key, value);

expire(key, time);

}

/**

*

List类型

* 将值从右侧放入List类型的缓存中,尾插法,并设置过期时间,单位为秒

* @param key 缓存key

* @param value 要放入缓存的值

* @param time 过期时间

*/

public void rSet(String key, Object value, long time) {

redisTemplate.opsForList().rightPush(key, value);

expire(key, time);

}

/**

*

List类型

* 将list集合从左边放入缓存,头插法

* @param key 缓存key

* @param list 要放入缓存的集合

*/

public void lSet(String key, List list) {

redisTemplate.opsForList().leftPushAll(key, list);

}

/**

*

List类型

* 将list集合从右边放入缓存,尾插法

* @param key 缓存key

* @param list 要放入缓存的集合

*/

public void rSet(String key, List list) {

redisTemplate.opsForList().rightPushAll(key, list);

}

/**

*

List类型

* 将list集合从左边放入缓存,头插法,并设置过期时间,单位为秒

* @param key 缓存key

* @param list 要放入缓存的集合

* @param time 过期时间

*/

public void lSet(String key, List list, long time) {

redisTemplate.opsForList().leftPushAll(key, list);

expire(key, time);

}

/**

*

List类型

* 将list集合从右边放入缓存,尾插法,并设置过期时间,单位为秒

* @param key 缓存key

* @param list 要放入缓存的集合

* @param time 过期时间

*/

public void rSet(String key, List list, long time) {

redisTemplate.opsForList().rightPushAll(key, list);

expire(key, time);

}

/**

*

List类型

* 修改指定key的list集合中指定下标的值

* @param key 缓存key

* @param index 要修改的值的下标

* @param value 修改的值

*/

public void lUpdateIndex(String key, long index, Object value) {

redisTemplate.opsForList().set(key, index, value);

}

/**

*

List类型

*

移除指定key的list集合中指定个数的指定值

*

若count = 0,则表示移除全部

*

若count > 0,则表示从List集合的左侧开始数

*

若count < 0,则表示从List集合的右侧开始数

* @param key 缓存key

* @param count 要移除的元素个数

* @param value 要移除的值

* @return

*/

public Long lRemove(String key, long count, Object value) {

Long l = redisTemplate.opsForList().remove(key, count, value);

return l == null ? 0L : l;

}

//===============================ZSet=============================

/**

*

ZSet类型

* 添加ZSet类型的缓存,这是一个有序集合,是按照元素的scores的值由小到大排序的

* @param key 缓存key

* @param value 要添加的值

* @param scores 值的scores,根据此值的大小来排序

*/

public void zAdd(String key, String value, double scores) {

redisTemplate.opsForZSet().add(key, value, scores);

}

/**

*

ZSet类型

* 批量添加ZSet类型的缓存,将一个set集合添加的ZSet中

* @param key 缓存key

* @param values 要放入缓存的set集合

*/

public void zAdd(String key, Set> values) {

redisTemplate.opsForZSet().add(key, values);

}

/**

*

ZSet类型

* 移除指定key中ZSet集合中的一个或多个指定的元素

* @param key 缓存key

* @param values 要移除的元素

* @return

*/

public Long zRemove(String key, Object... values) {

Long l = redisTemplate.opsForZSet().remove(key, values);

return l == null ? 0L : l;

}

/**

*

ZSet类型

* 增加指定key的ZSet集合中指定元素的scores,并返回增加后的scores值

* @param key 缓存key

* @param value 要增加scores的元素

* @param delta 递增因子,即加几

* @return 增加后的scores值

*/

public Double zincr(String key, String value, double delta) {

return redisTemplate.opsForZSet().incrementScore(key, value, delta);

}

/**

*

ZSet类型

* 返回指定key中ZSet集合中指定元素的下标

* @param key 缓存key

* @param value 要获取下标的元素

* @return 指定元素的下标

*/

public Long zRank(String key, Object value) {

return redisTemplate.opsForZSet().rank(key, value);

}

/**

*

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,由小到大排序

* @param key 缓存key

* @param start 开始下标,包含在内

* @param end 截止下标,也包含在内

* @return 指定下标区间内的元素

*/

public Set zRange(String key, long start, long end) {

return redisTemplate.opsForZSet().range(key, start, end);

}

/**

*

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,由大到小排序

* @param key 缓存key

* @param start 开始下标,包含在内

* @param end 截止下标,也包含在内

* @return 指定下标区间内的元素

*/

public Set zReRange(String key, long start, long end) {

return redisTemplate.opsForZSet().reverseRange(key, start, end);

}

/**

*

ZSet类型

* 获取指定key的ZSet集合中指定下标区间的元素,并带上元素的scores

* @param key 缓存key

* @param start 开始下标,包含在内

* @param end 截止下标,也包含在内

* @return 指定下标区间内的元素

*/

public Set> zRangeWithScores(String key, long start, long end) {

return redisTemplate.opsForZSet().rangeWithScores(key, start, end);

}

/**

*

ZSet类型

* 获取指定key的ZSet集合中指定scores的元素

* @param key 缓存key

* @param scores 值的scores,根据此值的大小来排序

* @return

*/

public Object zScores(String key, double scores) {

return redisTemplate.opsForZSet().score(key, scores);

}

}

测试演示

首先获取一个临时token

然后获取验证码图片

其次是真正的登录接口调用

这里获取到真正的token后,前端就要在之后的接口中将这个token放入header中,至于这个header的字段名叫什么,在 这里的配置文件中会配置,配置后,接口的登录校验就会从header中获取这个字段的值来进行登录校验

其他接口,调用的时候会校验是否登录

已经登录后的调用返回: 未登录的调用返回:

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: 

发表评论

返回顶部暗黑模式