License文档

C++获取Windows系统License信息的方法 是通过调用WMI获得License信息的。 #include "stdafx.h" #include #include #include #include #include #include #pragma comment(lib, "Framedyn.lib") #pragma comment(lib, "Wbemuuid.lib") #pragma comment(lib, " 阅读详情

License学习文档

一、简介

License,即版权许可证,一般用于收费软件给付费用户提供的访问许可证明。根据应用部署位置的不同,一般可以分为以下两种情况讨论:

  • 应用部署在开发者自己的云服务器上。这种情况下用户通过账号登录的形式远程访问,因此只需要在账号登录的时候校验目标账号的有效期、访问权限等信息即可。
  • 应用部署在客户的内网环境。因为这种情况开发者无法控制客户的网络环境,也不能保证应用所在服务器可以访问外网,因此通常的做法是使用服务器许可文件,在应用启动的时候加载证书,然后在登录或者其他关键操作的地方校验证书的有效性。

License使用前提:

想要使用License,我们需要明确证书内部的内容,生成方式,存储位置,加密方法,证书内容校验等。
使用原理:
1、生成密钥对,包含私钥和公钥。
2、授权者保留私钥,使用私钥对授权信息诸如使用截止日期,mac 地址等内容生成 license 签名证书。
3、公钥给使用者,放在代码中使用,用于验证 license 签名证书是否符合使用条件。

二、环境配置

1.导入依赖
<dependency>
    <groupId>de.schlichtherle.truelicense</groupId>
    <artifactId>truelicense-core</artifactId>
    <version>1.33</version>
    <scope>provided</scope>
</dependency>

本机端口号和MAC地址记录

{
    "ipAddress":["192.168.0.102"],     			//IP地址
    "macAddress":["B4-0E-DE-D1-ED-9F"],			//MAC地址
    "cpuSerial":"178BFBFF00A50F00",				//CPU序列号
        "mainBoardSerial":"YX026BMC"			    //主板序列号
}

License证书模板内容如下:实体类LicenseCreatorParam

{
	"subject":"ccx-models",
	"privateAlias":"privateKey",
	"keyPass":"5T7Zz5Y0dJFcqTxvzkH5LDGJJSGMzQ",
	"storePass":"3538cef8e7",
	"licensePath":"C:/Users/zifangsky/Desktop/license.lic",
	"privateKeysStorePath":"C:/Users/zifangsky/Desktop/privateKeys.keystore",
	"issuedTime":"2018-04-26 14:48:12",
	"expiryTime":"2018-12-31 00:00:00",	
	"consumerType":"User",
	"consumerAmount":1,
	"description":"这是证书描述信息",
	"licenseCheckModel":{
        "ipAddress":["192.168.245.1","10.0.5.22"],
		"macAddress":["00-50-56-C0-00-01","50-7B-9D-F9-18-41"],
		"cpuSerial":"BFEBFBFF000406E3",
		"mainBoardSerial":"L1HF65E00X9"
    } 
}

三、使用JDK自带的 keytool 工具生成公私钥证书库

1.keytool简介
Keytool 是一个Java 数据证书的管理工具 ,Keytool 将密钥(key)和证书(certificates)存在一个称为keystore的文件中 在keystore里,包含两种数据: 
密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密) 
可信任的证书实体(trusted certificate entries)——只包含公钥
2.项目中的使用

以下命令在 window cmd 命令窗口执行,注意当前执行目录,最后生成的密钥对即在该目录下:
1、首先要用 KeyTool 工具来生成私匙库:(-alias别名 -validity 3650 表示10年有效)

#生成命令
keytool -genkey -alias privatekey -keysize 1024 -keystore privateKeys.store -validity 3650

2、然后把私匙库内的证书导出到一个文件当中

keytool -export -alias privatekey -file certfile.cer -keystore privateKeys.store

3、然后再把这个证书文件导入到公匙库

keytool -import -alias publiccert -file certfile.cer -keystore publicCerts.store

