1.问题来源
我们使用SpringMVC的时候,正常情况下调用一个mapper接口,我们需要在service里面先实例化一个mapper对象,然后调用对应的方法。现在有一种情况:有多个service,每个service里面都有一个selectAll()方法,执行相同的业务流程,唯一不同的就是方法内部调用的方法来自不同的mapper对象,这样我们就需要写很多相似的代码。
问题来了:有没有一种简单的方法,可以将这个类似的selectAll()方法从service里面抽取出来,做成一个公共的查询方法,调用的时候,只需要传入不同的mapper对象,就可以去执行整个方法呢?基于这个想法,我们可以使用以下方式来满足我们的要求:
1. 实现一个公共的mapper接口BaseDao.java,定义getList()方法;
2. 所有普通mapper都继承BaseDao接口
3. 实现一个公共的service类BaseService.java,实现selectAll()方法,将BaseDao作为参数传入。
4. 所有普通service都继承BaseService类
5. 普通service中调用这个selectAll()方法即可。
2.实现
2.1 创建BaseDao
将业务逻辑相似的方法都抽取出来
import java.util.List;
public interface BaseDao<T> {
/**
* <h5>功能:根据条件获取全部信息</h5>
*
* @param paramMap
* @return List<T>
*/
List<T> selectAll();
}
2.2 继承BaseDao
import org.apache.ibatis.annotations.Mapper;
import com.qfx.modules.common.dao.BaseDao;
import com.qfx.modules.system.entity.SysMenu;
@Mapper
public interface SysMenuMapper extends BaseDao<SysMenu>{
}
2.3 创建BaseService
这里要注意,抽取的公共方法selectAll()中,参数是mapper的父类BaseDao
import java.util.List;
import com.qfx.modules.common.dao.BaseDao;
public class BaseService<T> {
/**
* 查询信息(这里抽取为公共方法)
* @param baseDao mapper实例
* @return
*/
protected List<T> selectAll(BaseDao<T> baseDao) {
// 相同流程1略...
// 动态调用不同mapper的selectAll()方法
List<T> list = baseDao.selectAll();
// 相同流程2略...
return list;
}
}
注意点:
2.4 继承BaseService
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.qfx.modules.common.service.BaseService;
import com.qfx.modules.system.dao.SysMenuMapper;
import com.qfx.modules.system.entity.SysMenu;
@Service
public class SysMenuSer extends BaseService<SysMenu> {
@Autowired
SysMenuMapper sysMenuMapper;
/**
* 查询菜单信息
*/
public List<SysMenu> getList() {
// 调用BaseService中的selectAll()方法
return selectAll(sysMenuMapper);
}
}
重点关注这里:
2.5 测试
至此,mapper接口动态调用的功能已经实现,我们执行一下单元测试,看看是否成功。
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.alibaba.fastjson.JSONObject;
import com.qfx.modules.system.entity.SysMenu;
import com.qfx.modules.system.service.impl.SysMenuSer;
@SpringBootTest
class RunAppTests {
@Autowired
SysMenuSer sysMenuSer;
@Test
void test() {
List<SysMenu> sysMenuList = sysMenuSer.getList();
for (SysMenu sysMenu : sysMenuList) {
System.out.println(JSONObject.toJSONString(sysMenu));
}
}
}
执行结果:正常输出,到这里就结束了,其他业务继续正常编写即可。
3.扩展(抽取分页方法)
这里将pagehelper分页的方法抽取为一个公共的方法,完整代码如下:
3.1 创建BaseDao
创建公共接口BaseDao.java
import java.util.List;
import java.util.Map;
public interface BaseDao<T> {
/**
* <h5>功能:根据条件获取全部信息</h5>
*
* @param paramMap
* @return List<T>
*/
List<T> selectAll(Map<String, Object> paramMap);
}
3.2 继承BaseDao
Mapper接口继承BaseDao接口
import com.qfx.modules.common.dao.BaseDao;
import com.qfx.modules.system.entity.SysMenu;
public interface SysMenuMapper extends BaseDao<SysMenu>{
}
3.3 创建BaseService
封装了 获取从request中传递过来的参数信息
、获取分页信息
、分页查询信息
等公共方法。
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qfx.modules.common.dao.BaseDao;
public class BaseService<T> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
protected static String CURRENT_PAGE_NAME = "page";
protected static String PAGE_SIZE_NAME = "limit";
@Autowired
protected HttpServletRequest request;
/**
* <h5>功能:获取从request中传递过来的参数信息</h5>
*
* @return Map<String, Object>
*/
protected Map<String, Object> getMaps() {
Map<String, Object> paramMap = new HashMap<String, Object>();
Enumeration<String> enume = request.getParameterNames();
while (enume.hasMoreElements()) {
String key = (String) enume.nextElement();
String[] values = request.getParameterValues(key);
paramMap.put(key, values.length == 1 ? request.getParameter(key).trim() : values);
}
return paramMap;
}
/**
* @功能描述:获取分页信息
*
* @param map
* @return
*
* @作者:zhangpj @创建时间:2018年3月23日
*/
protected Page<T> getPage(Map<String, Object> map) {
int pageNum = 1;
int pageSize = 10;
if (map.containsKey(CURRENT_PAGE_NAME) && !"".equals(map.get(CURRENT_PAGE_NAME))) {
pageNum = Integer.parseInt((String) map.get(CURRENT_PAGE_NAME));
}
if (map.containsKey(PAGE_SIZE_NAME) && !"".equals(map.get(PAGE_SIZE_NAME))) {
pageSize = Integer.parseInt((String) map.get(PAGE_SIZE_NAME));
}
Page<T> page = new Page<>(pageNum, pageSize);
return page;
}
/**
* 分页查询信息(这里抽取为公共方法)
* @param baseDao
* @return
*/
protected Map<String, Object> selectAll(BaseDao<T> baseDao) {
Map<String, Object> paramMap = getMaps();
Page<T> page = getPage(paramMap);
PageHelper.startPage(page.getPageNum(), page.getPageSize());
List<T> list = baseDao.selectAll(paramMap);
PageInfo<T> pageInfo = new PageInfo<>(list);
long total = pageInfo.getTotal();
Map<String, Object> map = new HashMap<>();
map.put("code", 0);
map.put("count", total);
map.put("data", pageInfo.getList());
return map;
}
}
3.4 继承BaseService
继承BaseService类,直接调用其中的方法即可
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.qfx.modules.common.service.BaseService;
import com.qfx.modules.system.dao.SysMenuMapper;
import com.qfx.modules.system.entity.SysMenu;
@Service
public class SysMenuSerImpl extends BaseService<SysMenu> {
@Autowired
SysMenuMapper sysMenuMapper;
/**
* 分页查询菜单信息(抽取为公共方法)
*/
public Map<String, Object> getList() {
return selectAll(sysMenuMapper);
}
}
重点关注这里:
3.5 Controller
正常编写控制器即可
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.qfx.modules.system.service.impl.SysMenuSerImpl;
@RestController
@RequestMapping("sys/menu")
public class SysMenuCtl {
@Autowired
SysMenuSerImpl sysMenuSerImpl;
/**
* 分页查询菜单信息
* @return
*/
@RequestMapping("list")
public Map<String,Object> list(){
return sysMenuSerImpl.getList();
}
}
3.6 测试
http://127.0.0.1:8081/sys/menu/list?page=2&limit=2
http://127.0.0.1:8081/sys/menu/list?page=6&limit=2