2016-08-18 3 views
0

Мне нужно установить сервлет (только сервлет не обработчик по некоторым причинам) для работы с файлами за пределами войны. Здесь https://stackoverflow.com/a/28735121/5057736 я нашел следующее решение:Jetty: путь контекста сервлета по умолчанию

Server server = new Server(8080); 

ServletContextHandler ctx = new ServletContextHandler(); 
ctx.setContextPath("/"); 

DefaultServlet defaultServlet = new DefaultServlet(); 
ServletHolder holderPwd = new ServletHolder("default", defaultServlet); 
holderPwd.setInitParameter("resourceBase", "./src/webapp/"); 

ctx.addServlet(holderPwd, "/*");//LINE N 
ctx.addServlet(InfoServiceSocketServlet.class, "/info"); 

server.setHandler(ctx); 

Это решение работает, и это то, что мне нужно. Однако он перестает работать, как только я меняю LINE N на ctx.addServlet(holderPwd, "/foo/*");. Я попробовал «/ foo /», «/ foo», но результат тот же - я получаю not found. Зачем? Как я могу заставить его работать с этим определенным контекстом? Я использую причал 9.2.15 по тем же причинам.

ответ

6

DefaultServlet предназначен для просмотра URI запроса после contextPath.

В вашем примере кода, когда вы изменили URL-шаблон сервлета из / в /foo/* полученный файл разыскиваются на диск теперь включает /foo/ часть.

Другими словами, запрос URI из /css/main.css результатов в файл (на диске) он ожидает найти в ./src/webapp/foo/css/main.css

Ваш пример имеет несколько недостатков. Не разумно иметь пустую базу ресурсов для вашего ServletContextHandler, так как самому ServletContextнужен доступ к этому значению конфигурации.

Вы бы исправить это путем удаления ...

holderPwd.setInitParameter("resourceBase", "./src/webapp/"); 

и используя ServletContextHandler.setBaseResource(Resource) вместо ...

ctx.setResourceBase(Resource.newResource(new File("./src/webapp"))); 

Это позволит следующим ServletContext методам (используются бесчисленными библиотеками сервлет) для работы а также

  • String getRealPath(String path)
  • URL getResource(String path)
  • InputStream getResourceAsStream(String path)
  • Set<String> getResources(String path)

Наконец, чтобы сделать эту установку вменяемой в ServletContextHandler, вы добавите имя default Servlet, на "по умолчанию URL-шаблон", который бывает реализован как DefaultServlet.

Как это:

// Lastly, the default servlet for root content 
// It is important that this is added last. 
String defName = "default"; // the important "default" name 
ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class); 
holderDef.setInitParameter("dirAllowed","true"); 
ctx.addServlet(holderDef,"/"); // the servlet spec "default url-pattern" 

Теперь, если вы также есть необходимость обслуживания статического контента из запроса URI /foo/* из каталога, не принадлежащие к веб-приложение, вы можете сделать это. Это потребует установки другого DefaultServlet, который не участвует в ServletContext.

Примером этой установки является ...

package jetty; 

import org.eclipse.jetty.server.Server; 
import org.eclipse.jetty.server.ServerConnector; 
import org.eclipse.jetty.servlet.DefaultServlet; 
import org.eclipse.jetty.servlet.ServletContextHandler; 
import org.eclipse.jetty.servlet.ServletHolder; 
import org.eclipse.jetty.util.resource.PathResource; 

import java.io.File; 
import java.nio.file.Path; 

public class ManyDefaultServlet 
{ 
    public static void main(String[] args) throws Exception { 
     Server server = new Server(); 
     ServerConnector connector = new ServerConnector(server); 
     connector.setPort(8080); 
     server.addConnector(connector); 

     // The filesystem paths we will map 
     Path homePath = new File(System.getProperty("user.home")).toPath().toRealPath(); 
     Path pwdPath = new File(System.getProperty("user.dir")).toPath().toRealPath(); 

     // Setup the basic application "context" for this application at "/" 
     // This is also known as the handler tree (in jetty speak) 
     ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 
     context.setContextPath("/"); 
     context.setBaseResource(new PathResource(pwdPath)); 
     server.setHandler(context); 

     // Fist, add special pathspec of "/home/" content mapped to the homePath 
     ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class); 
     holderHome.setInitParameter("resourceBase",homePath.toUri().toASCIIString()); 
     holderHome.setInitParameter("dirAllowed","true"); 
     // Use request pathInfo, don't calculate from contextPath 
     holderHome.setInitParameter("pathInfoOnly","true"); 
     context.addServlet(holderHome,"/foo/*"); // must end in "/*" for pathInfo to work 

     // Lastly, the default servlet for root content 
     // It is important that this is last. 
     String defName = "default"; // the important "default" name 
     ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class); 
     holderDef.setInitParameter("dirAllowed","true"); 
     context.addServlet(holderDef,"/"); // the servlet spec "default url-pattern" 

     server.start(); 
     server.join(); 
    } 
} 

При этом используется вторым DefaultServlet, с использованием уникальной ресурсной базы только для этого DefaultServlet и отображается в URL-шаблон, который заканчивается в /*.

И наконец, параметру init для этой второй DefaultServlet предлагается использовать pathInfo URI запроса, а не разделять на contextPath, как обычно.

Для получения дополнительной информации о том, что весь этот Pathinfo, запрос URI, contextPath и URL-модели, заканчивающиеся в /* все о см в useful answer by @30thh

Это самостоятельные DefaultServlet декларация не участвует в ServletContext и библиотеки не смогут видеть или получать доступ к содержимому с этого DefaultServlet с помощью методов ServletContext. Однако все входящие запросы HTTP-клиента могут легко запросить контент через этот шаблон url.

+0

К сожалению, я не могу выдвигать более одного раза. Спасибо за подробное объяснение. –