Introdução ao Jooby

Introdução ao Jooby

1. Visão geral

Jooby é um framework micro web escalável e rápido construído sobre osNIO web servers mais usados. É muito simples e modular, claramente projetado para a arquitetura da web moderna. Ele vem com suporte paraJavascripteKotlin também.

Por padrão,Jooby vem com ótimo suporte paraNetty, Jetty, and Undertow.

Neste artigo, aprenderemos sobre a estrutura geral do projetoJooby e como construir um aplicativo da web simples usandoJooby.

2. Arquitetura de Aplicação

Uma estrutura de aplicativoJooby simples será semelhante a abaixo:

├── public
|   └── welcome.html
├── conf
|   ├── application.conf
|   └── logback.xml
└── src
|   ├── main
|   |   └── java
|   |       └── com
|   |           └── example
|   |               └── jooby
|   |                   └── App.java
|   └── test
|       └── java
|           └── com
|               └── example
|                   └── jooby
|                       └── AppTest.java
├── pom.xml

O ponto a ser observado aqui é que no diretóriopublic podemos colocar arquivos estáticos como css / js / html etc. No diretórioconf, podemos colocar qualquer arquivo de configuração que um aplicativo precise, comologback.xml ouapplication.conf etc.

3. Dependência do Maven

Podemos criar um aplicativoJooby simples adicionando a seguinte dependência em nossopom.xml:


    org.jooby
    jooby-netty
    1.1.3

Se quisermos escolherJetty ouUndertow, podemos usar a seguinte dependência:


    org.jooby
    jooby-jetty
    1.1.3


    org.jooby
    jooby-undertow
    1.1.3

Você pode verificar a versão mais recente do projetoJooby noCentral Maven Repository.

Jooby also has a dedicated Maven archetype. Podemos usá-lo para criar um projeto de amostra com todas as dependências necessárias pré-construídas.

Podemos usar o seguinte script para gerar o projeto de amostra:

mvn archetype:generate -B -DgroupId=com.example.jooby -DartifactId=jooby
-Dversion=1.0 -DarchetypeArtifactId=jooby-archetype
-DarchetypeGroupId=org.jooby -DarchetypeVersion=1.1.3

4. Construindo um aplicativo

4.1. Iniciando o servidor

Para iniciar o servidor incorporado, precisamos usar o seguinte trecho de código:

public class App extends Jooby {
    public static void main(String[] args) {
        run(App::new, args);
    }
}

Uma vez iniciado, o servidor estará rodando emdefault port8080.

Também podemos configurar o servidor back-end com porta personalizada e portaHTTPS personalizada:

{
    port( 8081 );
    securePort( 8443 );
}

4.2. Implementando o Roteador

É muito fácil criar um roteador baseado em caminho emJooby. Por exemplo, podemos criar um roteador para o caminho ‘/login’ da seguinte maneira:

{
    get( "/login", () -> "Hello from example");
}

De forma semelhante, se quisermos lidar com outros métodosHTTP como POST, PUT, etc, podemos usar o snippet de código abaixo:

{
    post( "/save", req -> {
        Mutant token = req.param( "token" );
        return token.intValue();
    });
}

Aqui, estamos obtendo o token do nome do parâmetro da solicitação. Por padrão, todos os parâmetros de solicitação são inseridos no tipo de dadosJooby'sMutant. Com base na expectativa, podemos convertê-lo em qualquer tipo de dados primitivo suportado.

Podemos verificar qualquer parâmetro de URL da seguinte maneira:

{
    get( "/user/{id}", req -> "Hello user : " + req.param("id").value() );
    get( "/user/:id", req -> "Hello user: " + req.param("id").value() );
}

Podemos usar qualquer um dos itens acima. Também é possível encontrar parâmetros começando com um conteúdo fixo. Por exemplo, podemos encontrar um parâmetro de URL começando com ‘uid:' da seguinte maneira:

{
    get( "/uid:{id}", req -> "Hello User with id : uid" +
        req.param("id").value());
}

4.3. Implementando controlador de padrão MVC

Para um aplicativo corporativo,Jooby vem com uma API MVC muito parecida com qualquer outra estrutura MVC como Spring MVC.

Por exemplo, podemos lidar com um caminho chamado ‘/hello’:

@Path("/hello")
public class GetController {
    @GET
    public String hello() {
        return "Hello example";
    }
}

De forma muito semelhante, podemos criar um manipulador para lidar com outros métodos HTTP com@POST, @PUT, @DELETE, etc. anotação.

4.4. Tratamento de conteúdo estático

Para servir qualquer conteúdo estático como HTML, Javascript, CSS, imagem, etc., precisamos colocar esses arquivos no diretóriopublic.

Uma vez colocado, do roteador, podemos mapear qualquer URL para esses recursos:

