首页 文章

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

提问于
浏览
3

我在带有3.18.9内核的linux机器上使用带有java版本“1.8.0_45”的jetty v9.2.10.v20150310 .

问题是,如果我将上下文路径设置为非根值;即,/ embed我可以在我的嵌入式码头服务器上访问我的网页 . 但是,如果我将上下文路径设置为root;即,“/”我无法访问该页面 . 有趣的是,当我通过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成功交互,如下所示:

curl http:// host:8080 / customServlet?command = exp

如果我尝试在firefox或chrome中使用http://host:8080/customServlet并且servletWebDir设置为"/"我得到404.请注意,此代码在jetty v8.1.16.v20140903下正常工作 .

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

Updated code that uses setBaseResource and drops the ResourceHandler:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
final String servletWebDir = "/";
final String theBaseResourceDir = "/aa/bb/cc";
Resource theBaseResource = null;
try{
    theBaseResource = Resource.newResource( theBaseResourceDir );
}
catch( MalformedURLException e ){
    System.err.println( "setup failed on newResource with the exception " + e.toString() );
    System.exit(0);
}

servletHandler.setBaseResource( theBaseResource );
System.err.println("Class path->" + servletHandler.getClassPath() );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );
final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler } );
server.setHandler( handlers );

无论servletWebDir的值如何,这个新代码都不再为Web浏览器提供静态页面 . 通过curl与自定义servlet交互仍然有效 . 如果上面的新代码是正确的,我错过了什么?类路径在错误日志中报告为null . 我接下来可以尝试什么?

乔金 - :

我尝试了你建议的代码 . 我非常感谢您为准备代码示例所花费的时间和精力 . 但是代码在运行时失败 . 错误日志指出:

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

该例外并未确定应公开的确切成员 . 我的更新代码确实有效,我不必将一大堆方法从私有更改为公共 .

Joakim请您解释一下您的解决方案的好处,如果我没有弄错,需要将私有方法和数据成员更改为公共数据成员和方法,从而失去封装的一些好处 .

Updated Code that fixes this problem:

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 );

1 回答

  • 1

    您正在使用 ServletContextHandler ,您不能将其与 ResourceHandler 混合,因为 ServletContextHandler 的内置 DefaultServlet 将提供文件(或给出错误响应),使 ResourceHandler 永远不会执行 .

    To Fix:

    放弃 ResourceHandler (无论如何它远远低于 DefaultServlet ) .

    servletHandler.setBaseResource(Resource)设置为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"));
    

    资源路径应指向目录,而不是特定文件 .

    有关详细信息,请参阅previous answer about this .

    Example:

    package jetty;
    
    import java.io.File;
    import java.net.MalformedURLException;
    import java.net.URI;
    import java.nio.file.Path;
    
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.servlet.DefaultServlet;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    import org.eclipse.jetty.servlet.ServletHolder;
    import org.eclipse.jetty.util.resource.Resource;
    
    public class SimpleServletExample
    {
        public static void main(String[] args)
        {
            try
            {
                Server server = new Server(8080);
    
                // Find the full path to the webroot.
                // Use the real path, with real file system case for all parts of the path
                // Otherwise we fall afoul of alias checking.
                // (esp on OSX and Windows. Unix and Linux do not have this issue)
                Path webrootPath = new File("src/test/resources/sample-files").toPath().toRealPath();
    
                URI webrootUri = webrootPath.toUri();
    
                System.err.println("webroot uri: " + webrootUri);
    
                Resource webroot = Resource.newResource(webrootUri);
                if (!webroot.exists())
                {
                    System.err.println("Resource does not exist: " + webroot);
                    System.exit(-1);
                }
    
                if (!webroot.isDirectory())
                {
                    System.err.println("Resource is not a directory: " + webroot);
                    System.exit(-1);
                }
    
                // Establish ServletContext for all servlets
                ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
                context.setContextPath("/");
                context.setBaseResource(webroot);
                // What file(s) should be used when client requests a directory
                context.setWelcomeFiles(new String[] { "index.html" });
                server.setHandler(context);
    
                // Add a servlet (technique #1)
                ServletHolder holderHello = context.addServlet(HelloServlet.class,"/hello");
                holderHello.setInitOrder(0);
    
                // Add default servlet last (always last) (technique #2)
                // Must be named "default", must be on path mapping "/"
                ServletHolder holderDef = new ServletHolder("default",DefaultServlet.class);
                holderDef.setInitParameter("dirAllowed","true");
                context.addServlet(holderDef,"/");
    
                // Start server
                server.start();
            }
            catch (MalformedURLException e)
            {
                System.err.println("Unable to establish webroot");
                e.printStackTrace(System.err);
            }
            catch (Throwable t)
            {
                t.printStackTrace(System.err);
            }
        }
    }
    

相关问题