去年指导学弟完成毕业设计时,发现很多同学在开发企业级管理系统时容易陷入技术选型混乱、架构设计不合理、数据库性能低下等典型问题。这个基于Spring Boot的员工管理系统实战指南,正是针对计算机专业毕业设计中的高频痛点,总结出的全流程解决方案。
这类系统看似简单,实则涉及前后端分离架构设计、RESTful API规范、数据库事务控制、权限管理等企业级开发必备技能。我们采用Java 17 + Spring Boot 3.x + MySQL 8的技术栈,既能满足毕业设计的技术先进性要求,又保证了开发效率和系统稳定性。
Java语言在企业级开发中仍占据主导地位,Spring Boot的自动配置特性可以快速搭建项目骨架。MySQL作为关系型数据库的经典选择,与JPA/Hibernate的配合能大幅减少SQL编写工作量。实测在16GB内存的开发机上,该技术栈能轻松支撑200+并发请求。
避坑提示:切勿盲目追求最新版本,Spring Boot 3.x要求JDK 17+,需提前配置好开发环境
我们采用经典的三层架构:
特别增加了DTO层实现前后端数据解耦,通过MapStruct实现对象转换。这种设计虽然增加了少量编码工作,但能有效避免后期接口调整时的连锁修改。
员工管理系统主要包含以下表:
sql复制CREATE TABLE `employee` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`employee_no` VARCHAR(20) UNIQUE,
`name` VARCHAR(50) NOT NULL,
`department_id` BIGINT,
`position` VARCHAR(50),
PRIMARY KEY (`id`),
FOREIGN KEY (`department_id`) REFERENCES `department`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
通过Spring Data REST可以快速生成基础CRUD接口,但我们建议手动实现以便更好地控制业务逻辑:
java复制@RestController
@RequestMapping("/api/employees")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping
public Page<EmployeeDTO> listEmployees(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return employeeService.getAllEmployees(page, size);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public EmployeeDTO createEmployee(@Valid @RequestBody EmployeeDTO dto) {
return employeeService.createEmployee(dto);
}
}
以薪资计算为例,需要处理:
java复制@Service
@Transactional
public class SalaryServiceImpl implements SalaryService {
public Salary calculateSalary(Long employeeId, SalaryCalculationDTO dto) {
// 验证员工状态
Employee employee = employeeRepository.findById(employeeId)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found"));
if (!employee.isActive()) {
throw new BusinessException("Inactive employee cannot calculate salary");
}
// 计算应发金额
BigDecimal total = dto.getBaseSalary()
.add(dto.getBonus())
.subtract(dto.getDeduction());
// 计算个税(简化版)
BigDecimal tax = calculateIncomeTax(total);
// 生成薪资记录
Salary salary = new Salary();
salary.setEmployee(employee);
salary.setGrossAmount(total);
salary.setTaxAmount(tax);
salary.setNetAmount(total.subtract(tax));
return salaryRepository.save(salary);
}
}
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
在Service层实现数据过滤逻辑:
java复制public Page<EmployeeDTO> getDepartmentEmployees(Long deptId, Pageable pageable) {
// 验证当前用户是否有权限访问该部门数据
if (!securityService.canAccessDepartment(deptId)) {
throw new AccessDeniedException("No permission to access this department");
}
return employeeRepository.findByDepartmentId(deptId, pageable)
.map(employeeMapper::toDto);
}
使用布局方言实现页面复用:
html复制<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">员工管理系统</title>
</head>
<body>
<div layout:fragment="content">
<!-- 页面具体内容 -->
</div>
</body>
</html>
使用Fetch API实现无刷新操作:
javascript复制async function deleteEmployee(id) {
if (!confirm('确定删除该员工吗?')) return;
try {
const response = await fetch(`/api/employees/${id}`, {
method: 'DELETE'
});
if (response.ok) {
location.reload(); // 刷新列表
}
} catch (error) {
console.error('删除失败:', error);
}
}
java复制@Testcontainers
@SpringBootTest
class EmployeeControllerIT {
@Container
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", mysql::getJdbcUrl);
registry.add("spring.datasource.username", mysql::getUsername);
registry.add("spring.datasource.password", mysql::getPassword);
}
@Test
void shouldCreateEmployee() {
EmployeeDTO dto = new EmployeeDTO("1001", "张三");
given()
.contentType(ContentType.JSON)
.body(dto)
.when()
.post("/api/employees")
.then()
.statusCode(HttpStatus.CREATED.value());
}
}
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
connection-timeout: 30000
idle-timeout: 600000
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true);
}
}
java复制@Aspect
@Component
@RequiredArgsConstructor
public class LoggingAspect {
private final LogService logService;
@AfterReturning(pointcut = "@annotation(operationLog)", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, OperationLog operationLog, Object result) {
logService.saveAsync(buildLog(joinPoint, operationLog, result));
}
}
经验之谈:文档质量直接影响答辩评分,建议使用GitBook组织文档,既专业又便于版本控制