在开发springboot项目的开发过程中我们总会使用到mvc模式,在controller层写接口,service中写业务,dao层进行数据持久化。这种模式总会service的实现层写很多代码,这样会使得seviceimpl类中有很多业务代码,以及注入很多的bean,后期维护起来会相当麻烦。今天采用命令模式,模板模式来实现各业务接口的解耦。
1.Executor
public interface Executor { <R extends Receiver> R getReceiver(Class<R> clazz); default <T> T execute(Command<T> command) { return command.execute(this); } }
2.Receiver
public interface Receiver { }
3.CommanExecutor
@Component
@Transactional
public class CommandExecutor implements Executor {
@Autowired(
required = false
)
private Map<String, DomainService> domainServices;
public CommandExecutor() {
}
public <R extends Receiver> R getReceiver(Class<R> clazz) {
return (Receiver)this.domainServices.get(String_.lowerFirst(clazz.getSimpleName()));
}
public Map<String, DomainService> getDomainServices() {
return this.domainServices;
}
}
4.DomainService
public interface DomainService extends Receiver {
}
5.DomainServiceImpl
public class DomainServiceImpl implements DomainService {
public DomainServiceImpl() {
}
}
6.CommandQry
public abstract class CommonQry<T> implements Command<T> {
private static final Logger log = LoggerFactory.getLogger(CommonQry.class);
protected Integer pageNo = (Integer)ThreadLocal_.get("page_param_offset_page");
protected Integer pageSize = (Integer)ThreadLocal_.get("page_param_offset_size");
protected Boolean isSensitized;
protected LambdaQueryWrapper queryWrapper;
public CommonQry() {
this.isSensitized = Boolean.FALSE;
}
protected <E extends BaseEntity, R extends BaseMapper> List<E> paginate(Class<R> clazz) {
IPage page = null;
try {
Method method = clazz.getMethod("selectPage", IPage.class, Wrapper.class);
if (Object_.isNotEmpty(page = (IPage)method.invoke(Spring_.getBean(clazz), this.page(), this.queryWrapper))) {
if (PageHelper.pageable() && !String_.equals(PageHelper.getPageType(), "cursor")) {
ThreadLocal_.set("page_total_number", page.getTotal());
}
if (!this.isSensitized) {
return page.getRecords();
}
this.desensitized(page.getRecords());
}
return page.getRecords();
} catch (Exception var4) {
throw new BusinessException(ErrorEnum.E881);
}
}
protected <E> E desensitized(E e) {
Field[] fields = e.getClass().getDeclaredFields();
Field[] var3 = fields;
int var4 = fields.length;
for(int var5 = 0; var5 < var4; ++var5) {
Field field = var3[var5];
field.setAccessible(true);
try {
CcbDesensitizedUtil.setNewValueForField(e, field, field.get(e));
} catch (Exception var8) {
throw new BusinessException("数据脱敏失败");
}
}
return e;
}
protected <E> List<E> desensitized(List<E> lists) {
Iterator var2 = lists.iterator();
while(var2.hasNext()) {
E record = var2.next();
this.desensitized(record);
}
return lists;
}
protected Page page() {
return new Page(this.pageNo == null ? 1L : (long)this.pageNo, this.pageSize == null ? 10L : (long)this.pageSize);
}
}
7.baseApi
public class BaseApi { @Autowired( required = false ) protected CommandExecutor commandExecutor; @Autowired( required = false ) protected QueryExecutor queryExecutor; public BaseApi() { } @ApiResult @Operation( summary = "测试联通性", description = "请求接口前可调用该接口测试接口是否活着" ) @GetMapping({"/isalive"}) public String isAlive() { return "ok"; }
8.使用案列,本案中我们将数据查询的接口独立成为一个类,这样我们就实现了将复杂代码从业务模块中独立出来了
@RestController
@RequestMapping("/api/user")
@Tag(name = "用户管理",description = "用户管理")
public class SysUserApi extends BaseApi {
public static final String[] VALID_FIELD = {"userNo","email","mobile"};
@Pagination
@PostMapping("/list")
@ApiResult(successCode = 200,successMsg = "查询成功")
@PreAuthorize("hasAuthority('system:user:list')")
@Operation(summary = "用户列表查询",description = "用户列表查询")
public List<SysUser> list(@RequestBody SysUserVo userVo) {
return commandExecutor.execute(SysUserQry.builder().userVo(userVo).build());
}
@PostMapping("/add")
@PreAuthorize("hasAuthority('system:user:add')")
@ApiResult(successCode = 200,successMsg = "操作成功")
@Operation(summary = "新增用户",description = "新增用户")
public void add(@RequestBody @Validated({Create.class}) SysUserDto userDto) {
SysUser user = UserMapper.USER_MAPPER.toEntity(userDto);
commandExecutor.getReceiver(SysUserManager.class).duplicationValid(user,VALID_FIELD);
userDto.setPassword();
commandExecutor.execute(new SysUserCmd(userDto));
}
@PostMapping("/update")
@ApiResult(successCode = 200,successMsg = "操作成功")
@Operation(summary = "修改用户",description = "修改用户")
@PreAuthorize("hasAuthority('system:user:update')")
public void update(@RequestBody @Validated({Update.class}) SysUserDto userDto) {
SysUser user = UserMapper.USER_MAPPER.toEntity(userDto);
if (Object_.isNotEmpty(user.getId())) {
commandExecutor.getReceiver(SysUserManager.class).findById(user.getId()).ifPresent(bean -> {
commandExecutor.getReceiver(SysUserManager.class).duplicationValid(user,VALID_FIELD);
commandExecutor.execute(new SysUserCmd(userDto.getId(),userDto));
});
}
}
@GetMapping("/deleteById/{ids}")
@ApiResult(successCode = 200,successMsg = "操作成功")
@Operation(summary = "删除用户",description = "删除用户")
@PreAuthorize("hasAuthority('system:user:delete')")
public void deleteByIds(@PathVariable("ids") String ids) {
List<Long> longIds = new ArrayList<>();
for (String s : ids.split(",")) {
Long id = Long.parseLong(s);
commandExecutor.getReceiver(SysUserManager.class).findById(id).ifPresent(user -> {
longIds.add(id);
});
}
commandExecutor.getReceiver(SysUserManager.class).remove(longIds);
}
}
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bit.common.command.Executor;
import com.bit.common.core.command.CommonQry;
import com.bit.common.model.Authentication;
import com.bit.common.utils.AuthenticationHolder;
import com.bit.common.utils.Object_;
import com.bit.common.utils.String_;
import com.nii.admin.domain.entity.SysUser;
import com.nii.admin.domain.repository.SysUserDao;
import com.nii.admin.infra.utils.List_;
import com.nii.model.vo.SysUserVo;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class SysUserQry extends CommonQry<List<SysUser>> {
private SysUserVo userVo;
@Override
public List<SysUser> execute(Executor executor) {
isSensitized = true;
queryWrapper = new LambdaQueryWrapper<SysUser>()
.eq(Object_.isNotEmpty(userVo.getSex()), SysUser::getSex, userVo.getSex())
.eq(Object_.isNotEmpty(userVo.getState()), SysUser::getState, userVo.getState())
.eq(Object_.isNotEmpty(userVo.getDeptId()), SysUser::getDeptId, userVo.getDeptId())
.like(String_.isNotEmpty(userVo.getUserNo()), SysUser::getUserNo, userVo.getUserNo())
.like(String_.isNotEmpty(userVo.getMobile()), SysUser::getMobile, userVo.getMobile())
.like(String_.isNotEmpty(userVo.getEmail()), SysUser::getEmail, userVo.getEmail())
.like(String_.isNotEmpty(userVo.getUserName()), SysUser::getUserName, userVo.getUserName());
return this.paginate(SysUserDao.class);
}
}