这套基于Java的电子合同签署系统采用了典型的分层架构设计,前端通过UniApp实现多端适配,后端基于Spring Boot框架构建。系统最显著的特点是实现了"一次开发,多端运行"的现代开发理念,完美覆盖了移动端APP、微信生态(小程序+公众号)以及传统H5页面。
在技术选型上,后端采用Spring Boot 2.7 + MyBatis-Plus 3.5 + MySQL 8.0的组合,这种技术栈的选择主要基于三个考量:首先,Spring Boot的自动配置和起步依赖特性大幅减少了XML配置,使开发者能更专注于业务逻辑;其次,MyBatis-Plus在传统MyBatis基础上增强了CRUD操作和条件构造器,特别适合电子合同这类需要复杂查询的业务场景;最后,MySQL 8.0对JSON类型的完善支持,为系统中动态表单和合同模板的存储提供了便利。
前端架构方面,选择UniApp框架主要解决了多端一致性的痛点。通过Vue语法编写一套代码,即可编译发布到iOS、Android、微信小程序、H5等多个平台。实测表明,在合同签署这样的中低频操作场景下,UniApp的性能表现完全满足业务需求,同时大幅降低了开发和维护成本。
合同模板管理是系统的核心功能之一,我们设计了一套灵活的模板引擎架构:
模板存储结构:采用MySQL的JSON类型字段存储模板元数据,包括占位符定义、签署区域坐标等。实际模板文件(PDF/Word)则存储在阿里云OSS,通过外键关联。
动态渲染流程:
java复制// PDF模板渲染核心代码示例
public byte[] renderPdfTemplate(Long templateId, Map<String, String> variables) {
// 1. 从OSS获取模板文件
byte[] templateBytes = ossService.getObject(templateBucket, getTemplatePath(templateId));
// 2. 加载PDF文档
PDDocument document = PDDocument.load(templateBytes);
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
// 3. 填充表单字段
if (acroForm != null) {
for (PDField field : acroForm.getFields()) {
String fieldName = field.getFullyQualifiedName();
if (variables.containsKey(fieldName)) {
field.setValue(variables.get(fieldName));
}
}
}
// 4. 添加签署区域标记
addSignAreas(document, templateId);
// 5. 输出最终PDF
ByteArrayOutputStream baos = new ByteArrayOutputStream();
document.save(baos);
document.close();
return baos.toByteArray();
}
注意事项:PDFBox在处理中文字体时需要特别配置,否则会出现乱码。建议将常用字体文件打包到项目中,通过PDType0Font加载。
针对不同终端设备的特点,我们实现了差异化的签名采集策略:
移动端APP:利用设备原生API获取高精度手写轨迹数据,采样率可达200点/秒。通过贝塞尔曲线算法优化笔迹渲染,使签名效果更接近真实书写。
微信小程序:基于canvas实现,受限于微信环境,采用60fps的采样率。通过附加的压力感应算法(基于书写速度模拟)增强表现力。
H5页面:使用Pointer Events API统一处理触摸和鼠标输入,兼容PC和平板设备。采用简化版的笔迹平滑算法以保证性能。
javascript复制// UniApp签名组件核心逻辑
export default {
data() {
return {
points: [],
isDrawing: false
}
},
methods: {
handleTouchStart(e) {
this.isDrawing = true
this.points.push({
x: e.touches[0].x,
y: e.touches[0].y,
time: Date.now()
})
},
handleTouchMove(e) {
if (!this.isDrawing) return
const newPoint = {
x: e.touches[0].x,
y: e.touches[0].y,
time: Date.now()
}
// 笔迹平滑处理
if (this.points.length > 2) {
const prev = this.points[this.points.length - 1]
const distance = Math.sqrt(
Math.pow(newPoint.x - prev.x, 2) +
Math.pow(newPoint.y - prev.y, 2)
)
// 过滤微小抖动
if (distance > 2) {
this.points.push(newPoint)
}
} else {
this.points.push(newPoint)
}
this.drawPath()
}
}
}
为确保电子签名的法律效力,系统实现了与多家CA机构的对接:
证书申请流程:
证书存储方案:
签名验签流程:
java复制public class DigitalSignatureService {
public byte[] signDocument(byte[] document, Certificate certificate) {
// 1. 创建签名对象
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
// 2. 添加签名者信息
ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA")
.build(certificate.getPrivateKey());
// 3. 构建签名
CMSProcessableByteArray content = new CMSProcessableByteArray(document);
CMSSignedData signedData = generator.generate(content, true);
return signedData.getEncoded();
}
public boolean verifySignature(byte[] signedData) {
// 验证逻辑...
}
}
系统采用双链存证方案确保合同不可篡改:
存证数据结构:
json复制{
"contractId": "CT20240501-001",
"hash": "a1b2c3...",
"timestamp": 1714546800,
"parties": ["user1", "user2"],
"signatures": ["sig1", "sig2"]
}
针对合同签署高峰期,系统实施了多级优化:
数据库层面:
应用层面:
监控体系:
为确保各终端数据一致性,设计了智能同步机制:
问题现象:签署时提示"证书无效"
问题现象:证书申请失败
问题现象:签署位置偏移
问题现象:签名笔迹失真
推荐采用Kubernetes集群部署,配置建议:
证书管理:
数据备份:
安全更新:
这套电子合同系统在实际项目中已经支撑了日均10万+的签署量,通过持续优化,核心接口的99线稳定在200ms以内。特别值得一提的是多端一致性的实现,使得不同平台的用户都能获得近乎一致的签署体验,这在实际业务中显著提升了签署完成率。