美文网首页
springboot泛型封装开发

springboot泛型封装开发

作者: 古甲哈醒 | 来源:发表于2020-03-12 11:54 被阅读0次

    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<T>) 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泛型封装开发

          本文链接:https://www.haomeiwen.com/subject/vmsyjhtx.html