SpringBoot 项目(若依脚手架)3

mac2025-02-09  11

前言:

紧接着 上一章 “SpringBoot 项目(若依脚手架)2” 补充

5.1.2.1 MessageUtils 工具类中,使用到的 SpringUtils 工具类

package com.ruoyi.common.utils.spring; import org.springframework.aop.framework.AopContext; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; /** * spring工具类 方便在非spring管理环境中获取bean * * @author ruoyi */ @Component public final class SpringUtils implements BeanFactoryPostProcessor { /** Spring应用上下文环境 */ private static ConfigurableListableBeanFactory beanFactory; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { SpringUtils.beanFactory = beanFactory; } /** * 获取对象 * * @param name * @return Object 一个以所给名字注册的bean的实例 * @throws BeansException * */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) throws BeansException { return (T) beanFactory.getBean(name); } /** * 获取类型为requiredType的对象 * * @param clz * @return * @throws BeansException * */ public static <T> T getBean(Class<T> clz) throws BeansException { T result = (T) beanFactory.getBean(clz); return result; } /** * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true * * @param name * @return boolean */ public static boolean containsBean(String name) { return beanFactory.containsBean(name); } /** * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) * * @param name * @return boolean * @throws NoSuchBeanDefinitionException * */ public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { return beanFactory.isSingleton(name); } /** * @param name * @return Class 注册对象的类型 * @throws NoSuchBeanDefinitionException * */ public static Class<?> getType(String name) throws NoSuchBeanDefinitionException { return beanFactory.getType(name); } /** * 如果给定的bean名字在bean定义中有别名,则返回这些别名 * * @param name * @return * @throws NoSuchBeanDefinitionException * */ public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { return beanFactory.getAliases(name); } /** * 获取aop代理对象 * * @param invoker * @return */ @SuppressWarnings("unchecked") public static <T> T getAopProxy(T invoker) { return (T) AopContext.currentProxy(); } }

5.2 用户相关的异常类  

CaptchaException :验证码错误异常类

package com.ruoyi.common.exception.user; /** * 验证码错误异常类 * @author liangcy * @create 2019/10/12 - 10:33 */ public class CaptchaException extends UserException{ private static final long serialVersionUID = 1L; public CaptchaException() { super("user.jcaptcha.error", null); } } RoleBlockedException: 角色锁定异常类 package com.ruoyi.common.exception.user; /** * 角色锁定异常类 * * @author ruoyi */ public class RoleBlockedException extends UserException { private static final long serialVersionUID = 1L; public RoleBlockedException() { super("role.blocked", null); } } UserBlockedException : 用户锁定异常 package com.ruoyi.common.exception.user; /** * @author liangcy * @create 2019/10/13 - 11:10 */ public class UserBlockedException extends UserException { private static final long serialVersionUID = 1L; public UserBlockedException() { super("user.blocked", null); } } UserDeleteException : 用户被删除异常 package com.ruoyi.common.exception.user; /** * @author liangcy * @create 2019/10/13 - 11:09 */ public class UserDeleteException extends UserException { private static final long serialVersionUID = 1L; public UserDeleteException() { super("user.password.delete", null); } } UserException : 用户异常 package com.ruoyi.common.exception.user; import com.ruoyi.common.exception.base.BaseException; /** * @author liangcy * @create 2019/10/12 - 10:31 */ public class UserException extends BaseException { private static final long serialVersionUID = 1L; public UserException(String code, Object[] args) { super("user", code, args, null); } } UserNotExistsException :用户不存在异常 package com.ruoyi.common.exception.user; /** * @author liangcy * @create 2019/10/12 - 10:39 */ public class UserNotExistsException extends UserException { private static final long serialVersionUID = 1L; public UserNotExistsException() { super("user.not.exists", null); } } UserPasswordNotMatchException : 密码错误异常 package com.ruoyi.common.exception.user; /** * @author liangcy * @create 2019/10/12 - 10:47 */ public class UserPasswordNotMatchException extends UserException { private static final long serialVersionUID = 1L; public UserPasswordNotMatchException(){ super("user.password.not.match", null); } }

