springboot泛型封装开发方式

 更新时间:2023年12月15日 08:55:00   作者:古甲哈醒  
这篇文章主要介绍了springboot泛型封装开发方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

JDK1.5出来后,Java开始支持泛型开发,通过将父类声明为泛型,子类继承父类,子类就能拥有父类的方法,而不需要再写代码。

泛型开发能使我们的代码开发提供了很大的简便,简化了我们的代码。

在springboot项目中(其他项目也一样),我们经常要用到增删改查接口,从controller/service/dao层,每一层都要写增删改查代码,每一张数据表都要重复一遍增删改查功能。虽然写起来简单,但是作为程序员来讲,写重复性的代码就是在浪费时间,浪费生命。

程序员的主要精力应该放在如何实现业务上面。

下面我们来看下怎样通过泛型开发来封装代码,简化开发。

一、声明泛型父类

泛型父类包括:controller/service/dao三层。

1、声明泛型虚基类AbstractController,定义接口方法:

public abstract class AbstractController<T, K>{

    /**
     * 新增
     * @param t
     * @return
     */
    public abstract RtnData insert(T t);

    /**
     * 修改
     * @param t
     * @return
     */
    public abstract RtnData update(T t);

    /**
     * 删除
     * @param
     * @return
     */
    public abstract RtnData delete(K id);

    /**
     * 按主键查询
     * @param
     * @return
     */
    public abstract RtnData get(K Id);

    /**
     * 分页查询
     * @return
     */
    public abstract RtnData queryPageList(int pageSize, int pageIndex, Map<String,Object> params);

    /**
     * 多条件查询
     * @return
     */
    public abstract RtnData queryList(Map<String,Object> params);

}

2、实现泛型父类BaseController,继承 AbstractController

这里我们定义泛型父类BaseController,继承并实现AbstractController方法,并且在BaseController中定义每个方法的RequestMapping。

这样业务类直接继承BaseController就可以使用默认实现好的增删改查接口了。

public class BaseController<T, K> extends AbstractController<T, K> {

    @Autowired
    private IService<T, K> service;

    @PostMapping("/insert")
    @Override
    public RtnData insert(@RequestBody T t) {
        return RtnData.ok(service.insert(t));
    }

    @PostMapping("/update")
    @Override
    public RtnData update(@RequestBody T t) {
        return RtnData.ok(service.update(t));
    }

    @GetMapping("/delete")
    @Override
    public RtnData delete(K id) {
        return RtnData.ok(service.delete(id));
    }

    @GetMapping("/get")
    @Override
    public RtnData get(K id) {
        return RtnData.ok(service.get(id));
    }

    @GetMapping("/page-list")
    @Override
    public RtnData queryPageList(@RequestParam(required = false, defaultValue = "20") int pageSize,
                                 @RequestParam(required = false, defaultValue = "1") int pageIndex,
                                 @RequestParam Map<String,Object> params) {
        return RtnData.ok(service.queryPageList(pageSize, pageIndex, params));
    }

    @GetMapping("/list")
    @Override
    public RtnData queryList(@RequestParam Map<String, Object> params) {
        return RtnData.ok(service.queryList(params));
    }
}

BaseController注入了泛型IService,用于实现具体的业务操作

3、声明泛型业务接口类IService

public interface IService<T,K>{

    /**
     * 新增
     * @param t
     * @return
     */
    public Object insert(T t);

    /**
     * 修改
     * @param t
     * @return
     */
    public Object update(T t);

    /**
     * 删除
     * @param
     * @return
     */
    public Object delete(K id);

    /**
     * 按主键查询
     * @param
     * @return
     */
    public T get(K id);

    /**
     * 分页查询
     * @param pageSize
     * @param pageIndex
     * @param params
     * @return
     */
    Object queryPageList(int pageSize, int pageIndex, Map<String, Object> params);

    /**
     * 条件查询
     * @param params
     * @return
     */
    Object queryList(Map<String, Object> params);
}

4、定义泛型业务类BaseService,实现IService类

BaseService实现IService接口中发方法,编写增删改查操作默认业务实现。子类通过继承BaseService就拥有它的方法。

public class BaseService<T,K> implements IService<T,K> {

    @Autowired
    protected Mapper<T, K> mapper;

    private Class<T> modelClass;//当前泛型的真实类型Class

    public BaseService() {
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<T>) pt.getActualTypeArguments()[0];
    }

    @Override
    public Object insert(T t) {
        return mapper.insert(t);
    }

    @Override
    public Object update(T t) {
        return mapper.updateByPrimaryKey(t);
    }

    @Override
    public Object delete(K id) {
        return mapper.deleteByPrimaryKey(id);
    }

    @Override
    public T get(K id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public Object queryPageList(int pageSize, int pageIndex, Map<String, Object> params) {
        PageHelper.startPage(pageIndex, pageSize);
        Page page = mapper.queryPageList(params);//Page本身是一个ArrayList对象,转换为json时不会保留分页信息
        PageInfo pageInfo = page.toPageInfo();//将page转换成pageInfo会保存分页信息返回
        return new PageModel(pageInfo);
    }

    @Override
    public Object queryList(Map<String, Object> params) {
        return mapper.queryList(params);
    }

}

