Java:以 JSON 响应的简单 HTTP 服务器应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28571086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Simple HTTP Server application that responds in JSON
提问by SomethingSomething
I want to create a very simple HTTP server application in Java.
我想用 Java 创建一个非常简单的 HTTP 服务器应用程序。
For example, if I run the server on localhostin port 8080, and I make to following call from my browser, I want to get a Json array with the string 'hello world!':
例如,如果我在localhost的端口8080上运行服务器,并从浏览器进行以下调用,我想获得一个带有字符串“hello world!”的 Json 数组:
http://localhost:8080/func1?param1=123¶m2=456
I would like to have in the server something that looks like this (very abstract code):
我想在服务器中有这样的东西(非常抽象的代码):
// Retunrs JSON String
String func1(String param1, String param2) {
// Do Something with the params
String jsonFormattedResponse = "['hello world!']";
return jsonFormattedResponse;
}
I guess that this function should not actually "return" the json, but to send it using some HTTP response handler or something similar...
我想这个函数实际上不应该“返回”json,而是使用一些HTTP响应处理程序或类似的东西发送它......
What it the simplest way to do it, without a need to get familiar with many kinds of 3rd party libraries that have special features and methodology?
最简单的方法是什么,而无需熟悉具有特殊功能和方法的多种 3rd 方库?
采纳答案by xehpuk
You could use classes from the package com.sun.net.httpserver
:
您可以使用包中的类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<String, List<String>> 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<String, List<String>> getRequestParameters(final URI requestUri) {
final Map<String, List<String>> 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);
}
}
}
回答by Rafa
If you are already familiar with servlet you do not need much to create a simple server to achieve what you want. But I would like to emphasize that your needs will likely to increase rapidly and therefore you may need to move to a RESTful framework (e.g.: Spring WS, Apache CXF) down the road.
如果您已经熟悉 servlet,您不需要太多创建一个简单的服务器来实现您想要的。但我想强调的是,您的需求可能会迅速增加,因此您可能需要在未来转向 RESTful 框架(例如:Spring WS、Apache CXF)。
You need to register URIs and get parameters using the standard servlet technology. Maybe you can start here: http://docs.oracle.com/cd/E13222_01/wls/docs92/webapp/configureservlet.html
您需要使用标准 servlet 技术注册 URI 并获取参数。也许你可以从这里开始:http: //docs.oracle.com/cd/E13222_01/wls/docs92/webapp/configureservlet.html
Next, you need a JSON provider and serialize (aka marshall) it in JSON format. I recommend HymanSON. Take a look at this tutorial: http://www.sivalabs.in/2011/03/json-processing-using-Hymanson-java-json.html
接下来,您需要一个 JSON 提供程序并以 JSON 格式对其进行序列化(又名编组)。我推荐Hyman逊。看看这个教程:http: //www.sivalabs.in/2011/03/json-processing-using-Hymanson-java-json.html
Finally, your code will look similar to this:
最后,您的代码将类似于:
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 );
}
}
Map URLs in your web.xml:
在 web.xml 中映射 URL:
<servlet>
<servlet-name>func1Servlet</servlet-name>
<servlet-class>myservlets.func1servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>func1Servlet</servlet-name>
<url-pattern>/func1/*</url-pattern>
</servlet-mapping>
Keep in mind this is a pseudo-code. There are lots you can do to enhance it, adding some utility classes, etc...
请记住,这是一个伪代码。您可以做很多事情来增强它,添加一些实用程序类等...
Nevertheless, as your project grows your need for a more comprehensive framework becomes more evident.
然而,随着项目的增长,您对更全面的框架的需求变得更加明显。
回答by Richard
You could :
你可以 :
Install Apache Tomcat, and just drop a JSP into the ROOT project that implements this.
安装 Apache Tomcat,然后将一个 JSP 放入实现此功能的 ROOT 项目中。
I second @xehpuk. It's not actually that hard to write your own single class HTTP server using just standard Java. If you want to do it in earlier versions you can use NanoHTTPD, which is a pretty well known single class HTTP server implementation.
我第二次@xehpuk。仅使用标准 Java 编写您自己的单类 HTTP 服务器实际上并不难。如果你想在早期版本中做到这一点,你可以使用 NanoHTTPD,这是一个非常著名的单类 HTTP 服务器实现。
I would personally recommend that you look into Apache Sling (pretty much THE Reference implementation of a Java REST api). You could probably implement your requirements here using Sling without ANY programming at all.
我个人建议您查看 Apache Sling(几乎是 Java REST api 的参考实现)。您可以在这里使用 Sling 实现您的要求,而无需进行任何编程。
But as others have suggested, the standard way to do this is to create a java WARand deploy it into a 'servlet container' such as Tomcat or Jetty etc.
但正如其他人所建议的那样,执行此操作的标准方法是创建一个java WAR并将其部署到“servlet 容器”中,例如 Tomcat 或 Jetty 等。
回答by user2418306
Run main
to start the server on port 8080
运行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:
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.Hymanson.core', name: 'Hymanson-databind', version: '2.9.4'
}