前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速生成通用接口业务配置

快速生成通用接口业务配置

作者头像
程序员朱永胜
发布2023-08-21 10:16:17
2180
发布2023-08-21 10:16:17
举报
文章被收录于专栏:朱永胜的私房菜

这个是干什么的?

简单介绍下:

作用:通过插件一键生成某个表对应的增删改查等基础或者说通用接口,这里面的代码是基础版的,后续改良后,很多业务的通用功能,比如流程的启动,自动下一步,通用导出,通用导入等等。

原理:核心就是BasicControllerPostProcessor ,通过动态生成代理对象,完成逻辑实现。这里呢经过实践呢后续也有不少优化的,后续我总结后发一个新版的

一、核心处理类

代码语言:javascript
复制
package com.nari.core.handler;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;


/**
 * 动态加载baseMapper,baseDao,baseService
 *
 * @author <a href="mailto:njpkhuan@gmail.com">朱永胜</a>
 * @version 1.0.0
 * @since 2021/3/2
 */
@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BasicControllerPostProcessor extends CommonAnnotationBeanPostProcessor {

    private static final long serialVersionUID = -945664767382485314L;

    @SuppressWarnings("NullableProblems")
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        String packageName = beanClass.getPackage().getName();
        log.trace("beanName---{},packageName:{}", beanName, packageName);
        List<String> per = ListUtil.of("com.nari.supervision.daily");
        List<String> tail = ListUtil.of("outbound","personal");
        if (per.stream().anyMatch(packageName::contains)) {
            if (tail.stream().map(v -> v + ".controller").anyMatch(packageName::contains)) {
                try {
                    updateResourceName(beanClass, beanName, "basicService", "Controller", "Service");
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
            if (tail.stream().map(v -> v + ".service").anyMatch(packageName::contains)) {
                try {
                    updateResourceName(beanClass, beanName, "basicMapper", "Service", "TransformImpl");
                    updateResourceName(beanClass, beanName, "basicDao", "Service", "Mapper");
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
            if (tail.stream().map(v -> v + "serviceImpl").anyMatch(packageName::contains)) {
                try {
                    updateResourceName(beanClass, beanName, "basicMapper", "Service", "TransformImpl");
                    updateResourceName(beanClass, beanName, "basicDao", "Service", "Mapper");
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return null;
    }

    private void updateResourceName(Class<?> beanClass, String beanName, String destField, String searchString, String replaceString)
            throws NoSuchFieldException, IllegalAccessException {
        Field field = beanClass.getSuperclass().getDeclaredField(destField);
        Resource basicMapper = field.getAnnotation(Resource.class);
        InvocationHandler invocationHandler = Proxy.getInvocationHandler(basicMapper);
        Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
        memberValues.setAccessible(true);
        //noinspection unchecked
        Map<String, Object> map = (Map<String, Object>) memberValues.get(invocationHandler);
        map.put("name", StringUtils.replace(beanName, searchString, replaceString));
    }
}

二、基础类

BasicController

代码语言:javascript
复制
package com.nari.core.basic;

import com.nari.core.annotation.OperationLog;
import com.nari.core.groups.basic.InsertGroup;
import com.nari.core.groups.basic.UpdateGroup;
import com.nari.core.groups.query.PageQueryGroup;
import com.nari.core.web.ApiResult;
import com.nari.core.web.BaseParam;
import com.nari.core.web.PageResult;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiSort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;


/**
 * 基础接口管理
 *
 * @author <a href="mailto:njpkhuan@gmail.com">朱永胜</a>
 * @version 1.0.0
 * @since 2021/3/1
 */
@Slf4j
@Valid
public class BasicController<T extends BasicModel, Q extends BaseParam, V, D, M extends BasicMapper<T, Q, D, V>> extends com.nari.core.web.BaseController {

    @Resource
    private BasicService<T, Q, V, D, M> basicService;

    /**
     * 添加
     *
     * @param query {@link Q}
     */
    @PostMapping
    @ApiOperation(value = "1.1 添加")
    @OperationLog(value = "添加")
    @Validated(value = InsertGroup.class)
    public ApiResult insert(@RequestBody Q query) {
        basicService.insert(query);
        return success("添加成功!");
    }


    /**
     * 根据id删除
     *
     * @param id 主键
     */
    @DeleteMapping("/{id}")
    @ApiOperation(value = "1.2 根据id删除")
    @OperationLog(value = "根据id删除")
    public ApiResult del(@PathVariable("id") String id) {
        basicService.del(id);
        return success("删除成功!");
    }

    /**
     * 根据id删除-软删除,实际修改标识符
     *
     * @param id 主键
     */
    @DeleteMapping("/{id}/weak")
    @ApiOperation(value = "1.3 根据id删除-软删除,实际修改标识符")
    @OperationLog(value = "根据id删除-软删除,实际修改标识符")
    public ApiResult delWeak(@PathVariable("id") String id) {
        basicService.delWeak(id);
        return success("删除成功!");
    }


    /**
     * 根据id更新信息
     *
     * @param query {@link Q}
     */
    @PutMapping("update")
    @ApiOperation(value = "1.4 根据id更新信息")
    @OperationLog(value = "根据id更新信息")
    @Validated(value = UpdateGroup.class)
    public ApiResult<V> update(@RequestBody Q query) {
        return success(basicService.update(query));
    }

    /**
     * 根据id更新信息-批量
     *
     * @param query {@link Q}
     */
    @PutMapping("updateBatch")
    @ApiOperation(value = "1.5 根据id更新信息-批量")
    @OperationLog(value = "根据id更新信息-批量")
    @Validated(value = UpdateGroup.class)
    public ApiResult updateBatch(@RequestBody List<Q> query) {
        basicService.updateBatch(query);
        return success();
    }


    /**
     * 查询单个数据
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    @ApiOperation(value = "1.6 查询单个数据")
    @OperationLog(value = "查询单个数据")
    public ApiResult<V> select(@PathVariable("id") String id) {
        return success(basicService.select(id));
    }

    /**
     * 分页
     *
     * @param query {@link Q}
     */
    @GetMapping("page")
    @ApiOperation(value = "1.7 分页")
    @OperationLog(value = "分页")
    @Validated(value = PageQueryGroup.class)
    public ApiResult<PageResult<V>> listUser(Q query) {
        return success(basicService.page(query));
    }
}

BasicDao

代码语言:javascript
复制
package com.nari.core.basic;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.nari.core.web.BaseParam;
import com.nari.core.web.PageParam;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 基础接口
 *
 * @author <a href="mailto:njpkhuan@gmail.com">朱永胜</a>
 * @version 1.0.0
 * @since 2021/3/1
 */
public interface BasicDao<T extends BasicModel, D, Q extends BaseParam> extends BaseMapper<T> {
    List<D> selectPageRel(@Param("page") PageParam<D, Q> page, @Param("param") Q param);
}

BasicEnum

代码语言:javascript
复制
package com.nari.core.basic;


/**
 * 基础枚举
 * 主要用来配合apijson实现枚举展示
 *
 * @author <a href="mailto:17602556550@189.cn">朱永胜</a>
 * @version 1.0.0
 * @since 2023/5/25
 */
public interface BasicEnum {
    String getName();

    Integer getValue();
}

BasicMapper

代码语言:javascript
复制
package com.nari.core.basic;

import org.mapstruct.MappingTarget;

import java.util.List;


/**
 * 基础转换
 *
 * @author <a href="mailto:njpkhuan@gmail.com">朱永胜</a>
 * @version 1.0.0
 * @since 2021/3/1
 */
public interface BasicMapper<T, Q, D, V> {
    T query2do(Q query);

    V dto2View(D dto);

    D do2dto(T role);

    void update(Q query, @MappingTarget T t);

    List<V> dto2ViewPage(List<D> dto);
}

BasicModel

代码语言:javascript
复制
package com.nari.core.basic;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * 通用模型
 *
 * @author <a href="mailto:17602556550@189.cn">朱永胜</a>
 * @version 1.0.0
 * @since 2023/5/26
 */
@Data
public class BasicModel {
    /**
     * 主键
     */
    private String id;

    /**
     * 删除标识
     */
    @ApiModelProperty(value = "删除标识")
    private String deleted;
}

BasicService

代码语言:javascript
复制
package com.nari.core.basic;

import cn.hutool.core.util.IdUtil;
import com.nari.core.web.BaseParam;
import com.nari.core.web.PageParam;
import com.nari.core.web.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;


/**
 * 基础服务
 *
 * @author <a href="mailto:njpkhuan@gmail.com">朱永胜</a>
 * @version 1.0.0
 * @since 2021/3/1
 */
@Slf4j
public class BasicService<T extends BasicModel, Q extends BaseParam, V, D, M extends BasicMapper<T, Q, D, V>> {
    @Resource
    private BasicDao<T, D, Q> basicDao;

    @Resource
    private BasicMapper<T, Q, D, V> basicMapper;

    /**
     * 添加
     *
     * @param query {@link Q}
     * @author <a href = "mailto:njpkhuan@gmail.com" >朱永胜</a >
     * @since 2021/3/1
     * @since 1.0.0
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(@Valid Q query) {
        T t = basicMapper.query2do(query);
        t.setId(IdUtil.simpleUUID());
        basicDao.insert(t);
    }

    /**
     * 删除
     *
     * @param id {@link Q}
     * @author <a href = "mailto:njpkhuan@gmail.com" >朱永胜</a >
     * @since 2021/3/1
     * @since 1.0.0
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(@NotNull String id) {
        basicDao.deleteById(id);
    }

    /**
     * 根据用户id更新
     *
     * @param query @{@link Q}
     * @author <a href = "mailto:njpkhuan@gmail.com" >朱永胜</a >
     * @since 2021/3/1
     * @since 1.0.0
     */
    @Transactional(rollbackFor = Exception.class)
    public V update(@Valid Q query) {
        T data = basicMapper.query2do(query);
        basicDao.updateById(data);
        D d = basicMapper.do2dto(data);
        return basicMapper.dto2View(d);
    }

    /**
     * 查询
     *
     * @param id 主键
     * @author <a href = "mailto:njpkhuan@gmail.com" >朱永胜</a >
     * @since 2021/3/1
     * @since 1.0.0
     */
    public V select(@NotNull String id) {
        T data = basicDao.selectById(id);
        D d = basicMapper.do2dto(data);
        return basicMapper.dto2View(d);
    }


    /**
     * 查询多条记录
     *
     * @param query {@link Q}
     * @author <a href = "mailto:njpkhuan@gmail.com" >朱永胜</a >
     * @since 2021/2/23
     * @since 1.0.0
     */
    public PageResult<V> page(@Valid Q query) {
        PageParam<D, Q> page = new PageParam<>(query);
        page.setDefaultOrder("create_time desc");
        List<D> list = basicDao.selectPageRel(page, query);

        List<V> vList = basicMapper.dto2ViewPage(list);
        log.trace("{}", list);

        return new PageResult<>(vList, page.getTotal());
    }

    /**
     * 软删除
     *
     * @author <a href="mailto:17602556550@189.cn">朱永胜</a>
     * @since 2023/5/26
     */
    @Transactional(rollbackFor = Exception.class)
    public void delWeak(String id) {
        T t = basicDao.selectById(id);
        t.setDeleted("1");
        basicDao.updateById(t);
    }

    /**
     * 批量更新
     *
     * @author <a href="mailto:17602556550@189.cn">朱永胜</a>
     * @since 2023/6/6
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(List<Q> query) {
        query.forEach(this::update);
    }
}

GenericSuperclassUtil

代码语言:javascript
复制
package com.nari.core.basic;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class GenericSuperclassUtil {

    /*
     * 获取泛型类Class对象,不是泛型类则返回null
     */
    public static Class<?> getActualTypeArgument(Class<?> clazz) {
        Class<?> entitiClass = null;
        Type genericSuperclass = clazz.getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass)
                    .getActualTypeArguments();
            if (actualTypeArguments != null && actualTypeArguments.length > 0) {
                entitiClass = (Class<?>) actualTypeArguments[0];
            }
        }

        return entitiClass;
    }

    /*
     * 获取泛型类Class对象,不是泛型类则返回null
     */
    static Class<?> getActualTypeArgument(Class<?> clazz, Integer pos) {
        Class<?> entitiClass = null;
        Type genericSuperclass = clazz.getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass)
                    .getActualTypeArguments();
            if (actualTypeArguments != null && actualTypeArguments.length > pos) {
                entitiClass = (Class<?>) actualTypeArguments[pos];
            }
        }

        return entitiClass;
    }
}

三、POM

代码语言:javascript
复制
  <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
  
  <dependency>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct</artifactId>
      <version>${org.mapstruct.version}</version>
  </dependency>
代码语言:javascript
复制
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </path>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-mapstruct-binding</artifactId>
                <version>0.2.0</version>
            </path>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${org.mapstruct.version}</version>
            </path>
        </annotationProcessorPaths>

    </configuration>
</plugin>

本文由 mdnice 多平台发布

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这个是干什么的?
  • 一、核心处理类
  • 二、基础类
    • BasicController
      • BasicDao
        • BasicEnum
          • BasicMapper
            • BasicModel
              • BasicService
                • GenericSuperclassUtil
                • 三、POM
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档