Java 远程调用 NX 11 完整实战:参数读取、修改、STP 文件导出(附环境配置 + 源码)

这里写目录标题

前言

在工业设计、智能制造场景中,经常需要通过Java 后端程序远程操控 Siemens NX(UG),实现模型参数自动化读取、批量修改、模型格式转换(导出 STP)等操作,替代人工手动处理,大幅提升效率。

本文基于 NX 11.0 版本,完整实现 Java 对接 NX 的核心功能:

NX 环境变量配置 + Jar 包加载

Java 远程打开 NX 模型文件

读取模型所有表达式参数

批量修改模型参数并保存

调用 NX 命令行工具导出 STP 214 文件

完整业务层代码(SpringBoot 环境)

全程可直接复制运行,适合二次开发!

一、核心环境准备(必看!)

1.1 软件与依赖

本地已安装 Siemens NX 11.0(必须完整安装,不能绿色版)

Java 开发环境:JDK 8+

框架:SpringBoot(普通 Java 项目也可使用)

1.2 关键环境配置

NX 二次开发必须配置系统环境变量,否则 Java 无法加载 NX 底层依赖,会直接报错:no libnxopen... in java.library.path

  1. 配置 PATH 环境变量
    添加 NX 的二进制文件目录(根据自己安装路径修改):
    plaintext
    D:\Siemens\NX 11.0\UGII
    D:\Siemens\NX 11.0\UGII\cpplibs
  2. 配置 UGII_ROOT_DIR
    plaintext
    UGII_ROOT_DIR = D:\Siemens\NX 11.0\UGII\
  3. 配置 java.library.path(代码启动参数)
    IDEA 启动配置中添加 JVM 参数:
    plaintext
    -Djava.library.path=D:\Siemens\NX 11.0\UGII

1.3 导入 NX 官方 Jar 包

从 NX 安装目录复制核心 Jar 到项目中(本地加载):

找到 NX 安装目录:NX 11.0\UGII\java

复制以下 Jar 到项目 lib 目录:

nxopen.jar

二、实现逻辑总览

整体流程非常清晰:

初始化 NX 会话:Java 连接 NX 后台进程

打开模型文件:加载 .prt 模型

读取参数:遍历模型表达式,封装为 Map 返回

修改参数:根据传入的键值对更新表达式,执行模型更新

导出 STP:调用 NX 自带的 step214ug.cmd 命令行工具,执行格式转换

关闭会话:释放 NX 资源,避免进程卡死

三、完整实现代码(SpringBoot Service 层)

核心功能说明

readModelParams:读取 NX 模型所有参数

writeModelParams:批量修改参数并保存模型

exportStp:导出 STP 文件并提供下载

封装工具方法:打开文件、关闭文件、参数转换、表达式修改

完整源码

配置环境变量

bash 复制代码
package com.example.creotest2.demos.service.impl;


import com.example.creotest2.demos.DTO.FileDTO;
import com.example.creotest2.demos.service.SomNxService;

import com.example.creotest2.demos.utils.FileProcess;

import com.ptc.cipjava.jxthrowable;

import nxopen.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;

import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;

/**
 * Creo 参数 读写接口(对接前端专用)
 * 接口1:读取模型参数 → 返回 Map<String,Object>
 * 接口2:传入修改后的 Map → 更新模型并保存
 */
@Service
public class SomNxServiceImpl implements SomNxService {


    private static boolean useSystemLookAndFeel = true;

    private static Session theSession;



    //读取nx模型参数
    public  Map<String, Object> readModelParams(String partName) throws Exception {
        Map<String, Object> partParaMap = new HashMap<>();
        try {
            String prtFile = "E:\\willdelete\\creo\\creotest2\\creotest2\\"+partName+".prt";

            Part part =  openPartFile(prtFile);
            ExpressionCollection expressions = part.expressions();
            partParaMap = paramsToMap(expressions);
            closePartFile(part);
            return  partParaMap;

        }catch (Exception e){
            e.printStackTrace();
            return partParaMap;
        }finally {
        }
    }


    // 写参数
    public   FileDTO writeModelParams(String partName, Map<String, Object> map) throws jxthrowable, RemoteException, NXException {
        FileDTO fileDTO = new FileDTO();

        try {
            //首先根据文件名找到对应的part文件,然后获取相关参数,根据传入的参数得key和value进行修改
            String prtFile = "E:\\willdelete\\creo\\creotest2\\creotest2\\"+partName+".prt";
            Part part =  openPartFile(prtFile);
            updateExpression(part,map);
            theSession.updateManager().doUpdate(Update.Option._NOW);
            part.save(BasePart.SaveComponents.TRUE,BasePart.CloseAfterSave.FALSE);
            fileDTO.setFileName(partName);
            closePartFile(part);
            return fileDTO;
        }catch (Exception  e){
            e.printStackTrace();
            return fileDTO;
        }finally {
        }

    }


