feat(新增): Redis乱码问题,获取当前登录用户信息,用户退出接口

This commit is contained in:
bunny 2024-03-23 00:36:54 +08:00
parent 8cb99adc5e
commit 5bcd1428c2
17 changed files with 190 additions and 32 deletions

View File

@ -1,6 +1,13 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="customHeaders">
<set>
<option value="token" />
</set>
</option>
</inspection_tool>
<inspection_tool class="RawUseOfParameterizedType" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UNCHECKED_WARNING" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>

View File

@ -0,0 +1,90 @@
package com.atguigu.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
@Slf4j
public class RedisConfiguration {
/**
* 使用StringRedisSerializer序列化为字符串
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
// 设置key序列化为String
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// 设置value序列化为JSON使用GenericJackson2JsonRedisSerializer替换默认的序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
/**
* 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
*/
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
StringRedisSerializer redisSerializer = new StringRedisSerializer();
// json序列化
Jackson2JsonRedisSerializer<Object> serializer = jsonRedisSerializer();
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();
}
/**
* 指定的日期模式
*/
public Jackson2JsonRedisSerializer<Object> jsonRedisSerializer() {
// LocalDatetime序列化默认不兼容jdk8日期序列化
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
ObjectMapper mapper = new ObjectMapper();
// 设置Object访问权限
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 记录序列化之后的数据类型方便反序列化
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
// 关闭默认的日期格式化方式默认UTC日期格式 yyyy-MM-ddTHH:mm:ss.SSS
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(javaTimeModule);
return new Jackson2JsonRedisSerializer<>(mapper, Object.class);
}
}

View File

@ -12,4 +12,5 @@ public class EnumException {
public static final String CAPTCHA_IS_EMPTY = "提交验证码不能为空";
public static final String KEY_IS_EMPTY = "验证码key不能为空";
public static final String VERIFICATION_CODE_DOES_NOT_MATCH = "验证码不匹配";
public static final String VERIFICATION_CODE_IS_EMPTY = "验证码失效或不存在";
}

View File