{
    assets( "/employee" , "form.html" );
}

4.5. Formulário de Manuseio

A interfaceJooby’sRequest por padrão lida com qualquer objeto de formulário sem usar qualquer conversão de tipo manual.

Vamos supor que precisamos enviar os detalhes do funcionário por meio de um formulário. Na primeira etapa, precisamos criar um objeto beanEmployee que usaremos para armazenar os dados:

public class Employee {
    String id;
    String name;
    String email;

    // standard constructors, getters and setters
}

Agora, precisamos criar uma página para criar o formulário:

A seguir, criaremos um gerenciador de postagem para abordar este formulário e buscar os dados enviados:

post( "/submitForm", req -> {
    Employee employee = req.params(Employee.class);
    // ...
    return "empoyee data saved successfullly";
});

O ponto a ser observado aqui é que devemos declarar o formulárioenctype comoapplication/x-www-form-urlencoded para suportar a vinculação dinâmica do formulário.

PorRequest.file(String filename), podemos recuperar o arquivo carregado:

post( "/upload", req -> {
    Upload upload = req.file("file");
    // ...
    upload.close();
});

4.6. Implementando um Filtro

Fora da caixa, Jooby fornece a flexibilidade para definir filtros globais, bem como os filtros baseados em caminho.

Implementar filtro emJooby é um pouco complicado, poiswe need to configure the URL path twice, once for the filter and once again for the handler.

Por exemplo, se tivermos que implementar um filtro para um caminho de URL chamado ‘/filter',, precisamos implementar o filtro explicitamente neste caminho:

get( "/filter", ( req, resp, chain ) -> {
    // ...
    chain.next( req, resp );
});

A sintaxe é muito semelhante ao filtroServlet. É possível restringir a solicitação e enviar de volta a resposta no próprio filtro chamando o métodoResponse.send(Result result).

Depois que o filtro é implementado, precisamos implementar o manipulador de solicitações:

get("/filter", (req, resp) -> {
    resp.send("filter response");
});

4.7. Sessão

Jooby vem com dois tipos de implementação de sessão; na memória e com base em cookies.

A implementação do gerenciamento de sessões na memória é bastante simples. Temos as opções de escolher qualquer um dos armazenamentos de sessão de alto rendimento disponíveis comJooby comoEhCache, Guava, HazleCast, Cassandra, Couchbase, Redis, MongoDB,eMemcached.

Por exemplo, para implementar um armazenamento de sessão baseado em Redis, precisamos adicionar a seguinte dependência do Maven:


    org.jooby
    jooby-jedis
    1.1.3

Agora podemos usar o snippet de código abaixo para ativar o gerenciamento de sessões:

{
    use(new Redis());
    session(RedisSessionStore.class);

    get( "/session" , req -> {
        Session session = req.session();
        session.set("token", "value");
        return session.get("token").value();
    });
}

O ponto a ser observado aqui é que podemos configurar o url deRedis como a propriedade‘db' emapplication.conf.

Para habilitar o gerenciamento de sessão baseado em cookie, precisamos declararcookieSession(). If cookie based approach is selected, we must need to declare application.secret property in the application.conf file. Uma vez que cada cookie será assinado com esta chave secreta, é sempre aconselhável usar um fragmento de string aleatório longo como uma chave secreta. **

Tanto na abordagem na memória quanto na baseada em cookies, devemos declarar o parâmetro de configuração necessário no arquivoapplication.conf, caso contrário, o aplicativo lançará umIllegalStateException na inicialização.

5. Teste

Testar a rota MVC é realmente fácil, pois uma rota está vinculada a uma estratégia para alguma classe. Isso facilita a execução de testes de unidade em todas as rotas.

Por exemplo, podemos criar rapidamente um caso de teste para o URL padrão:

public class AppTest {

    @ClassRule
    public static JoobyRule app = new JoobyRule(new App());

    @Test
    public void given_defaultUrl_expect_fixedString() {

        get("/").then().assertThat().body(equalTo("Hello World!"))
          .statusCode(200).contentType("text/html;charset=UTF-8");
    }
}

O ponto a ser observado aqui é que usar a anotação@ClassRule criará apenas uma instância do servidor para todos os casos de teste. Se precisarmos construir instâncias separadas dos servidores para cada caso de teste, temos que usar a anotação@Rule sem o modificador estático.

Também podemos usarJooby’s MockRouter para testar o caminho da mesma maneira:

@Test
public void given_defaultUrl_with_mockrouter_expect_fixedString()
  throws Throwable {

    String result = new MockRouter(new App()).get("/");

    assertEquals("Hello World!", result);
}

6. Conclusão

Neste tutorial, exploramos o projetoJooby e sua funcionalidade essencial.

Como sempre, o código-fonte completo está disponívelover on GitHub.