作为一个稀有的Java妹子,所写的所有博客都只是当作自己的笔记,留下证据自己之前是有用心学习的~哈哈哈哈(如果有不对的地方,也请大家指出,不要悄悄咪咪的不告诉我)
1.概述
有的时候,需要一个接口根据不同的业务场景实现不同的功能,比如支付接口有多个运营商,不同的运营商的对接方式不同,但是对自己本身的系统来说,入口应该只有一个,就是调用的接口是同一个,不过有不同的实现类,来完成不同的支付方式的对接。
2.上代码
用户的授权接口,根据不同的传参调用不同的认证方法,验证方法有:校验密码、校验密码和验证码等等,这个根据业务场景自定义。
1、定义接口
public interface ITokenGranter {
/**
* 获取用户信息
*
* @param tokenParameter 授权参数
* @return UserInfo
*/
UserInfo grant(TokenParameter tokenParameter);
}
2、写不同的实现类
(1)、校验验证码和密码
@Component
public class CaptchaTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "captcha";
private IUserClient userClient;
private RedisUtil redisUtil;
//校验方法的实现类
@Override
public UserInfo grant(TokenParameter tokenParameter) {
HttpServletRequest request = WebUtil.getRequest();
String key = request.getHeader(TokenUtil.CAPTCHA_HEADER_KEY);
String code = request.getHeader(TokenUtil.CAPTCHA_HEADER_CODE);
// 获取验证码
String redisCode = String.valueOf(redisUtil.get(CacheNames.CAPTCHA_KEY + key));
// 判断验证码
if (code == null || !StringUtil.equalsIgnoreCase(redisCode, code)) {
throw new ServiceException(TokenUtil.CAPTCHA_NOT_CORRECT);
}
String tenantId = tokenParameter.getArgs().getStr("tenantId");
String account = tokenParameter.getArgs().getStr("account");
String password = tokenParameter.getArgs().getStr("password");
UserInfo userInfo = null;
if (Func.isNoneBlank(account, password)) {
// 获取用户类型
String userType = tokenParameter.getArgs().getStr("userType");
R<UserInfo> result;
// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
if (userType.equals(BladeUserEnum.WEB.getName())) {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
} else if (userType.equals(BladeUserEnum.APP.getName())) {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
} else {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
}
userInfo = result.isSuccess() ? result.getData() : null;
}
return userInfo;
}
}
(2)、校验密码
public class PasswordTokenGranter implements ITokenGranter {
public static final String GRANT_TYPE = "password";
private IUserClient userClient;
@Override
public UserInfo grant(TokenParameter tokenParameter) {
String tenantId = tokenParameter.getArgs().getStr("tenantId");
String account = tokenParameter.getArgs().getStr("account");
String password = tokenParameter.getArgs().getStr("password");
UserInfo userInfo = null;
if (Func.isNoneBlank(account, password)) {
// 获取用户类型
String userType = tokenParameter.getArgs().getStr("userType");
R<UserInfo> result;
// 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
if (userType.equals(BladeUserEnum.WEB.getName())) {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
} else if (userType.equals(BladeUserEnum.APP.getName())) {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
} else {
result = userClient.userInfo(tenantId, account, DigestUtil.encrypt(password));
}
userInfo = result.isSuccess() ? result.getData() : null;
}
return userInfo;
}
}
3、定义接口实现类的创建
public class TokenGranterBuilder {
/**
* TokenGranter缓存池
*/
private static Map<String, ITokenGranter> granterPool = new ConcurrentHashMap<>();
//先创建所有实现类的实例放进map中
static {
granterPool.put(PasswordTokenGranter.GRANT_TYPE, SpringUtil.getBean(PasswordTokenGranter.class));
granterPool.put(CaptchaTokenGranter.GRANT_TYPE, SpringUtil.getBean(CaptchaTokenGranter.class));
granterPool.put(RefreshTokenGranter.GRANT_TYPE, SpringUtil.getBean(RefreshTokenGranter.class));
}
/**
* 获取TokenGranter
*
* @param grantType 授权类型
* @return ITokenGranter
*/
public static ITokenGranter getGranter(String grantType) {
//根据前端传的类型返回不同的实例
ITokenGranter tokenGranter = granterPool.get(Func.toStr(grantType, PasswordTokenGranter.GRANT_TYPE));
if (tokenGranter == null) {
throw new SecureException("no grantType was found");
} else {
return tokenGranter;
}
}
}
4、调用类
public class AuthController {
private RedisUtil redisUtil;
@PostMapping("token")
public R<AuthInfo> token(String grantType,String refreshToken,String tenantId, String account,String password) {
String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
TokenParameter tokenParameter = new TokenParameter();
tokenParameter.getArgs().set("tenantId", tenantId)
.set("account", account)
.set("password", password)
.set("grantType", grantType)
.set("refreshToken", refreshToken)
.set("userType", userType);
//通过构造器获取实例,这里就是根据类型返回的实例
ITokenGranter granter = TokenGranterBuilder.getGranter(grantType);
UserInfo userInfo = granter.grant(tokenParameter);
if (userInfo == null || userInfo.getUser() == null || userInfo.getUser().getId() == null) {
return R.fail(TokenUtil.USER_NOT_FOUND);
}
return R.data(TokenUtil.createAuthInfo(userInfo));
}