从Servlet3.0开始提供异步功能,从Servlet3.1开始又提供了对non-blocking I/O的支持。Servlet3.1提供的non-blocking I/O功能,需要用到如下两个接口:
javax.servlet.ReadListener
javax.servlet.WriteListener
自此,JavaEE中的web开发也开始真正支持reactive编程范式了。
但网上能找到的例子比较少,我把找到的一些好的例子放到这里,方便以后参考或使用。
目录
一、Java EE Tutorial中的例子
@WebServlet(urlPatterns={"/asyncioservlet"}, asyncSupported=true)
public class AsyncIOServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
final AsyncContext acontext = request.startAsync();
final ServletInputStream input = request.getInputStream();
input.setReadListener(new ReadListener() {
byte buffer[] = new byte[4*1024];
StringBuilder sbuilder = new StringBuilder();
@Override
public void onDataAvailable() {
try {
do {
int length = input.read(buffer);
sbuilder.append(new String(buffer, 0, length));
} while(input.isReady());
} catch (IOException ex) { ... }
}
@Override
public void onAllDataRead() {
try {
acontext.getResponse().getWriter()
.write("...the response...");
} catch (IOException ex) { ... }
acontext.complete();
}
@Override
public void onError(Throwable t) { ... }
});
}
}
参考文档:Servlet Nonblocking I/O
17.13 Nonblocking I/O - Java Platform, Enterprise Edition: The Java EE Tutorial (Release 7)
二、Weblogic中的例子
1.non_blocking_io_read
package examples.servlet.servlet31.non_blocking_io_read;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* This Servlet as a client creates HTTP connection to ServerServlet, sends two
* parts of data with 3 seconds sleeping in between, in order to simulate data
* blocking.
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
@WebServlet(name = "ClientServlet", urlPatterns = {"/client"})
public class ClientServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and <code>POST</code> methods.
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Non-blocking I/O Read</title>");
out.println("</head>");
out.println("<body>");
HttpURLConnection conn = connectServerServlet(request);
writeData(out, conn.getOutputStream());
readData(out, conn.getInputStream());
out.println("</body>");
out.println("</html>");
}
/**
* Gets the connection of ServerServlet.
*
* @param request
* @return
* @throws ServletException
* @throws IOException
*/
private HttpURLConnection connectServerServlet(HttpServletRequest request)
throws ServletException, IOException {
// set ServerServlet URL
String urlPath = "http://"
+ request.getServerName()
+ ":" + request.getLocalPort()
+ request.getContextPath()
+ "/server";
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setChunkedStreamingMode(6);
conn.setRequestProperty("Content-Type", "text/plain");
conn.connect();
return conn;
}
/**
* Sends two parts of 'Hello World' with 3 seconds sleeping in between to ServerServlet.
*
* @param out
* @param output
*/
private void writeData(PrintWriter out, OutputStream output) {
try {
out.println("<p>Client is sending <code>Hello World!</code> to server. <p>");
// Sending the first part of data to server
String firstPart = "Hello ";
out.println("<p>Sending 1st part to server: <p>");
out.println("<p><code>" + firstPart + "</code></p>");
output.write(firstPart.getBytes());
output.flush();
out.println("<p>Sleep 3 seconds simulating data blocking.<p>");
out.flush();
// sleep on purpose
Thread.sleep(3000);
// Sending the second part of data to server
String secondPart = "World!";
out.println("<p>Sending 2nd part to server: <p>");
out.println("<p><code>" + secondPart + "</code></p>");
out.flush();
output.write(secondPart.getBytes());
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (Exception ex) {
// ignore
}
}
}
}
/**
* Reads data from ServerServlet.
*
* @param out
* @param input
*/
private void readData(PrintWriter out, InputStream input) {
try {
out.println("<p>---------------------------------</p>");
out.println("<p>Client is receiving data from server.</p>");
out.flush();
out.print("<p><code>");
int r = input.read();
while (r != -1) {
out.print((char) r);
r = input.read();
}
out.print("</code></p>");
out.println("<p>Client has received all data from server.</p>");
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (Exception ex) {
}
}
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
package examples.servlet.servlet31.non_blocking_io_read;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
/**
* The implementation of ReadListener
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
public class ReadListenerImpl implements ReadListener {
private ServletInputStream input;
private ServletOutputStream output;
private AsyncContext context;
private StringBuilder sb = new StringBuilder();
public ReadListenerImpl(ServletInputStream input, ServletOutputStream output, AsyncContext context) {
this.input = input;
this.output = output;
this.context = context;
}
/**
* do when data is available to be read.
*/
@Override
public void onDataAvailable() throws IOException {
while (input.isReady()) {
sb.append((char) input.read());
}
}
/**
* do when all the data has been read.
*/
@Override
public void onAllDataRead() throws IOException {
try {
output.println("ServerServlet has received '" + sb.toString() + "'.");
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
context.complete();
}
}
/**
* do when error occurs.
*/
@Override
public void onError(Throwable t) {
context.complete();
t.printStackTrace();
}
}
package examples.servlet.servlet31.non_blocking_io_read;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* This Servlet sets the ReadListener for ServletInputStream, illustrates the
* usage of servlet 3.1 API for non-blocking IO.
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
@WebServlet(name = "ServerServlet", urlPatterns = {"/server"}, asyncSupported = true)
public class ServerServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and <code>POST</code> methods.
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// async read
final AsyncContext context = request.startAsync();
final ServletInputStream input = request.getInputStream();
final ServletOutputStream output = response.getOutputStream();
input.setReadListener(new ReadListenerImpl(input, output, context));
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
2.non_blocking_io_write
package examples.servlet.servlet31.non_blocking_io_write;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.BufferedWriter;
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.net.HttpURLConnection;
import java.net.URL;
/**
* This Servlet as a client creates HTTP connection to ServerServlet, sends two
* parts of data with 3 seconds sleeping in between, in order to simulate data
* blocking.
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
@WebServlet(name = "ClientServlet", urlPatterns = {"/client"})
public class ClientServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and <code>POST</code> methods.
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Non-blocking I/O Write</title>");
out.println("</head>");
out.println("<body>");
HttpURLConnection conn = connectServerServlet(request);
writeData(out, conn.getOutputStream());
readData(out, conn.getInputStream());
out.println("</body>");
out.println("</html>");
}
/**
* Gets the connection of ServerServlet.
*
* @param request
* @return
* @throws ServletException
* @throws IOException
*/
private HttpURLConnection connectServerServlet(HttpServletRequest request)
throws ServletException, IOException {
// set ServerServlet URL
String urlPath = "http://"
+ request.getServerName()
+ ":" + request.getLocalPort()
+ request.getContextPath()
+ "/server";
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setChunkedStreamingMode(5);
conn.setRequestProperty("Content-Type", "text/plain");
conn.connect();
return conn;
}
/**
* Sends 'hi' to ServerServlet.
*
* @param out
* @param output
*/
private void writeData(PrintWriter out, OutputStream output) {
try {
out.println("<p>Client say hello to server.</p>");
out.flush();
output.write("Hello".getBytes());
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (Exception ex) {
// ignore
}
}
}
}
/**
* Reads data from ServerServlet.
*
* @param out
* @param input
*/
private void readData(PrintWriter out, InputStream input) {
try {
out.println("<p>------------------------------------</p>");
out.println("<p>Client is receiving data from server.</p>");
out.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
for (String line; reader != null && (line = reader.readLine()) != null;) {
out.print("<code>");
out.print(line);
out.flush();
out.print("</code>");
}
out.println("<p>Client has received all data from server.</p>");
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (Exception ex) {
}
}
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
package examples.servlet.servlet31.non_blocking_io_write;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* This Servlet sets the WriteListener for ServletInputStream, illustrates the
* usage of servlet 3.1 API for non-blocking IO.
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
@WebServlet(name = "ServerServlet", urlPatterns = {"/server"}, asyncSupported = true)
public class ServerServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and <code>POST</code> methods.
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// async write
final AsyncContext context = request.startAsync();
final ServletOutputStream output = response.getOutputStream();
output.setWriteListener(new WriteListenerImpl(output, context));
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
package examples.servlet.servlet31.non_blocking_io_write;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.AsyncContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
/**
* The implementation of WriteListener
*
* @author Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
public class WriteListenerImpl implements WriteListener {
private ServletOutputStream output;
private AsyncContext context;
public WriteListenerImpl(ServletOutputStream output, AsyncContext context) {
this.context = context;
this.output = output;
}
/**
* do when the data is available to be written
*/
@Override
public void onWritePossible() throws IOException {
if (output.isReady()) {
output.println("<p>Server is sending back 5 hello...</p>");
output.flush();
}
for (int i = 1; i <= 5 && output.isReady(); i++) {
output.println("<p>Hello " + i + ".</p>");
output.println("<p>Sleep 3 seconds simulating data blocking.<p>");
output.flush();
// sleep on purpose
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// ignore
}
}
output.println("<p>Sending completes.</p>");
output.flush();
context.complete();
}
/**
* do when error occurs.
*/
@Override
public void onError(Throwable t) {
context.complete();
t.printStackTrace();
}
}
参考代码所在路径:
<WLS_HOME>\wlserver\samples\server\examples\src\examples\javaee7\servlet
三、IBM的例子
package org.javaee7.servlet.nonblocking;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
/**
* @author Arun Gupta
*/
public class MyReadListener implements ReadListener {
private ServletInputStream input = null;
private AsyncContext context = null;
private final PrintWriter output;
ArrayList<String> responseData = new ArrayList<String>();
public MyReadListener(ServletInputStream in, AsyncContext ac, PrintWriter out) {
this.input = in;
this.context = ac;
this.output = out;
}
@Override
public void onDataAvailable() throws IOException {
output.println("onDataAvailable called to read post data on thread : " + Thread.currentThread().getName());
int len = -1;
byte b[] = new byte[1024];
// must call isReady() immediately before each read.
while (input.isReady() && !input.isFinished()) {
len = input.read(b);
if (len > 0) {
String data = new String(b, 0, len);
responseData.add("<br>" + len + " bytes of data read: " + data);
}
}
}
@Override
public void onAllDataRead() {
while (!responseData.isEmpty()) {
output.println(responseData.get(0));
responseData.remove(0);
}
output.println("</body>");
output.println("</html>");
context.complete();
}
@Override
public void onError(Throwable t) {
Logger.getLogger(MyReadListener.class.getName()).log(Level.SEVERE, null, t);
context.complete();
}
}
package org.javaee7.servlet.nonblocking;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
/**
* @author Arun Gupta
*/
public class MyWriteListener implements WriteListener {
private ServletOutputStream output = null;
private AsyncContext context = null;
private ArrayList<String> outputData = null;
public MyWriteListener(ServletOutputStream out, AsyncContext ac, ArrayList<String> outData) {
this.output = out;
this.context = ac;
this.outputData = outData;
}
@Override
public void onWritePossible() throws IOException {
output.println("<p>WriteListener:onWritePossible() called to send response data on thread : " + Thread.currentThread().getName());
while (output.isReady() && !outputData.isEmpty()) {
output.println(outputData.get(0));
outputData.remove(0);
}
if (outputData.isEmpty()) {
this.context.complete();
}
}
@Override
public void onError(Throwable t) {
Logger.getLogger(MyWriteListener.class.getName()).log(Level.SEVERE, null, t);
context.complete();
}
}
package org.javaee7.servlet.nonblocking;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.javaee7.servlet.nonblocking.MyReadListener;
/**
* @author Arun Gupta
*/
@WebServlet(urlPatterns = { "/ReadTestServlet" }, asyncSupported = true)
public class ReadTestServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try {
PrintWriter output = response.getWriter();
output.println("<html>");
output.println("<head>");
output.println("<title>Reading asynchronously</title>");
output.println("<meta charset=\"utf-8\"></meta>");
output.println("<title>Servlet 3.1 WAS Classic tests</title>");
output.println("<style>");
output.println(".frm1{padding: 15px;background-color: #9666af; margin-bottom: 10px;}");
output.println(".frm2{padding-left: 25px; font-family: Verdana; color: #440055;}");
output.println(".big{font-size: 26px; color: white;}");
output.println(".small{font-size: 12px;}");
output.println("button, select{padding: 5px; padding-left: 20px; padding-right: 20px; margin:10px; width: 270px}");
output.println("</style>");
output.println("</head>");
output.println("<body>");
output.println("<body>");
output.println("<div class=\"frm1\">");
output.println("<div class=\"big\"> WAS Java EE 7 Sample - Non-blocking I/O using Servlet 3.1</div>");
output.println("</div>");
output.println("<div class=\"frm2\">");
output.println("</div>");
output.println("</head>");
output.println("<body>");
output.println("<h3>The following post data was read asynchronously using a Servlet 3.1 readListener</h3>");
AsyncContext context = request.startAsync();
ServletInputStream input = request.getInputStream();
input.setReadListener(new MyReadListener(input, context, output));
} catch (IOException ex) {
Logger.getLogger(ReadTestServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
package org.javaee7.servlet.nonblocking;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Arun Gupta
*/
@WebServlet(urlPatterns = { "/WriteTestServlet" }, asyncSupported = true)
public class WriteTestServlet extends HttpServlet {
/**
* Processes requests for both HTTP
* <code>GET</code> and
* <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int numlines = new Integer(request.getParameter("numberOfResponseLines"));
ArrayList<String> outputData = new ArrayList<String>();;
response.setContentType("text/html;charset=UTF-8");
try {
ServletOutputStream output = response.getOutputStream();
// Write out the header
output.println("<!DOCTYPE html>");
output.println("<html>");
output.println("<head>");
output.println("<title>Writing Asynchronously</title>");
output.println("<meta charset=\"utf-8\"></meta>");
output.println("<title>Servlet 3.1 WAS Classic tests</title>");
output.println("<style>");
output.println(".frm1{padding: 15px;background-color: #9666af; margin-bottom: 10px;}");
output.println(".frm2{padding-left: 25px; font-family: Verdana; color: #440055;}");
output.println(".big{font-size: 26px; color: white;}");
output.println(".small{font-size: 12px;}");
output.println("button, select{padding: 5px; padding-left: 20px; padding-right: 20px; margin:10px; width: 270px}");
output.println("</style>");
output.println("</head>");
output.println("<body>");
output.println("<body>");
output.println("<div class=\"frm1\">");
output.println("<div class=\"big\"> WAS Java EE 7 Sample - Non-blocking I/O using Servlet 3.1</div>");
output.println("</div>");
output.println("<div class=\"frm2\">");
output.println("</div>");
output.println("</head>");
output.println("<body>");
output.println("<h3>The following response data was written asynchronously using a Servelt 3.1 WriteListener</h3>");
// create verbose response data a write remaining response data from a write listener
String data = "This response data content was written " + numlines + " times from the onWritePossible() method of a Servlet 3.1 javax.servlet.WriteListener.";
for (int i = 0; i <= numlines; i++) {
outputData.add("<br>" + i + " : " + data);
}
outputData.add("</body>");
outputData.add("</html>");
AsyncContext context = request.startAsync();
output.setWriteListener(new MyWriteListener(output, context, outputData));
} catch (IOException ex) {
Logger.getLogger(WriteTestServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP
* <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTP
* <code>POST</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
参考工程:https://github.com/WASdev/sample.javaee7.servlet.nonblocking