基于SSH框架的校园运动会综合管理系统 - 源码深度解析

JavaJavaScriptSSH框架HTMLCSSMySQLJSP+Servlet
2026-02-244 浏览

文章摘要

本项目是一款基于SSH(Struts2 + Spring + Hibernate)框架构建的校园运动会综合管理系统,旨在解决传统校园运动会组织过程中信息分散、流程繁琐、数据统计效率低下的核心痛点。系统通过数字化手段整合运动会全流程,将赛事安排、运动员报名、成绩录入与查询、信息发布等环节集中管理,显著...

校园运动会数字化管理平台技术解析

项目背景与需求分析

传统校园运动会组织过程中存在信息孤岛、流程繁琐、数据统计效率低下等核心问题。体育教师需要手动处理大量报名表格,裁判员使用纸质记录成绩,学生难以及时获取赛事信息,整个管理过程依赖人工操作,容易产生数据错误和沟通延迟。

针对这些痛点,基于SSH框架的校园运动会综合管理系统应运而生。该系统通过数字化手段整合运动会全流程管理,实现了从赛事规划、运动员报名、成绩录入到结果公示的闭环管理。系统采用模块化设计,为不同角色用户提供定制化功能界面,显著提升了管理效率和数据准确性。

技术架构设计

SSH框架整合方案

系统采用经典的SSH(Struts2 + Spring + Hibernate)三层架构,各层职责分明,耦合度低,便于维护和扩展。

表现层使用Struts2框架处理用户请求和页面跳转,通过配置struts.xml文件定义Action映射关系:

<package name="sports" extends="struts-default">
    <action name="athlete_*" method="{1}" 
            class="athleteAction">
        <result name="success">/athlete_list.jsp</result>
        <result name="input">/athlete_edit.jsp</result>
    </action>
</package>

业务逻辑层由Spring框架统一管理,通过依赖注入实现组件解耦:

@Service("athleteService")
@Transactional
public class AthleteServiceImpl implements AthleteService {
    
    @Autowired
    private AthleteDAO athleteDAO;
    
    @Override
    public void saveAthlete(Athlete athlete) {
        // 业务逻辑验证
        if (validateAthleteInfo(athlete)) {
            athleteDAO.save(athlete);
        }
    }
}

持久层采用Hibernate实现对象关系映射,简化数据库操作:

@Repository("athleteDAO")
public class AthleteDAOImpl extends HibernateDaoSupport implements AthleteDAO {
    
    public void save(Athlete athlete) {
        getHibernateTemplate().save(athlete);
    }
    
    public Athlete findById(Integer id) {
        return getHibernateTemplate().get(Athlete.class, id);
    }
}

配置文件整合

Spring配置文件applicationContext.xml负责整合三大框架:

<beans>
    <!-- 数据源配置 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/sports_db"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    
    <!-- Hibernate会话工厂 -->
    <bean id="sessionFactory" 
          class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    
    <!-- 事务管理 -->
    <bean id="transactionManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
</beans>

数据库设计解析

系统共设计11张数据表,涵盖运动员信息、赛事项目、成绩记录、器材管理等核心业务模块。

运动员信息表设计

运动员表(athlete)采用规范化设计,确保数据完整性和查询效率:

CREATE TABLE athlete (
    athlete_id INT PRIMARY KEY AUTO_INCREMENT,
    student_id VARCHAR(20) UNIQUE NOT NULL,
    name VARCHAR(50) NOT NULL,
    gender ENUM('男','女') NOT NULL,
    college VARCHAR(100) NOT NULL,
    class_name VARCHAR(50) NOT NULL,
    contact_phone VARCHAR(15),
    emergency_contact VARCHAR(50),
    health_status ENUM('良好','一般','需关注') DEFAULT '良好',
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_college (college),
    INDEX idx_class (class_name),
    INDEX idx_student_id (student_id)
);