最后生成的文件 privateKeys.store(私钥)、publicCerts.store(公钥)拷贝出来备用。

密钥需包含字母+数字
踩坑:The password does not match the default policy: At least six characters cons
密码与默认策略不匹配:至少6个字符

上述命令执行完成之后,会在当前路径下生成三个文件,分别是:privateKeys.keystore、publicCerts.keystore、certfile.cer。其中文件certfile.cer不再需要可以删除,文件privateKeys.keystore用于当前的项目给客户生成license文件,而文件publicCerts.keystore则随应用代码部署到客户服务器,用户解密license文件并校验其许可信息。

注意:我们使用的公钥和私钥分别如下

privateKeys: private1234
publicCerts: public1234

四、为客户生成license文件

1.建立一个单例模式下的证书管理器
public class LicenseManagerHolder {
    private static volatile LicenseManager licenseManager = null;
    private LicenseManagerHolder() {
    }
    public static LicenseManager getLicenseManager(LicenseParam param) {
        if (licenseManager == null) {
            synchronized (LicenseManagerHolder.class) {
                if (licenseManager == null) {
                    licenseManager = new LicenseManager(param);
                }
            }
        }
        return licenseManager;
    }
}
2.配置证书和公私钥内容

在licenseMakeConf.properties配置文件中配置私钥的配置信息和自定义的项目证书信息,该配置信息用于为客户生成License证书文件,内容如下:

##########common parameters###########
#私钥的别名
private.key.alias=privatekey
#privateKeyPwd(该密码生成密钥对的密码,需要妥善保管,不能让使用者知道)
private.key.pwd=private1234
#keyStorePwd(该密码是在使用keytool生成密钥对时设置的密钥库的访问密码)
key.store.pwd=public1234
#项目的唯一识别码
subject=licenseTest
#生成证书的地址
licPath=D:/license/license.lic
#密钥库的地址
priPath=/privateKeys.store
##########license content###########
#发布日期
issuedTime=2021-07-25
#有效开始日期
notBefore=2021-07-25
#有效截止日期
notAfter=2022-08-30
# ip 地址
ipAddress=192.168.0.102
# mac 地址
macAddress=B4-0E-DE-D1-ED-9F
# 使用者类型,用户(user)、电脑(computer)、其他(else)
consumerType=user
# 证书允许使用的消费者数量
consumerAmount=1
# 证书说明
info=power by xiamen yungu

在licenseVertifyConf.properties配置文件中配置证书验证时所需的配置信息,内容如下:

##########common parameters###########
#公钥别名
public.alias=publiccert
#使用keytool生成密钥对时设置的密钥库的访问密码
key.store.pwd= public1234
#证书路径
license.name=license.lic
#公共库路径
public.store.path=/publicCerts.store
#项目的唯一识别码
subject=licenseTest
3.生成License文件
@Slf4j
public class CreateLicense {

    /**
     * X500Princal 是一个证书文件的固有格式,详见API
     */
    private final static X500Principal DEFAULT_HOLDERAND_ISSUER = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US");

    private String priAlias;
    private String privateKeyPwd;
    private String keyStorePwd;
    private String subject;
    private String priPath;

    private String issued;
    private String notBefore;
    private String notAfter;
    private String ipAddress;
    private String macAddress;
    private String consumerType;
    private int consumerAmount;
    private String info;

    private String licPath;


    /**
     * 构造器,参数初始化
     *
     * @param confPath 参数配置文件路径
     */
    public CreateLicense(String confPath) {
        // 获取参数
        Properties prop = new Properties();
        try (InputStream in = getClass().getResourceAsStream(confPath)) {
            prop.load(in);
        } catch (IOException e) {
            log.error("CreateLicense Properties load inputStream error.", e);
        }
        //common param
        priAlias = prop.getProperty("private.key.alias");
        privateKeyPwd = prop.getProperty("private.key.pwd");
        keyStorePwd = prop.getProperty("key.store.pwd");
        subject = prop.getProperty("subject");
        priPath = prop.getProperty("priPath");
        // license content
        issued = prop.getProperty("issuedTime");
        notBefore = prop.getProperty("notBefore");
        notAfter = prop.getProperty("notAfter");
        ipAddress = prop.getProperty("ipAddress");
        macAddress = prop.getProperty("macAddress");
        consumerType = prop.getProperty("consumerType");
        consumerAmount = Integer.valueOf(prop.getProperty("consumerAmount"));
        info = prop.getProperty("info");

        licPath = prop.getProperty("licPath");
    }


