4.3.1.1 导入工具类
(1) 导入Constants 常量类
/*** 通用常量类* @author spikeCong* @date 2023/5/3**/
public class Constants {/*** UTF-8 字符集*/public static final String UTF8 = "UTF-8";/*** GBK 字符集*/public static final String GBK = "GBK";/*** http请求*/public static final String HTTP = "http://";/*** https请求*/public static final String HTTPS = "https://";/*** 通用成功标识*/public static final String SUCCESS = "0";/*** 通用失败标识*/public static final String FAIL = "1";/*** 登录成功*/public static final String LOGIN_SUCCESS = "Success";/*** 注销*/public static final String LOGOUT = "Logout";/*** 登录失败*/public static final String LOGIN_FAIL = "Error";/*** 验证码 redis key*/public static final String CAPTCHA_CODE_KEY = "captcha_codes:";/*** 登录用户 redis key*/public static final String LOGIN_TOKEN_KEY = "login_tokens:";/*** 防重提交 redis key*/public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";/*** 验证码有效期(分钟)*/public static final Integer CAPTCHA_EXPIRATION = 2;/*** 令牌*/public static final String TOKEN = "token";/*** 令牌前缀*/public static final String TOKEN_PREFIX = "Bearer ";/*** 令牌前缀*/public static final String LOGIN_USER_KEY = "login_user_key";/*** 用户ID*/public static final String JWT_USERID = "userid";/*** 用户名称*/public static final String JWT_USERNAME = "sub";/*** 用户头像*/public static final String JWT_AVATAR = "avatar";/*** 创建时间*/public static final String JWT_CREATED = "created";/*** 用户权限*/public static final String JWT_AUTHORITIES = "authorities";/*** 参数管理 cache key*/public static final String SYS_CONFIG_KEY = "sys_config:";/*** 字典管理 cache key*/public static final String SYS_DICT_KEY = "sys_dict:";/*** 资源映射路径 前缀*/public static final String RESOURCE_PREFIX = "/profile";/*** 默认为空消息*/public static final String DEFAULT_NULL_MESSAGE = "暂无承载数据";/*** 默认成功消息*/public static final String DEFAULT_SUCCESS_MESSAGE = "操作成功";/*** 默认失败消息*/public static final String DEFAULT_FAILURE_MESSAGE = "操作失败";
}
(2) 导入UUIDUtils
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。
/*** UUID生成器工具类* @author spikeCong* @date 2023/5/3**/
public class UUIDUtils {/*** 获取随机UUID** @return 随机UUID*/public static String randomUUID(){return UUID.randomUUID().toString();}/*** 简化的UUID,去掉了横线** @return 简化的UUID,去掉了横线*/public static String simpleUUID(){return UUID.randomUUID().toString().replaceAll("-", "");}
}
(3) 导入Kv类 链式map
链式映射是指在 Java 中使用 Map 接口的一种实现方式,它允许在一个键值映射中进行多次操作而无需创建新的 Map 对象。例如,可以在同一个 Map 中链式地添加、删除或更新键值对。
核心就是 重写 Map 接口的 put() 方法,以返回 this 引用,以实现链式调用
/*** 链式Map* 继承 LinkedCaseInsensitiveMap, 对key大小写不敏感的LinkedHashMap实现* @author spikeCong* @date 2023/5/3**/
public class ChainedMap extends LinkedCaseInsensitiveMap<Object> {private ChainedMap() {super();}/*** 创建ChainedMap** @return ChainedMap*/public static ChainedMap create() {return new ChainedMap();}public static <K, V> HashMap<K, V> newMap() {return new HashMap<>(16);}/*** 设置列** @param attr 属性* @param value 值* @return 本身*/public ChainedMap set(String attr, Object value) {this.put(attr, value);return this;}/*** 设置全部** @param map 属性* @return 本身*/public ChainedMap setAll(Map<? extends String, ?> map) {if (map != null) {this.putAll(map);}return this;}/*** 设置列,当键或值为null时忽略** @param attr 属性* @param value 值* @return 本身*/public ChainedMap setIgnoreNull(String attr, Object value) {if (attr != null && value != null) {set(attr, value);}return this;}public Object getObj(String key) {return super.get(key);}/*** 获得特定类型值** @param <T> 值类型* @param attr 字段名* @param defaultValue 默认值* @return 字段值*/@SuppressWarnings("unchecked")public <T> T get(String attr, T defaultValue) {final Object result = get(attr);return (T) (result != null ? result : defaultValue);}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public String getStr(String attr) {if (null == attr || attr.equals(StringPool.NULL)) {return StringPool.NULL;}return attr;}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Integer getInt(String attr) {if (attr == null) {return -1;}try {return Integer.valueOf(attr);} catch (final NumberFormatException nfe) {return -1;}}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Long getLong(String attr) {if (attr == null) {return -1L;}try {return Long.valueOf(attr);} catch (final NumberFormatException nfe) {return -1L;}}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Float getFloat(String attr) {if (attr != null) {return Float.valueOf(attr.trim());}return null;}public Double getDouble(String attr) {if (attr != null) {return Double.valueOf(attr.trim());}return null;}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Boolean getBool(String attr) {if (attr != null) {String val = String.valueOf(attr);val = val.toLowerCase().trim();return Boolean.parseBoolean(val);}return null;}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public byte[] getBytes(String attr) {return get(attr, null);}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Date getDate(String attr) {return get(attr, null);}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Time getTime(String attr) {return get(attr, null);}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Timestamp getTimestamp(String attr) {return get(attr, null);}/*** 获得特定类型值** @param attr 字段名* @return 字段值*/public Number getNumber(String attr) {return get(attr, null);}@Overridepublic ChainedMap clone() {ChainedMap clone = new ChainedMap();clone.putAll(this);return clone;}
}
(4) 导入序列化工具类
添加序列化工具类,让Redis使用FastJson序列化,提高序列化效率, 将存储在Redis中的value值,序列化为JSON格式便于查看
public class FastJsonJsonRedisSerializer<T> implements RedisSerializer<T>
(5) 导入Redis工具类
- 当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作
- 当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用
@Component
public class RedisCache{}
(6) 导入redis配置类
@Configuration
public class RedisConfig {}
4.3.1.2 生成验证码
(1) 导入依赖
<dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version>
</dependency>
(2) application.yml 增加redis配置
# Spring配置
spring:# redis 配置redis:# 地址host: localhost# 端口,默认为6379port: 6379# 密码password:# 连接超时时间timeout: 10sjedis:pool:# 连接池中的最小空闲连接min-idle: 3# 连接池中的最大空闲连接max-idle: 8# 连接池的最大数据库连接数max-active: 8# #连接池最大阻塞等待时间(使用负值表示没有限制)max-wait: -1ms
(3) 创建CaptchaController
@RestController
public class CaptchaController {//当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作@Autowiredprivate RedisTemplate redisTemplate;/*** 生成验证码* @param response* @return: com.mashibing.springsecurity_example.common.ResponseResult*/@GetMapping("/captchaImage")public ChainedMap getCode(HttpServletResponse response){SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4);//生成验证码,及验证码唯一标识String uuid = UUIDUtils.simpleUUID();String key = Constants.CAPTCHA_CODE_KEY + uuid;String code = specCaptcha.text().toLowerCase();//保存到redisredisTemplate.opsForValue().set(key, code, Duration.ofMinutes(30));return ChainedMap.create().set("uuid",uuid).set("img",specCaptcha.toBase64());}
}
(4) 查看接口文档进行测试
4.3.2 登录接口实现
4.3.2.1 数据库查询用户信息
(1) 创建SysUser类
- 创建sys_user表对应实体类,
com.msb.hjycommunity.system.domain.SysUser
public class SysUser extends BaseEntity {/** 用户ID */@Excel(name = "用户序号")@TableIdprivate Long userId;/** 部门ID */@Excel(name = "部门编号")private Long deptId;/** 用户账号 */@Excel(name = "登录名称")private String userName;/** 用户昵称 */@Excel(name = "用户名称")private String nickName;/** 用户邮箱 */@Excel(name = "用户邮箱")private String email;/** 手机号码 */@Excel(name = "手机号码")private String phonenumber;/** 用户性别 */@Excel(name="用户性别",replace = {"男_0","女_1","未知_0"})private String sex;/** 用户头像 */private String avatar;/** 密码 */private String password;/** 盐加密 */private String salt;/** 帐号状态(0正常 1停用) */@Excel(name = "帐号状态",replace = {"正常_0","停用_1"})private String status;/** 删除标志(0代表存在 2代表删除) */private String delFlag;/** 最后登录IP */@Excel(name = "最后登录IP")private String loginIp;/** 最后登录时间 */@Excel(name = "最后登录时间", width = 30, format = "yyyy-MM-dd HH:mm:ss")private Date loginDate;public SysUser() {}//对 用户名 邮箱 手机号进行校验@NotBlank(message = "用户账号不能为空")@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") public String getUserName() {return userName;}@Email(message = "邮箱格式不正确")@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")public String getEmail() {return email;}@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")public String getPhonenumber() {return phonenumber;}//序列化时忽略密码@JsonIgnorepublic String getPassword() {return password;}//......
}
(2) 创建 SysUserMapper
public interface SysUserMapper extends BaseMapper<SysUser> {/*** 通过用户名查询用户* @param userName 用户名* @return 用户对象信息*/public SysUser selectUserByUserName(String userName);
}
<mapper namespace="com.msb.hjycommunity.system.mapper.SysUserMapper"><select id="selectUserByUserName" parameterType="string" resultType="SysUser">SELECT * FROM sys_user where user_name = #{userName}</select></mapper>
- 测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestHjyCommunityApplication {@AutowiredSysUserMapper userMapper;@Testpublic void testSelectUserByUserName(){SysUser admin = userMapper.selectUserByUserName("admin");System.out.println(admin);}
}
(3) 创建 SysUserService
public interface SysUserService {/*** 通过用户名查询用户* @param userName * @return: com.msb.hjycommunity.system.domain.SysUser*/public SysUser selectUserByUserName(String userName);
}
@Service
@Slf4j
public class SysUserServiceImpl implements SysUserService {@Resourceprivate SysUserMapper sysUserMapper;@Overridepublic SysUser selectUserByUserName(String userName) {return sysUserMapper.selectUserByUserName(userName);}
}