Вопрос не очень хорошо сказано, его трудно понять, что ваша цель есть.
Совет: В будущем, спросите, как достичь цели, а затем указать путь к которому вы пытаетесь
Давайте предположим, у вас есть веб-приложение под названием example-webapp.war
Он имеет простой WEB-INF/web.xml
с записью сервлета как таковой ...
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.company.foo.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
example-webapp.war
приходит со своим собственным com.company.foo.TestServlet
(находится в WebApp-х WEB-INF/classes
плачевными ctory)
Теперь у вас есть встроенный-Jetty экземпляр, вы хотите запустить example-webapp.war
, но вы хотите использовать реализацию com.company.foo.TestServlet
, которая существует вне example-webapp.war
(с различной функциональностью).
Вы можете выполнить это, сначала узнав, что спецификация сервлета имеет разгрузку класса загрузчика webapp с его сервера, а затем настраивает этот изолирующий слой класса загрузчика, чтобы вытолкнуть небольшое отверстие через эту изоляцию.
Это отверстие должно:
- сделать веб-приложение Загрузчик классов способны видеть класс сервера
- Принудительный веб-приложение, чтобы использовать версию класса сервера по версии класса WebApp
Это достаточно легко выполнить во встроенном причале.
Давайте начнем с создания пользовательской версии com.company.foo.TestServlet
и ее доступности в пути к классам для сервера встроенной пристани.
Наконец, настройте WebAppContext
, чтобы сконфигурировать изолирующее отверстие класса загрузчика, упомянутое выше. (Использование системных классов и конфигураций серверных классов)
package demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class EmbedWithOverridenServlet
{
public static void main(String[] args) throws Exception
{
int port = 8080;
Server server = new Server(port);
String wardir = "path/to/example-webapp.war";
WebAppContext webapp = new WebAppContext();
webapp.setWar(wardir);
webapp.setContextPath("/");
// don't hide server classes from webapps (hole #1 from answer)
// (allow webapp to use ones from system classloader)
webapp.addServerClass("-com.company.foo.");
// webapp cannot change or replace these classes
// force use of server classes (hole #2 from answer)
webapp.addSystemClass("com.company.foo.");
server.setHandler(webapp);
try
{
server.start();
server.dumpStdErr();
makeWebRequest(new URI("http://localhost:8080/test"));
}
finally
{
server.stop();
}
}
private static void makeWebRequest(URI uri) throws IOException
{
HttpURLConnection conn = (HttpURLConnection)uri.toURL().openConnection();
conn.setAllowUserInteraction(false);
int status = conn.getResponseCode();
System.out.printf("Response Status: %d%n", status);
if(status != 200)
{
System.out.printf("ERROR: %s%n", conn.getResponseMessage());
return;
}
try(InputStream in = conn.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
BufferedReader buf = new BufferedReader(reader))
{
System.out.printf("Response Content Type: %s%n", conn.getHeaderField("Content-Type"));
String line;
while ((line = buf.readLine()) != null)
{
System.out.printf("[resp] %s%n",line);
}
}
}
}
Update: 2014-Oct-16
Проект демонстрирует это доступно на github.com/jetty-project/jetty-classloader-manipulation
example-webapp
является вполне нормальным WebApp с a single servlet от its own.
example-embedded-servlet-override
имеет replacement for that servlet, а также embedded jetty main class для развертывания example-webapp
. У этого есть system property check against use.server.class
, чтобы продемонстрировать как поведение, нормальное (изолированное), так и переопределенное (дырокол).
Результат выглядит следующим образом:
Нормальный/Изолированный Поведение: (нет системы опоры или с помощью -Duse.server.class=false
.)
Response Status: 200
Response Content Type: text/plain; charset=ISO-8859-1
[resp] Hello Test Class: com.company.foo.TestServlet
from ClassLoader [email protected]
Переопределенный/Перфорация Поведение: (с использованием -Duse.server.class=true
)
Response Status: 200
Response Content Type: text/html; charset=ISO-8859-1
[resp] <html><body>
[resp] <h1>Hello Server Impl</h1>
[resp] <p>Class: com.company.foo.TestServlet
from ClassLoader [email protected]</p>
[resp] </body></html>
Надеюсь, это поможет вам понять он характер того, с чем вы работаете.
Вопрос не ясен. Похоже, вы хотите, чтобы класс сервера переопределял класс webapp? Это правильно? –
@JoakimErdfelt Конечным результатом является то, что я хочу, чтобы 'WebAppContext' загружал класс, который является (как строка) в' web.xml', используя загрузчик классов. Класс (другая версия), однако, также присутствует в коде, создающем сервер.Вышеприведенный код показывает, что 'WebAppContext', похоже, не уважает загрузчика классов: он находит класс. Это упрощенный пример, показывающий, что «WebAppContext» достигает другого загрузчика классов, пытающегося найти класс. Интересно, что я делаю неправильно, я ожидаю, что он не сможет найти этот класс. – EECOLOR
пример, который у вас есть, слишком надуманный, я вижу, что вы пытаетесь манипулировать загрузчиками классов, но там должен быть лучший способ, но сначала нам нужно понять, какова ваша цель, а не ваши попытки добраться туда. Таким образом, это класс, определенный в web.xml webapp, и вы хотите, чтобы этот класс загружался из загрузчика класса сервера (ваш особый случай нужен), а не загрузчик классов webapp (который имеет тот же класс, по имени, но не функциональность). Это правильное утверждение вашего вопроса? –