本文介绍了嵌入式Jetty服务器,在根上下文下看不到网页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我正在具有3.18.9内核的Linux机器上使用Java版本为"1.8.0_45"的jetty v9.2.10.v20150310.

I am using jetty v9.2.10.v20150310 with java version "1.8.0_45" on a linux box with a 3.18.9 kernel.

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

The problem is that if I set the context path to a non root value; i.e., /embed I can access my web page on my embedded jetty server. However if I set the context path to root; i.e., "/" I cannot access the page. Interestingly this problem does not show up when I interact with the servlet via curl.

这是代码:

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.

If I change servletWebDir from "/" to "/embed" everything works as it should.If not I get a 404.

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

I can interact successfully with the servlet via curl commands a follows:

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

If I attempt to use http://host:8080/customServlet in either firefox orchrome with servletWebDir set to "/" I get a 404. Note that this code works fine under jetty v8.1.16.v20140903.

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

What am I doing wrong? What have I missed in Jetty v9.x?

使用setBaseResource并删除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交互仍然有效.如果上面的新代码正确,我错过了什么吗?在错误日志中,类路径被报告为空.我接下来可以尝试什么?

This new code no longer serves a static page to a web browser regardless of the value of servletWebDir. Interacting with the custom servlet via curl still works.If the above new code is correct have I missed something? The class path is reported as null in the error logs. What can I try next?

Joakim:

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

I tried the code you suggested. I really appreciate the time and effort you took to prepare the code sample. However the code fails at run time. The error log states:

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

STDERR: 2015-05-09 15:51:32.278:WARN:/embed:main: unavailablejava.lang.IllegalAccessException: Class org.eclipse.jetty.server.handler.ContextHandler$Context can not access a member of class customServlet with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)

该异常未标识应公开的确切成员.我更新的代码可以正常工作,而不必将一整套方法从私有更改为公开.

The exception does not identify the exact member that should be made public.My updated code does work and I do not have to change a whole bunch of methods from private to public.

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

Joakim could you please explain the benefits of your solution which, if I am not mistaken, requires changing private methods and data members to publicdata members and methods and therefore losing some of the benefits of encapsulation.

已更新的可解决此问题的代码:

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永远不会执行.

You are using a ServletContextHandler, you cannot mix that with a ResourceHandler, as the built-in DefaultServlet of the ServletContextHandler will serve the files (or give an error response), leaving the ResourceHandler to never execute.

要修复:

拖放ResourceHandler(无论如何,它都远低于DefaultServlet).

Drop the ResourceHandler (its far inferior to the DefaultServlet anyway).

设置 servletHandler.setBaseResource(Resource) 到您的Web应用程序根目录(您的静态文件所在的目录).这可以是URL,URI或文件系统路径引用.

Set the servletHandler.setBaseResource(Resource) to your web application root directory (where your static files are). This can be a URL, URI, or file system path reference.

示例:

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

// or URL
servletHandler.setBaseResource(Resource.newResource("jar:file://tmp/b.jar!/webroot"));

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

The resource path should point to a directory, not a specific file.

有关更多详细信息,请参见有关此问题的先前答案.

See previous answer about this for more details.

示例:

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

这篇关于嵌入式Jetty服务器,在根上下文下看不到网页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 00:33