2023.056.07和09培训
项目实战
目录
一、infracore(基础核心层)
1.1database
1.2config
1.3util
二、业务领域模块
2.1structure模块
2.1.1domain层
2.1.2application层
2.1.3adapter层
2.2sensor模块
2.2.1domian层
2.2.2application层
2.2.3adapter层
一、infracore(基础核心层)
编写整个项目中全部通用的部分,包括:数据库操作、配置类、工具类(随机数、随机ID生成器、格式校验器)、缓存配置......
1.1database
Mysql包:
具体模块包(一个数据表对应一个模块)
DO数据容器(与数据表一一对应)
Mapper(Mybatis或plus操作数据库的SQL)
MapperEnum(字段枚举类)
MapperHelper(面向数据库层面的缓存服务类)
1.2config
1.3util
@Slf4j
public class SnowFlakeUtil {/*** 派号器workid:0~31* 机房datacenterid:0~31*/private static Snowflake snowflake = IdUtil.createSnowflake(1, 1);public static Long nextId() {return snowflake.nextId();}
}
二、业务领域模块
2.1structure模块
一个业务领域一个包
structure模块下的结构:
2.1.1domain层
domain领域层:
结构物基础信息 + 系统工程管理结点信息 + 文档信息 + 安全信息 + 统计信息
把零碎的、分散的基础信息,组建成完整的专业领域
reader
做所有的数据库读操作,组织各个数据表的数据结构,封装成专业名词,参数校验、分页、数据封装、无效数据剔除......
专业名词封装
//专业名词
@Data
public class Structure {private String id; // 唯一标识private String code; // 桥梁自定义编码-用于外连接-连接到工程结构树节点中的结构物节点上private String structureCode; // 结构物编码-数据对接专用-TDengine超级表名需要private String structureName; // 结构物名称private double longitude; // 经度private double latitude; // 纬度private String structureType; // 结构物类型-根据数据字典:桥梁、隧道、边坡、涵洞...private String address; // 结构物准确地址描述private long sensorCount;public static Structure generateStructure(StructureDO structureDO,long sensorCount){Structure structure = new Structure();BeanUtils.copyProperties(structureDO, structure);structure.setSensorCount(sensorCount);return structure;}}
reader编写对应方法
/*** @author: yangkx* @Title: SensorReader* @ProjectName: SwjtuPeixun* @Description:* @date: 2023-06-11 10:14*/
@Component
public class SensorReader {@Autowiredprivate SensorMapper sensorMapper;@Autowiredprivate MonitorSchemeMapper monitorSchemeMapper;//获取一座桥下面的所有传感器public List<Sensor> getAllForStructure(String structureNodeCode){LambdaQueryWrapper<SensorDO> lqw = new LambdaQueryWrapper<>();lqw.eq(SensorDO::getCode, structureNodeCode);List<SensorDO> records = sensorMapper.selectList(lqw);List<Sensor> result = new ArrayList<>();for(SensorDO record : records){String monitorSchemeId = record.getMonitorSchemeId();MonitorSchemeDO monitorScheme = monitorSchemeMapper.getById(monitorSchemeId);//专业名词Sensor sensor = Sensor.generateSensor(record, monitorScheme);//System.out.println(" " + sensor);//System.out.println(record);result.add(sensor);}return result;}}
writer
做所有的增删改操作
1)在reader包里,添加StructureCreateEntity类
添加转化为DO类的方法
@Data
public class StructureCreateEntity {private String code; // 桥梁自定义编码-用于外连接-连接到工程结构树节点中的结构物节点上private String structureCode; // 结构物编码-数据对接专用-TDengine超级表名需要private String structureName; // 结构物名称private String type; // 结构物类型-例如大桥,中桥,小桥private String level; // 结构物级别-例如2类,1类private double longitude; // 经度private double latitude; // 纬度private StructureType structureType; // 结构物类型-根据数据字典:桥梁、隧道、边坡、涵洞...//private String structureImage; // 结构物图片路径private String fileId; // Bimface模型文件IDprivate String address; // 结构物准确地址描述private String structureStyle; // 结构形式,如:150m钢筋混凝土箱型肋拱private String beginYear; // 结构物开始服役年份private String endYear; // 结构物结束服役年份(若有预期的,可填,没有则不填)private String structureDescribe; // 结构物描述private double bimLatitude; // BIM三维地图坐标经度private double bimLongitude; // BIM三维地图坐标纬度private double bimRotation; // BIM三维地图坐标旋转角度系数private double bimHigh; // BIM三维地图坐标高度public StructureDO toStructureDO(){StructureDO structureDO = new StructureDO();BeanUtils.copyProperties(this, structureDO);return structureDO;}
}
2) 回到database包里,在structure里新建StructureType类
public enum StructureType {BRIDGE("桥梁"),TUNNEL("隧道"),CULVERT("涵洞");private final String value;StructureType(String value){this.value = value;}public String value(){return value;}public static StructureType parseType(String type) throws Exception{switch (type){case "桥梁":return StructureType.BRIDGE;case "隧道":return StructureType.TUNNEL;case "涵洞":return StructureType.CULVERT;default:throw new Exception("工程结构结点类型解析失败");}}}
3)修改StructureService 添加create方法
public void create(CreateInDTO param) throws Exception{structureWriter.create(param.toEntity());}
4)为writer添加相应方法
@Component
public class StructureWriter {@Autowiredprivate StructureMapper structureMapper;public boolean create(StructureCreateEntity entity) throws Exception {int insertResult = structureMapper.insert(entity.toStructureDO());if(insertResult != 1)throw new Exception("插入失败!");return true;}public boolean uploadImage(String structureNodeCode,String url) throws Exception {int var = structureMapper.uploadImageUrl(structureNodeCode, url);if(var != 1)throw new Exception("插入失败!");return true;}}
5)修改applivation层里的StructureService
添加方法
public boolean create(CreateInDTO param) throws Exception{boolean var = structureWriter.create(param.toEntity());return var;
}public boolean uploadImage(String structureNodeCode, MultipartFile file) throws Exception{//1.判断文件有效if(file == null)throw new Exception("上传的文件异常");//2.先判断这个结构物存不存在if(structureNodeCode == null || "".equals(structureNodeCode))throw new Exception("输入结构物为空");Structure structure = structureReader.getByNodeCode(structureNodeCode);if(structure == null)throw new Exception("结构物不存在");//3.file上传到文件服务器String url = fileToHost(file);if(url == null || "".equals(url))throw new Exception("文件上传失败");boolean flag = structureWriter.uploadImage(structureNodeCode, url);return flag;
}private String fileToHost(MultipartFile file){System.out.println("文件正在上传到服务器");StringBuilder builder = new StringBuilder();builder.append("image").append(Math.random() * 1000000).append(".png");return builder.toString();}
6)转到adapter里 修改controller 进行测试
2.1.2application层
应用服务层: 编写具体的业务逻辑
event:领域时间驱动,发布器和处理器
DTO:Data Transfer Object
service:具体执行的业务逻辑,不关心数据,只管用
StructureService:structure的业务操作
@Service
public class StructureService {@Autowiredprivate StructureReader structureReader;public StructureOutDTO getByNodeCode(QueryParamInDTO param) throws Exception {if(!param.isValid())return null;Structure structure = structureReader.getByNodeCode(param.getStructureNodeCode());System.out.println(" " + structure);System.out.println("原始经纬度:" + structure.getLatitude() + " " + structure.getLongitude());//开始经纬度偏离业务 模拟switch(param.getIdentify()){case "超级管理员":System.out.println("超级管理员 经纬度:" + structure.getLatitude() + " " + structure.getLongitude());break;case "普通管理员":double random = Math.random();double rate = (random - 0.5) / (double)100;structure.setLatitude(structure.getLatitude() * (1D + rate));structure.setLongitude(structure.getLongitude() * (1D + rate));System.out.println("普通管理员 经纬度:" + structure.getLatitude() + " " + structure.getLongitude());break;case "用户":double random2 = Math.random();double rate2 = ((random2 - 0.5) / (double)100) * 2;structure.setLatitude(structure.getLatitude() * (1D + rate2));structure.setLongitude(structure.getLongitude() * (1D + rate2));System.out.println("用户 经纬度:" + structure.getLatitude() + " " + structure.getLongitude());break;default:break;}StructureOutDTO structureOutDTO = StructureOutDTO.generate(structure, param.getIdentify());return structureOutDTO;}}
QueryParamInDTO:封装查询参数
@Data
public class QueryParamInDTO {private String structureNodeCode;private String identify="用户";public QueryParamInDTO(String structureNodeCode, String identify) {this.structureNodeCode = structureNodeCode;this.identify = identify;}public QueryParamInDTO() {}public boolean isValid(){if(structureNodeCode == null || "".equals(structureNodeCode))return false;if(identify == null || "".equals(identify))return false;return true;}}
StructureOutDTO:封装数据 再次添加额外数据
@Data
public class StructureOutDTO {private String id; // 唯一标识private String code; // 桥梁自定义编码-用于外连接-连接到工程结构树节点中的结构物节点上private String structureCode; // 结构物编码-数据对接专用-TDengine超级表名需要private String structureName; // 结构物名称private double longitude; // 经度private double latitude; // 纬度private String structureType; // 结构物类型-根据数据字典:桥梁、隧道、边坡、涵洞...private String address; // 结构物准确地址描述//额外信息private long sensorCount;//再加额外数据private Date queryTime;private String userIdentify;public static StructureOutDTO generate(Structure structure,String identify){StructureOutDTO structureOutDTO = new StructureOutDTO();BeanUtils.copyProperties(structure, structureOutDTO);structureOutDTO.setUserIdentify(identify);structureOutDTO.setQueryTime(new Date(System.currentTimeMillis()));return structureOutDTO;}}
CreateInDTO:获取数据封装转化为Entity
@Data
public class CreateInDTO {private String code; // 桥梁自定义编码-用于外连接-连接到工程结构树节点中的结构物节点上private String structureCode; // 结构物编码-数据对接专用-TDengine超级表名需要private String structureName; // 结构物名称private String type; // 结构物类型-例如大桥,中桥,小桥private String level; // 结构物级别-例如2类,1类private double longitude; // 经度private double latitude; // 纬度//字符串 ---> enumprivate String structureType; // 结构物类型-根据数据字典:桥梁、隧道、边坡、涵洞...//private String structureImage; // 结构物图片路径private String fileId; // Bimface模型文件IDprivate String address; // 结构物准确地址描述private String structureStyle; // 结构形式,如:150m钢筋混凝土箱型肋拱private String beginYear; // 结构物开始服役年份private String endYear; // 结构物结束服役年份(若有预期的,可填,没有则不填)private String structureDescribe; // 结构物描述private double bimLatitude; // BIM三维地图坐标经度private double bimLongitude; // BIM三维地图坐标纬度private double bimRotation; // BIM三维地图坐标旋转角度系数private double bimHigh; // BIM三维地图坐标高度public StructureCreateEntity toEntity() throws Exception{StructureCreateEntity structureCreateEntity = new StructureCreateEntity();BeanUtils.copyProperties(this, structureCreateEntity);StructureType structureType = StructureType.parseType(this.structureType);if(structureType != null)structureCreateEntity.setStructureType(structureType);return structureCreateEntity;}}
2.1.3adapter层
适配器:适配客户、第三方需求
VO:
controller:接口开放
anticorrosive:防腐层 用于保证这个领域application层的纯洁性
test1:
编写Controller 在网页进行测试
@RestController
@RequestMapping("/structure")
public class StructureController {@Autowiredprivate StructureService structureService;@GetMapping("/query/{structureNodeCode}")public StructureOutDTO query(@PathVariable(value = "structureNodeCode") String structureNodeCode) throws Exception {QueryParamInDTO param = new QueryParamInDTO();param.setStructureNodeCode(structureNodeCode);StructureOutDTO outDTO = structureService.getByNodeCode(param);return outDTO;}}
测试结果:
test2:
修改StructureContorller
测试图片插入
@PostMapping("/create")public boolean create(@RequestBody CreateInDTO param) throws Exception{structureService.create(param);return true;
}@GetMapping("/uploadImage/{structureNodeCode}")public boolean uploadImage(@PathVariable("structureNodeCode") String structureNodeCode) throws Exception{boolean b = structureService.uploadImage(structureNodeCode,null);return b;
}
测试结果
2.2sensor模块
模块结构同structure模块,下面的模块结构也一样,就不再细说了
2.2.1domian层
domain领域层:
结构物基础信息 + 系统工程管理结点信息 + 文档信息 + 安全信息 + 统计信息
把零碎的、分散的基础信息,组建成完整的专业领域
task1:返回封装好的sensor
在reader包下新建entity包,新建Sensor类
Sensor类 = sensorDO + monitorSchemeDO
在Sensor类里添加generateSensor静态方法,返回封装好的Sensor对象
/*** @author: yangkx* @Title: Sensor* @ProjectName: SwjtuPeixun* @Description:* @date: 2023-06-11 10:45*/
//专业名词类
@Data
public class Sensor {private String id = SnowFlakeUtil.nextId().toString();private String sensorId; // 内部使用的,数据对接用的 id//private String monitorSchemeId; // 监测方案 id,与数据字典 - 监测方案挂钩private String monitorSchemeId; //监测方案 唯一 idprivate String monitorTypeName; // 监测类型名private String monitorContentName; // 监测内容名private String type; // 一级分类,结构响应、作用...private String location; // 位置private String sensorInstallCode; // 设备安装代码,一般是按规范指定的传感器idprivate String componentId; // BIM模型上的组件idprivate String sensorType; // 传感器类型,如倾角计private String sensorName; // 传感器名字,有需要再使用private String remark; // 备注public static Sensor generateSensor(SensorDO sensorDO, MonitorSchemeDO monitorSchemeDO){//sensorDO的数据Sensor sensor = new Sensor();sensor.setId(sensorDO.getId());sensor.setSensorId(sensorDO.getSensorId());sensor.setLocation(sensorDO.getLocation());sensor.setSensorInstallCode(sensorDO.getSensorInstallCode());sensor.setComponentId(sensorDO.getComponentId());sensor.setSensorType(sensorDO.getSensorType());sensor.setSensorName(sensorDO.getSensorName());sensor.setRemark(sensorDO.getRemark());//monitorSchemeDO的数据sensor.setMonitorSchemeId(monitorSchemeDO.getId());sensor.setMonitorTypeName(monitorSchemeDO.getMonitorTypeName());sensor.setMonitorContentName(monitorSchemeDO.getMonitorContentName());sensor.setType(monitorSchemeDO.getType());//返回封装好的对象return sensor;}
}
测试专业名词
1)Reader里编写对应方法
@Component
public class SensorReader {@Autowiredprivate SensorMapper sensorMapper;@Autowiredprivate MonitorSchemeMapper monitorSchemeMapper;//获取一座桥下面的所有传感器public List<Sensor> getAllForStructure(String structureNodeCode){LambdaQueryWrapper<SensorDO> lqw = new LambdaQueryWrapper<>();lqw.eq(SensorDO::getCode, structureNodeCode);List<SensorDO> records = sensorMapper.selectList(lqw);List<Sensor> result = new ArrayList<>();for(SensorDO record : records){String monitorSchemeId = record.getMonitorSchemeId();MonitorSchemeDO monitorScheme = monitorSchemeMapper.getById(monitorSchemeId);//专业名词Sensor sensor = Sensor.generateSensor(record, monitorScheme);//System.out.println(" " + sensor);//System.out.println(record);result.add(sensor);}return result;}}
2)test类调用reader里的方法
@Component
public class TestClass {@Autowiredprivate StructureReader structureReader;@Autowiredprivate SensorReader sensorReader;@PostConstructprivate void init(){//structureReader.getAll();sensorReader.getAllForStructure("1609494584646307840");}}
3)运行结果
2.2.2application层
应用服务层: 编写具体的业务逻辑
event:领域时间驱动,发布器和处理器
DTO:Data Transfer Object
service:具体执行的业务逻辑,不关心数据,只管用
@Service
public class SensorService {@Autowiredprivate SensorReader sensorReader;public void getForStructure(String structureNodeCode){List<Sensor> records = sensorReader.getAllForStructure(structureNodeCode);return;}}
2.2.3adapter层
适配器:适配客户、第三方需求
VO:
controller:接口开放
anticorrosive:防腐层 用于保证这个领域application层的纯洁性