Servlets 嵌入式Jetty服务器,无法在根上下文下查看网页

Servlets 嵌入式Jetty服务器,无法在根上下文下查看网页,servlets,jetty,Servlets,Jetty,我使用的是jetty v9.2.10.v20150310,java版本为“1.8.0_45”,linux内核为3.18.9 问题是,如果我将上下文路径设置为非根值;i、 例如,/embed我可以在嵌入式jetty服务器上访问我的网页。但是,如果我将上下文路径设置为root;i、 例如,“/”我无法访问该页面。有趣的是,当我通过curl与servlet交互时,这个问题并没有出现 代码如下: final ServletContextHandler servletHandler = new Servl

我使用的是jetty v9.2.10.v20150310,java版本为“1.8.0_45”,linux内核为3.18.9

问题是,如果我将上下文路径设置为非根值;i、 例如,/embed我可以在嵌入式jetty服务器上访问我的网页。但是,如果我将上下文路径设置为root;i、 例如,“/”我无法访问该页面。有趣的是,当我通过curl与servlet交互时,这个问题并没有出现

代码如下:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String servletWebDir = "/";
servletHandler.setContextPath( servletWebDir );

final customServlet iass = new customServlet();

final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );

final ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(false);
resourceHandler.setResourceBase(".");

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler, resourceHandler } );

server.setHandler( handlers );
如果我将servletWebDir从“/”更改为“/embed”,一切都会正常工作。 如果不是,我会得到404

我可以通过以下curl命令与servlet成功交互:

卷曲

如果我尝试在firefox或 servletWebDir设置为“/”的chrome,我得到一个404。请注意,该代码在jetty v8.1.16.v20140903下运行良好

我做错了什么?我在Jetty v9.x中错过了什么

更新了使用setBaseResource并删除ResourceHandler的代码:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );
final ServletContextHandler servletHandler=new ServletContextHandler(ServletContextHandler.SESSIONS);
最后一个字符串servletWebDir=“/”;
最后一个字符串theBaseResourceDir=“/aa/bb/cc”;
Resource theBaseResource=null;
试一试{
theBaseResource=Resource.newResource(theBaseResourceDir);
}
捕获(格式错误){
System.err.println(“在newResource上安装失败,出现异常”+e.toString());
系统出口(0);
}
setBaseResource(theBaseResource);
System.err.println(“类路径->”+servletHandler.getClassPath());
最终customServlet iass=新customServlet();
最终服务持有人=新服务持有人(iass);
servletHolder.setInitOrder(0);
addServlet(servletHolder,“/customServlet”);
final HandlerList handlers=new HandlerList();
setHandlers(新处理程序[]{servletHandler});
setHandler(处理程序);
不管servletWebDir的值是多少,这段新代码不再为web浏览器提供静态页面。通过curl与定制servlet交互仍然有效。 如果上面的新代码是正确的,我是否遗漏了什么?类路径在错误日志中报告为null。下一步我能试试什么

约阿金:

我试过你建议的密码。我非常感谢您为准备代码示例所花费的时间和精力。但是,代码在运行时失败。错误日志说明:

标准:2015-05-09 15:51:32.278:警告:/embed:main:不可用 java.lang.IllegalAccessException:Class org.eclipse.jetty.server.handler.ContextHandler$Context无法访问修饰符为“private”的customServlet类的成员 在sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)中

例外情况没有确定应该公开的确切成员。 我更新的代码确实有效,而且我不必将一大堆方法从private更改为public

Joakim您能解释一下您的解决方案的好处吗?如果我没有弄错的话,您的解决方案需要将私有方法和数据成员更改为公共方法 数据成员和方法,因此失去了封装的一些好处

更新了修复此问题的代码:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );

您使用的是
ServletContextHandler
,不能将其与
ResourceHandler
混合使用,因为
ServletContextHandler
的内置
DefaultServlet
将为文件提供服务(或给出错误响应),从而使
ResourceHandler
永远无法执行

要修复:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );
删除
ResourceHandler
(无论如何,它远不如
DefaultServlet

将设置为web应用程序根目录(静态文件所在的位置)。这可以是URL、URI或文件系统路径引用

示例:

// As a file system reference
servletHandler.setBaseResource(Resource.newResource("/path/to/res"));

// or URL
servletHandler.setBaseResource(Resource.newResource("jar:file://tmp/b.jar!/webroot"));
资源路径应该指向一个目录,而不是一个特定的文件

有关更多详细信息,请参阅

示例:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );
包装码头;
导入java.io.File;
导入java.net.MalformedURLException;
导入java.net.URI;
导入java.nio.file.Path;
导入org.eclipse.jetty.server.server;
导入org.eclipse.jetty.servlet.DefaultServlet;
导入org.eclipse.jetty.servlet.ServletContextHandler;
导入org.eclipse.jetty.servlet.ServletHolder;
导入org.eclipse.jetty.util.resource.resource;
公共类SimpleServleteExample
{
公共静态void main(字符串[]args)
{
尝试
{
服务器=新服务器(8080);
//找到webroot的完整路径。
//使用真实路径,路径的所有部分都使用真实文件系统案例
//否则,我们将与别名检查发生冲突。
//(OSX和Windows上的esp。Unix和Linux上没有此问题)
Path webrootPath=新文件(“src/test/resources/sample files”).toPath().toRealPath();
URI webrootUri=webrootPath.toUri();
System.err.println(“webrootUri:+webrootUri”);
Resource webroot=Resource.newResource(webrootUri);
如果(!webroot.exists())
{
System.err.println(“资源不存在:+webroot”);
系统退出(-1);
}
如果(!webroot.isDirectory())
{
System.err.println(“资源不是目录:“+webroot”);
系统退出(-1);
}
//为所有servlet建立servlet上下文
ServletContextHandler上下文=新的ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath(“/”);
setBaseResource(webroot);
//客户端请求目录时应使用哪些文件
setWelcomeFiles(新字符串[]{“index.html”});
setHandler(上下文);
//添加一个servlet(技术#1)
ServletHolder-holderHello=context.addServlet(HelloServlet.class,“/hello”);
holderHello.setInitO