开始前必读:基于grpc从零开始搭建一个准生产分布式应用(0) - quickStart
common包中的源码,因后续要用所以一次性全建好了。
一、common工程完整结构
二、引入依赖包
<?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"><parent><artifactId>base-grpc-framework-parent</artifactId><groupId>com.zd</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>base-grpc-framework-common</artifactId><dependencies><dependency><groupId>net.devh</groupId><artifactId>grpc-server-spring-boot-starter</artifactId><scope>compile</scope></dependency><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java-util</artifactId><scope>compile</scope></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><scope>compile</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><scope>compile</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>compile</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><scope>compile</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><scope>compile</scope></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><scope>compile</scope></dependency></dependencies></project>
三、源码-常量
package com.zd.baseframework.common.constants;/*** @Title: com.zd.baseframework.common.constants.ResponseConst* @Description 系统常量类,定义一些返回码等,这里不建议定义成(int, string)枚举,因为1个错误码可能对应多个描述字段,分开来定义更灵活,* 同时定义在一个类里面又达到了一种封装效果* @author liudong* @date 2022/6/15 8:48 PM*/
public interface ResponseConst {int SUCCESS = 0;int FAIL = 1;interface Msg{String SYS_ERROR = "系统异常 ";String SUCCESS = "请求成功";String FAIL = "请求失败";}}
package com.zd.baseframework.common.enumeration;/*** @author liudong* @Title: AppEnum* @Description 和系统相关的一些枚举值* @date 2022/2/6 12:27 PM*/
public interface AppEnum {enum AppType implements AppEnum {X_APP, DOMAIN, PLUGIN,;}enum Protocol implements AppEnum {HTTP("http"), HTTPS("https"), GRPC("grpc"),;private final String value;Protocol(String value) {this.value = value;}@Overridepublic String toString() {return this.value;}}
}
四、源码-对象基础类
Dao实体基础类
package com.zd.baseframework.common.entity.dao;import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.util.Date;/*** @author liudong* @Title: BaseEntity* @Description 此基类主要用于mybatis的实体定义继承用,这里固定了三个参数* id:数据库代理主键* ctime:创建时间* utime:更新时间* @date 2022/1/23 6:55 PM*/
@Data
@EqualsAndHashCode(callSuper = false, of = {"id"})
public abstract class BaseEntity<T extends Model<T>> extends Model<T> {@TableId(value = "id", type = IdType.ASSIGN_ID)private Long id;@TableField(value = "ctime", fill = FieldFill.INSERT, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date ctime;@TableField(value = "utime", fill = FieldFill.INSERT_UPDATE, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER)@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date utime;
}
package com.zd.baseframework.common.entity.dao;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.util.Date;@Slf4j
@Component
public class BaseMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 设置创建与更新时间Date nowTime = new Date();if (metaObject.hasGetter("ctime")) {// 记录创建信息this.setFieldValByName("ctime", nowTime, metaObject);}if (metaObject.hasGetter("utime")) {// 记录更新时间this.setFieldValByName("utime", nowTime, metaObject);}}@Overridepublic void updateFill(MetaObject metaObject) {if (metaObject.hasGetter("utime")) {Date nowTime = new Date();// 记录更新信息this.setFieldValByName("utime", nowTime, metaObject);}}
}
Http实体基础类
package com.zd.baseframework.common.entity.http;import com.zd.baseframework.common.constants.ResponseConst;
import lombok.Data;/*** @author liudong* @Title: com.zd.baseframework.common.entity.http.ResponseEntity* @Description 用于controller的正常返回* @date 2022/1/23 7:00 PM*/
@Data
public class BaseResponse<T> {/*响应状态码@see ResponseConstants*/private Integer status;/*响应概要信息*/private String message;/*响应数据*/private T data;public BaseResponse() {}public BaseResponse(Integer status, String message) {this.status = status;this.data = null;this.message = message;}public BaseResponse(Integer status, String message, T data) {this(status, message);this.data = data;}/*响应成功*/public static <T> BaseResponse<T> success(T o) {return new BaseResponse<>(ResponseConst.SUCCESS, ResponseConst.Msg.SUCCESS, o);}public static <T> BaseResponse<T> success(String msg, T o) {return new BaseResponse<>(ResponseConst.SUCCESS, msg, o);}/*响应失败*/public static <T> BaseResponse<T> error() {return new BaseResponse<>(ResponseConst.FAIL, ResponseConst.Msg.FAIL);}public static <T> BaseResponse<T> error(String msg) {return new BaseResponse<>(ResponseConst.FAIL, msg);}public static <T> BaseResponse<T> error(Integer status, String msg) {return new BaseResponse<>(status, msg);}
}
package com.zd.baseframework.common.entity.http;import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;/*** @author liudong* @Title: com.zd.baseframework.common.entity.http.FileResponseEntity* @Description 用于controller返回文件上传的返回值* @date 2022/1/23 7:11 PM*/
@Slf4j
public class FileResponse {public static ResponseEntity responseSuccess(File file) {if (file == null) {return null;}HttpHeaders headers = new HttpHeaders();headers.add("Cache-Control", "no-cache, no-store, must-revalidate");headers.add("Content-Disposition", "attachment; filename=" + file.getName());headers.add("Pragma", "no-cache");headers.add("Expires", "0");headers.add("Last-Modified", new Date().toString());headers.add("ETag", String.valueOf(System.currentTimeMillis()));return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));}public static ResponseEntity responseSuccess(String content, String fileName) {if (content == null) {return null;}File file = new File(fileName);try {OutputStream os = new FileOutputStream(file);os.write(content.getBytes());os.close();} catch (IOException e) {log.error("write to file error");}HttpHeaders headers = new HttpHeaders();headers.add("Cache-Control", "no-cache, no-store, must-revalidate");headers.add("Content-Disposition", "attachment; filename=" + file.getName());headers.add("Pragma", "no-cache");headers.add("Expires", "0");headers.add("Last-Modified", new Date().toString());headers.add("ETag", String.valueOf(System.currentTimeMillis()));return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));}}
package com.zd.baseframework.common.entity.http;import com.zd.baseframework.common.constants.ResponseConst;
import lombok.Data;import java.util.List;@Data
public class ListBaseResponse<T> extends BaseResponse<T> {/*数据的总条数*/private Long count;public ListBaseResponse() {super();}public ListBaseResponse(Integer status, String message) {super(status, message);}public ListBaseResponse(Integer status, String msg, T value, Integer count) {super(status, msg, value);this.count = Long.valueOf(count == null ? 0 : count);}public static ListBaseResponse responseListSuccess(String msg, List list) {long size = 0L;if (list != null) {size = list.size();}return new ListBaseResponse(ResponseConst.SUCCESS, msg, list, Math.toIntExact(size));}public static ListBaseResponse responseListSuccess(String msg, List list, Integer count) {return new ListBaseResponse(ResponseConst.SUCCESS, msg, list, count);}
}
package com.zd.baseframework.common.entity.http;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zd.baseframework.common.constants.ResponseConst;
import lombok.Data;/*** @author liudong* @Title: com.zd.baseframework.common.entity.http.PageResponseEntity* @Description 分页响应对象* @date 2022/1/23 7:30 PM*/
@Data
public class PageBaseResponse<T> extends ListBaseResponse<T> {/*偏移位置,用于内部计算*/private Long offset;/*每页多少条*/private Long pageSize;/*当前第几页*/private Long currentPage;public PageBaseResponse() {super();}public PageBaseResponse(Integer status, String message) {super(status, message);}public PageBaseResponse(Integer status, String msg, T value, Integer count, Integer offset, Integer pageSize, Integer currentPage) {super(status, msg, value, count);this.offset = Long.valueOf(offset);this.pageSize = Long.valueOf(pageSize);this.currentPage = Long.valueOf(currentPage);}/*为了适应IPage,暂定这样,后续有可能优化*/public PageBaseResponse(Integer status, String msg, T value, Long count, Long offset, Long pageSize, Long currentPage) {super(status, msg, value, Math.toIntExact(count));this.offset = Long.valueOf(offset);this.pageSize = Long.valueOf(pageSize);this.currentPage = Long.valueOf(currentPage);}public static <T> PageBaseResponse<T> responseListSuccess(String msg, IPage pageEntity) {return new PageBaseResponse(ResponseConst.SUCCESS, msg, pageEntity.getRecords(),Math.toIntExact(pageEntity.getTotal()),Math.toIntExact(pageEntity.offset()),Math.toIntExact(pageEntity.getSize()),Math.toIntExact(pageEntity.getCurrent()));}}
MapStruct工具类
可查看基于grpc从零开始搭建一个准生产分布式应用(5) - MapStruct传输对象转换附录部分
Model实体基础类
@Data
public abstract class BaseModel {private Long id;private Date ctime;private Date utime;
}
package com.zd.baseframework.common.entity.model;import lombok.Data;import java.util.List;@Data
public class WrapBoForDto<T> {private Integer count;private Integer offset;private Integer pageSize;private Integer currentPage;private List<T> data;
}
五、源码-异常
package com.zd.baseframework.common.exceptions;/*** @author liudong* @Title: AppException* @Description 基础异常类,用于处理普通业务上的异常,直接抛送即可,定义不同的异常类主要是用于区别异常的类型* @date 2022/1/17 4:52 PM*/
//TODO 异常传导链断了,需要修复
public class AppException extends RuntimeException {private Integer status;public AppException() {super();}public AppException(String message) {super(message);}public AppException(String s, Throwable throwable) {super(s, throwable);}public AppException(Throwable throwable) {super(throwable);}public AppException(Integer status, String message) {super(message);this.status = status;}public Integer getStatus() {return this.status;}}