    /**
     * 生成证书,在证书发布者端执行
     *
     * @throws Exception
     */
    public void create() throws Exception {
        LicenseManager licenseManager = LicenseManagerHolder.getLicenseManager(initLicenseParams());
        licenseManager.store(buildLicenseContent(), new File(licPath));
        log.info("------ 证书发布成功 ------");
    }

    /**
     * 初始化证书的相关参数
     *
     * @return
     */
    private LicenseParam initLicenseParams() {
        Class<CreateLicense> clazz = CreateLicense.class;
        Preferences preferences = Preferences.userNodeForPackage(clazz);
        // 设置对证书内容加密的对称密码
        CipherParam cipherParam = new DefaultCipherParam(keyStorePwd);
        // 参数 1,2 从哪个Class.getResource()获得密钥库;
        // 参数 3 密钥库的别名;
        // 参数 4 密钥库存储密码;
        // 参数 5 密钥库密码
        KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(clazz, priPath, priAlias, keyStorePwd, privateKeyPwd);
        // 返回生成证书时需要的参数
        return new DefaultLicenseParam(subject, preferences, privateStoreParam, cipherParam);
    }

    /**
     * 通过外部配置文件构建证书的的相关信息
     *
     * @return
     * @throws ParseException
     */
    public LicenseContent buildLicenseContent() throws ParseException {
        LicenseContent content = new LicenseContent();
        SimpleDateFormat formate = new SimpleDateFormat("yyyy-MM-dd");
        content.setConsumerAmount(consumerAmount);
        content.setConsumerType(consumerType);
        content.setHolder(DEFAULT_HOLDERAND_ISSUER);
        content.setIssuer(DEFAULT_HOLDERAND_ISSUER);
        content.setIssued(formate.parse(issued));
        content.setNotBefore(formate.parse(notBefore));
        content.setNotAfter(formate.parse(notAfter));
        content.setInfo(info);
        // 扩展字段
        Map<String, String> map = new HashMap<>(4);
        map.put("ip", ipAddress);
        map.put("mac", macAddress);
        content.setExtra(map);
        return content;
    }
}
4.生成证书方法测试
public static void main(String[] args) throws Exception {
    CreateLicense clicense = new CreateLicense("/licenseCreateParam.properties");
    clicense.create();
}
5.测试结果
在配置文件对应的磁盘目录中,系统可自动生成License许可证书,需注意,证书内部的开始时间,生效时间,结束时间要符合正常逻辑,否则无法生成License证书。

五、License校验

1.书写验证License信息类

用公钥验证 license 证书,验证用户系统启动时是否有证书且证书是否在生效期间内等信息。

package com.zony.metro.license;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.prefs.Preferences;

