开始前必读:基于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;
}
@Override
public 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 {
@Override
public 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);
}
}
@Override
public 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;
}
}