1.创建登录参数类
这里我们通过定义loginType来区分登录类型
package com.demo.form;
import lombok.Data;
/**
* 用户登录对象
*
* @author ruoyi
*/
@Data
public class LoginBody {
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 登录类型
*/
private String loginType;
}
2.创建LoginService类
此类我简化了,并没有使用接口去实现;用于模拟公共的代码逻辑,例如创建token,记录登录信息等等。
package com.demo.service.impl;
import com.demo.form.LoginBody;
/**
* @Description
* @Author lc
* @Date 2023/12/26 15:59
**/
public class LoginService {
public String login(LoginBody loginBody) {
// 验证登录是否成功
//todo 这里是模拟,实际应该是调用对应的登录方法
//登录成功返回token
//todo 这里是模拟,实际应该返回token
//todo 这里是其他公共的逻辑
return "token";
}
}
3.创建ILoginService接口
用于定义登录验证方法,不同的登录方式均实现此接口,getLoginType()方法在工厂模式中会用到
package com.demo.service;
import com.demo.form.LoginBody;
/**
* @Description
* @Author lc
* @Date 2023/12/26 15:56
**/
public interface ILoginService {
/**
* 判断是否登录成功
*
* @param loginBody 登录信息
* @return 结果
*/
boolean isLogin(LoginBody loginBody);
/**
* 获取登录类型
*
* @return 登录类型
*/
String getLoginType();
}
4.创建具体实现类
这里创建了手机号登录,微信登录两种登录案例;
package com.demo.service.impl;
import com.demo.form.LoginBody;
import com.demo.service.ILoginService;
import org.springframework.stereotype.Service;
/**
* @Description 手机号登录
* @Author lc
* @Date 2023/12/26 16:00
**/
@Service
public class PhoneLoginServiceImpl implements ILoginService {
@Override
public boolean isLogin(LoginBody loginBody) {
System.out.println("手机号登录验证");
return true;
}
@Override
public String getLoginType() {
return "phone";
}
}
package com.demo.service.impl;
import com.demo.form.LoginBody;
import com.demo.service.ILoginService;
import org.springframework.stereotype.Service;
/**
* @Description 微信登录
* @Author lc
* @Date 2023/12/26 16:00
**/
@Service
public class WxLoginServiceImpl implements ILoginService {
@Override
public boolean isLogin(LoginBody loginBody) {
System.out.println("微信登录验证");
return true;
}
@Override
public String getLoginType() {
return "wx";
}
}
5.创建工厂类
这里我们通过applicationContext.getBeansOfType()去获取ILoginService接口的所有实现类,再通过具体实现类的getLoginType()方法作为beanMap的键,达到不同登录类型调用不同实现类的目的。这样做区别于if else,后期添加登录方式的时候,无需在乎其他代码,只需要添加一个实现类,就能实现添加登录方式的需求。
package com.demo.utils;
import com.demo.service.ILoginService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* 登录服务工厂类
*/
@Component
public class LoginServiceFactory implements ApplicationContextAware {
private static Map<String, ILoginService> serviceBeanMap;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, ILoginService> map = applicationContext.getBeansOfType(ILoginService.class);
serviceBeanMap = new HashMap<>();
map.forEach((key, value) -> serviceBeanMap.put(value.getLoginType(), value));
}
public static ILoginService getLoginService(String loginType){
ILoginService loginService = serviceBeanMap.get(loginType);
if(loginService == null){
throw new RuntimeException("登录类型有误");
}
return loginService;
}
}
6.LoginService最终效果
最后我们补充上步骤2中的代码以及类总体结构
public String login(LoginBody loginBody) {
// 验证登录是否成功
// 根据登录类型获取对应的登录服务
ILoginService loginService = LoginServiceFactory.getLoginService(loginBody.getLoginType());
// 调用登录服务的登录方法
boolean login = loginService.isLogin(loginBody);
//登录成功返回token
//todo 这里是模拟,实际应该返回token
//todo 这里是其他公共的逻辑
return "token";
}