You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在/home路由正确提供带样式的静态文件?Java HttpServer问题

问题

根目录为TodoList,包含TodoList/Views/index.html和style.css文件。期望在/home路由下提供这两个文件,但访问localhost:8080/home时仅加载HTML内容,CSS样式丢失。现有代码如下:

import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) throws IOException {
        int port = 8080;
        HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);

        server.createContext("/home", new RequestHandler());
        server.start();

        System.out.println("Server started on port " + port);
    }
}

class RequestHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String requestPath = exchange.getRequestURI().getPath();
        
        if (requestPath.equals("/home")) {
            serveFile(exchange, "Views/index.html", "text/html");
            serveFile(exchange, "Views/style.css", "text/css");
        } else {
            // Handle other requests here
            // For example, you could serve a 404 page
            String response = "404 - Not Found";
            exchange.sendResponseHeaders(404, response.length());
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(response.getBytes());
            }
        }
    }

    private void serveFile(HttpExchange exchange, String filePath, String contentType) throws IOException {
        Path path = Paths.get(filePath);
        byte[] fileBytes = Files.readAllBytes(path);

        exchange.getResponseHeaders().set("Content-Type", contentType);
        exchange.sendResponseHeaders(200, fileBytes.length);

        try (OutputStream os = exchange.getResponseBody()) {
            os.write(fileBytes);
        }
    }
}
问题原因
  1. 重复响应错误:一个HTTP请求只能对应一个响应。当前代码在处理/home请求时连续调用两次serveFile,第一次发送HTML响应后,第二次尝试发送CSS响应会触发异常,导致CSS无法正常返回。
  2. 路由未覆盖CSS请求:浏览器加载HTML后,会自动发起CSS文件请求(若HTML中引用style.css,实际请求路径为/home/style.css),但当前代码仅处理/home路径,其他路径直接返回404,导致CSS请求失败。
修复方案

调整路由逻辑,让服务器能够处理/home(返回HTML)和/home/style.css(返回CSS)两种请求,同时保证每个请求仅返回一个响应。

以下是优化后的代码(单Handler处理所有子路径):

import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) throws IOException {
        int port = 8080;
        HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);

        server.createContext("/home", new RequestHandler());
        server.start();

        System.out.println("Server started on port " + port);
    }
}

class RequestHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String requestPath = exchange.getRequestURI().getPath();
        String targetFile = null;
        String contentType = null;

        // 匹配请求路径,分配对应的文件和内容类型
        if (requestPath.equals("/home") || requestPath.equals("/home/")) {
            targetFile = "Views/index.html";
            contentType = "text/html";
        } else if (requestPath.equals("/home/style.css")) {
            targetFile = "Views/style.css";
            contentType = "text/css";
        } else {
            // 未知路径返回404
            sendErrorResponse(exchange, 404, "404 - Not Found");
            return;
        }

        Path file = Paths.get(targetFile);
        // 检查文件是否存在
        if (!Files.exists(file)) {
            sendErrorResponse(exchange, 404, "404 - File Not Found");
            return;
        }

        // 读取文件并发送响应
        byte[] fileContent = Files.readAllBytes(file);
        exchange.getResponseHeaders().set("Content-Type", contentType);
        exchange.sendResponseHeaders(200, fileContent.length);
        
        try (OutputStream output = exchange.getResponseBody()) {
            output.write(fileContent);
        }
    }

    // 封装错误响应发送逻辑
    private void sendErrorResponse(HttpExchange exchange, int code, String message) throws IOException {
        exchange.sendResponseHeaders(code, message.length());
        try (OutputStream output = exchange.getResponseBody()) {
            output.write(message.getBytes());
        }
    }
}
额外注意事项
  • 确保HTML中的CSS引用路径正确,应写为:<link rel="stylesheet" href="/home/style.css">,这样浏览器才会请求正确的路由地址。
  • 添加了文件存在性检查,避免因文件丢失导致的运行时异常。

内容的提问来源于stack exchange,提问作者Aliayub Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:48:10