原來使用 Spring 實(shí)現(xiàn)策略模式可以這么簡單!

微信登錄 QQ 登錄 微博登錄

定義策略接口
LoginHandler,其中包括兩個(gè)方法:獲取策略類型的方法 處理策略邏輯的方法
public interface LoginHandler<T extends Serializable> {
/**
* 獲取登錄類型
*
* @return
*/
LoginType getLoginType();
/**
* 登錄
*
* @param request
* @return
*/
LoginResponse<String, T> handleLogin(LoginRequest request);
}
LoginHandler 的 getLoginType 方法用來獲取登錄的類型(即策略類型),用于根據(jù)客戶端傳遞的參數(shù)直接獲取到對(duì)應(yīng)的策略實(shí)現(xiàn)。@Data
public class LoginRequest {
private LoginType loginType;
private Long userId;
}
public enum LoginType {
QQ,
WE_CHAT,
WEI_BO;
}
實(shí)現(xiàn)策略接口
微信登錄
@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);
}
}
創(chuàng)建策略的簡單工廠
@Component
public class LoginHandlerFactory implements InitializingBean, ApplicationContextAware {
private static final Map<LoginType, LoginHandler<Serializable>> LOGIN_HANDLER_MAP = new EnumMap<>(LoginType.class);
private ApplicationContext appContext;
/**
* 根據(jù)登錄類型獲取對(duì)應(yīng)的處理器
*
* @param loginType 登錄類型
* @return 登錄類型對(duì)應(yīng)的處理器
*/
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實(shí)現(xiàn) InitializingBean 接口,在 afterPropertiesSet 方法中,基于 Spring 容器將所有 LoginHandler 自動(dòng)注冊到 LOGIN_HANDLER_MAP,從而 Spring 容器啟動(dòng)完成后, getHandler 方法可以直接通過 loginType 來獲取對(duì)應(yīng)的登錄處理器。創(chuàng)建登錄服務(wù)
LoginHandlerFactory 來獲取對(duì)應(yīng)的登錄處理器,從而處理不同類型的第三方登錄:@Service
public class LoginServiceImpl implements LoginService {
@Autowired
private LoginHandlerFactory loginHandlerFactory;
@Override
public LoginResponse<String, Serializable> login(LoginRequest request) {
LoginType loginType = request.getLoginType();
// 根據(jù) loginType 找到對(duì)應(yīng)的登錄處理器
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 實(shí)現(xiàn)策略模式就是這么簡單,還不快學(xué)起來!有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號(hào)
好文章,我在看??
