您的位置:首页 > 教程 > JAVA/JAVA编程 > 如何利用泛型封装通用的service层

如何利用泛型封装通用的service层

2022-06-21 18:14:28 来源:易采站长站 作者:

如何利用泛型封装通用的service层

目录
一、首先建立一个实体类WebVisitRecordEntity二、有了实体类之后三、实现BaseApi四、定义类自己的api五、测试六、扩展性七、总结

身为一名开发人员,大家都知道,我们经常会在项目中大量的编写许多重复的代码,比如说vHZ站长之家-易采站长站-Easck.Com

public Entity find(String id);

像这种代码,简单,但是写多了,可能也会容易出错,那么我们能不能直接编写一套完整的,通用的方法呢,这样既不用重复编写,还不用出错,说道通用的方法,泛型是个不错的选择.vHZ站长之家-易采站长站-Easck.Com

基础架构:spring-boot+spring mvc+spring jpa.vHZ站长之家-易采站长站-Easck.Com

jpa是个好东西,个人感觉它最大的好处是不需要自己手动建表.还能在修改了表字段以后,自动给你添加上上去,它不像mybatis,业务改了之后,还需要调整sql语句,vHZ站长之家-易采站长站-Easck.Com

好了,废话不多说,上代码:vHZ站长之家-易采站长站-Easck.Com

vHZ站长之家-易采站长站-Easck.Com

一、首先建立一个实体类WebVisitRecordEntity

继承BaseEntity.BaseEntity在项目里面,是所有实体类的最顶层.里面是封装了一些通用的属性.vHZ站长之家-易采站长站-Easck.Com

1.BaseEntityvHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function; 
import cn.yxw.function.Enum.status.StatusEnum; 
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
 
/**
 * @Author : yuanxw
 * @Description: 所有实体的父类
 * @Date: Created in 17:03 2018/5/15
 */
@MappedSuperclass
public abstract class BaseEntity implements Serializable{
 
    /**
     * id
     */
    @Id
    @Column(length = 32 )
    private String id;
 
    /**
     * 创建时间
     */
    private Date createTime;
 
    /**
     * 创建人
     */
    @Column(length = 32 )
    private String createUser;
 
    /**
     * 更新时间
     */
    private Date updateTime;
 
    /**
     * 更新人
     */
    @Column(length = 32 )
    private String updateUser;
 
    /**
     * 删除标记 --系统只做逻辑删除
     */
    @Column(length = 8 )
    private String delStatus = StatusEnum.FALSE.getStatus();
 
    /**
     * 启用标记 --默认已启用
     */
    @Column(length = 8 )
    private String enAbleStatus = StatusEnum.TRUE.getStatus();
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public Date getCreateTime() {
        return createTime;
    }
 
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
 
    public String getCreateUser() {
        return createUser;
    }
 
    public void setCreateUser(String createUser) {
        this.createUser = createUser;
    }
 
    public Date getUpdateTime() {
        return updateTime;
    }
 
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
 
    public String getUpdateUser() {
        return updateUser;
    }
 
    public void setUpdateUser(String updateUser) {
        this.updateUser = updateUser;
    }
 
    public String getDelStatus() {
        return delStatus;
    }
 
    public void setDelStatus(String delStatus) {
        this.delStatus = delStatus;
    }
 
    public String getEnAbleStatus() {
        return enAbleStatus;
    }
 
    public void setEnAbleStatus(String enAbleStatus) {
        this.enAbleStatus = enAbleStatus;
    }
}

2.WebVisitRecordEntityvHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function.domain.plugins; 
import cn.yxw.function.BaseEntity; 
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 15:16 2018/6/20
 */
@Entity()
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "web_visit_Record")
public class WebVisitRecordEntity extends BaseEntity {
 
    private static final long serialVersionUID = 341666498307329777L;
    /**
     * 访问次数
     */
    private int count = 0;
 
    public int getCount() {
        return count;
    }
 
    public void setCount(int count) {
        this.count = count;
    }
}

vHZ站长之家-易采站长站-Easck.Com

二、有了实体类之后

首先建立一个顶层的api接口。所有通用的api方法,可以放在这里(ResultBean是一个封装了一个结果的数据类,里面包含了定义执行是否成功,执行返回的数据,执行错误提示的消息)vHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function; 
import cn.yxw.function.result.ResultBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 10:32 2018/5/25
 */
public interface BaseApi<T extends BaseEntity> {
 
