前面的几章我们构建了通用实体模型、注册中心、链路收集系统、本章我们将开始讲解如何构建我们的权限架构服务的生产者,我们微服务完全遵循我们的rest full规范,因此我们实际上可以高度抽象化一些我们的通用接口出来,因此本章我们将这些提供服务的生产者接口高度抽象出来,理论上这些高度抽象出来的接口是可以作为一个独立的module需要的时候使用maven引入,不过此处就不再解耦出来,而是直接写在我们的权限架构服务的生产者项目中。
直接在我们的工程中创建权限架构服务的生产者的modules如下所示:
接着在我们的rbac-produce项目中创建如下的包结构:
很明显我们的高度抽象化的基础类是写在我们的base包里,那么这时候我们就要思考我们经常在开发中遇到的都是那些经常会使用到的一些业务,然后我们把这些通用的业务抽象化出来成为我们的基础工具包,我们经常在开发中遇到的就是新增数据、修改数据、获取数据、删除数据、分页查询、判断是否重复因此我们把这几块高度抽象出来成为一个基础工具包,以后我们的业务中开发人员只要继承我们的基础工具包就可以了,完全不用写这些重复性的代码。
在我们编写抽象类之前我们要把我们第二章写的实体模型通过maven引入到我们的rbac-produce项目中,在我们pom.xml文件中加入以下配置以后的完整配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.produce</groupId>
<artifactId>rbac-produce</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>rbac-produce</name>
<description>权限架构服务提供者</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.base</groupId>
<artifactId>model</artifactId>
<version>[0.0.1-SNAPSHOT,)</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
现在开始编写我们的基础工具包的常量类,在我们的base包底下我们创建constant包,并在该包中创建SystemStaticConst.java类,文件内容如下:
package com.produce.common.base.constant;
/**
* Created by Administrator on 2017/8/7 0007.
*/
public class SystemStaticConst {
public final static String RESULT = "result";
public final static boolean SUCCESS = true;
public final static boolean FAIL = false;
public final static String MSG = "msg";
}
接着开始编写我们的基础工具包的dao接口类,在我们的base包底下我们创建dao包,并在该包中创建GenericDao.java接口类,文件内容如下:
package com.produce.common.base.dao;
import com.base.common.QueryBase;
import java.util.List;
/**
* Dao通用模版
* */
public interface GenericDao<T, Q extends QueryBase>{
/**
* 功能描述:根据ID来获取数据
* @param id
* @return
*/
T getById(int id);
/**
* 根据主键值获取对象
* @param entity
* */
public T get(T entity);
/**
* 获取全部实体
* */
public List<T> loadAll();
/**
* 查找是否存在
* @param queryModel 查询条件
* @return int
* */
public int isExist(Q queryModel);
/**
* 保存
* @param entity 保存对象
* @return int
* @throws Exception
* */
public int save(T entity) throws Exception;
/**
* 更新
* @param entity 修改对象
* @return int
* @throws Exception
* */
public int update(T entity) throws Exception;
/**
* 删除
* @param entity 删除对象
* @throws Exception
* @return int
* */
public int delete(T entity) throws Exception;
/**
* 分页查询
* @param queryModel 查询条件
* */
public List<T> findByPage(Q queryModel);
/**
* 统计
* @param queryModel 查询条件
* @return int
* */
public int count(Q queryModel);
/**
* 查询
* @param queryModel 查询条件
* */
public List<T> query(Q queryModel);
/**
* 根据id数组删除记录
* @param ids 数组
* @return int
* */
public int deleteByIds(String[] ids) throws Exception;
}
接着再编写我们的基础工具包的service抽象类,在我们的base包底下我们创建service包,并在该包中创建GenericService.java抽象类,文件内容如下:
package com.produce.common.base.service;
import com.base.common.Page;
import com.base.common.QueryBase;
import com.produce.common.base.dao.GenericDao;
import java.util.List;
/**
* 通用Service
* @author linzf
* */
public abstract class GenericService<T, Q extends QueryBase> {
protected abstract GenericDao<T, Q> getDao();
/**
* 功能描述:根据ID来获取数据
* @param id
* @return
*/
public T getById(int id){
return getDao().getById(id);
}
/**
* 根据主键值获取对象
* @param entity
* */
public T get(T entity){
return getDao().get(entity);
}
/**
* 获取全部实体
* */
public List<T> loadAll(){
return getDao().loadAll();
}
/**
* 查找是否存在
* @param queryModel 查询条件
* */
public boolean isExist(Q queryModel){
return getDao().isExist(queryModel)>0;
}
/**
* 保存
* @param entity 保存对象
* @return boolean
* @throws Exception
* */
public boolean save(T entity) throws Exception{
return getDao().save(entity)>0;
}
/**
* 更新
* @param entity 修改对象
* @return boolean
* @throws Exception
* */
public boolean update(T entity) throws Exception{
return getDao().update(entity)>0;
}
/**
* 删除
* @param entity 删除对象
* @return boolean
* @throws Exception
* */
public boolean delete(T entity) throws Exception{
return getDao().delete(entity)>0;
}
/**
* 分页查询
* @param queryModel 查询条件
* */
public Page findByPage(Q queryModel){
List<T> list = getDao().findByPage(queryModel);
int count = getDao().count(queryModel);
return new Page(list, count);
}
/**
* 统计
* @param queryModel 查询条件
* @return int
* */
public int count(Q queryModel){
return getDao().count(queryModel);
}
/**
* 查询
* @param queryModel 查询条件
* */
public List<T> query(Q queryModel){
return getDao().query(queryModel);
}
/**
* 根据id数组删除记录
* @param ids 数组
* @return boolean
* */
public boolean deleteByIds(String[] ids) throws Exception{
return getDao().deleteByIds(ids)>0;
}
/**
* 功能描述:批量删除数据
* @param entityList
* @return
*/
public boolean removeBath(List<T> entityList) throws Exception{
for(T t:entityList){
if(!delete(t)){
return false;
}
}
return true;
}
}
接着再编写我们的基础工具包的controller抽象类,在我们的base包底下我们创建controller包,并在该包中创建GenericController.java抽象类,文件内容如下:
package com.produce.common.base.controller;
import com.base.common.Page;
import com.base.common.QueryBase;
import com.base.util.json.JsonHelper;
import com.produce.common.base.constant.SystemStaticConst;
import com.produce.common.base.service.GenericService;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class GenericController<T, Q extends QueryBase> {
// 抽象方法
protected abstract GenericService<T, Q> getService();
/**
* 功能描述:根据ID来获取数据
* @param id
* @return
*/
@RequestMapping(value = "/getById",method = RequestMethod.POST)
public Map<String,Object> getById(int id)throws Exception{
Map<String,Object> result = new HashMap<String, Object>();
T t = getService().getById(id);
if(t==null){
result.put(SystemStaticConst.RESULT,SystemStaticConst.FAIL);
result.put(SystemStaticConst.MSG,"获取数据失败!");
result.put("entity",t);
}else{
result.put(SystemStaticConst.RESULT,SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"获取数据成功!");
result.put("entity",t);
}
return result;
}
/**
* 功能描述:获取数据
* @param entity
* @return
*/
@RequestMapping(value = "/get",method = RequestMethod.POST)
public Map<String,Object> get(@RequestBody T entity)throws Exception{
Map<String,Object> result = new HashMap<String, Object>();
T t = getService().get(entity);
if(t==null){
result.put(SystemStaticConst.RESULT,SystemStaticConst.FAIL);
result.put(SystemStaticConst.MSG,"获取数据失败!");
result.put("entity",t);
}else{
result.put(SystemStaticConst.RESULT,SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"获取数据成功!");
result.put("entity",t);
}
return result;
}
/**
* 功能描述:保存数据
* @param entity
* @return
*/
@RequestMapping(value = "/save",method = RequestMethod.POST)
public Map<String,Object> save(@RequestBody T entity) throws Exception{
boolean success = getService().save(entity);
Map<String,Object> result = new HashMap<String, Object>();
if(success==true){
result.put(SystemStaticConst.RESULT,SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"增加数据成功!");
result.put("entity",entity);
}else{
result.put(SystemStaticConst.RESULT,SystemStaticConst.FAIL);
result.put(SystemStaticConst.MSG,"增加数据失败!");
}
return result;
}
/**
* 功能描述:更新数据
* @param entity
* @return
*/
@RequestMapping(value = "/update",method = RequestMethod.POST)
public Map<String,Object> update(@RequestBody T entity) throws Exception{
boolean success = getService().update(entity);
Map<String,Object> result = new HashMap<String, Object>();
if(success==true){
result.put(SystemStaticConst.RESULT,SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"更新数据成功!");
result.put("entity",entity);
}else{
result.put(SystemStaticConst.RESULT,SystemStaticConst.FAIL);
result.put(SystemStaticConst.MSG,"更新数据失败!");
}
return result;
}
/**
* 功能描述:实现删除数据
* @param entity
* @return
*/
@RequestMapping(value = "/remove",method = RequestMethod.POST)
public Map<String,Object> remove(@RequestBody T entity) throws Exception{
Map<String,Object> result = new HashMap<String, Object>();
getService().delete(entity);
result.put(SystemStaticConst.RESULT,SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"删除数据成功!");
return result;
}
/**
* 功能描述:实现批量删除的记录
* @param json
* @return
*/
@RequestMapping(value = "/removeBath",method = RequestMethod.POST)
public Map<String,Object> removeBath(String json) throws Exception{
Map<String,Object> result = new HashMap<String, Object>();
getService().removeBath((List<T>) JsonHelper.toList(json,(Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]));
result.put(SystemStaticConst.RESULT, SystemStaticConst.SUCCESS);
result.put(SystemStaticConst.MSG,"删除数据成功!");
return result;
}
/**
* 功能描述:获取分页的数据
* @param entity
* @return
*/
@RequestMapping(value = "/list",method = RequestMethod.POST)
public Map<String,Object> list(@RequestBody Q entity){
Map<String,Object> result = new HashMap<String, Object>();
Page page = getService().findByPage(entity);
result.put("totalCount",page.getTotal());
result.put("result",page.getRows());
return result;
}
/**
* 功能描述:判断当前的元素是否已经存在
* @param entity
* @return
*/
@RequestMapping(value = "/isExist",method = RequestMethod.POST)
public Map<String,Object> isExist(@RequestBody Q entity){
Map<String,Object> result = new HashMap<String, Object>();
if(getService().query(entity).size()>0){
result.put("valid",false);
}else{
result.put("valid",true);
}
return result;
}
}
在我们的系统运行的过程中总是会遇到各种各样的报错,如果每一个报错我们都要自己去try-catch那么这代码编写起来也未免太麻烦了,因此我们需要一个全局异常捕获类,因此我们在config包底下新建了一个exception包,并创建了GlobalExceptionHandler.java全局异常处理类内容如下:
package com.produce.common.config.exception;
import com.produce.common.base.constant.SystemStaticConst;
import org.apache.catalina.connector.ClientAbortException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
* 类描述:错误捕获异常处理类,当出现报错的时候将错误数据用json的形式返回给页面。
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = SQLException.class)
@ResponseBody
public Map<String, Object> sqlExceptionHelper(HttpServletRequest req, SQLException e){
Map<String, Object> returnMap = new HashMap<String, Object>();
returnMap.put(SystemStaticConst.RESULT, SystemStaticConst.FAIL);
returnMap.put(SystemStaticConst.MSG,e.getMessage());
return returnMap;
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String, Object> handleGlobalException(HttpServletRequest req, Exception e){
Map<String, Object> returnMap = new HashMap<String, Object>();
returnMap.put(SystemStaticConst.RESULT, SystemStaticConst.FAIL);
returnMap.put(SystemStaticConst.MSG,e.getMessage());
return returnMap;
}
@ExceptionHandler(value = ClientAbortException.class)
public void handleGlobalClientAbortException(HttpServletRequest req, ClientAbortException e){
//System.out.println("------------socket断开连接-------------"+e.getLocalizedMessage());
System.out.println("------------socket断开连接-------------"+e.getLocalizedMessage());
}
}
到此为止我们已经完全了权限架构服务生产者的高度抽象化的工作,再下一章我们将讲诉我们如何基于我们本章的通用类来实现我们的权限架构服务生产者的具体业务实现逻辑。
到此为止的GitHub项目地址:https://github.com/185594-5-27/spring-cloud-rbac/tree/master-base-produce
上一篇文章地址:基于springboot+redis+bootstrap+mysql开发一套属于自己的分布式springcloud云权限架构(五)【构建鉴权中心】
下一篇文章地址:基于springboot+redis+bootstrap+mysql开发一套属于自己的分布式springcloud云权限架构(七)【权限架构生产者(数据字典)】
QQ交流群:578746866