命令模式和模板模式以及构造者模式在工程中的应用

发布时间 2023-07-08 22:54:53作者: dengyy

  在开发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);
    }
}