import de.schlichtherle.license.*;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LicenseVertify
{
    /**
     * 公钥别名
     */
    private String pubAlias;
    /**
     * 该密码是在使用keytool生成密钥对时设置的密钥库的访问密码
     */
    private String keyStorePwd;
    /**
     * 系统的统一识别码
     */
    private String onlykey;
    /**
     * 证书路径
     */
    private String licName;
    /**
     * 公钥库路径
     */
    private String pubPath;
    private String confPath="/licenseVertifyConf.properties";
    public LicenseVertify(String onlykey)
    {
        setConf(confPath,onlykey);
    }

    public LicenseVertify(String confPath,String onlykey)
    {
        setConf(confPath,onlykey);
    }
    /**
     * 通过外部配置文件获取配置信息
     * @param confPath  配置文件路径
     * @param onlykey 系统的统一识别码
     */
    public void setConf(String confPath,String onlykey)
    {
        // 获取参数
        Properties prop = new Properties();
        InputStream in = getClass().getResourceAsStream(confPath);
        try
        {
            prop.load(in);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        this.onlykey=onlykey;
        pubAlias = prop.getProperty("public.alias");
        keyStorePwd = prop.getProperty("key.store.pwd");
        licName = prop.getProperty("license.name");
        pubPath = prop.getProperty("public.store.path");
        keyStorePwd = prop.getProperty("key.store.pwd");
    }

    /**
     * 初始化证书的相关参数
     * @param  //系统的统一识别码
     * @return
     */
    private LicenseParam initLicenseParams()
    {
        Class<LicenseVertify> clazz=LicenseVertify.class;
        Preferences pre=Preferences.userNodeForPackage(clazz);
        CipherParam cipherParam=new DefaultCipherParam(keyStorePwd);
        KeyStoreParam pubStoreParam=new DefaultKeyStoreParam(clazz, pubPath, pubAlias, keyStorePwd, null);
        LicenseParam licenseParam=new DefaultLicenseParam(onlykey, pre, pubStoreParam, cipherParam);
        return licenseParam;
    }

    private LicenseManager getLicenseManager()
    {
        return LicenseManagerHolder.getLicenseManager(initLicenseParams());
    }
    /**
     * 安装证书证书
     * @param //存放证书的路径
     * @return
     */
    public void install(String licdir)
    {
        try
        {
            LicenseManager licenseManager=getLicenseManager();
            licenseManager.install(new File(licdir+File.separator+licName));
            System.out.println("安装证书成功!");
        }
        catch (Exception e)
        {
            System.out.println("安装证书失败!");
            e.printStackTrace();
            System.exit(0);
        }

    }

    /**
     * 验证证书的合法性
     * @return 0、合法,1、证书过期,2、证书错误
     */
    public int vertify()
    {
        try
        {
            LicenseManager licenseManager=getLicenseManager();
            licenseManager.verify();
            System.out.println("验证证书成功!");
            return 0;
        }
        catch(LicenseContentException ex)
        {
            System.out.println("证书已经过期!");
            ex.printStackTrace();
            return 1;
        }
        catch (Exception e)
        {
            System.out.println("验证证书失败!");
            e.printStackTrace();
            return 2;
        }
    }

    /**
     * 验证证书的合法性
     */
    public boolean vertifyExtra() {
        try {
            LicenseManager licenseManager = getLicenseManager();
            LicenseContent verify = licenseManager.verify();
            log.info("验证证书成功!");
            Map<String, String> extra = (Map) verify.getExtra();
            String ip = extra.get("ip");
            InetAddress inetAddress = InetAddress.getLocalHost();
            String localIp = inetAddress.toString().split("/")[1];
            if (!Objects.equals(ip, localIp)) {
                log.error("IP 地址验证不通过");
                return false;
            }
            String mac = extra.get("mac");
            String localMac = getLocalMac(inetAddress);
            if (!Objects.equals(mac, localMac)) {
                log.error("MAC 地址验证不通过");
                return false;
            }
            log.info("IP、MAC地址验证通过");
            return true;
        } catch (LicenseContentException ex) {
            log.error("证书已经过期!", ex);
            return false;
        } catch (Exception e) {
            log.error("验证证书失败!", e);
            return false;
        }
    }

    /**
     * 得到本机 mac 地址
     *
     * @param inetAddress
     * @throws //SocketException
     */
    private String getLocalMac(InetAddress inetAddress) throws SocketException {
        //获取网卡,获取地址
        byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                sb.append("-");
            }
            //字节转换为整数
            int temp = mac[i] & 0xff;
            String str = Integer.toHexString(temp);
            if (str.length() == 1) {
                sb.append("0" + str);
            } else {
                sb.append(str);
            }
        }
        return sb.toString().toUpperCase();
    }
}
2.项目启动时,安装证书并验证信息