    /**
     * 查询
     * @param id
     * @return
     */
    T get(String id);
 
    /**
     * 查询
     * @param id
     * @return
     */
    T find(String id);
 
    /**
     * 删除
     * @param id
     * @return
     */
    ResultBean<T> delete(String id);
 
    ResultBean<T> delete(T entity);
 
    /**
     * 创建
     * @param entity
     * @return
     */
    ResultBean<T> create(T entity);
 
    /**
     * 更新
     * @param entity
     * @return
     */
    ResultBean<T> update(T entity);
 
    /**
     * 读取所有
     * @param pageable
     * @return
     */
    Page<T> page(Pageable pageable);
 
    /**
     * 判断id是否存在
     * @param id
     * @return
     */
    boolean exists(String id);
 
}

vHZ站长之家-易采站长站-Easck.Com

三、实现BaseApi

既然是要定义通用的api,那么不仅仅只是一套接口,我们需要在定义一个可以实现BaseApi的BaseServiceImpl,之后的所有实现类,都可以继承这个BaseServiceImpl.java的泛型,给了我们的项目很好的扩展性,而顶层BaseEntity也给了我很好的实现方案,将BaseEntity作为泛型的入口vHZ站长之家-易采站长站-Easck.Com

1.基本时限BaseApivHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function.service.impl.domain.userCenter; 
import cn.yxw.function.BaseApi;
import cn.yxw.function.BaseEntity;
import cn.yxw.function.result.ResultBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; 
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 14:31 2018/6/20
 */
public class BaseServiceImpl<T extends BaseEntity> implements BaseApi<T> { 
 
    @Override
    public T get(String id) {
        return null;
    }
 
    @Override
    public T find(String id) {
        return null;
    }
 
    @Override
    public ResultBean<T> delete(String id) {
        return null;
    }
 
    @Override
    public ResultBean<T> delete(T entity) {
        return null;
    }
 
    @Override
    public ResultBean<T> create(T entity) {
        return null;
    }
 
    @Override
    public ResultBean<T> update(T entity) {
        return null;
    }
 
    @Override
    public Page<T> page(Pageable pageable) {
        return null;
    }
 
    @Override
    public boolean exists(String id) {
        return false;
    }
}

2.使用jpa作为BaseServiceImpl的属性.vHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function.service.impl.domain.userCenter; 
import cn.yxw.function.BaseApi;
import cn.yxw.function.BaseEntity;
import cn.yxw.function.Enum.code.ServiceCodeEnum;
import cn.yxw.function.result.ResultBean;
import cn.yxw.function.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 14:31 2018/6/20
 */
public class BaseServiceImpl<T extends BaseEntity> implements BaseApi<T> {
 
    @Autowired
    private JpaRepository<T, String> baseRepository;
 
 
    @Override
    public T get(String id) {
        T entity =  this.baseRepository.getOne(id);
        return entity;
    }
 
    @Override
    public T find(String id) {
        return this.baseRepository.findById(id).get();
    }
 
    @Override
    public ResultBean<T> delete(String id) {
        this.baseRepository.deleteById(id);
        return ResultBean.success("");
    }
 
    @Override
    public ResultBean<T> delete(T entity) {
        this.baseRepository.delete(entity);
        return ResultBean.success(entity);
    }
 
    @Override
    public ResultBean<T> create(T entity) {
        if(ObjectUtil.isNull(entity)){
            return ResultBean.failfure("数据为空,无法创建!");
        }
        if(this.exists(entity.getId())){
            return ResultBean.failfure("实体id相同,无法重复创建!");
        }
        entity = this.baseRepository.saveAndFlush(entity);
        if(ObjectUtil.isNull(entity)){
            return ResultBean.failfure(ServiceCodeEnum.CORE_SYSTEM_FAILURE);
        }
        return ResultBean.success(entity);
    }
 
    @Override
    public ResultBean<T> update(T entity) {
        if(ObjectUtil.isNull(entity)){
            return ResultBean.failfure("数据为空,无法创建!");
        }
        if(!this.exists(entity.getId())){
            return ResultBean.failfure("数据库不存在该数据,无法执行更新");
        }
        entity = this.baseRepository.saveAndFlush(entity);
        if(ObjectUtil.isNull(entity)){
            return ResultBean.failfure(ServiceCodeEnum.CORE_SYSTEM_FAILURE);
        }
        return ResultBean.success(entity);
    }
 
