Java: a simple HTTP server application that responds in JSON

I want to create a very simple HTTP server application in Java.

For example, if I start the server on localhost on port 8080 , and I make the following call from my browser, I want to get a Json array with string 'hello world!':

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

I would like to have something similar to this on the server (very abstract code):

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

I assume that this function should not actually “return” json, but send it using some kind of HTTP response handler or something similar ...

What is the easiest way to do this, without having to get acquainted with many types of third-party libraries that have special functions and methodology?

+7
java java-server
source share
4 answers

You can use the classes from the com.sun.net.httpserver package:

 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); } } } 
+9
source

If you are already familiar with the servlet, you do not need to create a simple server to achieve what you want. But I would like to emphasize that your needs are likely to increase rapidly, and therefore you may need to go into RESTful frameworks (for example: Spring WS, Apache CXF) along the way.

You need to register the URI and get the parameters using standard servlet technology. Perhaps you can start here: http://docs.oracle.com/cd/E13222_01/wls/docs92/webapp/configureservlet.html

Next, you need a JSON provider and serialize it (aka marshall) in JSON format. I recommend JACKSON. Take a look at this tutorial: http://www.sivalabs.in/2011/03/json-processing-using-jackson-java-json.html

Finally, your code will look something like 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 the urls in your web.xml:

 <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 that this is pseudo code. There are many features you can do to improve it by adding some utility classes, etc.

However, as your project grows, your need for a more integrated structure becomes more apparent.

+1
source

You can:

Install Apache Tomcat and just release JSP into a ROOT project that implements this.

I second @xehpuk. In fact, it is not so difficult to write your own HTTP server of the same class using only standard Java. If you want to do this in earlier versions, you can use NanoHTTPD, which is a fairly well-known implementation of a single-class HTTP server.

I personally would recommend you learn Apache Sling (pretty much the reference implementation of the Java REST api). Perhaps you could implement your requirements here using Sling without ANY programming at all.

But, as others suggested, the standard way to do this is to create a java WAR and deploy it to a “servlet container” such as Tomcat or Jetty, etc.

+1
source

Run main to start the server on port 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:

 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' } 
0
source

All Articles