我正在运行嵌入式Jetty(9.1.0.v20131115)设置,并且有几个处理程序设置来处理几个不同上下文的请求。
当用户提交表单时,其中一个处理程序会执行登录功能。它的设置如下:
ContextHandler loginContext = new ContextHandler("/login");
loginContext.setHandler(new LoginHandler());
// Other handlers go here...
contexts.setHandlers(new Handler[]{rootContext, logoutContext, loginContext, resourceHandler});
server.setHandler(contexts);
那应该是非常标准的,没什么特别的。令我困惑的是,当我通过调试器运行LoginHandler时,HttpServletRequest对象没有参数,即使表单显然有两个表单输入元素!
这是我通过netcat捕获的请求的副本:
POST /login HTTP/1.1
Host: localhost:52520
Connection: keep-alive
Content-Length: 31
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:52520
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:52520/dashboard/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
username=myuser&password=mypass
最重要的是,如果我将表单操作更改为GET而不是POST,则参数显示就好了!
为了让Handler接受POST参数,还有什么特别之处吗?
答案 0 :(得分:2)
似乎工作正常。
package jetty;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.IO;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class JettyPostTest
{
public static class LoginHandler extends HandlerWrapper
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
out.printf("username = %s\n",request.getParameter("username"));
out.printf("password = %s\n",request.getParameter("password"));
baseRequest.setHandled(true);
}
}
private static Server server;
private static int port;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
// collection for handlers
HandlerCollection handlers = new HandlerCollection();
server.setHandler(handlers);
// login context
ContextHandler loginContext = new ContextHandler("/login");
loginContext.setHandler(new LoginHandler());
handlers.addHandler(loginContext);
// default handler
handlers.addHandler(new DefaultHandler());
// start server
server.start();
// grab port
port = connector.getLocalPort();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testPostParameters() throws IOException
{
StringBuilder req = new StringBuilder();
req.append("POST /login/ HTTP/1.1\r\n");
req.append("Host: localhost:").append(port).append("\r\n");
req.append("Connection: close\r\n");
req.append("Content-Length: 31\r\n");
req.append("Cache-Control: max-age=0\r\n");
req.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n");
req.append("Origin: http://localhost:").append(port).append("\r\n");
req.append("User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36\r\n");
req.append("Content-Type: application/x-www-form-urlencoded\r\n");
req.append("Referer: http://localhost:").append(port).append("/dashboard/\r\n");
req.append("Accept-Encoding: gzip,deflate,sdch\r\n");
req.append("Accept-Language: en-US,en;q=0.8\r\n");
req.append("\r\n");
req.append("username=myuser&password=mypass\r\n");
try (Socket socket = new Socket())
{
socket.connect(new InetSocketAddress("localhost",port));
// Write request
try (OutputStream out = socket.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(out);
InputStream in = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(in))
{
StringReader reqStream = new StringReader(req.toString());
IO.copy(reqStream,writer);
writer.flush();
out.flush();
StringWriter respStream = new StringWriter();
IO.copy(reader,respStream);
System.out.println(respStream.toString());
String expected = "username = myuser\npassword = mypass\n";
assertThat("Response",respStream.toString(),containsString(expected));
}
}
}
}
输出结果:
2013-12-18 13:23:08.856:INFO:oejs.Server:main: jetty-9.1.0.v20131115
2013-12-18 13:23:08.888:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.ContextHandler@49ada86{/login,null,AVAILABLE}
2013-12-18 13:23:08.897:INFO:oejs.ServerConnector:main: Started ServerConnector@3f14b553{HTTP/1.1}{0.0.0.0:34456}
HTTP/1.1 200 OK
Content-Type: text/plain; charset=ISO-8859-1
Connection: close
Server: Jetty(9.1.0.v20131115)
username = myuser
password = mypass
2013-12-18 13:23:08.994:INFO:oejs.ServerConnector:main: Stopped ServerConnector@3f14b553{HTTP/1.1}{0.0.0.0:0}
2013-12-18 13:23:08.995:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.h.ContextHandler@49ada86{/login,null,UNAVAILABLE}
只有我对您的请求所做的更改才是将Connection: keep-alive
更改为Connection: close
,让jetty关闭连接。此更改很小,仅允许测试快速执行,使用原始值不会更改测试结果。
您的问题中缺少某些信息。