JToolbox HTTP Service: Um Roteador Leve em Java
Criei um sistema de HTTP Service completo em Java puro (Vanilla Java), com foco em simplicidade e agilidade, semelhante a frameworks leves como o Gin Gonic em Go. A proposta principal é permitir que você crie rapidamente mini-projetos ou mock servers para realizar testes de integração, validando suas requisições HTTP (GET, POST, PUT, DELETE, etc.) de forma eficiente.
A Criação de Endpoints e Handlers
O núcleo deste serviço reside na definição de endpoints e na associação de Handlers. Um endpoint é a combinação única de um método HTTP e um caminho (path).
Para começar, você precisa apenas chamar a classe Server, definir a porta de execução e encadear os métodos HTTP (como get, post, delete) para criar seus endpoints.
O Fluxo de Roteamento
- Inicialização: Chame
Server.port()para iniciar o serviço na porta desejada (ex: 8080). - Definição do Endpoint: Use métodos como
.get("/caminho")para mapear a URL. - Associação do Handler: O segundo argumento é a função lambda ou a classe que implementa a interface
Handler— o código que será executado para processar a requisição e construir a resposta.
O Contexto da Requisição (HttpContext)
O HttpContext é o objeto central passado para cada Handler, contendo todos os utilitários para interagir com a requisição e montar a resposta. Com ele, você pode:
- Acessar query parameters (ex:
ctx.param("id")). - Ler o corpo da requisição (
ctx.body()) e desserializá-lo para classes Java. - Definir headers de resposta (ex:
ctx.header("Content-Type", "text/html")). - Enviar a resposta final com diferentes tipos (JSON, texto) e códigos de status (
ctx.send(),ctx.json(),ctx.text()).
Exemplo 1: Servindo um Conteúdo Estático na Raiz
Este exemplo demonstra como servir o conteúdo de um arquivo HTML estático na rota raiz (/), garantindo que falhas na leitura do arquivo sejam tratadas com um erro 500 (Internal Server Error).
public class WebServer {
public static void main(String[] args) {
Server server = Server.port(8080)
.get("/", ctx -> {
String content = Try.ofThrowing(() ->
File.read("./static/index.html")
)
.onFailure(e -> {
Logger.error("Error reading index.html: {}", e, e.getMessage());
ctx.status(500, HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
ctx.text("Error: Could not read index.html file.");
})
.orElse(null);
if (content != null) {
ctx.header("Content-Type", "text/html");
ctx.send(HttpStatus.OK, content);
}
});
server.start();
}
}
Exemplo 2: Criando Handlers Reutilizáveis (Classes)
Para encapsular lógica de negócios mais complexa ou para promover a reutilização, você pode criar uma classe que implementa a interface Handler:
class Hello implements Handler {
@Override
public void handle(HttpContext ctx) {
ctx.header("Content-Type", "text/html");
ctx.send(HttpStatus.OK, "Hello World!");
}
}
Exemplo 3: Handlers como Métodos Estáticos e não Estáticos (Lambdas)
Para endpoints simples e concisos, a criação de métodos publicos e/ou estáticos que retornam a interface Handler usando lambdas é a abordagem mais elegante e funcional:
public Handler hello() {
return ctx -> ctx.send(HttpStatus.OK, "Hello World!");
}
Como ficou o web site estático:
Esta minha lib esta disponivel no repositorio da Maven Central