yxh
5 天以前 68ff33beff11310e830b0615b5a81f83fad0f683
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package cn.lihu.jh.server.ecg;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
/**
 * 前端静态资源映射(配合"前端打进 jar"的合并部署方案)。
 *
 * <h3>作用</h3>
 * 把 jar 内 {@code META-INF/resources/frontend/} 下的前端构建产物映射到站点根路径。
 *
 * <pre>
 *   URL                         来源
 *   /assets/index-xxx.js   ->   classpath:/META-INF/resources/frontend/assets/index-xxx.js
 *   /logo.gif              ->   classpath:/META-INF/resources/frontend/logo.gif
 *   /favicon.ico           ->   classpath:/META-INF/resources/frontend/favicon.ico
 *   /static/jquery.min.js  ->   classpath:/META-INF/resources/frontend/static/jquery.min.js
 * </pre>
 *
 * <h3>⚠ 为什么【不能】用 {@code /**} 通配(重要)</h3>
 * 初版曾写成 {@code registry.addResourceHandler("/**")},这是**错误**的:
 * 一旦把 {@code /**} 指向前端目录,以下后端自带的路径会被静态资源处理器
 * 抢先匹配,导致静态文件找不到而**直接 404**,控制器不再有机会处理:
 * <ul>
 *   <li>{@code /doc.html}、{@code /swagger-ui/**}、{@code /v3/api-docs/**}
 *       —— Knife4j / springdoc 接口文档</li>
 *   <li>{@code /druid/**} —— Druid 监控台(其 Servlet 已启用)</li>
 *   <li>{@code /actuator/**} —— Spring Boot 监控端点</li>
 *   <li>{@code /jmreport/**} —— 积木报表(若将来启用)</li>
 *   <li>{@code /admin-api/**} —— 全部业务接口</li>
 *   <li>{@code /profile/**} —— 心电模块
 *       {@code WebConfig} 映射到文件系统上传目录</li>
 * </ul>
 * 因此这里改为**显式枚举前端真实存在的资源前缀**,把根路径留给后端自己。
 *
 * <h3>前端产物实际包含哪些顶层条目</h3>
 * 依据 {@code dist-prod} 的实际构建结果:
 * <pre>
 *   index.html, favicon.ico, logo.gif          ← 文件
 *   bigCall.html, smallCall.html               ← kiosk 页(建议删除,见部署指南)
 *   assets/                                    ← 带内容哈希的 js/css/字体/图片
 *   static/                                    ← jquery、axios、vue 等第三方静态库
 * </pre>
 *
 * <h3>SPA 深层路由的兜底</h3>
 * 本类**不负责** SPA 兜底(前端用 {@code createWebHistory()},刷新深层路由
 * 会 404)。兜底由 {@link SpaForwardController} 显式枚举 5 类页面路径完成,
 * 这样既修复刷新 404,又不会把后端真实的 404 吞成 index.html。
 *
 * @author 心电排队装机系统
 */
@Configuration
public class FrontendResourceConfig implements WebMvcConfigurer {
 
    /** 前端产物在 jar 内的位置,需与 jh-server/pom.xml 中 targetPath 保持一致 */
    private static final String FRONTEND_LOCATION = "classpath:/META-INF/resources/frontend/";
 
    /** 带内容哈希的资源可长缓存(30 天) */
    private static final long CACHE_HASHED = 3600L * 24 * 30;
 
    /** 无哈希的根级文件(logo.gif 等)短缓存,避免更新后浏览器不刷新(1 小时) */
    private static final long CACHE_UNHASHED = 3600L;
 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // Vite 产出的带哈希资源目录
        registry.addResourceHandler("/assets/**")
                .addResourceLocations(FRONTEND_LOCATION + "assets/")
                .setCachePeriod((int) CACHE_HASHED);
 
        // public/ 下原样拷贝的第三方静态库(jquery、axios、vue、element-ui 等)
        // 这些文件名不含哈希,用短缓存
        registry.addResourceHandler("/static/**")
                .addResourceLocations(FRONTEND_LOCATION + "static/")
                .setCachePeriod((int) CACHE_UNHASHED);
 
        // 根级静态文件。逐个列出,避免 /doc.html、/druid/** 等被误拦截
        // 文件名不含哈希,用短缓存
        registry.addResourceHandler(
                        "/favicon.ico",
                        "/logo.gif",
                        "/logo.png",
                        "/logo0.png")
                .addResourceLocations(FRONTEND_LOCATION)
                .setCachePeriod((int) CACHE_UNHASHED);
 
        // 注意:index.html 不在此处映射。
        // 它只应通过 SpaForwardController 的 forward:/frontend/index.html 访问,
        // 避免出现"两个入口都能拿到首页"的歧义。
    }
 
    /**
     * 注册前端免登录规则。
     * <p>
     * 必须显式声明为 Bean,框架才会通过
     * {@code JhWebSecurityConfigurerAdapter} 收集并生效。
     * 缺少此 Bean 的典型症状:接口都正常,但浏览器打开是白屏
     * ({@code /logo.gif}、{@code /favicon.ico}、页面路径均返回
     * {@code 401 账号未登录})。
     *
     * @see FrontendAuthorizeRequestsCustomizer
     */
    @Bean
    public FrontendAuthorizeRequestsCustomizer frontendAuthorizeRequestsCustomizer() {
        return new FrontendAuthorizeRequestsCustomizer();
    }
}