Merge remote-tracking branch 'origin/jetty-8'

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
	jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
	tests/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java
This commit is contained in:
Greg Wilkins 2013-07-04 15:00:47 +10:00
commit c33db24d94
9 changed files with 198 additions and 63 deletions

View File

@ -25,6 +25,7 @@ import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.DateCache; import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -59,7 +60,6 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
private boolean _logLatency = false; private boolean _logLatency = false;
private boolean _logCookies = false; private boolean _logCookies = false;
private boolean _logServer = false; private boolean _logServer = false;
private boolean _logDispatch = false;
private boolean _preferProxiedForAddress; private boolean _preferProxiedForAddress;
private transient DateCache _logDateCache; private transient DateCache _logDateCache;
private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z"; private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
@ -193,17 +193,10 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
} }
} }
if (_logDispatch || _logLatency) if (_logLatency)
{ {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (_logDispatch)
{
long d = request.getDispatchTime();
buf.append(' ');
buf.append(now - (d==0 ? request.getTimeStamp():d));
}
if (_logLatency) if (_logLatency)
{ {
buf.append(' '); buf.append(' ');
@ -340,24 +333,18 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
} }
/** /**
* Controls logging of the request dispatch time * @deprecated use {@link StatisticsHandler}
*
* @param value true - request dispatch time will be logged
* false - request dispatch time will not be logged
*/ */
public void setLogDispatch(boolean value) public void setLogDispatch(boolean value)
{ {
_logDispatch = value;
} }
/** /**
* Retrieve request dispatch time logging flag * @deprecated use {@link StatisticsHandler}
*
* @return value of the flag
*/ */
public boolean isLogDispatch() public boolean isLogDispatch()
{ {
return _logDispatch; return false;
} }
/** /**

View File

@ -38,7 +38,7 @@ public class AsyncContextState implements AsyncContext
_state=state; _state=state;
} }
private HttpChannelState state() HttpChannelState state()
{ {
HttpChannelState state=_state; HttpChannelState state=_state;
if (state==null) if (state==null)

View File

@ -203,7 +203,6 @@ public class Request implements HttpServletRequest
private HttpSession _session; private HttpSession _session;
private SessionManager _sessionManager; private SessionManager _sessionManager;
private long _timeStamp; private long _timeStamp;
private long _dispatchTime;
private HttpURI _uri; private HttpURI _uri;
private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime private MultiPartInputStreamParser _multiPartInputStream; //if the request is a multi-part mime
private AsyncContextState _async; private AsyncContextState _async;
@ -1395,16 +1394,6 @@ public class Request implements HttpServletRequest
return null; return null;
} }
/* ------------------------------------------------------------ */
/**
* Get timestamp of the request dispatch
*
* @return timestamp
*/
public long getDispatchTime()
{
return _dispatchTime;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public boolean isHandled() public boolean isHandled()
@ -1996,18 +1985,6 @@ public class Request implements HttpServletRequest
_scope = scope; _scope = scope;
} }
/* ------------------------------------------------------------ */
/**
* Set timetstamp of request dispatch
*
* @param value
* timestamp
*/
public void setDispatchTime(long value)
{
_dispatchTime = value;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public AsyncContext startAsync() throws IllegalStateException public AsyncContext startAsync() throws IllegalStateException

View File

@ -20,11 +20,14 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException; import java.io.IOException;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AsyncContextState;
import org.eclipse.jetty.server.HttpChannelState; import org.eclipse.jetty.server.HttpChannelState;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog; import org.eclipse.jetty.server.RequestLog;
@ -43,9 +46,37 @@ import org.eclipse.jetty.util.log.Logger;
*/ */
public class RequestLogHandler extends HandlerWrapper public class RequestLogHandler extends HandlerWrapper
{ {
private static final Logger LOG = Log.getLogger(RequestLogHandler.class);
private RequestLog _requestLog; private RequestLog _requestLog;
private final AsyncListener _listener = new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
event.getAsyncContext().addListener(this);
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
AsyncContextState context = (AsyncContextState)event.getAsyncContext();
Request request=context.getHttpChannelState().getBaseRequest();
Response response=request.getResponse();
_requestLog.log(request,response);
}
};
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* /*
@ -55,22 +86,19 @@ public class RequestLogHandler extends HandlerWrapper
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException throws IOException, ServletException
{ {
HttpChannelState continuation = baseRequest.getHttpChannelState();
if (!continuation.isInitial())
{
baseRequest.setDispatchTime(System.currentTimeMillis());
}
try try
{ {
super.handle(target, baseRequest, request, response); super.handle(target, baseRequest, request, response);
} }
finally finally
{ {
if (_requestLog != null && DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) if (baseRequest.getHttpChannelState().isAsync())
{ {
_requestLog.log(baseRequest, (Response)response); if (baseRequest.getHttpChannelState().isInitial())
baseRequest.getAsyncContext().addListener(_listener);
} }
else
_requestLog.log(baseRequest, (Response)response);
} }
} }

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.servlet;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.Socket; import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
@ -33,9 +35,14 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -53,15 +60,28 @@ public class AsyncServletTest
protected Server _server = new Server(); protected Server _server = new Server();
protected ServletHandler _servletHandler; protected ServletHandler _servletHandler;
protected ServerConnector _connector; protected ServerConnector _connector;
protected List<String> _log;
protected int _expectedLogs;
protected String _expectedCode;
@Before @Before
public void setUp() throws Exception public void setUp() throws Exception
{ {
_connector = new ServerConnector(_server); _connector = new ServerConnector(_server);
_server.setConnectors(new Connector[]{ _connector }); _server.setConnectors(new Connector[]{ _connector });
_log=new ArrayList<>();
RequestLog log=new Log();
RequestLogHandler logHandler = new RequestLogHandler();
logHandler.setRequestLog(log);
_server.setHandler(logHandler);
_expectedLogs=1;
_expectedCode="200 ";
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/ctx"); context.setContextPath("/ctx");
_server.setHandler(context); logHandler.setHandler(context);
_servletHandler=context.getServletHandler(); _servletHandler=context.getServletHandler();
ServletHolder holder=new ServletHolder(_servlet); ServletHolder holder=new ServletHolder(_servlet);
holder.setAsyncSupported(true); holder.setAsyncSupported(true);
@ -73,6 +93,8 @@ public class AsyncServletTest
@After @After
public void tearDown() throws Exception public void tearDown() throws Exception
{ {
assertEquals(_expectedLogs,_log.size());
Assert.assertThat(_log.get(0),Matchers.containsString(_expectedCode));
_server.stop(); _server.stop();
} }
@ -105,6 +127,7 @@ public class AsyncServletTest
@Test @Test
public void testSuspend() throws Exception public void testSuspend() throws Exception
{ {
_expectedCode="500 ";
String response=process("suspend=200",null); String response=process("suspend=200",null);
assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26)); assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26));
assertContains( assertContains(
@ -258,6 +281,7 @@ public class AsyncServletTest
@Test @Test
public void testSuspendWaitResumeSuspend() throws Exception public void testSuspendWaitResumeSuspend() throws Exception
{ {
_expectedCode="500 ";
String response=process("suspend=1000&resume=10&suspend2=10",null); String response=process("suspend=1000&resume=10&suspend2=10",null);
assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26)); assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26));
assertContains( assertContains(
@ -316,6 +340,7 @@ public class AsyncServletTest
@Test @Test
public void testSuspendTimeoutSuspend() throws Exception public void testSuspendTimeoutSuspend() throws Exception
{ {
_expectedCode="500 ";
String response=process("suspend=10&suspend2=10",null); String response=process("suspend=10&suspend2=10",null);
assertContains( assertContains(
"history: REQUEST\r\n"+ "history: REQUEST\r\n"+
@ -335,6 +360,7 @@ public class AsyncServletTest
@Test @Test
public void testAsyncRead() throws Exception public void testAsyncRead() throws Exception
{ {
_expectedLogs=2;
String header="GET /ctx/path/info?suspend=2000&resume=1500 HTTP/1.1\r\n"+ String header="GET /ctx/path/info?suspend=2000&resume=1500 HTTP/1.1\r\n"+
"Host: localhost\r\n"+ "Host: localhost\r\n"+
"Content-Length: 10\r\n"+ "Content-Length: 10\r\n"+
@ -691,4 +717,13 @@ public class AsyncServletTest
((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onComplete"); ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onComplete");
} }
}; };
class Log extends AbstractLifeCycle implements RequestLog
{
@Override
public void log(Request request, Response response)
{
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
}
}
} }

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.servlets.gzip.GzipTester;
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite; import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
import org.eclipse.jetty.servlets.gzip.TestServletLengthTypeStreamWrite; import org.eclipse.jetty.servlets.gzip.TestServletLengthTypeStreamWrite;
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWrite; import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWrite;
import org.eclipse.jetty.servlets.gzip.TestServletStreamLengthTypeWriteWithFlush;
import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite; import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite; import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite; import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite;
@ -73,12 +74,14 @@ public class GzipFilterContentLengthTest
{ TestServletLengthStreamTypeWrite.class, GzipFilter.GZIP }, { TestServletLengthStreamTypeWrite.class, GzipFilter.GZIP },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.GZIP }, { TestServletLengthTypeStreamWrite.class, GzipFilter.GZIP },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.GZIP }, { TestServletStreamLengthTypeWrite.class, GzipFilter.GZIP },
{ TestServletStreamLengthTypeWriteWithFlush.class, GzipFilter.GZIP },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.GZIP }, { TestServletStreamTypeLengthWrite.class, GzipFilter.GZIP },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.GZIP }, { TestServletTypeLengthStreamWrite.class, GzipFilter.GZIP },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.GZIP }, { TestServletTypeStreamLengthWrite.class, GzipFilter.GZIP },
{ TestServletLengthStreamTypeWrite.class, GzipFilter.DEFLATE }, { TestServletLengthStreamTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.DEFLATE }, { TestServletLengthTypeStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.DEFLATE }, { TestServletStreamLengthTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamLengthTypeWriteWithFlush.class, GzipFilter.DEFLATE },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.DEFLATE }, { TestServletStreamTypeLengthWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.DEFLATE }, { TestServletTypeLengthStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.DEFLATE } { TestServletTypeStreamLengthWrite.class, GzipFilter.DEFLATE }

View File

@ -18,13 +18,8 @@
package org.eclipse.jetty.servlets.gzip; package org.eclipse.jetty.servlets.gzip;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.*;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -113,7 +108,17 @@ public class GzipTester
// Assert the response headers // Assert the response headers
// Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK)); // Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
Assert.assertThat("Response.header[Content-Length]",response.get("Content-Length"),notNullValue());
// Response headers should have either a Transfer-Encoding indicating chunked OR a Content-Length
String contentLength = response.getHeader("Content-Length");
String transferEncoding = response.getHeader("Transfer-Encoding");
boolean chunked = (transferEncoding != null) && (transferEncoding.indexOf("chunk") >= 0);
if(!chunked) {
Assert.assertThat("Response.header[Content-Length]",contentLength,notNullValue());
} else {
Assert.assertThat("Response.header[Transfer-Encoding]",transferEncoding,notNullValue());
}
int qindex = compressionType.indexOf(";"); int qindex = compressionType.indexOf(";");
if (qindex < 0) if (qindex < 0)
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),containsString(compressionType)); Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),containsString(compressionType));

View File

@ -0,0 +1,72 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlets.gzip;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.servlets.GzipFilter;
/**
* A sample servlet to serve static content, using a order of construction that has caused problems for
* {@link GzipFilter} in the past.
*
* Using a real-world pattern of:
*
* <pre>
* 1) get stream
* 2) set content length
* 3) set content type
* 4) write and flush
* </pre>
*
* @see <a href="Eclipse Bug 354014">http://bugs.eclipse.org/354014</a>
*/
@SuppressWarnings("serial")
public class TestServletStreamLengthTypeWriteWithFlush extends TestDirContentServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String fileName = request.getServletPath();
byte[] dataBytes = loadContentFileBytes(fileName);
ServletOutputStream out = response.getOutputStream();
// set content-length of uncompressed content (GzipFilter should handle this)
response.setContentLength(dataBytes.length);
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
response.setHeader("ETag","W/etag-"+fileName);
for ( int i = 0 ; i < dataBytes.length ; i++)
{
out.write(dataBytes[i]);
// flush using response object (not the stream itself)
response.flushBuffer();
}
}
}

