在企业日常运营中,材料管理是至关重要的一环,涉及采购、收货、存储、发货等多个环节。传统的手工记录和人工操作方式不仅效率低下,而且容易出错,导致库存信息不准确、生产计划延误等问题。针对这一痛点,我们基于SpringBoot框架开发了一套支撑材料管理系统,通过数字化手段提升管理效率。
这个系统采用B/S架构,前端使用HTML+CSS+JavaScript技术栈,后端基于Java语言开发,数据库选用MySQL,服务器使用Tomcat。系统实现了材料分类管理、任务分配跟踪、文件上传下载等核心功能模块。经过实际部署测试,系统响应时间在200ms以内,能够支持50人以上的并发操作,显著提升了某制造企业的材料管理效率。
系统采用经典的三层架构设计,各层技术选型如下:
表现层(UI)
业务逻辑层(BLL)
数据层(DL)
系统主要分为以下功能模块:
用户管理模块
材料管理模块
任务管理模块
文件管理模块
系统数据库包含20余张表,以下是几个关键表的设计:
用户表(user)
sql复制CREATE TABLE `user` (
`user_id` mediumint(8) NOT NULL AUTO_INCREMENT,
`username` varchar(16) NOT NULL COMMENT '登录账号',
`password` varchar(64) NOT NULL COMMENT '加密密码',
`nickname` varchar(16) DEFAULT NULL COMMENT '显示名称',
`email` varchar(64) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(11) DEFAULT NULL COMMENT '手机号',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
材料分类表(material_classification)
sql复制CREATE TABLE `material_classification` (
`material_classification_id` int(10) NOT NULL AUTO_INCREMENT,
`material_type` varchar(64) DEFAULT NULL COMMENT '材料类型',
`parent_id` int(10) DEFAULT '0' COMMENT '父分类ID',
`sort_order` int(4) DEFAULT '0' COMMENT '排序权重',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`material_classification_id`),
KEY `idx_parent` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
文件上传表(upload)
sql复制CREATE TABLE `upload` (
`upload_id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL COMMENT '原始文件名',
`path` varchar(255) DEFAULT NULL COMMENT '访问路径',
`file_size` bigint(20) DEFAULT NULL COMMENT '文件大小(字节)',
`file_type` varchar(32) DEFAULT NULL COMMENT '文件类型',
`user_id` int(10) DEFAULT NULL COMMENT '上传用户',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`upload_id`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
为提高查询性能,我们在以下字段上建立了索引:
注意:索引不是越多越好,需要根据实际查询场景合理设计。我们通过EXPLAIN分析慢查询,有针对性地添加索引。
文件上传是系统的核心功能之一,我们实现了以下特性:
关键代码实现:
java复制@PostMapping("/upload")
public Result upload(@RequestParam("file") MultipartFile file,
@RequestParam(required = false) String materialType,
HttpServletRequest request) {
// 校验文件大小(最大50MB)
if(file.getSize() > 50 * 1024 * 1024) {
return Result.error("文件大小不能超过50MB");
}
// 校验文件类型
String fileExt = FilenameUtils.getExtension(file.getOriginalFilename());
if(!ArrayUtils.contains(ALLOW_TYPES, fileExt.toLowerCase())) {
return Result.error("不支持的文件类型");
}
try {
// 生成存储路径
String savePath = minioService.upload(file);
// 保存记录到数据库
Upload upload = new Upload();
upload.setName(file.getOriginalFilename());
upload.setPath(savePath);
upload.setFileSize(file.getSize());
upload.setFileType(file.getContentType());
upload.setUserId(getCurrentUserId());
uploadService.save(upload);
return Result.ok("上传成功").setData(upload);
} catch (Exception e) {
log.error("文件上传失败", e);
return Result.error("上传失败:" + e.getMessage());
}
}
任务管理模块实现了完整的任务生命周期管理:
状态机设计:
java复制public enum TaskStatus {
PENDING("待处理", "任务刚创建,尚未开始"),
PROCESSING("进行中", "任务正在处理"),
COMPLETED("已完成", "任务已完成"),
CANCELLED("已取消", "任务已取消");
private String name;
private String desc;
// 省略构造方法和getter
}
// 状态转换规则
private static final Map<TaskStatus, Set<TaskStatus>> STATUS_TRANSITION = Map.of(
PENDING, Set.of(PROCESSING, CANCELLED),
PROCESSING, Set.of(COMPLETED, CANCELLED),
COMPLETED, Collections.emptySet(),
CANCELLED, Collections.emptySet()
);
public boolean canTransferTo(TaskStatus targetStatus) {
return STATUS_TRANSITION.get(this).contains(targetStatus);
}
系统采用Spring Security框架实现安全控制:
安全配置示例:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
为提高系统响应速度,我们实施了多级缓存:
缓存配置示例:
java复制@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats());
return cacheManager;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
}
查询优化:
批量操作:
批量插入示例:
java复制@Transactional
public void batchInsertMaterials(List<Material> materials) {
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH);
MaterialMapper mapper = session.getMapper(MaterialMapper.class);
try {
for (int i = 0; i < materials.size(); i++) {
mapper.insert(materials.get(i));
if (i % 500 == 0 || i == materials.size() - 1) {
session.commit();
session.clearCache();
}
}
} finally {
session.close();
}
}
开发环境:
生产环境:
bash复制mysql -uroot -p < schema.sql
mysql -uroot -p < data.sql
bash复制mvn clean package -DskipTests
bash复制scp target/material-system.war user@server:/opt/tomcat/webapps/
nginx复制server {
listen 80;
server_name material.example.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /files/ {
alias /data/material/files/;
expires 30d;
}
}
问题现象:上传大文件时失败,前端报错"Network Error"
排查步骤:
解决方案:
properties复制# application.properties
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
问题现象:系统运行一段时间后出现"Timeout waiting for connection"错误
排查步骤:
解决方案:
properties复制# 使用HikariCP连接池
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.leak-detection-threshold=30000
spring.datasource.hikari.idle-timeout=600000
问题现象:数据更新后,前端仍显示旧数据
排查步骤:
解决方案:
java复制@CacheEvict(value = "material", key = "#material.id")
public void updateMaterial(Material material) {
materialMapper.updateById(material);
// 双删策略防止缓存不一致
redisTemplate.delete("material::" + material.getId());
Thread.sleep(500);
redisTemplate.delete("material::" + material.getId());
}
经过三个月的开发和测试,支撑材料管理系统已成功在某制造企业部署运行,有效解决了以下问题:
待改进方向:
在实际开发过程中,最大的收获是深入理解了企业级应用开发的全流程,从需求分析到部署运维。特别是在性能优化方面,通过实际压力测试和调优,系统吞吐量提升了3倍以上。