这里最重要的两行代码:

ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
modelClass = (Class) pt.getActualTypeArguments()[0];

通过泛型反射,获取子类中实际要操作的对象class,通过class,service就知道要对哪个对象进行增删改查操操作。

另外,我们注入了dao层的泛型Mapper<T, K>,通过Mybatis对数据库进行增删改查操作

5、声明Dao层泛型Mapper

public interface Mapper<T, K> {

    int deleteByPrimaryKey(K id);

    int insert(T record);

    int insertSelective(T record);

    T selectByPrimaryKey(K id);

    int updateByPrimaryKeySelective(T record);

    int updateByPrimaryKey(T record);

    /**
     * 分页查询(由子类实现)
     * @param params
     * @return
     */
    Page queryPageList(Map<String, Object> params);

    /**
     * 多条件查询(由子类实现)
     * @param params
     * @return
     */
    List<Map<String,Object>> queryList(Map<String, Object> params);
}

这里我们使用mybatis实现dao层的操作,这里的声明的接口方法名称与mybatis工具生成mapper.xml一致

到这里,我们的泛型父类代码已经全部编写完成。可以将上述代码达成jar包,放入项目里面作为基础包直接引用。

下面我们来说说怎么在项目里面实际使用。

二、项目应用

在项目里面引用,只需在子类代码层中继承上述父类,子类就拥有父类中的功能。

1、子类Controller

@RestController
@RequestMapping("/api/dic")
public class DataDicController extends BaseController<DataDic, Integer> {
}

看到没,里面什么方法也没写,只声明了RequestMapping,另外将泛型用具体对象类型替换。

DataDic是我操作的对象,Integer是DataDic的主键类型。

这个BaseController的新增接口地址是/api/dic/insert,/insert是使用父类的RequestMapping。

另外我也没写Service的注入,因为容器会根据要父类中要注入的泛型Service,直接找到IService对应的泛型实例

2、子类Service

@Service
public class DataDicService extends BaseService<DataDic, Integer> {
}

同样,Service也没有任何代码,也没有注入Mapper,只继承了泛型

3、子类Mapper

@Mapper
public interface DataDicMapper extends com.cc.app.base.dao.Mapper<DataDic, Integer> {
}

Mapper需要继承我们自己定义的泛型Mapper,这样才能被Service找到。

说明:我们通过工具生成的Mapper对象会包含默认的方法,大家不用删除,因为和继承的Mapper方法名一致,就当是覆盖Override

到此,所有工作结束,我们的DataDicController的增删改查接口写好 ,下面我们来测试。

三、接口测试

1、查询接口get

image.png

2、插入接口insert

image.png

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot项目中mybatis-plus@Mapper注入失败问题

    springboot项目中mybatis-plus@Mapper注入失败问题

    这篇文章主要介绍了springboot项目中mybatis-plus@Mapper注入失败问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Java多线程之ReentrantReadWriteLock源码解析

    Java多线程之ReentrantReadWriteLock源码解析

    这篇文章主要介绍了Java多线程之ReentrantReadWriteLock源码解析,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-05-05
  • springMvc请求的跳转和传值的方法

    springMvc请求的跳转和传值的方法

    本篇文章主要介绍了springMvc请求的跳转和传值的方法,这里整理了几种跳转方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • Java中实现二叉树的遍历与重构

    Java中实现二叉树的遍历与重构

    这篇文章主要介绍了Java中实现二叉树的遍历与重构,树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合,把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的,需要的朋友可以参考下
    2023-10-10
  • Elasticsearch配置文件示例示范

    Elasticsearch配置文件示例示范

    这篇文章主要为大家介绍了Elasticsearch配置文件的示例示范,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Java安全之Filter权限绕过的实现

    Java安全之Filter权限绕过的实现

    在一些需要挖掘一些无条件RCE中,大部分类似于一些系统大部分地方都做了权限控制的,而这时候想要利用权限绕过就显得格外重要,本文就介绍了如何实现,一起来了解一下
    2021-05-05
  • springboot集成nacos读取nacos配置数据的原理

    springboot集成nacos读取nacos配置数据的原理

    这篇文章主要介绍了springboot集成nacos读取nacos配置数据的原理,文中有详细的代码流程,对大家学习springboot集成nacos有一定的帮助,需要的朋友可以参考下
    2023-05-05
  • java子类调用父类的方法中包含子类重写的实例方法

    java子类调用父类的方法中包含子类重写的实例方法

    在本篇文章里小编给大家整理了关于java子类调用父类的方法中包含子类重写的实例方法以及相关知识点,需要的朋友们可以学习下。
    2019-09-09
  • Spring Boot接口幂等插件用法示例解析

    Spring Boot接口幂等插件用法示例解析

    这篇文章主要介绍了Spring Boot接口幂等插件用法示例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Java中的8大基本数据类型详解

    Java中的8大基本数据类型详解

    这篇文章主要介绍了Java中8大基本数据类型的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论