在项目启动时,加载并安装License证书信息,然后进行License证书内容判断,如果项目未安装证书或证书内容不合法,则项目无法启动。

@Component
public class LicenseCheck {

    @PostConstruct
    public void init() {
        VerifyLicense vlicense = new VerifyLicense();
        vlicense.install();
        if (!vlicense.vertify()) {
            Runtime.getRuntime().halt(1);
        }
    }
}
3.添加用户类型,用户数量验证
/**
     * 验证证书的合法性
     */
public boolean vertifyExtra(Map<String,Object> userLicenseContent) {
    try {
        LicenseManager licenseManager = getLicenseManager();
        //证书内部信息
        LicenseContent verify = licenseManager.verify();
        log.info("验证证书成功!");
        Map<String, String> extra = (Map) verify.getExtra();
        String ip = extra.get("ip");
        InetAddress inetAddress = InetAddress.getLocalHost();
        String localIp = inetAddress.toString().split("/")[1];
        if (!Objects.equals(ip, localIp)) {
            log.error("IP 地址验证不通过");
            return false;
        }
        String mac = extra.get("mac");
        String localMac = getLocalMac(inetAddress);
        if (!Objects.equals(mac, localMac)) {
            log.error("MAC 地址验证不通过");
            return false;
        }
        log.info("IP、MAC地址验证通过");
        //授权用户数量验证
        int consumerAmount = verify.getConsumerAmount();
        Integer userConsumerAmount = (Integer)userLicenseContent.get("userConsumerAmount");
        if(userConsumerAmount > consumerAmount){
            log.error("用户数量过大");
            return false;
        }
        //授权对象验证
        String consumerType = verify.getConsumerType();
        String userConsumerType = (String)userLicenseContent.get("userConsumerType");
        if(!consumerType.equals(userConsumerType)){
            log.error("该用户并不是授权用户");
            return false;
        }

        return true;
    } catch (LicenseContentException ex) {
        log.error("证书已经过期!", ex);
        return false;
    } catch (Exception e) {
        log.error("验证证书失败!", e);
        return false;
    }
}

在测试时,需要获取到用户的数量以及用户的类型,这里直接赋值了。

/**
    *@Description 安装证书,并验证证书的合法性
    *@Param []
    *@Return void
    *@Author ChuXu
    *@Date 2021/9/23
    *@Time 17:06
    */
@Test
public void testInstallLicense(){
    LicenseVertify vlicense=new LicenseVertify("licenseTest"); // 项目唯一识别码,对应生成配置文件的subject
    //        vlicense.install(System.getProperty("D:/license"));
    vlicense.install("D:/license");
    //验证License证书的基本信息
    //        vlicense.vertify();
    //验证License证书内部IP,MAC地址,用户数量,用户类型等信息
    Map<String, Object> map = new HashMap<>();
    map.put("userConsumerAmount",1);
    map.put("userConsumerType","op");
    vlicense.vertifyExtra(map);
}

参考文档:
https://www.cnblogs.com/jmcui/p/11909579.html
https://www.zifangsky.cn/1277.html

springboot实现License证书的授权和许可到期验证 在客户服务器部署软件项目后,为了项目版权管控或者对项目进行授权收费处理的,就需要实现项目的授权和许可验证。在这里讲解的是使用 license证书 的形式实现授权和许可验证(已通过测试)。主要是通过IP地址、MAC地址、CPU序列号、主板序列号服务器硬件信息生成一个License证书,同时可以设置生效时间与失效时间,控制项目到期之后项目不可用。 阅读详情

相关推荐

cad文档服务器部署,单一服务器 Network License Manager 快速入门指南

Network License Manager 在各种不同的操作系统中均受支持。 请查看《网络管理员手册》,确认您产品的支持操作系统。 特定版本的 Flex 仅支持其中列出的操作系统。以下列表中的操作系统支持为此技术解决方案列出的产品范围。Windows Vista 64 位 SP1Windows® XP 32 位 SP3Windows XP 64 位 SP2Windows 2003 R2 Ser...