    @Override
    public Page<T> page(Pageable pageable) {
        return null;
    }
 
    @Override
    public boolean exists(String id) {
        return this.baseRepository.existsById(id);
    }
}

vHZ站长之家-易采站长站-Easck.Com

四、定义类自己的api

继承BaseApi,定义实现类,继承BaseServiceImpl.并实现自己的apivHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function.domain.userCenter; 
import cn.yxw.function.BaseApi;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 14:44 2018/6/22
 */
public interface WebVisitRecordApi extends BaseApi<WebVisitRecordEntity> {
}
package cn.yxw.function.service.impl.domain.userCenter; 
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.domain.userCenter.WebVisitRecordApi;
import org.springframework.stereotype.Service;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 15:22 2018/6/20
 */
@Service
public class WebVisitRecordServiceImpl extends BaseServiceImpl<WebVisitRecordEntity> implements WebVisitRecordApi {   
}

vHZ站长之家-易采站长站-Easck.Com

五、测试

到这里,代码已经结束.>

package cn.yxw.function.controller.System.admin; 
import cn.yxw.function.controller.BaseController;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.result.ResultBean;
import cn.yxw.function.service.impl.domain.userCenter.WebVisitRecordServiceImpl;
import cn.yxw.function.util.ObjectUtil;
import com.alibaba.druid.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Date;
import java.util.Map;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 15:23 2018/6/20
 */
@RestController()
@RequestMapping(value = "web/record")
public class WebVisitRecordsController extends BaseController {
 
    @Autowired
    private WebVisitRecordServiceImpl webVisitRecordService; 
 
    @GetMapping(value = "/get")
    public Map get(String id){
        if(StringUtils.isEmpty(id)){
            return this.errorWithMsg("参数不得为空");
        }
        WebVisitRecordEntity entity = this.webVisitRecordService.find(id);
        return this.result(entity,"");
    }
 
    @PostMapping(value = "/create")
    public Map create(int num){
        WebVisitRecordEntity entity = new WebVisitRecordEntity();
        entity.setId(System.currentTimeMillis()+"");
        entity.setCreateTime(new Date());
        entity.setCount(num);
        ResultBean<WebVisitRecordEntity> result = this.webVisitRecordService.create(entity);
        return this.result(result.getDate(),result.getMsg());
    } 
 
    @PostMapping(value = "/update")
    public Map update(String id, int num){
        if(StringUtils.isEmpty(id)){
            return this.errorWithMsg("参数不得为空");
        }
        WebVisitRecordEntity entity = this.webVisitRecordService.find(id);
        if(ObjectUtil.isNull(entity)){
            return this.errorWithMsg("不存在该数据");
        }
        entity.setUpdateTime(new Date());
        entity.setCount(entity.getCount()+num);
        ResultBean<WebVisitRecordEntity> result = this.webVisitRecordService.update(entity);
        return this.result(result.getDate(),result.getMsg());
    } 
}

vHZ站长之家-易采站长站-Easck.Com

三次测试都已经成功,但是我们真实的项目不可能这么简单.所以我们再次测试下扩展性vHZ站长之家-易采站长站-Easck.Com

等等,不知道你们发现没有,上面的代码有一段是错误的.vHZ站长之家-易采站长站-Easck.Com

我在controller层的属性不是api,而是实现类.......vHZ站长之家-易采站长站-Easck.Com

虽然不影响,但是就无法扩展了...此处做修正vHZ站长之家-易采站长站-Easck.Com

vHZ站长之家-易采站长站-Easck.Com

vHZ站长之家-易采站长站-Easck.Com

六、扩展性

1.>

package cn.yxw.function.domain.userCenter; 
import cn.yxw.function.BaseApi;
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 14:44 2018/6/22
 */
public interface WebVisitRecordApi extends BaseApi<WebVisitRecordEntity> {
 
    /**
     * 统计所有的记录之和
     * @return
     */
    int countAll();
}

2. WebVisitRecordServiceImplvHZ站长之家-易采站长站-Easck.Com

package cn.yxw.function.service.impl.domain.userCenter;
 
import cn.yxw.function.domain.plugins.WebVisitRecordEntity;
import cn.yxw.function.domain.userCenter.WebVisitRecordApi;
import cn.yxw.function.util.ObjectUtil;
import org.springframework.stereotype.Service; 
import java.util.List;
 
