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