@ -29,7 +29,7 @@ public class GlobalExceptionHandler {
@ResponseBody
public Result<Object> exceptionHandler(RuntimeException exception) {
log.error("运行时异常信息:{}", exception.getMessage());
return Result.error(500, exception.getMessage());
return Result.error(500, "出错了啦");
}
// 捕获系统异常

View File

@ -2,10 +2,12 @@ package com.atguigu.spzx.manger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableCaching
@EnableScheduling
@ComponentScan("com.atguigu")
public class MangerApplication {

View File

@ -3,8 +3,8 @@ package com.atguigu.spzx.manger.controller;
import com.atguigu.spzx.manger.service.SysUserService;
import com.atguigu.spzx.manger.service.ValidateCodeService;
import com.atguigu.spzx.model.dto.system.LoginDto;
import com.atguigu.spzx.model.entity.system.SysUser;
import com.atguigu.spzx.model.vo.result.Result;
import com.atguigu.spzx.model.vo.result.ResultCodeEnum;
import com.atguigu.spzx.model.vo.system.LoginVo;
import com.atguigu.spzx.model.vo.system.ValidateCodeVo;
import io.swagger.v3.oas.annotations.Operation;
@ -21,17 +21,31 @@ public class IndexController {
@Autowired
private ValidateCodeService validateCodeService;
@Operation(summary = "登录请求", description = "登录请求实现")
@PostMapping("login")
public Result<LoginVo> login(@RequestBody LoginDto loginDto) {
LoginVo vo = sysUserService.login(loginDto);
return Result.success(vo, ResultCodeEnum.SUCCESS);
}
@Operation(summary = "生成验证码", description = "生成验证码信息")
@GetMapping("generateValidateCode")
public Result<ValidateCodeVo> generateValidateCode() {
ValidateCodeVo vo = validateCodeService.generateValidateCode();
return Result.success(vo, ResultCodeEnum.SUCCESS);
return Result.success(vo);
}
@Operation(summary = "登录请求", description = "登录请求实现")
@PostMapping("login")
public Result<LoginVo> login(@RequestBody LoginDto loginDto) {
LoginVo vo = sysUserService.login(loginDto);
return Result.success(vo);
}
@Operation(summary = "获取登录用户信息", description = "获取当前登录用户信息")
@GetMapping("getUserInfo")
public Result<SysUser> getUserInfo(@RequestHeader(name = "token") String token) {
SysUser sysUser = sysUserService.getUserInfo(token);
return Result.success(sysUser);
}
@Operation(summary = "用户退出", description = "用户退出接口")
@GetMapping(value = "/logout")
public Result logout(@RequestHeader(value = "token") String token) {
sysUserService.logout(token);
return Result.success();
}
}

View File

@ -1,6 +1,7 @@
package com.atguigu.spzx.manger.service;
import com.atguigu.spzx.model.dto.system.LoginDto;
import com.atguigu.spzx.model.entity.system.SysUser;
import com.atguigu.spzx.model.vo.system.LoginVo;
public interface SysUserService {
@ -11,4 +12,19 @@ public interface SysUserService {
* @return 登录后结果
*/
LoginVo login(LoginDto loginDto);
/**
* * 获取当前登录用户信息
*
* @param token token值
* @return 用户信息
*/
SysUser getUserInfo(String token);
/**
* * 用户退出接口
*
* @param token token值
*/
void logout(String token);
}

View File

@ -24,7 +24,7 @@ public class SysUserServiceImpl implements SysUserService {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private RedisTemplate redisTemplate;
private RedisTemplate<String, Object> redisTemplate;
/**
* * 登录请求实现
@ -38,12 +38,14 @@ public class SysUserServiceImpl implements SysUserService {
String userName = loginDto.getUserName();
String captcha = loginDto.getCaptcha();
String key = loginDto.getCodeKey();
// 得到Redis中验证码
String code = (String) redisTemplate.opsForValue().get(key);
stringEmptyUtil.isEmpty(userName, EnumException.USERNAME_IS_EMPTY);
stringEmptyUtil.isEmpty(password, EnumException.PASSWORD_IS_EMPTY);
stringEmptyUtil.isEmpty(captcha, EnumException.CAPTCHA_IS_EMPTY);
stringEmptyUtil.isEmpty(key, EnumException.KEY_IS_EMPTY);
// 得到Redis中验证码
String code = (String) redisTemplate.opsForValue().get(key);
stringEmptyUtil.isEmpty(code, EnumException.VERIFICATION_CODE_IS_EMPTY);
// 验证码不匹配
assert code != null;
if ((!Objects.equals(code.toLowerCase(), captcha.toLowerCase()))) {
@ -63,8 +65,32 @@ public class SysUserServiceImpl implements SysUserService {
}
// 登录成功
String token = UUID.randomUUID().toString().replaceAll("-", "");
redisTemplate.opsForValue().set(userName, token, 7, TimeUnit.DAYS);
redisTemplate.opsForValue().set(token, userName, 7, TimeUnit.DAYS);
// 返回loginVo对象
return LoginVo.builder().token(token).build();
}
/**
* * 获取当前登录用户信息
*
* @param token token值
* @return 用户信息
*/
@Override
public SysUser getUserInfo(String token) {
String username = (String) redisTemplate.opsForValue().get(token);
SysUser sysUser = sysUserMapper.selectByUsername(username);
sysUser.setPassword("******");
return sysUser;
}
/**
* * 用户退出接口
*
* @param token token值
*/
@Override
public void logout(String token) {
redisTemplate.delete(token);
}
}

View File

@ -2,31 +2,33 @@ package com.atguigu.spzx.model.entity.system;
import com.atguigu.spzx.model.entity.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.*;
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "系统用户实体类")
public class SysUser extends BaseEntity {
@Schema(description = "用户名")
private String userName;
@Schema(description = "用户名")
private String userName;
@Schema(description = "密码")
private String password;
@Schema(description = "密码")
private String password;
@Schema(description = "昵称")
private String name;
@Schema(description = "昵称")
private String name;
@Schema(description = "手机号码")
private String phone;
@Schema(description = "手机号码")
private String phone;
@Schema(description = "图像")
private String avatar;
@Schema(description = "图像")
private String avatar;
@Schema(description = "描述")
private String description;
@Schema(description = "状态1正常 0停用")
private Integer status;
@Schema(description = "描述")
private String description;
@Schema(description = "状态1正常 0停用")
private Integer status;
}

View File

@ -64,7 +64,7 @@ public class Result<T> {
* @return Result<T>
*/
public static <T> Result<T> success() {
return Result.success(null);
return Result.success(null, ResultCodeEnum.SUCCESS);
}
/**