原来使用 Spring 实现策略模式可以这么简单!
微信登录 QQ 登录 微博登录
定义策略接口
LoginHandler
,其中包括两个方法:获取策略类型的方法 处理策略逻辑的方法
public interface LoginHandler<T extends Serializable> {
/**
* 获取登录类型
*
* @return
*/
LoginType getLoginType();
/**
* 登录
*
* @param request
* @return
*/
LoginResponse<String, T> handleLogin(LoginRequest request);
}
LoginHandler
的 getLoginType
方法用来获取登录的类型(即策略类型),用于根据客户端传递的参数直接获取到对应的策略实现。@Data
public class LoginRequest {
private LoginType loginType;
private Long userId;
}
public enum LoginType {
QQ,
WE_CHAT,
WEI_BO;
}
实现策略接口
微信登录
@Component
public class WeChatLoginHandler implements LoginHandler<String> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 获取登录类型
*
* @return
*/
@Override
public LoginType getLoginType() {
return LoginType.WE_CHAT;
}
/**
* 登录
*
* @param request
* @return
*/
@Override
public LoginResponse<String, String> handleLogin(LoginRequest request) {
logger.info("微信登录:userId:{}", request.getUserId());
String weChatName = getWeChatName(request);
return LoginResponse.success("微信登录成功", weChatName);
}
private String getWeChatName(LoginRequest request) {
return "wupx";
}
}
QQ 登录
@Component
public class QQLoginHandler implements LoginHandler<Serializable> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 获取登录类型
*
* @return
*/
@Override
public LoginType getLoginType() {
return LoginType.QQ;
}
/**
* 登录
*
* @param request
* @return
*/
@Override
public LoginResponse<String, Serializable> handleLogin(LoginRequest request) {
logger.info("QQ登录:userId:{}", request.getUserId());
return LoginResponse.success("QQ登录成功", null);
}
}
微博登录
@Component
public class WeiBoLoginHandler implements LoginHandler<Serializable> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 获取登录类型
*
* @return
*/
@Override
public LoginType getLoginType() {
return LoginType.WEI_BO;
}
/**
* 登录
*
* @param request
* @return
*/
@Override
public LoginResponse<String, Serializable> handleLogin(LoginRequest request) {
logger.info("微博登录:userId:{}", request.getUserId());
return LoginResponse.success("微博登录成功", null);
}
}
创建策略的简单工厂
@Component
public class LoginHandlerFactory implements InitializingBean, ApplicationContextAware {
private static final Map<LoginType, LoginHandler<Serializable>> LOGIN_HANDLER_MAP = new EnumMap<>(LoginType.class);
private ApplicationContext appContext;
/**
* 根据登录类型获取对应的处理器
*
* @param loginType 登录类型
* @return 登录类型对应的处理器
*/
public LoginHandler<Serializable> getHandler(LoginType loginType) {
return LOGIN_HANDLER_MAP.get(loginType);
}
@Override
public void afterPropertiesSet() throws Exception {
// 将 Spring 容器中所有的 LoginHandler 注册到 LOGIN_HANDLER_MAP
appContext.getBeansOfType(LoginHandler.class)
.values()
.forEach(handler -> LOGIN_HANDLER_MAP.put(handler.getLoginType(), handler));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
appContext = applicationContext;
}
}
LoginHandlerFactory
实现 InitializingBean
接口,在 afterPropertiesSet
方法中,基于 Spring 容器将所有 LoginHandler
自动注册到 LOGIN_HANDLER_MAP
,从而 Spring 容器启动完成后, getHandler 方法可以直接通过 loginType
来获取对应的登录处理器。创建登录服务
LoginHandlerFactory
来获取对应的登录处理器,从而处理不同类型的第三方登录:@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private LoginHandlerFactory loginHandlerFactory;
@Override
public LoginResponse<String, Serializable> login(LoginRequest request) {
LoginType loginType = request.getLoginType();
// 根据 loginType 找到对应的登录处理器
LoginHandler<Serializable> loginHandler =
loginHandlerFactory.getHandler(loginType);
// 处理登录
return loginHandler.handleLogin(request);
}
}
测试
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
/**
* 登录
*/
@PostMapping("/login")
public LoginResponse<String, Serializable> login(@RequestParam LoginType loginType, @RequestParam Long userId) {
LoginRequest loginRequest = new LoginRequest();
loginRequest.setLoginType(loginType);
loginRequest.setUserId(userId);
return loginService.login(loginRequest);
}
}
@Component
public class GitHubLoginHandler implements LoginHandler<Serializable> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 获取登录类型
*
* @return
*/
@Override
public LoginType getLoginType() {
return LoginType.GIT_HUB;
}
/**
* 登录
*
* @param request
* @return
*/
@Override
public LoginResponse<String, Serializable> handleLogin(LoginRequest request) {
logger.info("GitHub登录:userId:{}", request.getUserId());
return LoginResponse.success("GitHub登录成功", null);
}
}
GitHubLoginHandler
注册到 LoginHandlerFactory
中,使用 Spring 实现策略模式就是这么简单,还不快学起来!有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️