该表设计特点:

  • 使用自增主键保证唯一性,同时保留学号作为业务唯一标识
  • 枚举类型字段约束数据规范性
  • 多字段索引优化查询性能
  • 时间戳字段跟踪数据变更历史

赛事项目表结构

赛事项目表(sports_event)支持灵活的赛事管理:

CREATE TABLE sports_event (
    event_id INT PRIMARY KEY AUTO_INCREMENT,
    event_code VARCHAR(10) UNIQUE NOT NULL,
    event_name VARCHAR(100) NOT NULL,
    event_type ENUM('田赛','径赛','球类','水上项目') NOT NULL,
    gender_limit ENUM('男','女','不限') DEFAULT '不限',
    max_participants INT DEFAULT 0,
    min_participants INT DEFAULT 1,
    registration_start DATETIME NOT NULL,
    registration_end DATETIME NOT NULL,
    event_time DATETIME NOT NULL,
    location VARCHAR(200),
    status ENUM('未开始','报名中','进行中','已结束') DEFAULT '未开始',
    rules_description TEXT,
    equipment_requirements TEXT,
    created_by INT,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (created_by) REFERENCES admin(admin_id)
);

赛事安排界面

成绩记录表设计

成绩表(score_record)设计支持复杂的排名逻辑:

CREATE TABLE score_record (
    record_id INT PRIMARY KEY AUTO_INCREMENT,
    athlete_id INT NOT NULL,
    event_id INT NOT NULL,
    score_value DECIMAL(8,2),
    score_unit VARCHAR(10),
    ranking INT,
    group_name VARCHAR(50),
    round_type ENUM('预赛','决赛','资格赛') DEFAULT '预赛',
    record_status ENUM('待审核','已确认','已取消') DEFAULT '待审核',
    recorded_by INT,
    record_time DATETIME NOT NULL,
    notes TEXT,
    FOREIGN KEY (athlete_id) REFERENCES athlete(athlete_id),
    FOREIGN KEY (event_id) REFERENCES sports_event(event_id),
    FOREIGN KEY (recorded_by) REFERENCES referee(referee_id),
    UNIQUE KEY unique_athlete_event_round (athlete_id, event_id, round_type),
    INDEX idx_event_ranking (event_id, ranking),
    INDEX idx_athlete_performance (athlete_id, score_value)
);

该表通过复合唯一约束防止重复录入,同时建立多维度索引支持复杂查询。

成绩查询界面

核心功能实现

运动员报名管理

报名功能通过Struts2 Action处理前端请求,Spring Service层实现业务逻辑:

public class AthleteAction extends ActionSupport {
    private Athlete athlete;
    private List<SportsEvent> availableEvents;
    
    public String register() {
        try {
            // 验证报名资格
            if (!athleteService.validateEligibility(athlete)) {
                addActionError("不符合报名条件");
                return INPUT;
            }
            
            // 执行报名操作
            athleteService.registerAthlete(athlete);
            addActionMessage("报名成功");
            return SUCCESS;
        } catch (Exception e) {
            addActionError("报名失败: " + e.getMessage());
            return ERROR;
        }
    }
    
    // Getter和Setter方法
    public Athlete getAthlete() { return athlete; }
    public void setAthlete(Athlete athlete) { this.athlete = athlete; }
}

业务逻辑层实现报名资格验证和冲突检测:

@Service
@Transactional
public class AthleteServiceImpl implements AthleteService {
    
    public boolean validateEligibility(Athlete athlete) {
        // 检查是否已报名同一项目
        String hql = "select count(*) from Registration where athleteId = ? and eventId = ?";
        Long count = (Long) getHibernateTemplate().find(hql, 
            athlete.getAthleteId(), athlete.getEventId()).get(0);
        
        if (count > 0) {
            throw new RuntimeException("该运动员已报名此项目");
        }
        
        // 检查项目人数限制
        hql = "select currentParticipants, maxParticipants from SportsEvent where eventId = ?";
        Object[] result = (Object[]) getHibernateTemplate().find(hql, athlete.getEventId()).get(0);
        Integer current = (Integer) result[0];
        Integer max = (Integer) result[1];
        
        return current < max;
    }
}

