Clock

🌐 基于SpringMVC的动态时钟设计

一个优雅的Web动态时钟实现,融合后端框架与前端动效


一、项目概述

1.1 项目背景

在现代Web开发中,SpringMVC作为经典的MVC框架,被广泛应用于企业级项目。本项目通过实现一个动态时钟,展示SpringMVC框架的基本使用流程,包括:

  • 控制器接收请求并处理业务逻辑
  • 视图解析器进行页面跳转
  • JSP页面结合EL表达式接收后端数据
  • JavaScript实现前端动态刷新效果

1.2 功能特点

功能 描述
🕐 实时时钟 基于服务器时间,每秒自动刷新
🎨 居中显示 页面垂直水平居中,适配不同屏幕
✨ 玻璃拟态 现代化UI设计,毛玻璃视觉效果
🔄 动态更新 冒号闪烁动画,时间变化平滑

二、技术栈

技术 版本 作用
SpringMVC 4.x/5.x MVC框架,处理请求与响应
Java JDK 1.8 后端逻辑开发
JSP 2.0+ 动态页面渲染
JavaScript ES6 前端动态刷新与动画
CSS3 - 页面布局与美化
Tomcat 8.0/9.0 Web服务器

三、项目结构

clock/
├── src/
│ ├── controller/
│ │ └── clockcontroller.java # 控制器
│ └── com/clock/util/
│ └── TimeUtil.java # 时间工具类
└── WebContent/
├── WEB-INF/
│ ├── web.xml # Web配置
│ ├── myspringmvc-servlet.xml # SpringMVC配置
│ └── view/
│ └── clock.jsp # 时钟页面


四、核心代码实现

4.1 web.xml - 前端控制器配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         version="4.0">
    
    <!-- 配置DispatcherServlet -->
    <servlet>
        <servlet-name>myspringmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/myspringmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 拦截所有.do请求 -->
    <servlet-mapping>
        <servlet-name>myspringmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>

4.2 SpringMVC配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="...">
    
    <!-- 开启注解驱动 -->
    <mvc:annotation-driven />
    
    <!-- 扫描控制器包 -->
    <context:component-scan base-package="controller" />
    
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

4.3 后端控制器

package controller;

import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.clock.util.TimeUtil;

public class clockcontroller implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, 
                                       HttpServletResponse response) throws Exception {
        // 1. 获取服务器系统当前时间
        Date nowDate = new Date();
        
        // 2. 格式化时间为 HH:mm:ss
        String formatTime = TimeUtil.formatHMS(nowDate);
        
        // 3. 存入ModelAndView
        ModelAndView mv = new ModelAndView();
        mv.addObject("rawDate", nowDate);
        mv.addObject("initTime", formatTime);
        mv.setViewName("clock");
        
        return mv;
    }
}

4.4 时间工具类

package com.clock.util;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeUtil {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    public static String formatHMS(Date date) {
        return date == null ? "" : sdf.format(date);
    }
}

4.5 前端时钟页面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8" isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>动态时钟</title>
<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    body {
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
        font-family: 'Microsoft YaHei', 'Segoe UI', sans-serif;
    }

    .title {
        font-size: 24px;
        margin-bottom: 30px;
        color: #e0e0e0;
        letter-spacing: 2px;
    }

    /* 玻璃拟态时钟容器 */
    .clock-box {
        background: rgba(255, 255, 255, 0.08);
        backdrop-filter: blur(15px);
        border: 1px solid rgba(255, 255, 255, 0.15);
        border-radius: 30px;
        padding: 50px 80px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    }

    /* 时钟数字 */
    #clock {
        font-size: 90px;
        font-weight: 300;
        color: #ffffff;
        font-family: 'Courier New', monospace;
        letter-spacing: 5px;
        text-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
    }

    /* 冒号闪烁动画 */
    .dot {
        animation: blink 1s infinite;
    }

    @keyframes blink {
        0%, 100% { opacity: 1; }
        50% { opacity: 0.2; }
    }
</style>
</head>

<body>
    <div class="title">⏰ 服务器时间 ⏰</div>
    <div class="clock-box">
        <div id="clock">--:--:--</div>
    </div>

    <script>
        // 接收后端传递的服务器初始时间
        var serverTimeStr = "${initTime}";
        
        // 将时间字符串转换为秒数
        function timeToSeconds(timeStr) {
            if (!timeStr || timeStr.indexOf("${") !== -1) return null;
            var parts = timeStr.split(':');
            return parseInt(parts[0]) * 3600 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
        }
        
        // 将秒数转换为时间字符串
        function secondsToTime(seconds) {
            var h = Math.floor(seconds / 3600) % 24;
            var m = Math.floor(seconds % 3600 / 60);
            var s = seconds % 60;
            return h.toString().padStart(2, '0') + ":" + 
                   m.toString().padStart(2, '0') + ":" + 
                   s.toString().padStart(2, '0');
        }
        
        var currentSeconds = timeToSeconds(serverTimeStr);
        
        function updateClock() {
            if (currentSeconds !== null) {
                var timeStr = secondsToTime(currentSeconds);
                var parts = timeStr.split(':');
                document.getElementById("clock").innerHTML = 
                    parts[0] + "<span class='dot'>:</span>" + 
                    parts[1] + "<span class='dot'>:</span>" + 
                    parts[2];
                currentSeconds = (currentSeconds + 1) % 86400;
            }
        }
        
        updateClock();
        setInterval(updateClock, 1000);
    </script>
</body>
</html>

六、技术要点总结

6.1 SpringMVC工作流程

用户请求 → DispatcherServlet → HandlerMapping → Controller → ModelAndView → ViewResolver → JSP响应

6.2 关键技术点

技术点 说明
Controller接口 实现handleRequest方法处理请求
ModelAndView 封装数据和视图名
InternalResourceViewResolver 视图解析,拼接前后缀
setInterval JavaScript定时器,每秒刷新

6.3 设计亮点

  1. 玻璃拟态设计backdrop-filter: blur() 实现毛玻璃效果
  2. 冒号闪烁动画:CSS动画让时钟更生动
  3. 基于服务器时间:使用后端时间戳,前端自增,减少请求

七、常见问题与解决

问题 原因 解决方案
时钟不刷新 JS错误或定时器未启动 检查浏览器控制台
时间不同步 使用客户端本地时间 改用后端传递的时间戳

八、总结

本项目通过SpringMVC框架实现了一个动态时钟应用,涵盖了:

  • ✅ SpringMVC环境搭建与配置
  • ✅ Controller控制器开发
  • ✅ 时间格式化工具类封装
  • ✅ JSP页面设计与EL表达式使用
  • ✅ JavaScript定时器实现动态刷新
  • ✅ CSS3现代化视觉效果

通过这个项目,可以快速掌握SpringMVC的基本使用流程,为进一步学习Java Web开发打下基础。


📚 参考资料

  1. 《Web程序设计》,余元辉,清华大学出版社
  2. Spring官方文档:https://spring.io/
posted @ 2026-06-07 10:44  计算机糕手  阅读(14)  评论(0)    收藏  举报