Spring MVC + Vue.js动态时钟
Spring MVC + Vue.js:SVG 动态表盘时钟
项目结构

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>


请求处理流程
用户访问项目根路径 / → 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 指针角度变化。
浙公网安备 33010602011771号