六、Service层

6.1  SysPasswordService 类:主要是用来验证登录密码的,后期会加上 登录次数限制、异步记录、缓存的功能

package com.ruoyi.framework.shiro.service; import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.system.domain.SysUser; import org.apache.shiro.crypto.hash.Md5Hash; import org.springframework.stereotype.Component; /** * 登录密码方法 * * @author liangcy * @create 2019/10/13 - 11:12 */ @Component public class SysPasswordService { public void validate(SysUser user, String password) { String loginName = user.getLoginName(); //TODO 从缓存中获取登录次数 if (!matches(user, password)) { //TODO 1、异步记录日志 2、将登录次数存入缓存中 throw new UserPasswordNotMatchException(); } else { //TODO 密码正确,清除缓存中用户名 } } private boolean matches(SysUser user, String password) { return user.getPassword().equals(encryptPassword(user.getLoginName(), password, user.getSalt())); } public String encryptPassword(String username, String password, String salt) { return new Md5Hash(username + password + salt).toHex().toString(); } }

6.2 ISysUserService  用户 业务层接口

package com.ruoyi.system.service; import com.ruoyi.system.domain.SysUser; import java.util.List; /** * @author liangcy * @create 2019/10/12 - 10:52 */ public interface ISysUserService { /** * 通过用户名查询用户 * * @param userName 用户名 * @return 用户对象信息 */ public SysUser selectUserByLoginName(String userName); /** * 通过手机号码查询用户 * * @param phoneNumber 手机号码 * @return 用户对象信息 */ public SysUser selectUserByPhoneNumber(String phoneNumber); /** * 通过邮箱查询用户 * * @param email 邮箱 * @return 用户对象信息 */ public SysUser selectUserByEmail(String email); }

6.2.1 SysUserServiceImplISysUserService 接口的实现类

package com.ruoyi.system.service.impl; import com.ruoyi.system.domain.SysUser; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * @author liangcy * @create 2019/10/13 - 9:59 */ @Service @Slf4j public class SysUserServiceImpl implements ISysUserService { @Resource private SysUserMapper userMapper; @Override public SysUser selectUserByLoginName(String userName) { return userMapper.selectUserByLoginName(userName); } @Override public SysUser selectUserByPhoneNumber(String phoneNumber) { return userMapper.selectUserByPhoneNumber(phoneNumber); } @Override public SysUser selectUserByEmail(String email) { return userMapper.selectUserByEmail(email); } }

6.3 SysLoginSerivice : 处理登录的业务逻辑类

package com.ruoyi.framework.shiro.service; import com.ruoyi.common.constant.ShiroConstants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.exception.user.*; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.system.domain.SysUser; import com.ruoyi.system.service.ISysUserService; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.Resource; /** * @author liangcy * @create 2019/10/11 - 23:10 */ @Component public class SysLoginSerivice { @Resource private ISysUserService userService; @Resource private SysPasswordService passwordService; /** * 登录 */ public SysUser login(String username, String password) { //验证码校验 if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA))) { //TODO 异步方法记录日志 验证码错误 throw new CaptchaException(); } // 用户名或密码为空 错误 if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { //TODO 异步方法记录日志 用户名或密码为空 throw new UserNotExistsException(); } // 密码如果不在指定范围内 错误 if(password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH ){ //TODO 记录日志 throw new UserPasswordNotMatchException(); } //查询用户信息 SysUser user = userService.selectUserByLoginName(username); if(user == null && maybeMobilePhoneNumber(username)){ user = userService.selectUserByPhoneNumber(username); } if( user == null && maybeEmail(username)) { user = userService.selectUserByEmail(username); } if( user == null){ //TODO 异步记录日志 throw new UserNotExistsException(); } if(UserStatus.DELETED.getCode().equals(user.getDelFlag())){ //TODO 异步记录日志 throw new UserDeleteException(); } if(UserStatus.DISABLE.getCode().equals(user.getStatus())){ //TODO 异步记录日志 throw new UserBlockedException(); } //校验密码是否正确 passwordService.validate(user, password); //TODO 异步记录日志,登录成功的信息 //TODO 记录登录信息 return user; } private boolean maybeEmail(String username) { if(!username.matches(UserConstants.EMAIL_PATTERN)){ return false; } return true; } private boolean maybeMobilePhoneNumber(String username) { if(!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)){ return false; } return true; } }

6.3.1 ServletUtils :客户端工具类

package com.ruoyi.common.utils; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /** * @author liangcy * @create 2019/10/11 - 23:22 */ public class ServletUtils { /** * 获取request */ public static HttpServletRequest getRequest(){ return getRequestAttributes().getRequest(); } public static ServletRequestAttributes getRequestAttributes(){ RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); return (ServletRequestAttributes) attributes; } }

6.3.2 UserConstants : 用户常量信息

package com.ruoyi.common.constant; /** * @author liangcy * @create 2019/10/12 - 10:44 */ public class UserConstants { /** 部门正常状态 */ public static final String DEPT_NORMAL = "0"; /** * 密码长度限制 */ public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MAX_LENGTH = 20; /** 登录名称是否唯一的返回结果码 */ public final static String USER_NAME_UNIQUE = "0"; public final static String USER_NAME_NOT_UNIQUE = "1"; /** e-mail 是否唯一的返回结果 */ public final static String USER_EMAIL_UNIQUE = "0"; public final static String USER_EMAIL_NOT_UNIQUE = "1"; /** 手机号码是否唯一的返回结果 */ public final static String USER_PHONE_UNIQUE = "0"; public final static String USER_PHONE_NOT_UNIQUE = "1"; /** 角色名称是否唯一的返回结果码 */ public final static String ROLE_NAME_UNIQUE = "0"; public final static String ROLE_NAME_NOT_UNIQUE = "1"; /** 角色权限是否唯一的返回结果码 */ public final static String ROLE_KEY_UNIQUE = "0"; public final static String ROLE_KEY_NOT_UNIQUE = "1"; /** 部门名称是否唯一的返回结果码 */ public final static String DEPT_NAME_UNIQUE = "0"; public final static String DEPT_NAME_NOT_UNIQUE = "1"; /** 岗位名称是否唯一的返回结果码 */ public final static String POST_NAME_UNIQUE = "0"; public final static String POST_NAME_NOT_UNIQUE = "1"; /** 岗位编码是否唯一的返回结果码 */ public final static String POST_CODE_UNIQUE = "0"; public final static String POST_CODE_NOT_UNIQUE = "1"; /** 菜单名称是否唯一的返回结果码 */ public final static String MENU_NAME_UNIQUE = "0"; public final static String MENU_NAME_NOT_UNIQUE = "1"; /** 字典类型是否唯一的返回结果码 */ public final static String DICT_TYPE_UNIQUE = "0"; public final static String DICT_TYPE_NOT_UNIQUE = "1"; /** * 手机号码格式限制 */ public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$"; /** * 邮箱格式限制 */ public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?"; }

6.3.3 UserStatus :用户状态

package com.ruoyi.common.enums; import lombok.Getter; /** * 用户状态 * * @author liangcy * @create 2019/10/13 - 11:04 */ @Getter public enum UserStatus { OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); private final String code; private final String info; UserStatus(String code, String info) { this.code = code; this.info = info; } }

七、测试 SysLoginSerivice 的登录方法

package com.ruoyi.framework.shiro.service; import com.ruoyi.system.domain.SysUser; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import static org.junit.Assert.*; /** * @author liangcy * @create 2019/11/1 - 13:28 */ @RunWith(SpringRunner.class) @SpringBootTest public class SysLoginSeriviceTest { @Resource SysLoginSerivice loginSerivice; @Test public void login() { SysUser user = loginSerivice.login("admin", "1234"); System.out.println(user); } }

测试结果:

用户名密码正确:

用户名或密码错误:

 

最新回复(0)