1. Introduct to EzyHTTP
EzyHTTP (Easy going to HTTP Interaction) is a lightweight framework support to interact to HTTP, it includes both http server and http client.
2. Structure of ezyhttp-server
- When client request to server, Servlet receive the request first
- The request must pass through the list of interceptor before pass to controller
- The controller handle the request and return response to the Servlet
- If have any exceptions unprocessed by the Interceptor and the Controller, an ExcetionHandler will process that exception and return result to the Servlet
- After all the Servlet will send the response to client
3. Install EzyHTTP
To create a http server application we need add dependency
<dependency>
<groupId>com.tvd12</groupId>
<artifactId>ezyhttp-server-boot</artifactId>
<version>0.0.6</version>
</dependency>
To use http cleint we need add dependency
<dependency>
<groupId>com.tvd12</groupId>
<artifactId>ezyhttp-client</artifactId>
<version>0.0.6</version>
</dependency>
The latest version can be found in the Maven Central repository.
4. Create an http server example
Let’s say we need create an http server application to manage user, we need 2 apis:
: Add user to systemapi/v1/users/add
: Get user by nameapi/v1/users/{username}
Firstly, we need create a maven project with
: user-management-applicationname
: com.example.user_managementpackage
: 1.8java version
Next, we need add ezyhttp-server-boot dependency We use lombok to generate getter, setter, contructor so you need install and add lombok dependency to pom.xml
4.1 Create the application entry point class
package com.example.user_management;
import com.tvd12.ezyhttp.core.boot.EzyHttpApplicationBootstrap;
import com.tvd12.ezyhttp.server.core.asm.RequestHandlerImplementer;
public class App {
public static void main(String[] args) throws Exception {
RequestHandlerImplementer.setDebug(true);
EzyHttpApplicationBootstrap.start(App.class);
}
}
4.2 Create User class to keep user information
package com.example.user_management.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {
protected String username;
protected String password;
}
4.3 Create UserService class to manage user information
package com.example.user_management.service;
import com.example.user_management.entity.User;
import com.tvd12.ezyfox.bean.annotation.EzySingleton;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@EzySingleton
public class UserService {
protected final Map<String, User> users = new ConcurrentHashMap<>();
public User addUser(User user) {
return users.put(user.getUsername(), user);
}
public User getUser(String username) {
return users.get(username);
}
}
4.4 Create UserController class to handle request from client
package com.example.user_management.controller;
import com.example.user_management.entity.User;
import com.example.user_management.service.UserService;
import com.tvd12.ezyfox.bean.annotation.EzyAutoBind;
import com.tvd12.ezyhttp.core.exception.HttpConflictException;
import com.tvd12.ezyhttp.core.exception.HttpNotFoundException;
import com.tvd12.ezyhttp.core.response.ResponseEntity;
import com.tvd12.ezyhttp.server.core.annotation.*;
import lombok.Setter;
@Setter
@Controller("/api/v1/users")
public class UserController {
@EzyAutoBind
protected UserService userService;
@DoPost("/add")
public ResponseEntity addUser(@RequestBody User user) {
User existed = userService.addUser(user);
if(existed == null)
return ResponseEntity.ok(Boolean.TRUE);
throw new HttpConflictException("user: " + user.getUsername() + " existed");
}
@DoGet("/{username}")
public User getUser(@PathVariable("username") String username) {
User user = userService.getUser(username);
if(user != null)
return user;
throw new HttpNotFoundException("user: " + username + " not found");
}
}
4.5 Create log4j.properties file in src/resources folder
The log4j.properties's content:
# Root logger option
log4j.rootLogger=INFO, stdout
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Ok, we done all, let’s start main class ‘App’ and great! We’ve had a http server application
4.6 Let’s take a test on postman
With api:
we have/api/v1/users/add
With api:
we have:/api/v1/users/{username}
Awesome! Everything ok.
5. Create a client example
With client, we have 2 way (2 class) to call http request
: A simple http client, it simply open a connection, send the request and return the response, it only supports sync methodHttpClient
: It use HttpClient class to send the request, but every request will add to a queue, and we need config number of threads to process this queue. It supports both sync and async method Firstly, we need add ezyhttp-client dependency to maven Next, create a test package with name: com.example.user_management.test inHttpClientProxy
folder To testsrc/test/java
api, we need create a class ApiAddUserTest with content:/api/v1/users/add
package com.example.user_management.test;
import com.example.user_management.entity.User;
import com.tvd12.ezyhttp.client.HttpClient;
import com.tvd12.ezyhttp.client.request.PostRequest;
import com.tvd12.ezyhttp.client.request.Request;
import com.tvd12.ezyhttp.client.request.RequestEntity;
import com.tvd12.ezyhttp.core.constant.StatusCodes;
public class ApiAddUserTest {
public static void main(String[] args) throws Exception {
HttpClient httpClient = HttpClient.builder()
.build();
User body = new User();
body.setUsername("dev");
body.setPassword("123456");
RequestEntity entity = RequestEntity.body(body);
Request request = new PostRequest()
.setURL("http://localhost:8080/api/v1/users/add")
.setEntity(entity)
.setResponseType(Boolean.class)
.setResponseType(StatusCodes.CONFLICT, String.class);
Boolean reponse = httpClient.call(request);
System.out.println("add user reponse: " + reponse);
}
}
And we get output: add user reponse:
To test true
api, we need create a class ApiAddUserTest with content:/api/v1/users/users/{username}
package com.example.user_management.test;
import com.tvd12.ezyhttp.client.HttpClientProxy;
import com.tvd12.ezyhttp.client.request.GetRequest;
import com.tvd12.ezyhttp.client.request.Request;
import com.tvd12.ezyhttp.client.request.RequestEntity;
import com.tvd12.ezyhttp.core.constant.StatusCodes;
public class ApiGetUserTest {
public static void main(String[] args) throws Exception {
HttpClientProxy httpClient = HttpClientProxy.builder()
.build();
httpClient.start();
RequestEntity entity = RequestEntity.builder().build();
Request helloRequest = new GetRequest()
.setURL("http://localhost:8080/api/v1/users/dev")
.setEntity(entity)
.setResponseType(String.class)
.setResponseType(StatusCodes.NOT_FOUND, String.class);
String reponse = httpClient.call(helloRequest, 10000);
System.out.println("get user reponse: " + reponse);
}
}
And get get output: get user reponse:
{"username":"dev","password":"123456"}
6. Conclusion
With EzyHTTP everything are simple, you don’t need care about HttpServlet, HttpRequest, HttpResponse, how to serialize/deserialize request/response and bean management, with the IOC EzyHTTP will care for you