View File

@ -20,15 +20,24 @@ package org.eclipse.jetty.continuation;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -41,19 +50,27 @@ public class ContinuationTest extends ContinuationBase
protected ServletHandler _servletHandler; protected ServletHandler _servletHandler;
protected ServerConnector _connector; protected ServerConnector _connector;
FilterHolder _filter; FilterHolder _filter;
protected List<String> _log = new ArrayList<String>();
@Before @Before
public void setUp() throws Exception public void setUp() throws Exception
{ {
_connector = new ServerConnector(_server); _connector = new ServerConnector(_server);
_server.setConnectors(new Connector[]{ _connector }); _server.setConnectors(new Connector[]{ _connector });
_log.clear();
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setRequestLog(new Log());
_server.setHandler(requestLogHandler);
ServletContextHandler servletContext = new ServletContextHandler(ServletContextHandler.NO_SECURITY|ServletContextHandler.NO_SESSIONS); ServletContextHandler servletContext = new ServletContextHandler(ServletContextHandler.NO_SECURITY|ServletContextHandler.NO_SESSIONS);
_server.setHandler(servletContext); requestLogHandler.setHandler(servletContext);
_servletHandler=servletContext.getServletHandler(); _servletHandler=servletContext.getServletHandler();
ServletHolder holder=new ServletHolder(_servlet); ServletHolder holder=new ServletHolder(_servlet);
holder.setAsyncSupported(true); holder.setAsyncSupported(true);
_servletHandler.addServletWithMapping(holder,"/"); _servletHandler.addServletWithMapping(holder,"/");
_server.start(); _server.start();
_port=_connector.getLocalPort(); _port=_connector.getLocalPort();
} }
@ -61,6 +78,9 @@ public class ContinuationTest extends ContinuationBase
@After @After
public void tearDown() throws Exception public void tearDown() throws Exception
{ {
Assert.assertEquals(1,_log.size());
Assert.assertTrue(_log.get(0).startsWith("200 "));
Assert.assertTrue(_log.get(0).endsWith(" /"));
_server.stop(); _server.stop();
} }
@ -172,4 +192,12 @@ public class ContinuationTest extends ContinuationBase
return IO.toString(in); return IO.toString(in);
} }
class Log extends AbstractLifeCycle implements RequestLog
{
public void log(Request request, Response response)
{
_log.add(response.getStatus()+" "+response.getContentCount()+" "+request.getRequestURI());
}
}
} }