📜 ⬆️ ⬇️

Spark - A stunning web microframe for Java

image

Small introduction


Spark is just a wonderful microframe for building web applications on Java effortlessly. Spark strives for simplicity and provides only a minimal set of functions. However, it provides everything you need to create a web application that fits in a few lines of code. With the syntax inspired by Sinatra, the code looks very clean.

Let's start with the ubiquitous helloworld.

Create a new project and import Spark. Personally, I use maven to manage dependencies.
')
Add to pom.xml.

<dependency>    <groupId>com.sparkjava</groupId>    <artifactId>spark-core</artifactId>    <version>2.6.0</version> </dependency> 

Now let's proceed directly to the Hello World.

 import static spark.Spark.*; public class Main {   public static void main(String[] args) {       get("/hello", (req, res) -> "Hello, World!");   } } 

That's all. Everything is so simple!

Now spark listens for GET requests for / hello. Whenever we go to localhost : 4567 / hello, the handle () method is called. Inside it, we return the object to be sent to the client (in this case, “Hello World”).

My personal opinion is that this code is so concise that it does not even require explanations.

Stop stop. What about starting / stopping the server?

  1. Stop - just call the stop () method.
  2. Run - and here everything is interesting. The server automatically starts when you do something that requires starting the server (I know what sounds really strange). But you can start it manually by calling the init () method.

Template engine support


I would like to touch upon such a topic as template engines. Spark has a lot of native support of these. Namely:


For all of them there are "wrappers" from Spark. For example, let's take a look at my favorite Freemarker.

First, let's import the add. addiction.

  <dependency> <groupId>com.sparkjava</groupId> <artifactId>spark-template-freemarker</artifactId> <version>2.5.5</version> </dependency> 

Create a template "hello.ftl" in the src / main / resources directory.

 <html> <head> </head> <body> <h1>Hello, ${name}!</h1> </body> </html> 

Now you need to configure the freemarker so that it searches for templates in the resources. This is just 4 lines of code.

 FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine(); Configuration freeMarkerConfiguration = new Configuration(); freeMarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/")); freeMarkerEngine.setConfiguration(freeMarkerConfiguration); 

That's all, you can safely use freemarker.

 get("/", (request, response) -> { Map<String, Object> model = new HashMap<>(); model.put("name", "Freemarker"); return freeMarkerEngine.render(new ModelAndView(model, "hello.ftl")); }); 



Almost complete project


Let's write, some easy, but sufficient to show at least a small part of the capabilities of Spark? From the fact that you can really quickly write, only the abbreviation of links came to my head. Well, let's start?

We need to add another dependency Google Guava. As a result, we get 3 dependencies.

  <dependencies> <dependency> <groupId>com.sparkjava</groupId> <artifactId>spark-core</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>com.sparkjava</groupId> <artifactId>spark-template-freemarker</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> 

We need Guava, because it implements the hash function Murmur3. The whole plus is that it is quite strong resistant to collisions. Also, in order not to waste too much time, we will store all data only in variables, without any database, etc.

Make the backbone of the program.

 staticFileLocation("/static"); get("/shortener", (request, response) -> { }); get("/:url", (request, response) -> { }); 

: url is a parameter that can be obtained through the params () method. For example:

 get("/hello/:name", (request, response) -> { return "Hello: " + request.params(":name"); }); 

Something I was distracted, we will continue.

Create a collection (Map) for storage, set up a templating engine (as I said freemarker is my favorite, so it will be him) and specify a pairing where we will store statistical files. staticFiles.location ("/ static") will tell it that the files will be in src / main / resources / static . For example, the file / static / css / style.css will be available at http: // {host}: {port} /css/style.css . If you want to store files suppose in / var / www / public_html , then use the method staticFiles.externalLocation ("/ var / www / public_html") .

  ConcurrentHashMap<String, String> urls = new ConcurrentHashMap<String, String>(); FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine(); Configuration freemarkerConfiguration = new Configuration(); freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/templates/")); freeMarkerEngine.setConfiguration(freemarkerConfiguration); staticFileLocation("/static"); 

Set up redirection.

  get("/:url", (request, response) -> { if(urls.containsKey(request.url())) response.redirect(urls.get(request.url())); response.redirect("/"); return null; }); 

Now when the user follows a short link, if the link is in the collection, we move it to the desired site, if not, then to the main one.

Let's work with the front-end, otherwise we have completely forgotten about it. Let's start with the main one.
Here we will create a simple minimalist form. And we stuff the Proxima Nova font. Played of course ... but oh well.

 <!DOCTYPE html> <html lang="en" style="height:100%;"> <head> <meta charset='utf-8'> <link rel="stylesheet" href="style.css"> </head> <body> <div id="main"> <form action="/shortener" method="GET"> <input type="text" id="input" name="url" autocomplete="off" autofocus size="44" maxlength="512" /> </form> </div> </body> </html> 

 @font-face { font-family: Proxima Nova; src: url(pn.otf); } * { font-family: Proxima Nova; background: #2a2826; color: #9C9C9C; margin: 0; padding: 0; } body, html { height: 100%; } #main { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 1.5em; } #input { border: none; outline:none; font-size: 1.5em; } 

In the end, all this stuff looks like.



Now the page on which the link “shortener.ftl” will be displayed.

 <!DOCTYPE html> <html lang="en" style="height:100%;"> <head> <meta charset='utf-8'> <link rel="stylesheet" href="style.css"> </head> <body> <div id="main" style="text-align: center"> ${url} </div> </body> </html> 

The final project structure.



Well, we add the last lines. As a result, the Main class looks like this.

 import com.google.common.hash.Hashing; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; import spark.ModelAndView; import spark.Request; import spark.Response; import spark.template.freemarker.FreeMarkerEngine; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import static spark.Spark.*; public class Main { public static void main(String[] args) { ConcurrentHashMap<String, String> urls = new ConcurrentHashMap<String, String>(); FreeMarkerEngine freeMarkerEngine = new FreeMarkerEngine(); Configuration freemarkerConfiguration = new Configuration(); freemarkerConfiguration.setTemplateLoader(new ClassTemplateLoader(Main.class, "/templates/")); freeMarkerEngine.setConfiguration(freemarkerConfiguration); staticFileLocation("/static"); get("/shortener", (request, response) -> { String shortURL = "http://localhost:4567/" + Hashing.murmur3_32().hashString(request.queryParams("url"), StandardCharsets.UTF_8).toString(); Map<String, Object> model = new HashMap<>(); if(!urls.containsKey(shortURL)) { model.put("url", shortURL); urls.put(shortURL, request.queryParams("url")); return freeMarkerEngine.render(new ModelAndView(model, "shortener.ftl")); } model.put("url", shortURL); return freeMarkerEngine.render(new ModelAndView(model, "shortener.ftl")); }); get("/:url", (request, response) -> { if(urls.containsKey(request.url())) response.redirect(urls.get(request.url())); response.redirect("/"); return null; }); } } 

That's all. 41 lines of code and we wrote a link abbreviation.

Conclusion


At this point, I’ll finish this slightly protracted “Getting started” article. I am very sorry that in Runet this project was bypassed. If you like it, I will continue to write about Spark and reveal more of its features.

Links


→ Project site
→ SparkJava source codes

Source: https://habr.com/ru/post/339684/


All Articles