Java:以JSON响应的简单HTTP Server应用程序

我想用Java创建一个非常简单的HTTP服务器应用程序。

例如,如果我在端口8080中的 localhost上运行服务器,并且我从浏览器进行以下调用,我想获得一个带有字符串’hello world!’的Json数组:

http://localhost:8080/func1?param1=123&param2=456 

我想在服务器中看到这样的东西(非常抽象的代码):

 // Retunrs JSON String String func1(String param1, String param2) { // Do Something with the params String jsonFormattedResponse = "['hello world!']"; return jsonFormattedResponse; } 

我想这个函数实际上不应该“返回”json,而是使用一些HTTP响应处理程序或类似的东西发送它…

最简单的方法是什么,而不需要熟悉具有特殊function和方法的多种第三方库?

您可以使用com.sun.net.httpserver包中的类:

 import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpServer; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class JsonServer { private static final String HOSTNAME = "localhost"; private static final int PORT = 8080; private static final int BACKLOG = 1; private static final String HEADER_ALLOW = "Allow"; private static final String HEADER_CONTENT_TYPE = "Content-Type"; private static final Charset CHARSET = StandardCharsets.UTF_8; private static final int STATUS_OK = 200; private static final int STATUS_METHOD_NOT_ALLOWED = 405; private static final int NO_RESPONSE_LENGTH = -1; private static final String METHOD_GET = "GET"; private static final String METHOD_OPTIONS = "OPTIONS"; private static final String ALLOWED_METHODS = METHOD_GET + "," + METHOD_OPTIONS; public static void main(final String... args) throws IOException { final HttpServer server = HttpServer.create(new InetSocketAddress(HOSTNAME, PORT), BACKLOG); server.createContext("/func1", he -> { try { final Headers headers = he.getResponseHeaders(); final String requestMethod = he.getRequestMethod().toUpperCase(); switch (requestMethod) { case METHOD_GET: final Map> requestParameters = getRequestParameters(he.getRequestURI()); // do something with the request parameters final String responseBody = "['hello world!']"; headers.set(HEADER_CONTENT_TYPE, String.format("application/json; charset=%s", CHARSET)); final byte[] rawResponseBody = responseBody.getBytes(CHARSET); he.sendResponseHeaders(STATUS_OK, rawResponseBody.length); he.getResponseBody().write(rawResponseBody); break; case METHOD_OPTIONS: headers.set(HEADER_ALLOW, ALLOWED_METHODS); he.sendResponseHeaders(STATUS_OK, NO_RESPONSE_LENGTH); break; default: headers.set(HEADER_ALLOW, ALLOWED_METHODS); he.sendResponseHeaders(STATUS_METHOD_NOT_ALLOWED, NO_RESPONSE_LENGTH); break; } } finally { he.close(); } }); server.start(); } private static Map> getRequestParameters(final URI requestUri) { final Map> requestParameters = new LinkedHashMap<>(); final String requestQuery = requestUri.getRawQuery(); if (requestQuery != null) { final String[] rawRequestParameters = requestQuery.split("[&;]", -1); for (final String rawRequestParameter : rawRequestParameters) { final String[] requestParameter = rawRequestParameter.split("=", 2); final String requestParameterName = decodeUrlComponent(requestParameter[0]); requestParameters.putIfAbsent(requestParameterName, new ArrayList<>()); final String requestParameterValue = requestParameter.length > 1 ? decodeUrlComponent(requestParameter[1]) : null; requestParameters.get(requestParameterName).add(requestParameterValue); } } return requestParameters; } private static String decodeUrlComponent(final String urlComponent) { try { return URLDecoder.decode(urlComponent, CHARSET.name()); } catch (final UnsupportedEncodingException ex) { throw new InternalError(ex); } } } 

你可以 :

安装Apache Tomcat,然后将JSP放入实现此function的ROOT项目中。

我是第二个@xehpuk。 使用标准Java编写自己的单类HTTP服务器实际上并不困难。 如果你想在早期版本中使用它,你可以使用NanoHTTPD,这是一个众所周知的单类HTTP服务器实现。

我个人建议你研究一下Apache Sling(几乎是Java REST api的参考实现)。 您可以在没有任何编程的情况下使用Sling来实现您的需求。

但正如其他人所建议的那样,标准的方法是创建一个java WAR并将其部署到’servlet容器’中,例如Tomcat或Jetty等。

如果您已经熟悉servlet,那么创建一个简单的服务器就不需要太多了。 但我想强调一下,您的需求可能会迅速增加,因此您可能需要转向RESTful框架(例如:Spring WS,Apache CXF)。

您需要使用标准servlet技术注册URI并获取参数。 也许你可以从这里开始: http : //docs.oracle.com/cd/E13222_01/wls/docs92/webapp/configureservlet.html

接下来,您需要一个JSON提供程序并以JSON格式序列化(也称为marshall)。 我推荐JACKSON。 看看这个教程: http : //www.sivalabs.in/2011/03/json-processing-using-jackson-java-json.html

最后,您的代码看起来类似于:

 public class Func1Servlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String p1 = req.getParameter("param1"); String p2 = req.getParameter("param2"); // Do Something with the params ResponseJSON resultJSON = new ResponseJSON(); resultJSON.setProperty1(yourPropert1); resultJSON.setProperty2(yourPropert2); // Convert your JSON object into JSON string Writer strWriter = new StringWriter(); mapper.writeValue(strWriter, resultJSON); String resultString = strWriter.toString(); resp.setContentType("application/json"); out.println(resultString ); } } 

在web.xml中映射URL:

  func1Servlet myservlets.func1servlet   func1Servlet /func1/*  

请记住,这是一个伪代码。 您可以做很多事情来增强它,添加一些实用程序类等…

然而,随着您的项目的发展,您对更全面的框架的需求变得更加明显。

运行main以在端口8080上启动服务器

 public class Main { public static void main(String[] args) throws LifecycleException { Tomcat tomcat = new Tomcat(); Context context = tomcat.addContext("", null); Tomcat.addServlet(context, "func1", new HttpServlet() { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { Object response = func1(req.getParameter("param1"), req.getParameter("param2")); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(resp.getWriter(), response); } }); context.addServletMappingDecoded("/func1", "func1"); tomcat.start(); tomcat.getServer().await(); } private static String[] func1(String p1, String p2) { return new String[] { "hello world", p1, p2 }; } } 

Gradle依赖项:

 dependencies { compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '8.5.28' // doesn't work with tomcat 9 compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.4' }