【背景】
开发系统时,有平台端和运营端两套系统。
例如:用户列表接口,平台端和运营端都有该功能,但是业务逻辑大致一样,只是稍有差别,分两个接口又浪费时间,同一个接口写if else,以后又难以维护。
所以:只有用策略模式 或者 开发注解来实现。
策略模式:比较传统,代码比较多,需要后期维护,所以舍弃
注解:使用反射,代码少,不需要后期维护,@ServiceSelector
注解自动根据当前用户登录的是平台端还是运营端,自动走不同的实现,也可以继续加,使其成为多端实现
【实现】
/**
* 平台端接口
*/
public interface IPlatformService {}
/**
* 商户端接口
*/
public interface IBusinessService {}
/**
* service 选择器
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceSelector {
@AliasFor("field")
String value() default "";
@AliasFor("value")
String field() default "";
}
package com.trinity.common.core.aspect;
import com.trinity.common.core.annotation.ServiceSelector;
import com.trinity.common.core.constant.CacheConstants;
import com.trinity.common.core.exception.ServiceSelectorException;
import com.trinity.common.core.text.Convert;
import com.trinity.common.core.utils.ServletUtils;
import com.trinity.common.core.utils.SpringUtils;
import com.trinity.common.core.utils.StringUtils;
import com.trinity.common.core.web.service.IBusinessService;
import com.trinity.common.core.web.service.IPlatformService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import static com.trinity.common.core.constant.Constants.*;
/**
* service选择器
*
* @author zzf
*/
@Slf4j
@Aspect
@Component
public class ServiceSelectorAspect {
@Around("@annotation(com.trinity.common.core.annotation.ServiceSelector)")
public Object around(ProceedingJoinPoint point) throws Throwable {
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
ServiceSelector annotation = method.getAnnotation(ServiceSelector.class);
if (annotation == null) {
throw new ServiceSelectorException("Annotation cannot be empty");
}
String controllerField = annotation.field();
String value = annotation.value();
if (StringUtils.isBlank(controllerField) && StringUtils.isBlank(value)) {
throw new ServiceSelectorException("Not Null");
}
if (StringUtils.isBlank(controllerField)) {
controllerField = value;
}
Object controller = point.getTarget();
Class<?> controllerClass = controller.getClass();
Field[] fields = controllerClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
if (!StringUtils.equals(name, controllerField)) {
continue;
}
Class<?> type = field.getType();
if (!type.isInterface()) {
throw new ServiceSelectorException("This class is not an interface");
}
Map<String, ?> beanImpls = SpringUtils.getBeanImpls(type);
for (String key : beanImpls.keySet()) {
Object bean = beanImpls.get(key);
if (isPlatform() && bean instanceof IPlatformService) {
field.set(controller, bean);
return point.proceed();
}
if (!isPlatform() && bean instanceof IBusinessService) {
field.set(controller, bean);
return point.proceed();
}
// TODO: 2020/12/24 目前之分平台和运营端,因为有的用户只注册了,没有分配企业
/*if (isBusiness() && bean instanceof IBusinessService) {
field.set(controller, bean);
return point.proceed();
}
if (isOperator() && bean instanceof IOperatorService) {
field.set(controller, bean);
return point.proceed();
}*/
}
}
throw new ServiceSelectorException("Corresponding implementation not found");
}
/**
* 是否为平台端
*
* @return 结果
*/
public static boolean isPlatform() {
return getBusId() != null && PLATFORM_ID == getBusId();
}
/**
* 是否为商户
* 企业类型 1:商户;2:运营商
*
* @return
*/
public static boolean isBusiness() {
Long enterpriseType = Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.ENTERPRISE_TYPE));
return enterpriseType != null && BUSINESS == enterpriseType;
}
/**
* 是否为商户
* 企业类型 1:商户;2:运营商
*
* @return
*/
public static boolean isOperator() {
Long enterpriseType = Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.ENTERPRISE_TYPE));
return enterpriseType != null && OPERATOR == enterpriseType;
}
/**
* 获取业务系统id
*/
public static Long getBusId() {
return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_BUS_ID));
}
}
【使用】
/**
* controller
*
* @author zzf
*/
@RestController
@RequestMapping("/user")
public class SysUserController extends BaseController {
private ISysUserService userServiceSelector;
@PreAuthorize(hasPermi = "system:user:list")
@ServiceSelector("userServiceSelector")
@GetMapping("/list")
public TableDataInfo list(SysUser user) {
startPage();
List<SysUser> list = userServiceSelector.selectUserList(user);
return getDataTable(list);
}
}
/**
* 用户接口
*
* @author zzf
*/
public interface ISysUserService {
public List<SysUser> selectUserList(SysUser user);
}
/**
* 运营端实现
*
* @author zzf
*/
@Service
public class SysUserBServiceImpl implements ISysUserService, IBusinessService {
@Override
@DataScope(userAlias = "u")
public List<SysUser> selectUserList(SysUser user) {
// 代码省略
}
}
/**
* 平台端实现
*
* @author zzf
*/
@Service
public class SysUserServiceImpl implements ISysUserService, IPlatformService {
@Override
@DataScope(userAlias = "u")
public List<SysUser> selectUserList(SysUser user) {
// 代码省略
}
}