Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。本系列将一步步地写出一个Servlet程序。
这篇博文将演示如何分别处理GET
和POST
请求,以及处理请求中的参数。
编写doGet()
和doPost()
方法
首先把要实现的功能写好,后面才好调用不是。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doGet()</code></b>"); writer.print("</body>"); writer.print("</html>"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doPost()</code></b>"); writer.print("</body>"); writer.print("</html>"); } }
|
区分HTTP方法
因为servlet是调用service()
方法来处理请求的,所以对请求做区分也需要在service()
方法中进行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) req; HttpServletResponse httpServletResponse = (HttpServletResponse) res;
if ("GET".equalsIgnoreCase(httpServletRequest.getMethod())) { doGet(httpServletRequest, httpServletResponse); } else if ("POST".equalsIgnoreCase(httpServletRequest.getMethod())) { doPost(httpServletRequest, httpServletResponse); } else { httpServletResponse.sendError(501); } }
|
运行起来看看效果
首先发个GET
请求

再发个POST
请求

为什么不用HttpServlet
类呢
没错,上面做的,就是自己实现了一个简陋的HttpServlet
类,因为是循序渐进嘛,没头没脑的直接砸上来一个,算什么循序渐进。
那么现在就让DemoServlet
继承HttpServlet
。同时,因为HttpServlet
已经在service()
方法中实现了判断请求类型,所以DemoServlet
中不要覆盖service()
方法,只覆盖doGet()
和doPost()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class DemoServlet extends HttpServlet {
@Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doGet()</code></b>"); writer.print("</body>"); writer.print("</html>"); } }
@Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doPost()</code></b>"); writer.print("</body>"); writer.print("</html>"); } } }
|
处理请求中的参数
HTTP请求是可以带参数的,有了参数,那就得处理。
处理GET
请求的参数
GET
请求里带的参数,名字叫查询字符串(query string)
,是一组或多组key=value
格式的键值对。
Query string写在URL后面,以一个问号起头,用&
分隔各个键值对,即类似http://localhost:8080/appname/servlet?arg1=value1&arg2=value2&...&argN=valueN
。
在代码里使用HttpServletRequest#getQueryString()
方法,就可以获取到问号后面的query string,分别用&
和=
分割字符串,就可以取到每个参数的key和value。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
Optional<String> optionalQueryString = Optional.ofNullable(request.getQueryString());
String[] queryStrings = optionalQueryString.isPresent() ? optionalQueryString.get().split("&") : new String[]{};
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doGet()</code></b>");
writer.print("<br>");
for (String query : queryStrings) { String[] q = query.split("=");
writer.print(q[0] + " = " + q[1] + "<br>"); }
writer.print("<br>");
writer.print("</body>"); writer.print("</html>"); } }
|
运行一下,结果是这样子的:

处理POST
请求的参数
POST
请求的参数就叫参数(parameter),位于请求体(body)里,格式由Content-Type
请求头决定。详细介绍可以参考这篇MDN文档。
HttpServletRequest#getParameterMap()
方法可以取出请求中的所有参数,并放到一个Map中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
Map parameterMap = request.getParameterMap();
try (PrintWriter writer = response.getWriter()) { writer.print("<html lang=\"en\">"); writer.print("<body>"); writer.print("<b>Response from DemoServlet</b>"); writer.print("<b>Handled by <code>doPost()</code></b>");
writer.print("<br>");
parameterMap.forEach((k, v) -> writer.print(k + " = " + ((String[]) v)[0] + "<br>"));
writer.print("</body>"); writer.print("</html>"); } }
|
本文中将使用application/x-www-form-urlencoded
格式做示例。

系列博文