Java项目实战:基于最新技术栈的在线任务管理系统开发
一、项目概述与技术选型
随着远程协作的普及,任务管理系统成为团队高效协作的核心工具。本项目将采用2024-2025年主流的Java技术栈,开发一个功能完善的在线任务管理系统,包含任务创建、分配、跟踪、统计等核心功能。
技术栈选择:
- 后端框架:Spring Boot 3.2.x(基于Java 21)
- 安全框架:Spring Security 6.x + JWT
- 数据访问:Spring Data JPA + Hibernate 6.x
- 数据库:PostgreSQL 16(支持JSON类型和全文搜索)
- 前端框架:React 18 + TypeScript + Ant Design 5.x
- API文档:SpringDoc OpenAPI 3(替代Swagger)
- 缓存:Redis 7.x
- 部署:Docker + Kubernetes
选择理由:Spring Boot 3.2.x充分利用了Java 21的虚拟线程特性,能显著提升系统吞吐量;PostgreSQL相比MySQL提供了更丰富的数据类型和更强大的查询能力;React 18的并发渲染特性提升了前端交互体验。
二、项目架构设计
采用分层架构设计,具体如下:
- 表现层(Controller):处理HTTP请求,返回响应
- 业务逻辑层(Service):实现核心业务逻辑
- 数据访问层(Repository):与数据库交互
- 实体层(Entity):定义数据模型
- DTO层:数据传输对象,用于前后端数据交互
- 安全层:处理认证与授权
核心模块划分:
- 用户模块(User):用户管理、认证授权
- 任务模块(Task):任务CRUD、状态管理
- 项目模块(Project):项目管理、成员管理
- 统计模块(Statistics):任务统计、进度分析
三、核心功能实现(实操部分)
1. 项目初始化与配置
首先使用Spring Initializr创建项目,添加必要依赖:
<dependencies>
<!-- Spring Boot核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 安全框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 数据访问 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT支持 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<!-- API文档 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
配置文件(application.yml):
spring:
datasource:
url: jdbc:postgresql://localhost:5432/task_management
username: postgres
password: password
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
show-sql: true
data:
redis:
host: localhost
port: 6379
# JWT配置
jwt:
secret: your-secret-key-with-at-least-256-bits-length
expiration: 86400000 # 24小时
# 服务器配置
server:
port: 8080
tomcat:
threads:
virtual:
enabled: true # 启用虚拟线程
2. 数据模型设计
以任务(Task)实体为例,使用JPA注解定义:
@Entity
@Table(name = "tasks")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(length = 1000)
private String description;
@Enumerated(EnumType.STRING)
private TaskStatus status;
@Column(name = "due_date")
private LocalDateTime dueDate;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assignee_id")
private User assignee;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "project_id")
private Project project;
@Column(name = "priority")
@Enumerated(EnumType.STRING)
private Priority priority;
@Column(name = "created_at")
@CreationTimestamp
private LocalDateTime createdAt;
@Column(name = "updated_at")
@UpdateTimestamp
private LocalDateTime updatedAt;
// 任务标签,使用PostgreSQL的数组类型
@Column(name = "tags", columnDefinition = "text[]")
private String[] tags;
}
// 任务状态枚举
public enum TaskStatus {
TODO, IN_PROGRESS, REVIEW, COMPLETED, CANCELLED
}
// 优先级枚举
public enum Priority {
LOW, MEDIUM, HIGH, URGENT
}
上述代码定义了任务的基本属性,包括标题、描述、状态、截止日期等。特别注意:
- 使用了Lombok的@Data注解简化getter/setter等方法
- 使用了Java 8的LocalDateTime处理日期时间
- 利用PostgreSQL的数组类型存储任务标签
- 通过@ManyToOne建立与用户和项目的关联关系
3. 任务管理核心功能实现
创建任务DTO用于数据传输:
@Data
public class TaskDTO {
private Long id;
private String title;
private String description;
private TaskStatus status;
private LocalDateTime dueDate;
private Long assigneeId;
private String assigneeName;
private Long projectId;
private Priority priority;
private String[] tags;
private LocalDateTime createdAt;
}
任务仓库接口:
public interface TaskRepository extends JpaRepository<Task, Long> {
// 查找指定项目的任务
List<Task> findByProjectId(Long projectId, Pageable pageable);
// 查找指定负责人的任务
List<Task> findByAssigneeId(Long userId, Pageable pageable);
// 根据状态查找任务
List<Task> findByStatus(TaskStatus status, Pageable pageable);
// 全文搜索(使用PostgreSQL的全文搜索功能)
@Query(value = "SELECT * FROM tasks WHERE to_tsvector('english', title || ' ' || description) @@ plainto_tsquery('english', :query)", nativeQuery = true)
List<Task> fullTextSearch(@Param("query") String query, Pageable pageable);
}
任务服务实现:
@Service
@RequiredArgsConstructor
@Transactional
public class TaskServiceImpl implements TaskService {
private final TaskRepository taskRepository;
private final UserRepository userRepository;
private final ProjectRepository projectRepository;
private final ModelMapper modelMapper;
@Override
public TaskDTO createTask(TaskCreateRequest request, Long creatorId) {
// 验证负责人是否存在
User assignee = userRepository.findById(request.getAssigneeId())
.orElseThrow(() -> new ResourceNotFoundException("Assignee not found"));
// 验证项目是否存在
Project project = projectRepository.findById(request.getProjectId())
.orElseThrow(() -> new ResourceNotFoundException("Project not found"));
// 构建任务实体
Task task = Task.builder()
.title(request.getTitle())
.description(request.getDescription())
.status(TaskStatus.TODO)
.dueDate(request.getDueDate())
.assignee(assignee)
.project(project)
.priority(request.getPriority())
.tags(request.getTags())
.build();
// 保存任务
Task savedTask = taskRepository.save(task);
// 转换为DTO并返回
return modelMapper.map(savedTask, TaskDTO.class);
}
@Override
@Transactional(readOnly = true)
public Page<TaskDTO> getTasksByProject(Long projectId, int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("dueDate").ascending());
Page<Task> tasks = taskRepository.findByProjectId(projectId, pageable);
return tasks.map(task -> {
TaskDTO dto = modelMapper.map(task, TaskDTO.class);
dto.setAssigneeName(task.getAssignee().getName());
return dto;
});
}
@Override
public TaskDTO updateTaskStatus(Long taskId, TaskStatus status) {
Task task = taskRepository.findById(taskId)
.orElseThrow(() -> new ResourceNotFoundException("Task not found"));
task.setStatus(status);
Task updatedTask = taskRepository.save(task);
return modelMapper.map(updatedTask, TaskDTO.class);
}
// 其他方法实现...
}
上述服务实现了任务的创建、查询和状态更新等核心功能。特别注意:
- 使用@Transactional保证事务一致性
- 采用ModelMapper进行实体与DTO之间的转换
- 实现了基本的异常处理(资源未找到)
- 方法上添加@Transactional(readOnly = true)优化查询性能
任务控制器:
@RestController
@RequestMapping("/api/v1/tasks")
@RequiredArgsConstructor
@Tag(name = "Task Management", description = "APIs for task management")
public class TaskController {
private final TaskService taskService;
@PostMapping
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Operation(summary = "Create new task")
public ResponseEntity<TaskDTO> createTask(
@RequestBody @Valid TaskCreateRequest request,
Authentication authentication) {
Long userId = ((UserDetailsImpl) authentication.getPrincipal()).getId();
TaskDTO taskDTO = taskService.createTask(request, userId);
return new ResponseEntity<>(taskDTO, HttpStatus.CREATED);
}
@GetMapping("/project/{projectId}")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Operation(summary = "Get tasks by project ID")
public ResponseEntity<Page<TaskDTO>> getTasksByProject(
@PathVariable Long projectId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<TaskDTO> tasks = taskService.getTasksByProject(projectId, page, size);
return ResponseEntity.ok(tasks);
}
@PatchMapping("/{taskId}/status")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@Operation(summary = "Update task status")
public ResponseEntity<TaskDTO> updateTaskStatus(
@PathVariable Long taskId,
@RequestBody @Valid TaskStatusUpdateRequest request) {
TaskDTO taskDTO = taskService.updateTaskStatus(taskId, request.getStatus());
return ResponseEntity.ok(taskDTO);
}
// 其他端点...
}
控制器层特点:
- 使用SpringDoc注解生成API文档
- 通过@PreAuthorize实现基于角色的访问控制
- 从Authentication对象获取当前登录用户信息
- 使用@Valid进行请求参数验证
4. 缓存策略实现
为提高系统性能,对频繁访问的数据实施缓存:
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
// 默认缓存配置
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)) // 默认过期时间10分钟
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
// 针对不同缓存设置不同的过期时间
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put("tasks", defaultCacheConfig.entryTtl(Duration.ofMinutes(5)));
cacheConfigurations.put("projects", defaultCacheConfig.entryTtl(Duration.ofHours(1)));
cacheConfigurations.put("users", defaultCacheConfig.entryTtl(Duration.ofHours(2)));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(defaultCacheConfig)
.withInitialCacheConfigurations(cacheConfigurations)
.build();
}
}
在服务方法中使用缓存:
@Override
@Cacheable(value = "tasks", key = "#taskId")
@Transactional(readOnly = true)
public TaskDTO getTaskById(Long taskId) {
Task task = taskRepository.findById(taskId)
.orElseThrow(() -> new ResourceNotFoundException("Task not found"));
TaskDTO dto = modelMapper.map(task, TaskDTO.class);
dto.setAssigneeName(task.getAssignee().getName());
return dto;
}
@Override
@CacheEvict(value = "tasks", key = "#taskId")
public void deleteTask(Long taskId) {
if (!taskRepository.existsById(taskId)) {
throw new ResourceNotFoundException("Task not found");
}
taskRepository.deleteById(taskId);
}
@Override
@Caching(
evict = @CacheEvict(value = "tasks", key = "#taskId"),
put = @CachePut(value = "tasks", key = "#result.id")
)
public TaskDTO updateTask(Long taskId, TaskUpdateRequest request) {
// 更新任务逻辑...
}
缓存策略说明:
- 使用@EnableCaching开启缓存功能
- 针对不同类型的数据设置不同的过期时间
- 使用@Cacheable缓存查询结果
- 使用@CacheEvict在数据更新或删除时清除缓存
- 使用@Caching组合多个缓存操作
四、前端集成与部署
1. 前端API调用示例(React + TypeScript)
// taskApi.ts
import axios from 'axios';
import {
Task, TaskCreateRequest, TaskStatus } from '../types/task';
const API_BASE_URL = 'http://localhost:8080/api/v1';
// 创建任务
export const createTask = async (taskData: TaskCreateRequest): Promise<Task> => {
const response = await axios.post<Task>(`${
API_BASE_URL}/tasks`, taskData, {
headers: {
'Authorization': `Bearer ${
localStorage.getItem('token')}`
}
});
return response.data;
};
// 获取项目任务列表
export const getTasksByProject = async (projectId: number, page: number = 0, size: number = 10) => {
const response = await axios.get(`${
API_BASE_URL}/tasks/project/${
projectId}`, {
params: {
page, size },
headers: {
'Authorization': `Bearer ${
localStorage.getItem('token')}`
}
});
return response.data;
};
// 更新任务状态
export const updateTaskStatus = async (taskId: number, status: TaskStatus): Promise<Task> => {
const response = await axios.patch<Task>(`${
API_BASE_URL}/tasks/${
taskId}/status`,
{
status },
{
headers: {
'Authorization': `Bearer ${
localStorage.getItem('token')}`
}
}
);
return response.data;
};
2. Docker部署配置
Dockerfile:
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/task-management-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
# 使用虚拟线程
ENTRYPOINT ["java", "--enable-preview", "-jar", "app.jar"]
docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
depends_on:
- db
- redis
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/task_management
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=password
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
restart: always
db:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
- POSTGRES_DB=task_management
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres-data:/var/lib/postgresql/data
restart: always
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: always
volumes:
postgres-data:
redis-data:
五、项目扩展与优化建议
性能优化:
- 针对大数据量查询实现分页和懒加载
- 使用Redis缓存热点数据
- 实现数据库索引优化
- 考虑使用读写分离架构
功能扩展:
- 添加任务评论和附件功能
- 实现任务提醒(邮件、站内信)
- 添加任务统计和报表功能
- 集成第三方工具(如GitHub、Slack)
安全增强:
- 实现API限流防止滥用
- 添加敏感操作日志审计
- 定期轮换JWT密钥
- 实现IP白名单功能
可观测性:
- 集成Spring Boot Actuator监控系统健康状态
- 使用Micrometer收集 metrics
- 集成ELK栈实现日志收集和分析
- 添加分布式追踪(如Zipkin)
六、总结
本项目基于最新的Java技术栈实现了一个功能完善的在线任务管理系统,涵盖了从项目初始化、数据模型设计到核心功能实现、缓存策略、前端集成和部署的完整流程。通过本项目的实践,读者可以掌握:
- Spring Boot 3.2.x与Java 21的新特性应用
- 基于JWT的认证授权实现
- 数据库设计与优化技巧
- 缓存策略的合理应用
- 现代化的部署流程
实际开发中,还需要根据具体业务需求进行功能扩展和性能优化,同时注重代码质量和安全性。希望本教程能为读者的Java项目开发提供有价值的参考。
Java 项目实战,最新 Java 技术栈,在线任务管理系统,系统开发详解,Java 开发实战,任务管理系统搭建,技术栈应用指南,在线系统开发,Java 项目开发,实战开发教程,任务管理功能实现,最新技术实战,系统开发案例,Java 编程实践,任务管理系统开发
代码获取方式
https://pan.quark.cn/s/14fcf913bae6