weixin_42131013的博客 3921

license文件是什么?

License 文件对于软件开发者和用户都非常重要,它们明确了在使用和分发软件时应遵守的规则和限制。开源软件的 License 文件使得开发者可以自由地使用、修改和分发软件,同时也确保了开源软件社区的合作和透明性。开源软件是指根据特定许可证授权下向公众提供访问、使用、复制、修改和分发源代码的软件。许可证类型:文件会明确指定所使用的许可证类型,例如 MIT 许可证、Apache 许可证、GNU 通用公共许可证(GPL)等。这可能包括允许的用途、限制、责任限制、版权声明、作者和许可证持有者的信息等。

weixin_44943389的博客 5040

SAP License:SAP项目文档的考核标准

项目启动阶段 项目计划及对计划的调整 建议: 1、 对项目进度进行分类,定义每个阶段的关键任务。 2、 对每个阶段应形成的文档进行说明,哪类文档由谁制作,由谁签核必须做出统一的规定。最好能提供每类文档的标准模版。 3、 定义每个阶段结束的标志,和判定结束的标志。 4、 对于项目的进度控制可以参考项目管理方面的相关资料。在项目计划中应特别留意对项目变更的控制。 项目调研阶段 项目调研问卷 调研访谈记录(访谈确认) 原型分析AS-IS 业务蓝图TO-BE 项目培训文档 项目培训记录 培训考试题目及成绩 建议:.

SAP权限管控|SAP用户权限管理|SAP权限合规检查|SAP全日志管理 565

LICENSE文件介绍

类似于MIT许可证,允许软件被任意使用、复制、修改、合并、出版、分发、再授权和/或销售,只需在软件和软件的所有副本中包含版权声明和许可声明。允许软件被任意使用、复制、修改、合并、出版、分发、再授权和/或销售,只需在软件和软件的所有副本中包含版权声明和许可声明。要求任何以GPL许可证发布的衍生作品也必须使用GPL许可证,并且在软件和软件的所有副本中都包含原始软件的源代码。允许用户自由地使用、修改和分发软件,但要求在分发时包含原始许可证、版权声明、免责声明和相应的通知文件。🍎 GNU通用公共许可证(GPL)

ObjectX_9的博客 3078

C++ —— 单机软件加入Licence许可权限流程(附详细流程图、详细代码已持续更新..)

笼统的说:实现一个生成授权Lic文件应用程序(我们使用),生成的Lic文件给应用程序(客户使用)启动时读取一下对比加密后的字符串或自定义格式的密钥判断是否正确。

3467

Aspose 去水印与文档转换避坑指南:License 加载与格式错乱排查

在 Java 文档处理中,License 授权机制是商业库正常工作的基础,其原理是通过校验授权文件来解除功能限制。Aspose 系列组件在授权失效时会自动降级为评估模式,导致输出文档携带水印并限制处理能力。正确加载 License 并确保其生效,是保障文档转换质量与交付可靠性的关键技术价值,广泛应用于合同生成、报表导出、发票打印等场景。然而,开发者常因 classpath 资源遗漏、加载顺序错误或授权文件损坏而遭遇 aspose 去水印失败,同时转换后格式错乱、字体丢失等问题也频发。本文深入剖析 Licen

weixin_33178839的博客 150

【亲测免费】 TongWeb动态更新License文档

TongWeb动态更新License文档 【下载地址】TongWeb动态更新License文档分享 本仓库提供了一个资源文件,该文件名为“TongWeb动态更新license文档”。此文档详细描述了如何在TongWeb环境中动态更新License的相关操作和步骤 ...

gitblog_06631的博客 666

Aspose文档转PDF去水印实战:License加载与SaveOptions配置

