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

Java Jetty/Jersey项目无法访问src/main/resources静态文件排查

问题:Jetty/Jersey项目静态资源返回404错误

我正尝试用Maven创建一个简单的Java Jetty/Jersey项目,已经能通过Jersey的Java方法返回内容,但配置ServletContextHandler.setBaseResource后,访问src/main/resources下的文件始终返回404错误。我原本的预期是:请求先匹配Jersey的路径方法,匹配到就返回对应内容;没匹配到则自动搜索静态资源并返回。

WebServer.java 代码

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.glassfish.jersey I可选�jsonCOMw享受 manslaughter?Manks无重启ATE
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

public class WebServer {

    public static void main(String[] args) {
        Server server = createServer();
        try {
            server.start();
            System.out.println("Server started");
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Server createServer() {
        Server server = new Server(9090);
        ServletContextHandler context = new ServletContextHandler(server, "/");
        Resource resources = createStaticResources();
        context.setBaseResource(resources);
        ServletHolder servlet = createServlet();
        context.addServlet(servlet, "/*");
        return server;
    }

    private static ResourceConfig createResourceConfig() {
        ResourceConfig config = new ResourceConfig();
        config.packages("Controllers");
        config.register(MultiPartFeature.class);
        return config;
    }

    private static ServletHolder createServlet() {
        ResourceConfig config = createResourceConfig();
        ServletContainer container = new ServletContainer(config);
        ServletHolder servlet = new ServletHolder(container);
        return servlet;
    }

    private static Resource createStaticResources() {
        String[] locations = new String[] {
            "src/main/resources/"
        };
        Resource resources = new ResourceCollection(locations);
        return resources;
    }
}

Main.java 代码

package Controllers;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Path("/")
public class Main {
    
    @GET
    @Path("/")
    @Produces(MediaType.TEXT_PLAIN)
    public String helloWorld() {
        return "Hello World!";
    }

    @GET
    @Path("/page1")
    @Produces(MediaType.TEXT_PLAIN)
    public String page1() {
        return "Page 1";
    }
}

问题分析与修复方案

核心错误点

  1. Servlet映射拦截所有请求
    你把Jersey的ServletContainer映射到/*,这会让所有请求先经过Jersey处理。如果Jersey找不到匹配的@Path方法,就直接返回404,根本不会把请求交给Jetty的静态资源处理器,完全跳过了你期望的"静态资源 fallback"逻辑。

  2. 静态资源路径无效
    src/main/resources/是开发阶段的源代码目录,Maven构建后,该目录下的文件会被复制到target/classes/(类路径根目录)。直接用文件系统路径src/main/resources/在运行时(比如打包成JAR后)是找不到文件的,因为这个目录在运行环境中不存在。

修复方案

方案1:拆分请求处理,让Jetty负责静态资源

修改createServer方法,把Jersey的映射限制到特定前缀(比如/api/*),这样非API请求会由Jetty处理静态资源:

private static Server createServer() {
    Server server = new Server(w9操作应付用 unders新手推荐
之前认识�完整}
    Server server = new Server(9090);
    ServletContextHandler context = new ServletContextHandler(server, "/");
    // 使用类路径获取静态资源,兼容开发和运行环境
    context.setBaseResource(Resource.newClassPathResource("/"));
    ServletHolder servlet = createServlet();
    // 仅让Jersey处理/api开头的请求
    context.addServlet(servlet, "/api/*");
    return server;
}

同时调整Jersey控制器的路径前缀:

@Path("/api")
public class Main {
    
    @GET
    @Path("/")
    @Produces(MediaType.TEXT_PLAIN)
    public String helloWorld() {
        return "Hello World!";
    }

    @GET
    @Path("/page1")
    @Produces(MediaType.TEXT_PLAIN)
    public String page1() {
        return "Page 1";
    }
}

此时访问http://localhost:9090/api/会触发Jersey方法,访问http://localhost:9090/test.txt(假设src/main/resources/test.txt存在)会返回静态文件内容。

方案2:让Jersey处理静态资源(可选)

如果希望所有请求都经过Jersey再fallback到静态资源,可以注册Jersey的StaticContentFeature:

  1. 先在pom.xml添加依赖:
<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-mvc</artifactId>
    <version>你的Jersey版本</version>
</dependency>
  1. 修改createResourceConfig方法:
private static ResourceConfig createResourceConfig() {
    ResourceConfig config = new ResourceConfig();
    config.packages("Controllers");
    config.register(MultiPartFeature.class);
    // 配置静态资源映射到类路径根目录
    config.property(StaticContentFeature.STATIC_CONTENT_BASE_URI, "/");
    config.register(StaticContentFeature.class);
    return config;
}

保留/*的Servlet映射,Jersey会先匹配资源方法,找不到则返回静态资源。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:25:10