• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

gsq123

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

Spring MVC + Vue.js动态时钟

Spring MVC + Vue.js:SVG 动态表盘时钟

项目结构

image
ClockApp
├── src
│ └── com/clock/controller
│ └── ClockController.java
└── WebContent
└── WEB-INF
├── web.xml
├── springmvc-servlet.xml
└── jsp
└── clock.jsp

运行效果
部署至 Tomcat,访问 http://localhost:8080/ClockApp/ ,自动跳转到时钟页面。

表盘展示刻度、三针,秒针红色醒目,下方同步显示当前时间字符串。

配置文件

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

springmvc-servlet.xml

<?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"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="com.clock.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <mvc:annotation-driven/>
</beans>

核心代码
控制器:ClockController.java

package com.clock.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ClockController {

    @RequestMapping("/")
    public String index() {
        return "redirect:/clock";
    }

    @RequestMapping("/clock")
    public String showClock() {
        return "clock";
    }
}

视图页面:clock.jsp
使用 Vue 3 CDN + SVG 绘制表盘,通过 setInterval 每秒更新指针角度。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>动态时钟</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <style>
        #app { text-align: center; margin-top: 50px; }
        svg { background: #f9f9f9; border-radius: 50%; }
    </style>
</head>
<body>
<div id="app">
    <svg width="300" height="300" viewBox="-150 -150 300 300">
        <!-- 表盘刻度 -->
        <circle cx="0" cy="0" r="140" fill="none" stroke="#333" stroke-width="4"/>
        <g v-for="i in 12" :key="i">
            <line :x1="130*Math.cos((i-3)*Math.PI/6)" :y1="130*Math.sin((i-3)*Math.PI/6)"
                  :x2="140*Math.cos((i-3)*Math.PI/6)" :y2="140*Math.sin((i-3)*Math.PI/6)"
                  stroke="#333" stroke-width="2"/>
            <text :x="115*Math.cos((i-3)*Math.PI/6)" :y="115*Math.sin((i-3)*Math.PI/6)+5"
                  text-anchor="middle" font-size="14">{{ i }}</text>
        </g>
        <!-- 时针 -->
        <line x1="0" y1="0"
              :x2="60*Math.cos((hour-3)*Math.PI/6 + minute*Math.PI/360)"
              :y2="60*Math.sin((hour-3)*Math.PI/6 + minute*Math.PI/360)"
              stroke="#222" stroke-width="6" stroke-linecap="round"/>
        <!-- 分针 -->
        <line x1="0" y1="0"
              :x2="90*Math.cos((minute-15)*Math.PI/30)"
              :y2="90*Math.sin((minute-15)*Math.PI/30)"
              stroke="#555" stroke-width="4" stroke-linecap="round"/>
        <!-- 秒针 -->
        <line x1="0" y1="0"
              :x2="110*Math.cos((second-15)*Math.PI/30)"
              :y2="110*Math.sin((second-15)*Math.PI/30)"
              stroke="red" stroke-width="2" stroke-linecap="round"/>
        <!-- 中心圆点 -->
        <circle cx="0" cy="0" r="6" fill="#333"/>
    </svg>
    <p>当前时间:{{ timeStr }}</p>
</div>

<script>
    const { createApp } = Vue;
    createApp({
        data() {
            return {
                hour: 0,
                minute: 0,
                second: 0,
                timeStr: ''
            };
        },
        methods: {
            updateTime() {
                const now = new Date();
                this.hour = now.getHours() % 12;
                this.minute = now.getMinutes();
                this.second = now.getSeconds();
                this.timeStr = now.toLocaleTimeString();
            }
        },
        mounted() {
            this.updateTime();
            setInterval(this.updateTime, 1000);
        }
    }).mount('#app');
</script>
</body>
</html>

image
image

请求处理流程
用户访问项目根路径 / → DispatcherServlet 接收请求。

HandlerMapping 将 / 映射到 ClockController.index() 方法,返回 redirect:/clock。

浏览器重定向到 /clock,再次由 DispatcherServlet 处理。

/clock 映射到 showClock(),返回逻辑视图名 "clock"。

ViewResolver 拼接前缀 /WEB-INF/jsp/ 与后缀 .jsp,得到 /WEB-INF/jsp/clock.jsp。

服务器渲染 JSP(此时不包含动态数据),将 HTML 源码响应给客户端。

客户端浏览器加载 Vue 3 CDN,创建 Vue 实例,mounted 中启动定时器。

每秒更新 hour、minute、second 及 timeStr,绑定驱动 SVG 指针角度变化。

posted on 2026-06-07 10:34  YyB123  阅读(6)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3