/**
 * @Author : yuanxw
 * @Description:
 * @Date: Created in 15:22 2018/6/20
 */
@Service
public class WebVisitRecordServiceImpl extends BaseServiceImpl<WebVisitRecordEntity> implements WebVisitRecordApi { 
 
    @Override
    public int countAll() {
        List<WebVisitRecordEntity> list = super.baseRepository.findAll();
        int count = 0;
        if(ObjectUtil.isNull(list) || list.size() <= 0){
            return count;
        }
        for (WebVisitRecordEntity entity : list){
            count += entity.getCount();
        }
        return count;
    }
}

3. WebVisitRecordControllervHZ站长之家-易采站长站-Easck.Com

    @GetMapping(value = "count")
    public Map count(){
        return this.result(this.webVisitRecordService.countAll(),"执行成功");
    }

4.测试vHZ站长之家-易采站长站-Easck.Com

vHZ站长之家-易采站长站-Easck.Com

vHZ站长之家-易采站长站-Easck.Com

七、总结

emmmm.....其实我上面还有个小错误,就留给你们寻找吧vHZ站长之家-易采站长站-Easck.Com

其实,封装的这个service层,也有很大的局限性,比如说,如果我需要自定义dao层的方法,怎么办?需要执行sql语句怎么办,仔细想想,我们能不能再封装一个BaseRepository呢?然后作为BaseServiceImpl中的属性传入??????vHZ站长之家-易采站长站-Easck.Com

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易采站长站。vHZ站长之家-易采站长站-Easck.Com

如有侵权,请联系QQ:279390809 电话:15144810328

相关文章

  • Spring Cloud 整合Apache-SkyWalking实现链路跟踪的方法

    Spring Cloud 整合Apache-SkyWalking实现链路跟踪的方法

    什么是SkyWalking 查看官网https://skywalking.apache.org/ 分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。 安装 进入下载页面https://
    2020-06-18
  • 成功解决IDEA2020 Plugins 连不上、打不开的方法

    成功解决IDEA2020 Plugins 连不上、打不开的方法

    IntelliJ IDEA 2020.1 插件中心一直打不开,鉴于有部分同学反馈设置http proxy不能解决,所以可按以下顺序检查 一、设置 http proxy—勾上Auto-detect proxy setting,参照下图,加上地址 http://127.0.0
    2020-06-25
  • Java后台实现微信支付和微信退款

    Java后台实现微信支付和微信退款

    微信支付流程 都是我自己工作中开发的,亲测可用,不喜勿喷。 controller中我是这么写的,你们需要根据自己的业务需求改动。ResponseBean是我自己封装的,你们可以改成你们想要的形式
    2020-03-27
  • IDEA2020 1.1中Plugins加载不出来的问题及解决方法

    IDEA2020 1.1中Plugins加载不出来的问题及解决方法

    进入File-Setting 如图,取消勾选,点击确认后重启,点击了以后等一会就可以正常显示 ps:下面看下解决IDEA 2020.1.1 找不到程序包和符号 问题描述 IDEA 2020.1.1 maven项目build的时候报错,找
    2020-06-28
  • Intellij idea热部署插件JRebel的使用

    Intellij idea热部署插件JRebel的使用

    项目需求,一直用eclipse的我,也要改用IDEA了,一开始,很不习惯。经过几天的慢慢摸索和习惯之后,发现IDEA确实很好用。dark的界面是我喜欢的,智能的提示也让写代码不再枯燥。 遗
    2020-06-25
  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    详解基于IDEA2020.1的JAVA代码提示插件开发例子

    之前因为项目组有自己的代码规范,为了约束平时的开发规范,于是基于2019.1.3版本开发了一个代码提示的插件。但是在把IDEA切换到2020.1版本的时候,却发现疯狂报错,但是网上关于
    2020-06-25
  • springboot + rabbitmq 如何实现消息确认机制(踩坑经验)

    springboot + rabbitmq 如何实现消息确认机制(踩坑经验)

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷
    2020-07-01
  • JetBrains IntelliJ IDEA 2020安装与使用教程详解

    JetBrains IntelliJ IDEA 2020安装与使用教程详解

    对于JetBrains IntelliJ IDEA 2020的认识 IntelliJ IDEA 2020是一款JAVA编程软件,捷克IntelliJ公司研发推出。该软件提供了一个非常强大的JAVA集成开发环境,不仅添加了对Records的完整代码洞察支持,
    2020-06-28