责任链模式应用
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
应用场景
用户登录分为用户名密码登录和手机验证码登录,两种登录模式分别需要进行不同的信息校验;例如用户名密码登录需要进行用户是否存在、用户是否被锁定、密码校验等校验。手机验证码登录需要进行用户是否存在、验证码是否为空、验证码是否正确、用户是否锁定、用户是否被禁用等校验;责任链的另一个应用场景:SpringSecurity对请求过滤 FilterChainProxy
责任链处理类
责任链之前传递数据类
public class UserWrapper {
/**
* 数据库用户实体
*/
private AuthUser user;
/**
* 用户登录参数
*/
private LoginBo loginBo;
/**
* redis操作实例
*/
private RedisTemplate redisTemplate;
public UserWrapper() {
}
public UserWrapper(AuthUser user, LoginBo loginBo, RedisTemplate redisTemplate) {
this.user = user;
this.loginBo = loginBo;
this.redisTemplate = redisTemplate;
}
}
责任链抽象接口
public abstract class UserLoginCheckFilter {
/**
* 下一个处理类
*/
private UserLoginCheckFilter nextFilter;
public UserLoginCheckFilter(UserLoginCheckFilter userLoginCheckFilter) {
this.nextFilter = userLoginCheckFilter;
}
public UserLoginCheckFilter getNextFilt er() {
return this.nextFilter;
}
/**
* 执行处理方法
*
* @param userWrapper
* @return
*/
public abstract boolean process(UserWrapper userWrapper);
}
用户是否存在检查处理类
public class NullUserCheckFilter extends UserLoginCheckFilter {
public NullUserCheckFilter(UserLoginCheckFilter userLoginCheckFilter) {
super(userLoginCheckFilter);
}
@Override
public UserLoginCheckFilter getNextFilter() {
return super.getNextFilter();
}
/**
* 判断登录用户是否为空
*
* @param userWrapper
* @return
*/
@Override
public final boolean process(UserWrapper userWrapper) {
if (null == userWrapper.getUser()) {
throw new MixException(USER_NOT_EXIST);
}
return getNextFilter() == null ? true : getNextFilter().process(userWrapper);
}
}
密码校验处理类
public class PasswordCheckFilter extends UserLoginCheckFilter {
public PasswordCheckFilter(UserLoginCheckFilter userLoginCheckFilter) {
super(userLoginCheckFilter);
}
@Override
public UserLoginCheckFilter getNextFilter() {
return super.getNextFilter();
}
/**
* 判断密码是否正确
*
* @param userWrapper
* @return
*/
@Override
public final boolean process(UserWrapper userWrapper) {
try{
if (!PasswordUtil.base64Equal(userWrapper.getLoginBo().getCredential(),
userWrapper.getUser().getPassword(),
userWrapper.getUser().getSalt())) {
throw new MixException(BusinessErrorEnum.PASSWORD_ERROR);
}
}catch (IllegalArgumentException e){
throw new MixException(BusinessErrorEnum.BASE64_PASSWORD_ERROR);
}
return getNextFilter() == null ? true : getNextFilter().process(userWrapper);
}
}
验证码为空处理类
public class NullCodeCheckFilter extends UserLoginCheckFilter {
public NullCodeCheckFilter(UserLoginCheckFilter userLoginCheckFilter) {
super(userLoginCheckFilter);
}
@Override
public UserLoginCheckFilter getNextFilter() {
return super.getNextFilter();
}
/**
* 判断短信验证码是否为空
*
* @param userWrapper
* @return
*/
@Override
public final boolean process(UserWrapper userWrapper) {
String code = (String) userWrapper.getRedisTemplate().opsForValue().get(RedisConstant.AUTH_MESSAGE_CODE_KEY + userWrapper.getLoginBo().getLoginName());
if (null == code) {
throw new MixException(BusinessErrorEnum.MESSAGE_CODE_EXPIRE);
}
return getNextFilter() == null ? true : getNextFilter().process(userWrapper);
}
}
短信验证码校验处理类
public class ErrorCodeCheckFilter extends UserLoginCheckFilter {
public ErrorCodeCheckFilter(UserLoginCheckFilter userLoginCheckFilter) {
super(userLoginCheckFilter);
}
@Override
public UserLoginCheckFilter getNextFilter() {
return super.getNextFilter();
}
/**
* 判断短信验证码是否错误
*
* @param userWrapper
* @return
*/
@Override
public final boolean process(UserWrapper userWrapper) {
/**
* 查询短信code
*/
String code = (String) userWrapper.getRedisTemplate().opsForValue().get(RedisConstant.AUTH_MESSAGE_CODE_KEY + userWrapper.getLoginBo().getLoginName());
/**
* 判断短信验证码是否匹配
*/
if (!code.equals(userWrapper.getLoginBo().getCredential())) {
/**
* 获取输入错误验证码次数,如果大于3次,需要返回给前端错误次数过多,请求图片验证码
*/
String key = RedisConstant.AUTH_MESSAGE_CODE_COUNT_KEY + userWrapper.getLoginBo().getLoginName();
Integer errorCodeCount = (Integer) userWrapper.getRedisTemplate().opsForValue().get(key);
if (null != errorCodeCount && errorCodeCount.intValue() >= RedisConstant.AUTH_MESSAGE_CODE_ERROR_COUNT) {
throw new MixException(BusinessErrorEnum.ERROR_CODE_MANY);
} else {
throw new MixException(BusinessErrorEnum.MESSAGE_CODE_ERROR);
}
}
/**
* 短信验证码正确,继续执行后面的处理
*/
return getNextFilter() == null ? true : getNextFilter().process(userWrapper);
}
}
责任链调用
手机验证码登录处理逻辑
UserLoginCheckFilter userLoginCheckFilter = new NullUserCheckFilter(
new NullCodeCheckFilter(
new ErrorCodeCheckFilter(
new LockedUserCheckFilter(
new DisableUserCheckFilter(null)))));
boolean loginResult = userLoginCheckFilter.process(new UserWrapper(user, loginBo, redisTemplate));
if(loginResult){
// 登录成功处理逻辑
}
用户名密码登录处理逻辑
UserLoginCheckFilter userLoginCheckFilter = new NullUserCheckFilter(
new LockedUserCheckFilter(
new DisableUserCheckFilter(
new PasswordCheckFilter(null))));
boolean loginResult = userLoginCheckFilter.process(new UserWrapper(user, loginBo, redisTemplate));
if(loginResult){
// 登录成功处理逻辑
}