成绩录入与排名计算

成绩管理模块支持实时录入和自动排名:

@Entity
@Table(name = "score_record")
public class ScoreRecord {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer recordId;
    
    @ManyToOne
    @JoinColumn(name = "athlete_id")
    private Athlete athlete;
    
    @ManyToOne
    @JoinColumn(name = "event_id")
    private SportsEvent event;
    
    private BigDecimal scoreValue;
    private Integer ranking;
    
    @Transient
    public boolean isBetterThan(ScoreRecord other) {
        // 根据项目类型比较成绩
        if (event.getEventType() == EventType.TRACK) {
            return scoreValue.compareTo(other.getScoreValue()) < 0; // 时间越短越好
        } else {
            return scoreValue.compareTo(other.getScoreValue()) > 0; // 距离/分数越高越好
        }
    }
}

排名计算服务实现:

@Service
public class RankingService {
    
    public void calculateRanking(Integer eventId) {
        // 获取该赛事所有成绩记录
        String hql = "from ScoreRecord where event.eventId = ? order by scoreValue ";
        hql += isTrackEvent(eventId) ? "asc" : "desc"; // 田赛升序,径赛降序
        
        List<ScoreRecord> records = getHibernateTemplate().find(hql, eventId);
        
        // 计算排名(处理并列情况)
        int currentRank = 1;
        BigDecimal lastScore = null;
        int sameScoreCount = 0;
        
        for (ScoreRecord record : records) {
            if (lastScore != null && !record.getScoreValue().equals(lastScore)) {
                currentRank += sameScoreCount;
                sameScoreCount = 1;
            } else {
                sameScoreCount++;
            }
            
            record.setRanking(currentRank);
            lastScore = record.getScoreValue();
            getHibernateTemplate().update(record);
        }
    }
}

成绩录入界面

赛事安排与冲突检测

赛事安排功能确保时间地点不冲突:

@Service
public class ScheduleService {
    
    public boolean checkScheduleConflict(SportsEvent newEvent) {
        String hql = "from SportsEvent where eventTime between ? and ? and location = ? and eventId != ?";
        Date startTime = newEvent.getEventTime();
        Date endTime = calculateEndTime(newEvent);
        
        List<SportsEvent> conflicts = getHibernateTemplate().find(hql, 
            startTime, endTime, newEvent.getLocation(), 
            newEvent.getEventId() != null ? newEvent.getEventId() : -1);
        
        return conflicts.isEmpty();
    }
    
    private Date calculateEndTime(SportsEvent event) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(event.getEventTime());
        calendar.add(Calendar.MINUTE, event.getEstimatedDuration());
        return calendar.getTime();
    }
}

信息发布与权限控制

系统通过Struts2拦截器实现权限控制:

public class AuthInterceptor extends AbstractInterceptor {
    
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext context = invocation.getInvocationContext();
        Map<String, Object> session = context.getSession();
        
        User user = (User) session.get("currentUser");
        String actionName = invocation.getProxy().getActionName();
        
        if (user == null) {
            return "login"; // 重定向到登录页
        }
        
        if (!hasPermission(user, actionName)) {
            return "noPermission"; // 权限不足
        }
        
        return invocation.invoke();
    }
    
    private boolean hasPermission(User user, String actionName) {
        // 根据用户角色和请求action判断权限
        return user.getRole().getPermissions().contains(actionName);
    }
}

信息发布Action处理各类公告:

public class AnnouncementAction extends ActionSupport {
    private Announcement announcement;
    private File attachment;
    private String attachmentFileName;
    
    public String publish() {
        try {
            // 处理文件上传
            if (attachment != null) {
                String filePath = saveUploadFile(attachment, attachmentFileName);
                announcement.setAttachmentPath(filePath);
            }
            
            announcementService.publish(announcement);
            return SUCCESS;
        } catch (Exception e) {
            addActionError("发布失败: " + e.getMessage());
            return ERROR;
        }
    }
}