    //导出stp文件
    public   void exportStp(String partName,HttpServletResponse response) throws jxthrowable, RemoteException, NXException {

        try {

            String nxCmd = "D:\\Siemens\\NX 11.0\\STEP214UG\\step214ug.cmd";
            String inputfile = "E:\\willdelete\\creo\\creotest2\\creotest2\\"+partName+".prt";

            this.readModelParams(partName);

//            String inputfile = "E:\\willdelete\\creo\\creotest2\\creotest2\\zhichengzuo1.prt";
            String  outFile = "E:\\willdelete\\creo\\creotest2\\creotest2\\"+partName+".step";
            String defFile = "D:\\Siemens\\NX 11.0\\STEP214UG\\ugstep214.def";
            String  log = "E:\\willdelete\\creo\\creotest2\\creotest2"+partName+".log";


            File wordDir = new File("D:\\Siemens\\NX 11.0\\STEP214UG");

            String cmdLine = String.format("\"%s\" \"%s\" d=\"%s\"  o=\"%s\"  l=\"%s\"  ",nxCmd,inputfile,defFile,outFile,log );
            ProcessBuilder pb = new ProcessBuilder("cmd.exe","/c",cmdLine);

            pb.directory(wordDir);
            String command = String.join(" ",pb.command());
            System.out.printf(command);
            pb.redirectErrorStream(true);
            Process process = pb.start();


            try(BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), "GBK"))){
                String line;
                while ((line = reader.readLine()) != null){
                    System.out.println(line);
                }
            }
            int i = process.waitFor();
            System.out.printf(String.valueOf(i));
            File  file = new File(outFile);

            this.download(partName+".step",response);
            if (file.exists()){
                System.out.printf("生成成功"+file.getAbsolutePath());
            }else {
                System.out.printf(" 文件没生成");
            }
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        } catch (UnsupportedEncodingException unsupportedEncodingException) {
            unsupportedEncodingException.printStackTrace();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closePartFile(null);
        }

    }

    //将所有参数转换为map进行返回
    private  Map<String, Object> paramsToMap(ExpressionCollection expressions) throws jxthrowable, RemoteException, NXException {

        TaggedObjectCollection.Iterator iterator = expressions.iterator();
        Map<String, Object> map = new HashMap<>();
        while ( iterator.hasNext()){
            TaggedObject  obj = (TaggedObject) iterator.next();
            Expression  exp = (Expression) obj;

            String name = exp.name();
            double val = exp.value();
            map.put(name, val);
            System.out.printf("参数名: %-20s | 数值 : %.3f  \n ",exp.name(),exp.value());
        }
        // 核心:读取并返回 Map
        return map;
    }



    //关闭文件
    private     void  closePartFile (Part  part){
        if (part == null){
            return;
        }
        try {
            theSession.parts().closeAll(BasePart.CloseModified.CLOSE_MODIFIED,null);
        } catch (RemoteException e) {
            System.out.printf("所有零件已经关闭");
            e.printStackTrace();
        } catch (NXException e) {
            System.out.printf("零件关闭失败");
            e.printStackTrace();
        }
    }

    //打印零件的所有表达式
    private     void printAllExpression(Part part) throws RemoteException, NXException {
        System.out.printf("零件 所有表达式 \n");
        ExpressionCollection expressions = part.expressions();
        TaggedObjectCollection.Iterator iterator = expressions.iterator();
        while ( iterator.hasNext()){
            TaggedObject  obj = (TaggedObject) iterator.next();
            Expression  exp = (Expression) obj;
            System.out.printf("参数名: %-20s | 数值 : %.3f  \n ",exp.name(),exp.value());
        }

    }

    //修改零件的参数
    private    void updateExpression(Part part,Map<String,Object> paramMap) throws RemoteException, NXException {
        ExpressionCollection expressionCollection   =  part.expressions();
        TaggedObjectCollection.Iterator iterator = expressionCollection.iterator();

        while (iterator.hasNext()){
            TaggedObject obj = (TaggedObject) iterator.next();
            Expression expression   = (Expression) obj;
                if (paramMap.containsKey(expression.name())){
                    Object value = paramMap.get(expression.name());
                    if (value instanceof  Number){
                        double doubleValue = ((Number)value).doubleValue();
                        expression.setValue(doubleValue);
                        System.out.printf("参数 [%s] 已修改为 : %.3f%n",expression.name(),doubleValue);
                    }
                }
            }
    }



    public FileDTO upload(MultipartFile file) throws Exception{
        FileProcess fileProcess = new FileProcess();
        FileDTO upload = fileProcess.upload(file);
        return upload;
    }



    public void download(String   fileName, HttpServletResponse response) throws Exception {
        FileProcess fileProcess = new FileProcess();
        fileProcess.download(fileName,response);
    }


    //打印零件的基本信息  名称以及完整路径
    private     void printPartBasicInfo(Part part) throws NXException, RemoteException {
        System.out.printf("零件的基本信息 \n");
        System.out.printf("零件名称: %s%n",part.name() );
        System.out.printf("完整路径:  %s%n",part.fullPath());
    }

    //打开零件
    private      Part  openPartFile(String  filePath) throws RemoteException, NXException, MalformedURLException, NotBoundException {
        System.out.printf("正在打开零件文件\n");
        initNxSession();
        PartCollection.OpenData open = theSession.parts().open(filePath);
        Part part = open.part;
        return  part;
    }
    private     void initNxSession() throws NXException, RemoteException, NotBoundException, MalformedURLException {
        if ( System.getProperty("remoteserver") == null ) {
            theSession = (Session) SessionFactory.get("Session");
        }
        else {
            theSession = (Session) Naming.lookup(System.getProperty("remoteserver"));
        }
        System.out.printf("会话初始化成功 \n");
    }