Aspose 是 Java 生态中主流的文档处理 SDK,支持 Excel、PPT、Word 等格式转 PDF。其水印机制并非视觉层叠加,而是 License 校验失败后在渲染链路末端动态注入的元信息标记;因此‘去水印’本质是确保合法授权加载成功,并通过 PdfSaveOptions 精确控制输出行为。理解 License 加载优先级(代码内嵌 > 文件路径 > 环境变量)、版本匹配性(Cells/Slides/Words 专用 lic)及字体嵌入策略(如 setEmbedTrueTypeFonts、Fon

weixin_33600816的博客 285

License.Manager 开源项目安装和使用文档

License.Manager 开源项目安装和使用文档 1. 项目的目录结构及介绍 License.Manager/ ├── LICENSE # 项目许可证文件 ├── README.md # 项目说明文件 ├── appsettings.json # 应用配置文件 ├── License.Manager.csproj # ...

gitblog_00697的博客 902

Java后端集成Aspose.Words实战:从License到高效文档处理的避坑指南

在Java企业级开发中,Word文档的生成与转换是合同管理、报表导出等核心场景的常见需求。开发者常面临Apache POI处理复杂格式时代码失控的困境,而Aspose.Words for Java凭借纯Java环境下无需安装Office、高度还原格式的特性,成为业界青睐的解决方案。其核心原理是通过模拟Word对象模型,支持文档的创建、编辑、渲染与PDF转换,同时提供灵活的License授权机制与丰富的API接口。从环境搭建、模板替换、文档合并到批量缓存复用,技术实施涉及字体配置、样式处理、性能调优等关键环节

weixin_29279153的博客 128

Java生成Word文档:Aspose.Word 14.9集成、License与模板化实战

在Java后端开发中,动态生成Word报告、合同和公文是常见需求,而Apache POI手动排版往往繁琐易错。借助成熟的文档处理库,开发者可以大幅提升效率。Aspose.Word for Java 14.9作为一款无需安装Office的服务端文档生成工具,支持通过API实现Word创建、编辑、目录生成、PDF转换等能力。文章详细介绍了14.9版本的jar包集成、License注册方法,并演示了使用DocumentBuilder创建标题正文、插入合并表格、生成自动目录以及另存为PDF的完整流程。同时针对中文乱

weixin_34098209的博客 223

AMS EDA安装与License启动方法文档

AMS EDA安装与License启动方法文档 去发现同类优质开源项目:https://gitcode.com/ 本文档详细介绍了AMS EDA软件的安装步骤以及License的启动方法,旨在帮助用户顺利配置和使用AMS EDA软件。 文档内容 AMS EDA软件安装步骤 License启动与配置方法 常见问题与解决方法 使用说明 请确保在开始安装之前,您的计算机满足AMS EDA软件的系统...

gitblog_06713的博客 341

QT绘制饼图+柱状图+折线图

使用qt绘制,折线图,饼图,柱状图,多柱状图

梅山 3878

探索文档转换新境界:aspose-words的license和jar

探索文档转换新境界:aspose-words的license和jar 【下载地址】aspose-words的license和jar 本开源项目提供了aspose-words的license和jar资源文件,帮助开发者在无需依赖Office环境的情况下,轻松实现Word文档的格式转换。支持将Word文档转换为PNG、PDF...

gitblog_06716的博客 465

mac安全干净卸载Anaconda3

主要原因是python命令没有映射到已经安装的python版本上,则需要添加。修改~/.bash_profile文件,将anaconda相关删除。现在想卸载Anaconda,恢复使用mac系统自带的Python。最后在mac的应用目录删除Anaconda。查看所有版本的python所在安装目录。或者不使用软连接映射,也可使用。再次查看python映射。查看python版本。建立软连接,添加映射。

buyue 5961

5分钟搞定!用FunASR在本地快速部署达摩院Paraformer语音识别模型

本文提供了一份快速部署指南,教你如何在5分钟内利用FunASR工具包在本地电脑上启动达摩院Paraformer语音识别模型。Paraformer作为一款非自回归端到端模型,以其推理速度快、识别精度高的特点,结合FunASR的一键式模型加载和统一API,让开发者能轻松构建本地语音识别系统,极大降低了前沿AI技术的应用门槛。

q9w8e7r6t5的博客 605

YOLO X Layout开源大模型:MIT License许可,支持商用文档分析系统

本文介绍了如何在星图GPU平台上自动化部署yolo_x_layout文档理解模型镜像,实现高精度文档布局分析。该模型可快速识别PDF或扫描件中的标题、表格、图片、公式等11类结构化元素,典型应用于合同关键条款定位、财务票据智能解析等商用文档处理场景。

weixin_30798867的博客 609

PCB布局布线要求及多层电路板叠加原则

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考本文主要针对PCB布局布线中的要点进行了总结,并对多层电路板的叠加原则进行了解释。

Ka_wyb的博客 2934

jarjava用aspose.word18.8带license:功能全面的Java文档处理利器

jarjava用aspose.word18.8带license:功能全面的Java文档处理利器 【下载地址】jarjava用aspose.word18.8带license 此开源项目提供了一个Java专用的jar包,内含aspose.word 18.8版本及完整license授权。aspose.word是一款强大的Jav...

gitblog_06743的博客 642

CIMPro孪大师,支持 3DGS 高斯泼溅的一站式零代码数字孪生平台

高斯泼溅导入数字孪生开发引擎

2501_90821319的博客 1109

基于咸鱼最新九宫格图标验证码的语义增强模型识别

本文探讨了破解复杂验证码的技术思路,重点分析了某平台的九宫格验证码应对策略。作者提出通过图像语义抽取和增强技术来扩充数据集:先采集少量真实样本,利用形态学操作进行前增强生成变形图像,再通过叠加背景噪声进行后增强。同时强调真实数据集的重要性,建议采用真实+生成数据的混合训练方法。实验表明该方法可使模型准确率达到95%以上,但作者特别声明本文仅供技术研究,严禁用于非法用途。

码王吴彦祖的博客 601

.NET文档处理组件License注册原理与SetLicense踩坑排查指南

在.NET生态中,商业文档处理组件通常通过License文件控制授权状态,SetLicense则是开发者最常调用的注册入口。很多人以为调用后没有报错就等于注册成功,实际上组件可能在静默中退回评估模式,导致输出文档带水印或功能受限。理解许可证的签名结构、授权形态和版本匹配关系,是正确使用的前提。本文从文件路径、嵌入式资源、Stream、Metered计量授权等常见注册方式出发,剖析SetLicense的调用时机与验证手段,并整理多产品、多程序集场景下的授权管理方法。掌握这些排查思路,能帮助你在开发与生产环境中

weixin_28835789的博客 167

1、信息与物理世界:“It from Bit”还是“Bit from It”?

这篇博文探讨了物理学与信息理论之间的深刻联系,从惠勒提出的“It from Bit”概念出发,讨论了信息是否是物质世界的基础,或者物质是否是信息的来源。文章回顾了2013年举办的征文竞赛以及众多学者对这一问题的不同观点,涵盖了量子理论、热力学、计算机科学、黑洞物理以及时空本质等多个领域。同时,文章还分析了信息理论在哲学层面的含义,并展望了其在未来理论、实验和应用研究中的潜力与方向。

water的专栏 289

linux中license路径,配置文件—License Manager 指南 | 文档

// 用户信息First Name=Last Name=Organization=Department=Email=Address 1=City=State/Province=Country=Zip/Postal Code=Phone Number=// 功能和授权码Desktop Advanced=EEA123456789=10Desktop Standard=EEA123456789=10De...

weixin_42515024的博客 1488

基于STM32L4XX、HAL库的TESEO-LIV4FTR定位模块驱动程序设计

支持多星座系统:GPS、GLONASS、Galileo和北斗。支持NMEA 0183协议和ST专有协议。高灵敏度:-167dBm跟踪灵敏度。低功耗设计,适合物联网和便携设备。内置LNA和SAW滤波器。

zhusl6688的博客 237

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: SVN版本控制工具
下一篇: Springboot知识点小结
策马出凉州
博客等级 码龄7年 1粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值