通过Servlet访问指定前缀静态资源,解决JS/CSS/字体等文件404及解析异常问题
问题根因
你的代码存在两个核心错误导致返回内容无法正常解析:
- 流读取逻辑完全错误:你调用的无参
inputStream.read()方法每次仅返回单个字节的数值(0~255),并没有把文件内容写入你定义的buffer数组,最终输出的都是数组初始的0值,所以返回内容完全不可读。 - 缺失必要响应头:没有给返回内容配置正确的MIME类型、内容长度等信息,浏览器无法识别你返回的内容格式,自然无法正常渲染。
解决方案
第一步:修正Servlet代码
以下是完整可用的实现,适配文本、二进制类静态资源的返回:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 解析请求路径,匹配实际静态资源位置 String requestPath = req.getPathInfo(); // 配置默认访问页,比如访问/myPage/时直接返回首页 if (requestPath == null || requestPath.isBlank()) { requestPath = "/index.html"; } // 这里假设静态资源存放在webapp下的my-static目录,可根据你的实际存放位置调整路径拼接逻辑 String realPath = getServletContext().getRealPath("/my-static" + requestPath); File resourceFile = new File(realPath); // 2. 资源合法性校验 if (!resourceFile.exists() || resourceFile.isDirectory() || !resourceFile.canRead()) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); return; } // 可选:防止路径遍历漏洞,避免恶意用户读取服务器敏感文件 if (!realPath.startsWith(getServletContext().getRealPath("/my-static"))) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } // 3. 设置正确的响应头 // 自动匹配文件对应的MIME类型 String mimeType = getServletContext().getMimeType(resourceFile.getName()); resp.setContentType(mimeType != null ? mimeType : "application/octet-stream"); // 设置内容长度,避免浏览器端出现截断或者粘包问题 resp.setContentLengthLong(resourceFile.length()); // 可选:配置静态资源缓存,降低服务器压力,示例为缓存7天 resp.setHeader("Cache-Control", "public, max-age=604800"); // 4. 正确的流拷贝逻辑 try (FileInputStream in = new FileInputStream(resourceFile); OutputStream out = resp.getOutputStream()) { byte[] buffer = new byte[1024]; int bytesRead; // read(buffer)会将内容读入buffer数组,返回本次读取到的字节长度 while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } out.flush(); } catch (Exception e) { resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); e.printStackTrace(); } }
第二步:调整静态资源存放位置
把你需要返回的html、js、css、字体等所有静态资源都放到你代码里配置的对应目录下(上面示例是webapp下的my-static目录),访问/myPage/xxx.js时就会自动读取对应目录下的xxx.js返回。
注意事项
如果你的静态资源是放在jar包内部的类路径下,需要替换FileInputStream为this.getClass().getResourceAsStream("类路径下的资源位置")读取,避免文件找不到的问题。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