//    public static void main(String[] args) throws RemoteException, NXException, MalformedURLException, NotBoundException {
//
//        try {
//
////            System.out.println("java.lib.path:"+System.getProperty("java.library.path"));
//            initNxSession();
//            //打开指定的prt文件
//
//            String prtFile = "E:\\willdelete\\creo\\creotest2\\creotest2\\zhichengzuo1.prt";
//            Part part =  openPartFile(prtFile);
//            printPartBasicInfo(part);
////
////            //读取模型里边的参数
////            printAllExpression(part);
////            //修改参数
////            updateExpression(part,"底高",28.0);
////            theSession.updateManager().doUpdate(Update.Option._NOW);
////
////            //重新打印参数
////            printAllExpression(part);
////            //保存生成的零件
////            part.save(BasePart.SaveComponents.TRUE,BasePart.CloseAfterSave.FALSE);
//
//
////            exportStp();
////            exportIges();
//
//        }catch (Exception  e){
//
//            e.printStackTrace();
//        }finally {
//            closePartFile(null);
//        }
//    }

}

四、关键代码解析

4.1 NX 会话初始化

java

运行

private void initNxSession() throws Exception {

if (System.getProperty("remoteserver") == null) {

// 本地连接 NX

theSession = (Session) SessionFactory.get("Session");

} else {

// 远程 RMI 连接

theSession = (Session) Naming.lookup(System.getProperty("remoteserver"));

}

}

支持本地调用和远程调用两种模式

会话全局单例,避免重复创建导致 NX 崩溃

4.2 参数读取核心

通过 ExpressionCollection 获取模型所有表达式,遍历封装为 Map,直接返回给前端使用。

4.3 参数修改核心

java

运行

// 修改参数值

exp.setValue(value);

// 必须执行模型更新,修改才会生效

theSession.updateManager().doUpdate(Update.Option._NOW);

// 保存模型

part.save();

4.4 STP 导出核心

使用 Java ProcessBuilder 调用 NX 官方命令行工具 step214ug.cmd,无需自己写导出逻辑,稳定不报错。

命令格式:

cmd

step214ug.cmd "输入文件.prt" d="配置文件.def" o="输出文件.stp" l="日志.log"

五、常见问题与解决方案

  1. 报错:java.library.path 找不到依赖
    检查 PATH 环境变量是否添加 UGII 目录
    检查 IDEA JVM 参数是否配置 -Djava.library.path
  2. NX 进程卡死
    每次操作后必须调用 closePartFile() 关闭模型
    不要重复创建 Session 对象
  3. STP 导出失败
    检查 step214ug.cmd 路径是否正确
    模型文件路径不能包含中文、空格
    确保 NX 有读写文件权限
  4. 参数修改不生效
    忘记调用 doUpdate() 执行模型更新
    参数名称不匹配(区分大小写)
    六、总结
    本文完整实现了 Java + NX 11.0 远程自动化操作,涵盖工业场景最常用的三大功能:
    ✅ 模型参数一键读取
    ✅ 批量参数修改与保存
    ✅ 标准 STP 文件导出
    代码基于 SpringBoot 封装,可直接对接前端接口,也可用于自动化脚本、批量处理工具开发。
    使用建议:
    路径统一配置到 application.yml,不要硬编码
    增加异常捕获和日志记录,方便生产环境排查
    远程部署时,服务器必须安装 NX 并配置相同环境变量
    需要配套的 FileProcess 工具类、DTO 类、前端调用示例的同学,可以评论区留言,我会继续更新!

总结

相关推荐
早睡身体真不戳6 小时前
【无标题】
java·服务器·windows
布吉岛的石头6 小时前
Java 程序员第 38 阶段:Embedding 向量缓存实战,减少重复向量化计算开销
java·缓存·embedding
2401_833269306 小时前
【无标题】
java·开发语言
宇宙realman_9996 小时前
420B污染度等级查询代码
java·开发语言·算法
小白学大数据6 小时前
Playwright 爬虫:Python 爬取 JS 渲染的 JSP 网站
开发语言·javascript·爬虫·python·数据分析
折哥的程序人生 · 物流技术专研6 小时前
《Java 100 天进阶之路》第35篇:Java异常处理最佳实践
java·开发语言·后端·面试·求职招聘
AI玫瑰助手6 小时前
Python函数:位置参数与关键字参数的使用
开发语言·python·信息可视化
如竟没有火炬6 小时前
乘法表中第K小的数——二分
开发语言·数据结构·python·算法·leetcode·职场和发展·动态规划
凯瑟琳.奥古斯特6 小时前
选择题专练数据库原理精选30题
开发语言·数据库·职场和发展·数据库开发