旧项目上的 Jetty 和 Jersey 404 错误
Jetty and Jersey 404 error on an old project
作为我工作的一部分,我正在尝试更新我们的一些服务,其中一项正在使用 Jetty & Jersey 进行部署。不幸的是,代码非常旧(一些依赖项来自 2014 年),并且在编译和服务器启动时,每当我 运行 它来自我的 IDE 和 mvn jetty:run
时,根目录显示 Directory /
消息正确,而对于所有其他 URL,我收到错误 404 NOT FOUND
.
我在控制台上没有收到任何 warning/error 消息,我也不知道为什么会这样。我搜索了很多,但代码似乎是正确的,唯一缺少的是 web.xml
,但我认为 Jetty 是嵌入式的,我需要指出的是,这段代码已经 运行 投入生产作为 JAR。
您可以在下面看到一些文件:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>2.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.2.v20140723</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
参考下面的class启动服务器:
ApiService.java
import com.simple.api.restendpoint.*;
import org.apache.log4j.Logger;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.IPAccessHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import java.util.HashSet;
import java.util.Set;
public class ApiService {
Logger log = Logger.getLogger(ApiService.class);
private static ApiService instance;
private final Server server;
private ApiService(){
//CREATE CONFIG
Set<Class<?>> s = new HashSet<>();
s.add(restEndpoint.class);
ResourceConfig config = new ResourceConfig(s);
//CREATE CONTAINER
ServletContainer container = new ServletContainer(config);
//CREATE CONTEXT
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(new ServletHolder(container),"/*");
//CREATE RPC SERVER
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(50);
server = new Server(threadPool);
server.setHandler(context);
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("testkeystore");
sslContextFactory.setKeyStorePassword("testkeystore");
sslContextFactory.setKeyManagerPassword("testkeystore");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(Settings.getInstance().getRpcPort());
server.addConnector(sslConnector);
}
public static ApiService getInstance() {
if (instance==null) {
instance = new ApiService();
}
return instance;
}
public void start() {
try {
//START RPC
server.start();
server.join();
log.info("Server started");
}
catch (Exception e) {
//FAILED TO START RPC
log.error("Error starting server");
} finally {
server.destroy();
}
}
}
restEndpoint.java
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Context;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
@Path("/v4/restEndpoint")
@Produces({"application/json"})
public class restEndpoint {
Logger log = Logger.getLogger(restEndpoint.class);
private static final String VERSION = "v4";
private static final ExecutorService executors = Executors.newFixedThreadPool(20);
@Context
HttpServletRequest request;
@GET
@Path("/getsamplejson")
public void getSampleJson(@Suspended final AsyncResponse asyncResponse) {
executors.execute(new Runnable() {
@Override
public void run() {
String result = veryExpensiveOperation();
asyncResponse.resume(result);
}
private String veryExpensiveOperation() {
JSONObject sampleJson = new JSONObject().put("test", 0);
return sampleJson.toString();
}
});
}
}
知道为什么会这样吗?
http://localhost:8080/v4/restEndpoint/getsamplejson
returns 404 NOT FOUND
http://localhost:8080/
显示 Directory: /
我是否应该尝试将其构建为 JAR 并通过它 运行 而不是使用 mvn jetty:run
命令?
您有一个 embedded-jetty 实例,从代码开始。
您提供的 ApiService
来源证明了这一点。
您不能使用 jetty-maven-plugin
来管理/启动 / 运行 class。
jetty-maven-plugin
专门用于处理网络应用程序,可以作为 WAR 打包文件,也可以作为展开的网络应用程序目录。 (webapps 将有一个 WEB-INF/web.xml 和/或 Servlet 在其中注释 classes)
您需要使用项目独有的其他方式启动服务器,可能是某种主要 class 或测试用例,最终实例化 ApiService
并调用 .start()
就可以了。
作为我工作的一部分,我正在尝试更新我们的一些服务,其中一项正在使用 Jetty & Jersey 进行部署。不幸的是,代码非常旧(一些依赖项来自 2014 年),并且在编译和服务器启动时,每当我 运行 它来自我的 IDE 和 mvn jetty:run
时,根目录显示 Directory /
消息正确,而对于所有其他 URL,我收到错误 404 NOT FOUND
.
我在控制台上没有收到任何 warning/error 消息,我也不知道为什么会这样。我搜索了很多,但代码似乎是正确的,唯一缺少的是 web.xml
,但我认为 Jetty 是嵌入式的,我需要指出的是,这段代码已经 运行 投入生产作为 JAR。
您可以在下面看到一些文件:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>2.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.2.v20140723</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
参考下面的class启动服务器:
ApiService.java
import com.simple.api.restendpoint.*;
import org.apache.log4j.Logger;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.IPAccessHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import java.util.HashSet;
import java.util.Set;
public class ApiService {
Logger log = Logger.getLogger(ApiService.class);
private static ApiService instance;
private final Server server;
private ApiService(){
//CREATE CONFIG
Set<Class<?>> s = new HashSet<>();
s.add(restEndpoint.class);
ResourceConfig config = new ResourceConfig(s);
//CREATE CONTAINER
ServletContainer container = new ServletContainer(config);
//CREATE CONTEXT
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(new ServletHolder(container),"/*");
//CREATE RPC SERVER
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(50);
server = new Server(threadPool);
server.setHandler(context);
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("testkeystore");
sslContextFactory.setKeyStorePassword("testkeystore");
sslContextFactory.setKeyManagerPassword("testkeystore");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(Settings.getInstance().getRpcPort());
server.addConnector(sslConnector);
}
public static ApiService getInstance() {
if (instance==null) {
instance = new ApiService();
}
return instance;
}
public void start() {
try {
//START RPC
server.start();
server.join();
log.info("Server started");
}
catch (Exception e) {
//FAILED TO START RPC
log.error("Error starting server");
} finally {
server.destroy();
}
}
}
restEndpoint.java
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Context;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
@Path("/v4/restEndpoint")
@Produces({"application/json"})
public class restEndpoint {
Logger log = Logger.getLogger(restEndpoint.class);
private static final String VERSION = "v4";
private static final ExecutorService executors = Executors.newFixedThreadPool(20);
@Context
HttpServletRequest request;
@GET
@Path("/getsamplejson")
public void getSampleJson(@Suspended final AsyncResponse asyncResponse) {
executors.execute(new Runnable() {
@Override
public void run() {
String result = veryExpensiveOperation();
asyncResponse.resume(result);
}
private String veryExpensiveOperation() {
JSONObject sampleJson = new JSONObject().put("test", 0);
return sampleJson.toString();
}
});
}
}
知道为什么会这样吗?
http://localhost:8080/v4/restEndpoint/getsamplejson
returns 404 NOT FOUND
http://localhost:8080/
显示 Directory: /
我是否应该尝试将其构建为 JAR 并通过它 运行 而不是使用 mvn jetty:run
命令?
您有一个 embedded-jetty 实例,从代码开始。
您提供的 ApiService
来源证明了这一点。
您不能使用 jetty-maven-plugin
来管理/启动 / 运行 class。
jetty-maven-plugin
专门用于处理网络应用程序,可以作为 WAR 打包文件,也可以作为展开的网络应用程序目录。 (webapps 将有一个 WEB-INF/web.xml 和/或 Servlet 在其中注释 classes)
您需要使用项目独有的其他方式启动服务器,可能是某种主要 class 或测试用例,最终实例化 ApiService
并调用 .start()
就可以了。