信息发布界面

实体模型设计

系统采用面向对象的设计思想,通过Hibernate注解实现对象关系映射:

核心实体关系

@Entity
@Table(name = "athlete")
public class Athlete {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer athleteId;
    
    private String studentId;
    private String name;
    private String gender;
    private String college;
    
    @OneToMany(mappedBy = "athlete", cascade = CascadeType.ALL)
    private Set<Registration> registrations = new HashSet<>();
    
    @OneToMany(mappedBy = "athlete")
    private Set<ScoreRecord> scoreRecords = new HashSet<>();
}

@Entity
@Table(name = "sports_event")
public class SportsEvent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer eventId;
    
    private String eventName;
    private String eventType;
    
    @OneToMany(mappedBy = "event")
    private Set<Registration> registrations = new HashSet<>();
    
    @OneToMany(mappedBy = "event")
    private Set<ScoreRecord> scoreRecords = new HashSet<>();
    
    @ManyToOne
    @JoinColumn(name = "created_by")
    private Admin createdBy;
}

数据字典管理

系统维护完整的数据字典确保数据一致性:

@Entity
@Table(name = "data_dictionary")
public class DataDictionary {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer dictId;
    
    private String dictType;  // 如:EVENT_TYPE, GENDER
    private String dictCode;  // 如:TRACK, FIELD
    private String dictValue; // 如:径赛, 田赛
    private Integer sortOrder;
    private String description;
}

数据字典设计

性能优化策略

数据库查询优化

@Repository
public class AthleteDAOImpl extends HibernateDaoSupport implements AthleteDAO {
    
    public List<Athlete> findAthletesByCollegeWithPagination(String college, 
                                                           int page, int size) {
        String hql = "from Athlete where college = :college order by studentId";
        
        return getHibernateTemplate().execute(new HibernateCallback<List<Athlete>>() {
            @Override
            public List<Athlete> doInHibernate(Session session) throws HibernateException {
                Query query = session.createQuery(hql);
                query.setParameter("college", college);
                query.setFirstResult((page - 1) * size);
                query.setMaxResults(size);
                return query.list();
            }
        });
    }
}

缓存策略实现

<!-- Ehcache配置 -->
<ehcache>
    <cache name="athleteCache"
           maxElementsInMemory="1000"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"/>
</ehcache>
@Repository
@Cacheable(value = "athleteCache")
public class AthleteDAOImpl implements AthleteDAO {
    
    @CacheEvict(value = "athleteCache", key = "#athlete.athleteId")
    public void updateAthlete(Athlete athlete) {
        // 更新操作
    }
}

系统安全设计

密码加密存储

@Component
public class PasswordEncoder {
    
    public String encode(String rawPassword) {
        return DigestUtils.md5DigestAsHex((rawPassword + "sports_salt").getBytes());
    }
    
    public boolean matches(String rawPassword, String encodedPassword) {
        return encode(rawPassword).equals(encodedPassword);
    }
}

SQL注入防护

@Repository
public class SafeQueryDAO {
    
    public List<Athlete> findByNameSafe(String name) {
        String hql = "from Athlete where name = ?";
        return getHibernateTemplate().find(hql, name); // 使用参数化查询
    }
}

未来优化方向

移动端适配

开发响应式前端界面,支持移动设备访问。采用Bootstrap框架实现:

<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-sm-12">
            <!-- 移动端适配的赛事信息卡片 -->
        </div>
    </div>
</div>

实时通知功能

集成WebSocket实现实时成绩推送:

@ServerEndpoint("/websocket/score")
public class ScoreWebSocket {
    
    @OnOpen
    public void onOpen(Session session) {
        // 连接建立逻辑
    }
    
    @OnMessage
    public void onMessage(String message, Session session)
本文关键词
SSH框架校园运动会管理系统源码解析数字化管理

上下篇

上一篇
没有更多文章
下一篇
没有更多文章