1. 项目概述:当专利管理遇上SpringBoot
去年帮某科技企业做技术咨询时,发现他们还在用Excel表格管理上千件专利申请,版本混乱、状态更新滞后是常态。这促使我开发了这套基于SpringBoot的专利申请管理系统,核心解决三个痛点:流程标准化、状态可视化、文档版本化。系统上线后,该企业专利管理效率提升60%以上,特别适合拥有50-500件专利的中小型科技企业。
系统采用经典的三层架构设计:
- 前端:Thymeleaf + Bootstrap实现响应式布局
- 后端:SpringBoot 2.7 + MyBatis-Plus 3.5
- 数据库:MySQL 8.0(支持JSON字段存储专利附件元数据)
提示:源码包中的docker-compose.yml已包含MySQL和Redis的容器化配置,开箱即用
2. 核心功能模块拆解
2.1 智能表单引擎设计
专利申请书提交模块采用动态表单设计,通过JSON Schema定义字段校验规则。核心类PatentFormConfig实现了表单配置的热加载:
java复制@PostMapping("/dynamic-form")
public ResponseEntity<String> handleFormSubmit(
@RequestBody PatentFormData formData,
@RequestParam String formVersion) {
// 通过版本号获取对应校验规则
FormValidator validator = formVersionService.getValidator(formVersion);
ValidationResult result = validator.validate(formData);
if (!result.isValid()) {
throw new InvalidPatentFormException(result.getErrors());
}
// ...后续处理
}
表单特性包括:
- 条件字段显示(根据专利类型自动隐藏无关字段)
- 复合验证规则(如国际专利申请必须包含优先权声明)
- 历史版本比对(使用DiffMatchPatch算法高亮修改内容)
2.2 全链路状态追踪
状态机设计是专利管理的核心,我们采用Spring StateMachine实现:
plantuml复制[*] --> DRAFT : 创建草稿
DRAFT --> UNDER_REVIEW : 提交审核
UNDER_REVIEW --> REJECTED : 审核驳回
UNDER_REVIEW --> APPROVED : 审核通过
APPROVED --> FILED : 已提交专利局
FILED --> GRANTED : 授权
FILED --> REJECTED : 驳回
状态变更时会自动触发以下动作:
- 邮件通知相关责任人
- 生成操作日志(审计用)
- 更新仪表盘统计数据
2.3 文档版本控制系统
专利文档采用类似Git的版本管理机制:
- 每次修改生成新的版本号(SHA-1摘要前8位)
- 支持二进制差异存储(Delta编码)
- 实现版本回退和分支对比
核心存储结构:
sql复制CREATE TABLE patent_document (
id BIGINT PRIMARY KEY,
patent_id BIGINT NOT NULL,
content LONGBLOB,
delta_content BLOB, -- 差异内容
version_hash CHAR(8) NOT NULL,
parent_hash CHAR(8),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3. 关键技术实现细节
3.1 多格式文档处理
使用Apache Tika实现文档内容提取:
java复制public String extractText(InputStream stream) throws TikaException {
AutoDetectParser parser = new AutoDetectParser();
BodyContentHandler handler = new BodyContentHandler(-1);
Metadata metadata = new Metadata();
try (TikaInputStream tikaStream = TikaInputStream.get(stream)) {
parser.parse(tikaStream, handler, metadata, new ParseContext());
return handler.toString();
} catch (Exception e) {
throw new PatentDocumentException("文档解析失败", e);
}
}
支持格式包括:
- PDF(含扫描件OCR识别)
- Word/Excel/PowerPoint
- 图片(JPG/PNG/TIFF)
3.2 智能期限提醒
基于Quartz的定时任务系统实现:
java复制@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void checkDeadlines() {
List<Patent> patents = patentMapper.selectNearDeadline(3); // 3天内到期
patents.forEach(patent -> {
notificationService.sendReminder(
patent.getOwner(),
MessageTemplate.DEADLINE_REMINDER,
patent.getDeadlineDate()
);
});
}
提醒规则配置化:
yaml复制reminder:
rules:
- stage: FILED
triggers:
- type: BEFORE_DEADLINE
days: 30
template: APPLICATION_DEADLINE
- type: AFTER_EVENT
days: 7
template: FOLLOW_UP
3.3 可视化分析看板
使用ECharts实现的三个核心图表:
- 申请趋势图(按月份统计)
- 类型分布图(发明/实用新型/外观设计)
- 状态分布图(各流程阶段占比)
数据聚合采用MySQL窗口函数:
sql复制SELECT
DATE_FORMAT(apply_date, '%Y-%m') AS month,
COUNT(*) AS total,
SUM(CASE WHEN type='INVENTION' THEN 1 ELSE 0 END) AS inventions
FROM patents
WHERE apply_date BETWEEN :start AND :end
GROUP BY month
ORDER BY month;
4. 部署与运维实践
4.1 容器化部署方案
Docker Compose配置要点:
yaml复制services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- redis
- db
environment:
SPRING_PROFILES_ACTIVE: prod
db:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
4.2 性能优化实战
通过JMeter压测发现的三个性能瓶颈及解决方案:
-
专利列表查询慢(>2s)
- 添加复合索引:
ALTER TABLE patents ADD INDEX idx_status_type (status, type) - 引入Caffeine缓存查询结果
- 添加复合索引:
-
大文档上传超时(默认1分钟)
properties复制# application-prod.properties spring.servlet.multipart.max-file-size=50MB spring.servlet.multipart.max-request-size=100MB server.tomcat.connection-timeout=5m -
并发提交冲突
- 采用乐观锁控制:
java复制@Update("UPDATE patents SET version = version + 1 WHERE id = #{id} AND version = #{version}") int updateWithOptimisticLock(Patent patent);
4.3 安全防护措施
必须实现的五个安全配置:
- 启用Spring Security CSRF防护
- 专利文档下载URL增加时效签名
- 敏感操作日志记录(审计日志表)
- 密码加密存储(BCryptPasswordEncoder)
- 定期备份策略(每日增量+每周全量)
5. 二次开发指南
5.1 如何添加新专利类型
- 在
PatentType枚举中新增类型 - 配置对应的表单模板(resources/form-templates/)
- 添加状态流转规则(statemachine-config.xml)
5.2 对接官方专利API
与中国专利电子申请网对接示例:
java复制public class PatentOfficeClient {
private final WebClient webClient;
public PatentOfficeClient(String baseUrl) {
this.webClient = WebClient.builder()
.baseUrl(baseUrl)
.defaultHeader("X-Auth-Token", "${api.key}")
.build();
}
public Mono<SubmissionResult> submitApplication(PatentApplication app) {
return webClient.post()
.uri("/api/submit")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(app)
.retrieve()
.bodyToMono(SubmissionResult.class);
}
}
5.3 扩展提醒渠道
实现NotificationService接口示例:
java复制@Service
@RequiredArgsConstructor
public class WeChatNotificationService implements NotificationService {
private final WeChatClient client;
@Override
public void sendReminder(User user, String template, Object... params) {
String content = String.format(template, params);
client.sendTemplateMessage(
user.getWeChatId(),
"PATENT_REMINDER",
content);
}
}
6. 常见问题排坑记录
6.1 表单提交报错排查流程
mermaid复制graph TD
A[出现验证错误] --> B{错误类型}
B -->|字段缺失| C[检查表单配置版本]
B -->|格式错误| D[验证正则表达式]
B -->|业务规则| E[查看PatentRuleService日志]
C --> F[更新form_version表]
D --> G[修改JSON Schema]
E --> H[调整业务规则]
6.2 文档版本冲突解决
当出现版本冲突时(VersionConflictException),建议操作:
- 获取当前最新版本:
GET /api/patents/{id}/documents/latest - 使用合并工具处理差异
- 提交合并后的新版本:
POST /api/patents/{id}/documents/merge
6.3 性能问题快速诊断
使用Arthas进行线上诊断:
bash复制# 监控方法调用耗时
watch com.example.patent.service.* * '{params,returnObj,throwExp}' -x 3 -n 5
# 查看SQL执行
trace javax.sql.DataSource * '#cost>100'
7. 源码结构导读
核心包说明:
code复制src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── patent/
│ │ ├── config/ # 系统配置
│ │ ├── controller/ # 接口层
│ │ ├── domain/ # 领域模型
│ │ ├── repository/ # 数据访问
│ │ ├── service/ # 业务逻辑
│ │ └── PatentApplication.java
│ └── resources/
│ ├── static/ # 前端资源
│ ├── templates/ # Thymeleaf模板
│ └── application.yml
└── test/ # 测试代码
重点测试类:
- PatentServiceIntegrationTest:核心业务流程测试
- DocumentVersionControlTest:文档版本控制测试
- StateMachineTest:状态流转测试
提示:运行测试前需先启动测试容器
docker-compose -f docker-compose-test.yml up