springboot泛型封裝開發(fā)方式
JDK1.5出來后,Java開始支持泛型開發(fā),通過將父類聲明為泛型,子類繼承父類,子類就能擁有父類的方法,而不需要再寫代碼。
泛型開發(fā)能使我們的代碼開發(fā)提供了很大的簡便,簡化了我們的代碼。
在springboot項目中(其他項目也一樣),我們經(jīng)常要用到增刪改查接口,從controller/service/dao層,每一層都要寫增刪改查代碼,每一張數(shù)據(jù)表都要重復(fù)一遍增刪改查功能。雖然寫起來簡單,但是作為程序員來講,寫重復(fù)性的代碼就是在浪費時間,浪費生命。
程序員的主要精力應(yīng)該放在如何實現(xiàn)業(yè)務(wù)上面。
下面我們來看下怎樣通過泛型開發(fā)來封裝代碼,簡化開發(fā)。
一、聲明泛型父類
泛型父類包括: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、實現(xiàn)泛型父類BaseController,繼承 AbstractController
這里我們定義泛型父類BaseController,繼承并實現(xiàn)AbstractController方法,并且在BaseController中定義每個方法的RequestMapping。
這樣業(yè)務(wù)類直接繼承BaseController就可以使用默認(rèn)實現(xiàn)好的增刪改查接口了。
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,用于實現(xiàn)具體的業(yè)務(wù)操作
3、聲明泛型業(yè)務(wù)接口類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、定義泛型業(yè)務(wù)類BaseService,實現(xiàn)IService類
BaseService實現(xiàn)IService接口中發(fā)方法,編寫增刪改查操作默認(rèn)業(yè)務(wù)實現(xiàn)。子類通過繼承BaseService就擁有它的方法。
public class BaseService<T,K> implements IService<T,K> { @Autowired protected Mapper<T, K> mapper; private Class<T> modelClass;//當(dāng)前泛型的真實類型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對象,轉(zhuǎn)換為json時不會保留分頁信息 PageInfo pageInfo = page.toPageInfo();//將page轉(zhuǎn)換成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對數(shù)據(jù)庫進行增刪改查操作
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); /** * 分頁查詢(由子類實現(xiàn)) * @param params * @return */ Page queryPageList(Map<String, Object> params); /** * 多條件查詢(由子類實現(xiàn)) * @param params * @return */ List<Map<String,Object>> queryList(Map<String, Object> params); }
這里我們使用mybatis實現(xiàn)dao層的操作,這里的聲明的接口方法名稱與mybatis工具生成mapper.xml一致
到這里,我們的泛型父類代碼已經(jīng)全部編寫完成??梢詫⑸鲜龃a達(dá)成jar包,放入項目里面作為基礎(chǔ)包直接引用。
下面我們來說說怎么在項目里面實際使用。
二、項目應(yīng)用
在項目里面引用,只需在子類代碼層中繼承上述父類,子類就擁有父類中的功能。
1、子類Controller
@RestController @RequestMapping("/api/dic") public class DataDicController extends BaseController<DataDic, Integer> { }
看到?jīng)],里面什么方法也沒寫,只聲明了RequestMapping,另外將泛型用具體對象類型替換。
DataDic是我操作的對象,Integer是DataDic的主鍵類型。
這個BaseController的新增接口地址是/api/dic/insert,/insert是使用父類的RequestMapping。
另外我也沒寫Service的注入,因為容器會根據(jù)要父類中要注入的泛型Service,直接找到IService對應(yīng)的泛型實例
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對象會包含默認(rèn)的方法,大家不用刪除,因為和繼承的Mapper方法名一致,就當(dāng)是覆蓋Override
到此,所有工作結(jié)束,我們的DataDicController的增刪改查接口寫好 ,下面我們來測試。
三、接口測試
1、查詢接口get
2、插入接口insert
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Java反射機制提高SpringBoot的代碼質(zhì)量和可維護性
保持好的代碼質(zhì)量和遵守編碼標(biāo)準(zhǔn)是開發(fā)可維護和健壯軟件的重要方面,在本文中,我們將探討如何使用 Java 反射來提高 Spring Boot 應(yīng)用程序的代碼質(zhì)量和可維護性,需要的朋友可以參考下2023-10-10SpringBoot Import及自定義裝配實現(xiàn)方法解析
這篇文章主要介紹了SpringBoot Import及自定義裝配實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08Java并發(fā)編程之ReentrantLock實現(xiàn)原理及源碼剖析
ReentrantLock 是常用的鎖,相對于Synchronized ,lock鎖更人性化,閱讀性更強,文中將會詳細(xì)的說明,請君往下閱讀2021-09-09Java中的ArrayList.trimToSize()方法詳解
這篇文章主要介紹了Java中的ArrayList.trimToSize()方法詳解,前幾天看了Java?ArrayList,沒有明白trimToSize()這個方法是什么意思,所以看了一下源碼并且debug一下自己的一個例子,明白了其中的含義,需要的朋友可以參考下2023-11-11java如何實現(xiàn)postman中用x-www-form-urlencoded參數(shù)的請求
在Java開發(fā)中,模擬Postman發(fā)送x-www-form-urlencoded類型的請求是一個常見需求,本文主要介紹了如何在Java中實現(xiàn)這一功能,首先,需要通過導(dǎo)入http-client包來創(chuàng)建HTTP客戶端,接著,利用該客戶端發(fā)送Post請求2024-09-09Java Swing JPasswordField密碼框的實現(xiàn)示例
這篇文章主要介紹了Java Swing JPasswordField密碼框的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12