在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:NXCheckPart开源软件地址:https://gitee.com/mumulx/nxcheck-part开源软件介绍:基于Spring Cloud的NX三维模型检测系统的设计与实现毕设题目:基于Spring Cloud的NX三维模型检测系统的设计与实现 项目名:NXCheckPart 本项目不用做任何商用用途,仅供自己学习使用,如有侵权请联系本人[email protected] 介绍NXCheckPart是一个基于SpringBoot、SpringCloud、Spring Security、FastDfs、NX1926的分布式三维模型检测系统。将传统的NX的CheckMate功能进行扩展,使之不再拘束于只能在本地进行部件检查,而将其功能集成到web中,使得用户能够实时的进行三维模型的检测并且用户能够实时获取测试结果。 Spring Cloud是一个微服务治理框架,提供了一套服务拆分与管理的工具,对于分布式的开发有着很好的支持,因此是本系统主框架的不二之选。 本系统的优点如下:
本项目不用做任何商用用途,仅供自己学习使用,如有侵权请联系本人[email protected] 项目说明技术选型
项目结构
功能模块
项目架构图主要功能UML图文件上传 部件测试 获取测试结果 数据库表设计项目规划
项目主要功能介绍放弃properties配置文件类型,采用更为直观的yml文件格式来作为项目的配置文件。 项目结构说明NXCheckpartAdmin项目的核心代码模块,采用经典的三层模型 check-modeldodel层里面存放了各个实体类,与数据库中的数据相对应 check-mapper存放了mybatis所需要的xml文件和与之对应的接口文件 check-serviceservice层存放了我们service层的接口及其实现类 check-webcontroller层,是我们控制器所在的模块,里面也存放了一些配置信息包括:speingsecurity、exception统一处理、swagger配置、rabbitMq配置、 check-scheduler定时任务模块,我们采用springboot默认的Scheduler定时任务功能,首先在springboot启动类上加上 @EnableScheduling 注解用于开启基于注解的定时任务 /* * Created by IntelliJ IDEA. * User: 木木 * Date: 2020/10/23 * Time: 13:58 * 定时任务 */@Component@Slf4jpublic class SchedulerTask { @Resource RedisUtil redisUtil; @Resource CheckpartSendLogService checkpartSendLogService; @Autowired RabbitTemplate rabbitTemplate; @Resource SubmitRecordService submitRecordService; @Resource SubmitFileRecordService submitFileRecordService; @Resource SubmitRuleRecordService submitRuleRecordService; /* * @author mumulx * @creed: mumulx编写 * @email: [email protected] * @date 2020/10/23 13:59 * @param * @return void * 每6小时执行一次 将结果放到redis中 */ @Scheduled(fixedRate = 21600000) public void process() { RestTemplate restTemplate = new RestTemplate(); String url = "https://chp.shadiao.app/api.php"; LinkedMultiValueMap<String, String> lv = new LinkedMultiValueMap<>(); ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class); String body = responseEntity.getBody(); body.replaceAll(" ", "<br/>"); redisUtil.set(RedisKeyType.TALK_LOVE.getKey(), body); log.info("-------定时任务开启:" + body); } /* * 用于重试消息发送 * @author mumulx * @creed: mumulx编写 * @email: [email protected] * @date 2020/11/4 9:52 * @param * @return void * 1分钟执行一次 */ @Scheduled(fixedRate = 60000) public void mailResendTask() { log.info("消息重发定时任务开启"); List<CheckpartSendLog> CheckpartSendLogs = checkpartSendLogService.getMailSendLogsByStatus(); CheckpartSendLogs.forEach(checkpartSendLog -> { log.info("重试发送消息"); /**当超过重试次数后会标记消息发送失败--不再重复发送消息*/ if (checkpartSendLog.getCount() >= CheckPartContants.MAX_TRY_COUNT) { log.info("消息重试次数过多---消息发送失败"); checkpartSendLogService.updateMailSendLogStatus(checkpartSendLog.getMsgId(), 2);//直接设置该条消息发送失败 } else { log.info("准备发送消息"); checkpartSendLogService.updateCount(checkpartSendLog.getMsgId(), new Date()); Integer srId = checkpartSendLog.getSrId(); //获取需要重发消息的 测试记录 SubmitRecord submitRecord = submitRecordService.queryRecordBySrId(srId); //获取prts Map<Integer, String> parts = submitFileRecordService.queryFileRecordListBysrid(srId).stream().collect(Collectors.toMap(SubmitFileRecord::getSfrId, SubmitFileRecord::getSfrFileName)); //获取rules List<String> rules = submitRuleRecordService.queryCheckerListBySrId(srId); //对象包装 PartTestBoxed partTestBoxed = new PartTestBoxed(); partTestBoxed.setUserId(submitRecord.getSrUserId()); partTestBoxed.setParts(parts); partTestBoxed.setRules(rules); partTestBoxed.setTestRecordId(srId); log.info("重发的消息的基本信息:"+partTestBoxed.toString()); //重新发送消息 rabbitTemplate.convertAndSend(CheckPartContants.MAIL_EXCHANGE_NAME, CheckPartContants.MAIL_ROUTING_KEY_NAME, partTestBoxed, new CorrelationData(checkpartSendLog.getMsgId())); log.info("消息重发成功"); } }); } /* * 用于删除 测试记录---保存时间默认为30天 * @author mumulx * @creed: mumulx编写 * @email: [email protected] * @date 2020/11/6 16:16 * @param * @return void */ @Scheduled(fixedRate = 1800000) public void deleteSubmitRecordByexpiredTime() { List<Integer> srIds = submitRecordService .queryExpiredTimeList() .stream() .mapToInt(e -> e.getSrId()) .boxed() .collect(Collectors.toList()); //删除 测试规则记录信息 srIds.forEach(srId->{ log.info("检测到有测试记录要删除---已过期:srid="+srId); //删除测试文件记录信息--删除文件服务器上的文件--删除数据库中的数据 submitFileRecordService.deleteFileRecordBySrId(srId); //删除测试规则记录信息 submitRuleRecordService.deleteRuleRecordBySrId(srId); //删除测试记录 submitRecordService.deleteRecordBySrId(srId); log.info(srId+"记录删除成功"); }); }} process任务用于向redis中存储一段文字,该文字会出现在用户登录的界面上,并且每6小时更新一次。主要是对第三方的api的url发起请求获取响应结果,我们将结果放到redis中进行缓存。在使用时我们只需要向redis中获取值就可以了。 mailResendTask任务时消息重发任务,这部分放到RabbitMQ幂等性解决方案中详细介绍,主要的功能时重发失败的消息,确保消息的可用性。 deleteSubmitRecordByexpiredTime任务是用于删除测试记录的。当用户删除一条测试记录的时候,我们默认有一个存储时间为30天的回收站,当时间超过30天后就会被监听到,然后触发真正的删除记录的方法。删除包括了以下几个部分
NXRemoteServerProvider这里采用NX二次开发的远程模式,对NX的Check-mate功能进行二次开发。远程模式最重要的就是获取NX 的Session对象。我们这里采用Java设计模式中的单例模式可以有效的获取Session对象,即保证了Session的重复获取,也保证了Session在高并发场景下的安全问题。 NX二次开发环境的搭建我们这里采用Java来进行NX的二次开发,环境搭建必然是第一步,对于Java来说想要开发某一个功能我们必须要获取该功能的jar包。本项目也不例外,我们可以在NX的安装目录下(NX安装根目录/NXBIN)找到我们开发所需要的jar包。jar包名称如下: NXOpen.jarNXOpenRun.jarNXOpenRemote.jarNXOpenUI.jarNXOpenUIRun.jarNXOpenUIRemote.jarNXOpenUF.jarNXOpenUFRun.jarNXOpenUFRemote.jar 我们将jar包复制一份保存到本地的某一个文件夹中,继续后续的操作。 由于项目采用SpringBoot搭建,默认使用的时Maven项目构建工具,因此需要把我们获取的jar包存储到我们本地的Maven仓库中进行保存。打开命令提示符,cd到上一步我们jar包保存的位置,执行以下代码: mvn install:install-file -Dfile=NXOpen.jar -DgroupId=com.nx -DartifactId=NXOpen -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenRun.jar -DgroupId=com.nx -DartifactId=NXOpenRun -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenRemote.jar -DgroupId=com.nx -DartifactId=NXOpenRemote -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUI.jar -DgroupId=com.nx -DartifactId=NXOpenUI -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUIRun.jar -DgroupId=com.nx -DartifactId=NXOpenUIRun -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUIRemote.jar -DgroupId=com.nx -DartifactId=NXOpenUIRemote -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUF.jar -DgroupId=com.nx -DartifactId=NXOpenUF -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUFRun.jar -DgroupId=com.nx -DartifactId=NXOpenUFRun -Dversion=1.0.0 -Dpackaging=jarmvn install:install-file -Dfile=NXOpenUFRemote.jar -DgroupId=com.nx -DartifactId=NXOpenUFRemote -Dversion=1.0.0 -Dpackaging=jar 项目添加依赖: 为了方便统以控制NX的jar包的版本因此我们定义一个属性来控制jar包的版本 <properties> <NXOpen.version>1.0.0</NXOpen.version></properties> 导入jar包 <dependency> <groupId>com.nx</groupId> <artifactId>NXOpen</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenRun</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenRemote</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUF</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUFRemote</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUFRun</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUI</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUIRun</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency><dependency> <groupId>com.nx</groupId> <artifactId>NXOpenUIRemote</artifactId> <version>${NXOpen.version}</version> <scope>compile</scope></dependency> NX远程服务获取NX的Session,采用单例模式进行获取 @Slf4jpublic class SingleNxSession { private volatile static Session theSession=null; // 双重检测锁模式的 懒汉式单例 DCL懒汉式 public static Session getInstance(){ log.info("获取NX Session实例"); if (theSession==null){//第一层加测 //锁 synchronized (SingleNxSession.class){ //第二层检测 if (theSession==null){ NXRemotableObject.RemotingProtocol remotingProtocol = NXRemotableObject.RemotingProtocol.create(); try { theSession = (Session) SessionFactory.get("Session", remotingProtocol); } catch (Exception e) { log.error("获取nx session失败--可能是服务器没有nx许可证,出错信息如下:"); e.printStackTrace(); } } } } return theSession; }} 单例模式的DCL懒汉式说明: Check-Mate测试进行方法封装 /*** 执行prt文件的测试** @param partSaveUrl 部件位置 如D:\\workplace\\nx\\prt\\model1.prt* @param rules 测试的规则 如%mqc_check_feature_rollback* @param resultFilesDir 测试结果保存的位置 如D:\\workplace\\nx\\log\\* @return int 返回结果位测试的状态* @author mumulx* @creed: mumulx编写* @email: [email protected]* @date 2020/9/12 16:46*/public int execute(Map<Integer, String> partSaveUrl, List<String> rules, String resultFilesDir) throws RemoteException, NXException { //获取value集合---测试部件的存储位置 //不能强制转换 List<String> parts = partSaveUrl.values().stream().collect(Collectors.toList()); log.info("----开始部件检查"); Validation.Result result = null; int rs = -1; Session theSession = SingleNxSession.getInstance(); log.info("获取nxsession成功" + theSession); nxopen.validate.Validator[] validators1; validators1 = theSession.validationManager().findValidator("Check-Mate"); nxopen.validate.ValidatorOptions validatorOptions1; validatorOptions1 = validators1[0].validatorOptions(); validatorOptions1.setSkipChecking(false); validatorOptions1.setSkipCheckingDontLoadPart(false); validatorOptions1.setSaveResultInTeamcenter(nxopen.validate.ValidatorOptions.SaveModeTypes.DO_NOT_SAVE); validatorOptions1.setSavePartFile(nxopen.validate.ValidatorOptions.SaveModeTypes.DO_NOT_SAVE); validatorOptions1.setSaveResultInPart(false); //一个部件一个结果文件 validatorOptions1.setLogFileMode(nxopen.validate.ValidatorOptions.LogModeTypes.LOG_PER_PART); //保存结果文件 validatorOptions1.setGenerateLogFile(true); //结果文件保存位置 validatorOptions1.setLogFileDirectory(resultFilesDir); validators1[0].clearPartNodes(); for (String s : parts) { validators1[0].appendPartNode(s + ".prt"); } for (String s : rules) { validators1[0].appendCheckerNode("%" + s); } log.info("准备提交测试了"); result = validators1[0].commit(); if (Validation.Result.PASS == result) { rs = Validation.Result._PASS; } else if (result == Validation.Result.WARNING) { rs = Validation.Result._WARNING; } else if (result == Validation.Result.FAILED) { rs = Validation.Result._FAILED; } else if (result == Validation.Result.UNKNOWN) { rs = Validation.Result._UNKNOWN; } else if (result == Validation.Result.SKIPPED) { rs = Validation.Result._SKIPPED; } else { rs = -1; } log.info("----=====文件最终测试结果为" + rs); return rs;} 获取文件预览图 /** 获取部件的预览图* @author mumulx* @creed: mumulx编写* @email: [email protected]* @date 2020/11/5 16:11* @param partPath 文件在本地的存储位置--不加后缀:D:\workplace\nxdownload\9\122\285\model1* @return boolean**/private String getPrtPreviewImage(String partPath) throws NXException, IOException { //获取session Session theSession = SingleNxSession.getInstance(); //加载部件 theSession.parts().openActiveDisplay(partPath + ".prt", DisplayPartOption.ALLOW_ADDITIONAL); Part workPart = theSession.parts().work(); //调整视图 ----好像没什么用 workPart.modelingViews().workView().orient(View.Canned.TRIMETRIC, View.ScaleAdjustment.FIT); //获取预览图 BasePart.PreviewImageData previewImage = workPart.getPreviewImage(); //获取预览图数据 int height = previewImage.height; int width = previewImage.width; int[] pixels = previewImage.pixels; //构建图片 Buf |
请发表评论