Aplicativo da Web com IoC Starter. Mapeamento básico de consultas usando o contexto ioc, web ioc e ioc orm

imagem

1. Introdução


Desde o primeiro lançamento, muito tempo se passou ( link para o artigo anterior ). O que mudou?


  • estabilidade melhorada do sistema como um todo;
  • carregamento lento de componentes implementado;
  • Sistema de escuta básico embutido
  • suporte interno para programação orientada a aspectos (para dificuldade média em solucionar problemas, caso contrário, aconselho que você use a biblioteca AspectJ para o resto)
  • novo gerenciador de inicialização RequestFactory
  • trabalho integrado com cache baseado em EhCache, Guava
  • o trabalho com fluxos é integrado (inicialização pela anotação @SimpleTask e trabalho direto com o pool)

** Módulos


  • módulo para trabalhar com o banco de dados (ORM leve com suporte para JPA, Transações, Driver NO-SQL - Orient, métodos Crud, sistema de repositório e consultas geradas automaticamente a partir da função da classe de repositório)
  • Módulo de focinho da Web (mapeamento de link por meio de anotações, suporte para produtores / consumos personalizados, página de renderização de modelo de velocidade, solicitações de segurança básica, sessões, cookies, SSL) com base no Netty 4.1.30.

Estrutura de estrutura
struct


"Isso, é claro, é tudo de bom", você diz, "mas, de fato, tudo funciona?"
"Sim, funciona. Peço um corte."


Processo de implementação de exemplo


Para implementar o exemplo, usarei o Maven 3 e o Intelijj Idea 2018.2.


1) Conecte as dependências:


<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>example-webapp</artifactId> <groupId>org.ioc</groupId> <packaging>jar</packaging> <version>0.0.1</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <.source>1.8</source> <target>1.8</target> </configuration> <executions> <execution> <id>default-testCompile</id> <phase>test-compile</phase> <goals> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.ioc</groupId> <artifactId>context-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> <dependency> <groupId>org.ioc</groupId> <artifactId>orm-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> <dependency> <groupId>org.ioc</groupId> <artifactId>web-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> </dependencies> <repositories> <repository> <id>context</id> <url>https://raw.github.com/GenCloud/ioc_container/context</url> </repository> <repository> <id>cache</id> <url>https://raw.github.com/GenCloud/ioc_container/cache</url> </repository> <repository> <id>threading</id> <url>https://raw.github.com/GenCloud/ioc_container/threading</url> </repository> <repository> <id>orm</id> <url>https://raw.github.com/GenCloud/ioc_container/orm</url> </repository> <repository> <id>web</id> <url>https://raw.github.com/GenCloud/ioc_container/web</url> </repository> </repositories> </project> 

** Ele ainda não se mudou para Maven Central, infelizmente.


Estrutura do projeto:
a estrutura
Padrão MVC padrão, não é?


Crie um ponto de entrada para o aplicativo:


 package org.examples.webapp; import org.ioc.annotations.context.ScanPackage; import org.ioc.annotations.modules.CacheModule; import org.ioc.annotations.modules.DatabaseModule; import org.ioc.annotations.modules.ThreadingModule; import org.ioc.annotations.modules.WebModule; import org.ioc.context.starter.IoCStarter; @WebModule @CacheModule @ThreadingModule @DatabaseModule @ScanPackage(packages = {"org.examples.webapp"}) public class AppMain { public static void main(String[] args) { IoCStarter.start(AppMain.class); } } 

** Explicações:
Anotação @ScanPackages - define pacotes contextuais para identificar componentes (em pessoas comuns - "bandejas").
Anotação @WebModule - serve para conectar e inicializar uma fábrica na web.
Anotação @CacheModule - é usada para conectar e inicializar a fábrica de cache, é usada para a operação correta do ORM (em versões futuras, uma anotação não será necessária).
Anotação @ThreadingModule - é usada para conectar e inicializar uma fábrica de threads, é usada para a operação correta de uma fábrica da web (em versões futuras, uma anotação não será necessária).
Anotação @DatabaseModule - Usado para conectar e inicializar uma fábrica ORM.
Todas as fábricas possuem configuradores padrão, que você pode alterar por si próprio redefinindo as funções das configurações usadas pelas fábricas (em cada anotação de módulo, o configurador de classe é redefinido - Classe <?> AutoConfigurationClass () WebAutoConfiguration.class padrão ) ou desabilita qualquer configuração usando a anotação @Exclude na principal sala de aula.
O utilitário IoCStarter é a principal classe de inicializador de contexto.


Bem, tudo parece estar pronto, o contexto é inicializado, a web funciona na porta padrão 8081, mas não há link e, quando vamos ao site, isso realmente não nos dá nada. Bem, siga em frente.


Vamos criar um arquivo de configuração para nossos módulos. Por padrão, todas as configurações são carregadas em {working_dir} /configs/default_settings.properties - nós a criaremos no caminho apropriado.


 # Threading ioc.threads.poolName=shared ioc.threads.availableProcessors=4 ioc.threads.threadTimeout=0 ioc.threads.threadAllowCoreTimeOut=true ioc.threads.threadPoolPriority=NORMAL # Event dispather # -  ()    ( ) ioc.dispatcher.availableDescriptors=4 # Cache #   (EhFactory|GuavaFactory) cache.factory=org.ioc.cache.impl.EhFactory # Datasource #   (-, -  ) #LOCAL, LOCAL_SERVER, REMOTE datasource.orient.database-type=LOCAL #   datasource.orient.url=./database #    (   ) datasource.orient.database=orient #   datasource.orient.username=admin #   datasource.orient.password=admin #       (create, dropCreate, refresh, none) datasource.orient.ddl-auto=dropCreate #   ,      datasource.orient.showSql=true # Web server #     web.server.port=8081 #   SSL  web.server.ssl-enabled=false # in seconds #   ( 7200 . = 2 ) web.server.security.session.timeout=300 #  - web.server.velocity.input.encoding=UTF-8 web.server.velocity.output.encoding=UTF-8 #  - web.server.velocity.resource.loader=file #   web.server.velocity.resource.loader.class=org.apache.velocity.runtime.resource.loader.FileResourceLoader #    - web.server.velocity.resource.loading.path=./public 

Em seguida, precisamos de uma entidade de usuário e seu repositório de gerenciamento:
Implementação da entidade TblAccount:


 package org.examples.webapp.domain.entity; import org.ioc.web.security.user.UserDetails; import javax.persistence.*; import java.util.Collections; import java.util.List; @Entity public class TblAccount implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; @Column(name = "username") private String username; @Column(name = "password") private String password; @Transient private String repeatedPassword; public String getRepeatedPassword() { return repeatedPassword; } public void setRepeatedPassword(String repeatedPassword) { this.repeatedPassword = repeatedPassword; } @Override public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public List<String> getRoles() { return Collections.singletonList("ROLE_USER"); } } 

** Explicações:
Tudo é padrão como em todas as estruturas de suporte à JPA. Mapeie a entidade usando @ .Entity , crie a Chave Primária usando a anotação @ .Id , mapeie as colunas usando a anotação @Column. e herdar de UserDetails para identificar a entidade no módulo Security .


Implementação do repositório da entidade TblAccountRepository:


 package org.examples.webapp.domain.repository; import org.examples.webapp.domain.entity.TblAccount; import org.ioc.annotations.context.IoCRepository; import org.ioc.orm.repositories.CrudRepository; import javax.transaction.Transactional; @IoCRepository public interface TblAccountRepository extends CrudRepository<TblAccount, Long> { @Transactional TblAccount findByUsernameEq(String username); } 

** Explicações:
Anotação @IoCRepository - serve para determinar por contexto que a classe é um repositório e precisa ser processada "de maneira diferente" .
Suporta funções CRUD padrão:


  • Busca de entidade (ID do ID) - obtém uma entidade do tipo Entidade do banco de dados ou do cache pela Chave Primária;
  • List fetchAll () - obtém todas as entidades do tipo Entity, pré-carregando-as no cache;
  • void save (Entidade entidade) - cria / atualiza uma entidade do tipo Entidade no banco de dados e no cache;
  • exclusão nula (entidade da entidade) - exclui uma entidade do tipo Entidade do banco de dados e do cache;
  • boolean existe (ID do ID) - verifica se existe uma entidade no banco de dados usando a Chave Primária.
    Todos os pedidos CRUD ocorrem em uma transação.

Ele suporta a geração automática de consultas, redefinindo funções com palavras-chave, como na implementação acima ( TblAccount findByUsernameEq (String nome de usuário) ) e chamando consultas registradas ( NamedQuery )


A função findByUsernameEq (String username) - pesquisa uma entidade por seu campo de nome de usuário . Solicitação gerada:


  select * from tbl_account where username = 'username' 

Em seguida, precisamos de um nível para gerenciar a lógica de negócios.
Implementações de AccountService:


 package org.examples.webapp.service; import org.examples.webapp.domain.entity.TblAccount; import org.examples.webapp.domain.repository.TblAccountRepository; import org.examples.webapp.responces.IMessage; import org.ioc.annotations.context.IoCComponent; import org.ioc.annotations.context.IoCDependency; import org.ioc.web.model.http.Request; import org.ioc.web.security.configuration.SecurityConfigureAdapter; import org.ioc.web.security.encoder.bcrypt.BCryptEncoder; import org.ioc.web.security.user.UserDetails; import org.ioc.web.security.user.UserDetailsProcessor; import java.util.Objects; import static org.examples.webapp.responces.IMessage.Type.ERROR; import static org.examples.webapp.responces.IMessage.Type.OK; @IoCComponent public class AccountService implements UserDetailsProcessor { @IoCDependency private TblAccountRepository tblAccountRepository; @IoCDependency private BCryptEncoder bCryptEncoder; @IoCDependency private SecurityConfigureAdapter securityConfigureAdapter; @Override public UserDetails loadUserByUsername(String username) { return tblAccountRepository.findByUsernameEq(username); } public void save(TblAccount tblAccount) { tblAccountRepository.save(tblAccount); } public void delete(TblAccount tblAccount) { tblAccountRepository.delete(tblAccount); } public IMessage tryCreateUser(String username, String password, String repeatedPassword) { if (username == null || username.isEmpty() || password == null || password.isEmpty() || repeatedPassword == null || repeatedPassword.isEmpty()) { return new IMessage(ERROR, "Invalid request parameters!"); } if (!Objects.equals(password, repeatedPassword)) { return new IMessage(ERROR, "Repeated password doesn't match!"); } final UserDetails userDetails = loadUserByUsername(username); if (userDetails != null) { return new IMessage(ERROR, "Account already exists!"); } final TblAccount account = new TblAccount(); account.setUsername(username); account.setPassword(bCryptEncoder.encode(password)); save(account); return new IMessage(OK, "Successfully created!"); } public IMessage tryAuthenticateUser(Request request, String username, String password) { if (username == null || username.isEmpty() || password == null || password.isEmpty()) { return new IMessage(ERROR, "Invalid request parameters!"); } final UserDetails userDetails = loadUserByUsername(username); if (userDetails == null) { return new IMessage(ERROR, "Account not found!"); } if (!bCryptEncoder.match(password, userDetails.getPassword())) { return new IMessage(ERROR, "Password does not match!"); } securityConfigureAdapter.getContext().authenticate(request, userDetails); return new IMessage(OK, "Successfully authenticated"); } public IMessage logout(Request request) { if (securityConfigureAdapter.getContext().removeAuthInformation(request)) { return new IMessage(OK, "/"); } return new IMessage(ERROR, "Credentials not found or not authenticated!"); } } 

** Explicações:
Anotação @IoCComponent - serve para inicializar uma classe como um componente.
Anotação @IoCDependency - Usada para injetar dependências em uma instância de uma classe.
O utilitário BCryptEncoder é uma implementação do codec BCrypt para criptografia de senha (até o momento, o único codec).
Instância do sistema SecurityConfigureAdapter - é usada para trabalhar com solicitações de mapeamento e sessões do usuário.
Função UserDetails loadUserByUsername - função herdada UserDetailsProcessor , usada para carregar o usuário na sessão e definir o sinalizador de autenticação (no futuro para mapeamento padrão de autorização em Segurança )
A função IMessage tryCreateUser é uma função de criação de usuário.
Função IMessage tryAuthenticateUser - função de autenticação do usuário.
A função de logout do IMessage é uma função para limpar uma sessão de um usuário autorizado.
A classe IMessage é uma classe de utilitário para exibir as informações que precisamos no navegador (resposta json).


 package org.examples.webapp.responces; public class IMessage { private final String message; private final Type type; public IMessage(String message) { this.message = message; type = Type.OK; } public IMessage(Type type, String message) { this.message = message; this.type = type; } public String getMessage() { return message; } public Type getType() { return type; } public enum Type { OK, ERROR } } 

Agora você precisa da implementação do próprio link (mapeamento de solicitação):


 package org.examples.webapp.mapping; import org.examples.webapp.domain.entity.TblAccount; import org.examples.webapp.responces.IMessage; import org.examples.webapp.service.AccountService; import org.ioc.annotations.context.IoCDependency; import org.ioc.annotations.web.IoCController; import org.ioc.web.annotations.Credentials; import org.ioc.web.annotations.MappingMethod; import org.ioc.web.annotations.RequestParam; import org.ioc.web.annotations.UrlMapping; import org.ioc.web.model.ModelAndView; import org.ioc.web.model.http.Request; @IoCController @UrlMapping("/") public class MainMapping { @IoCDependency private AccountService accountService; @UrlMapping public ModelAndView index() { final ModelAndView modelAndView = new ModelAndView(); modelAndView.setView("index"); return modelAndView; } @UrlMapping(value = "signup", method = MappingMethod.POST) public IMessage createUser(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("repeatedPassword") String repeatedPassword) { return accountService.tryCreateUser(username, password, repeatedPassword); } @UrlMapping(value = "signin", method = MappingMethod.POST) public IMessage auth(Request request, @RequestParam("username") String username, @RequestParam("password") String password) { return accountService.tryAuthenticateUser(request, username, password); } @UrlMapping("signout") public IMessage signout(Request request) { return accountService.logout(request); } @UrlMapping("loginPage") public ModelAndView authenticated(@Credentials TblAccount account) { final ModelAndView modelAndView = new ModelAndView(); modelAndView.setView("auth"); modelAndView.addAttribute("account", account); return modelAndView; } } 

** Explicações:
Anotação @IoCController - serve para identificar a classe no contexto como um controlador (mapeador de solicitações de navegador)
Anotação @UrlMapping - indica que é necessário analisar uma função / classe para a presença de solicitações processadas pelos manipuladores de canal.
Parâmetros:


  • valor - a solicitação que precisamos;
  • método - método http para processamento (GET, POST, PUT, etc.);
  • consome - tipo http mime para verificar a presença de uma solicitação de um tipo específico (opcional);
  • produz - tipo de conteúdo http para retornar um tipo de conteúdo específico na resposta (Tipo de conteúdo: texto / html; charset = utf-8, Tipo de conteúdo: multipart / formulário de dados; limite = algo, etc. opcional;

Anotação @RequestParam - serve para determinar o nome do parâmetro recebido da solicitação. Como é impossível obter o nome atual do parâmetro do método por meio de reflexão padrão, fiquei com preguiça de conectar uma dependência extra de javaassist a um shaman com asm. Portanto, esse método de determinar o nome do parâmetro para incorporar esses valores de parâmetro obtido a partir da solicitação. Existe um análogo para o tipo GET - @PathVariable - o mesmo princípio de operação (não compatível com o POST ).
Anotação @Credentials - serve para inserir os dados atuais do usuário autorizado, caso contrário, poderá ser nulo se as informações do usuário autorizado não estiverem na sessão.
O sistema de classe Request é a informação atual sobre uma solicitação recebida, que contém coca, cabeçalhos e um canal do usuário, que pode ser enviado posteriormente para o Push Message's ... que já tem algum tipo de fantasia a esse respeito.
A classe de utilitário ModelAndView é um modelo de página com o nome do recurso sem uma extensão e atributos para incorporação no recurso.


Parece ser tudo, mas não - você deve definitivamente configurar o mapeamento disponível de solicitações para usuários.


 package org.examples.webapp.config; import org.ioc.annotations.configuration.Property; import org.ioc.annotations.configuration.PropertyFunction; import org.ioc.web.security.configuration.HttpContainer; import org.ioc.web.security.configuration.SecurityConfigureProcessor; import org.ioc.web.security.encoder.Encoder; import org.ioc.web.security.encoder.bcrypt.BCryptEncoder; import org.ioc.web.security.filter.CorsFilter; import org.ioc.web.security.filter.CsrfFilter; @Property public class SecurityConfig implements SecurityConfigureProcessor { @Override public void configure(HttpContainer httpContainer) { httpContainer. configureRequests(). anonymousRequests("/", "/signup", "/signin"). resourceRequests("/static/**"). authorizeRequests("/loginPage", "ROLE_USER"). authorizeRequests("/signout", "ROLE_USER"). and(). configureSession(). expiredPath("/"); } @PropertyFunction public CsrfFilter csrfFilter() { return new CsrfFilter(); } @PropertyFunction public CorsFilter corsFilter() { return new CorsFilter(); } @PropertyFunction public Encoder encoder() { return new BCryptEncoder(); } } 

** Explicações:
Anotação @Property - informa ao contexto que este é um arquivo de configuração e precisa ser inicializado.
Anotação @PropertyFunction - informa ao analisador de configuração que esta função retorna algum tipo e deve inicializá-la como um componente (bin).
Interface SecurityConfigureProcessor - um utilitário usado para configurar o mapeamento de solicitações.
A classe de modelo HttpContainer é um utilitário que armazena o mapeamento de solicitações especificadas pelo usuário.
A classe CsrfFilter é um filtro de solicitações inválidas (implementações da mecânica do CSRF).
A classe CorsFilter é um filtro de compartilhamento de recursos de origem cruzada.


Função AnonymousRequests - aceita uma variedade ilimitada de solicitações, não requer usuários autorizados e verificação de função (ROLE_ANONYMOUS).
A função resourceRequests - recebe uma matriz ilimitada de solicitações, serve especificamente para determinar qual caminho será o arquivo de recurso que não requer processamento complexo (css, js, imagens etc.).
Função authorizeRequests - recebe uma matriz ilimitada de solicitações, requer um usuário autorizado e a função específica inerente ao usuário.
Função ExpiredPath - ao limpar uma sessão que expirou no tempo, o usuário é redirecionado por esse mapeamento (link de redirecionamento).


Bem, havia páginas, scripts e estilos de site (não vou me aprofundar).


Título de spoiler

index.vm - página principal


 <html> <head> <meta charset="utf-8"/> <title>IoC Test</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/style.css"/> <link rel="stylesheet" href="/static/css/pnotify.custom.min.css"/> <link rel="stylesheet" href="/static/css/pnotify.css"/> <link rel="stylesheet" href="/static/css/pnotify.buttons.css"/> </head> <body> <div class="container"> <h1>IoC Starter Test</h1> <br> <h4>Create user</h4> <br> <form id="creation"> <label for="username">Username: </label> <input type="text" id="username" name="username" class="color-input-field"/> <label for="password">Password: </label> <input type="password" id="password" name="password" class="color-input-field"/> <label for="repeatedPassword">Repeate: </label> <input type="password" id="repeatedPassword" name="repeatedPassword" class="color-input-field"/> <button type="button" class="btn btn-success btn-create">Sing up!</button> </form> <h4>Authenticate</h4> <br> <form id="auth"> <label for="username">Username: </label> <input type="text" id="username" name="username" class="color-input-field"/> <label for="password">Password: </label> <input type="password" id="password" name="password" class="color-input-field"/> <button type="button" class="btn btn-danger btn-auth">Sing in!</button> </form> </div> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/bootstrap.min.js"></script> <script type="text/javascript" src="/static/js/scripts.js"></script> <script type="text/javascript" src="/static/js/pnotify.js"></script> <script type="text/javascript" src="/static/js/pnotify.buttons.js"></script> </body> </html> 

auth.vm - para exibir um usuário autorizado


 <html> <head> <meta charset="utf-8"/> <title>IoC Test</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/style.css"/> <link rel="stylesheet" href="/static/css/pnotify.custom.min.css"/> <link rel="stylesheet" href="/static/css/pnotify.css"/> <link rel="stylesheet" href="/static/css/pnotify.buttons.css"/> </head> <body> <div class="container"> <h1>Authorized page</h1> <br> <h4>Test auth data</h4> <div id="auth_data"> #if($!account) <h4>Hello @$!account.username, You successfully authenticated!</h4> <br> <button type="button" class="btn btn-success btn-logout">Logout!</button> #end </div> </div> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/bootstrap.min.js"></script> <script type="text/javascript" src="/static/js/scripts.js"></script> <script type="text/javascript" src="/static/js/pnotify.js"></script> <script type="text/javascript" src="/static/js/pnotify.buttons.js"></script> </body> </html> 

scripts.js - controller, para enviar e receber informações de solicitação para o servidor


 $(function () { $(".btn-create").click(function () { var cooki = cookie(); document.cookie = 'CSRF-TOKEN=' + cooki; $.ajax({ url: "/signup", data: $('#creation').serialize(), headers: {'X-CSRF-TOKEN': cooki}, crossDomain: true, xhrFields: { withCredentials: true }, type: "POST" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: data.message, type: 'success', hide: false }); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); $(".btn-auth").click(function () { var cooki = cookie(); document.cookie = 'CSRF-TOKEN=' + cooki; $.ajax({ url: "/signin", data: $('#auth').serialize(), headers: {'X-CSRF-TOKEN': cooki}, crossDomain: true, xhrFields: { withCredentials: true }, type: "POST" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: data.message, type: 'success', hide: false }); setTimeout(function () { window.location = "/loginPage"; }, 5000); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); $(".btn-logout").click(function () { $.ajax({ url: "/signout", crossDomain: true, xhrFields: { withCredentials: true }, type: "GET" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: 'Logouting...', type: 'success', hide: false }); setTimeout(function () { window.location = data.message; }, 5000); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); }); function cookie(a) { return a // if the placeholder was passed, return ? ( // a random number from 0 to 15 a ^ // unless b is 8, Math.random() // in which case * 16 // a random number from >> a / 4 // 8 to 11 ).toString(16) // in hexadecimal : ( // or otherwise a concatenated string: [1e7] + // 10000000 + -1e3 + // -1000 + -4e3 + // -4000 + -8e3 + // -80000000 + -1e11 // -100000000000, ).replace( // replacing /[018]/g, // zeroes, ones, and eights with cookie // random hex digits ) } 

Compile, execute tudo o que temos.
Se tudo estiver correto, veremos algo assim no final do download:


Log

[21.10.18 22: 29: 51: 990] INFO web.model.mapping.MappingContainer: método mapeado [/], method = [GET], para [org.ioc.web.model.ModelAndView org.examples.webapp .mapping.MainMapping.index ()]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: método mapeado [/ inscrição], método = [POST] para [org.examples.webapp.responces.IMessage.exemplos org.exemplos. webapp.mapping.MainMapping.createUser (java.lang.String, java.lang.String, java.lang.String)]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: método mapeado [/ signin], método = [POST] para [org.examples.webapp.responces.IMessage.exemplos org.exemplos. webapp.mapping.MainMapping.auth (org.ioc.web.model.http.Request, java.lang.String, java.lang.String)]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: método mapeado [/ signout], método = [GET] para [org.examples.webapp.responces.IMessage.exemplos org.exemplos. webapp.mapping.MainMapping.signout (org.ioc.web.model.http.Request)]
[21.10.18 22: 29: 51: 995] INFO web.model.mapping.MappingContainer: método mapeado [/ loginPage], método = [GET] para [org.ioc.web.model.ModelAndView org.examples públicos. webapp.mapping.MainMapping.authenticated (org.examples.webapp.domain.entity.TblAccount)]
[21.10.18 22: 29: 51: 997] INFO ioc.web.factory.HttpInitializerFactory: servidor HTTP iniciado na (s) porta (s): 8081 (http)


Resultado:
1) Página inicial
índice
2) Registro
inscrição
3) Autenticação
auth
4) A página com o resultado da autorização (redirecione após inserir o login e a senha corretamente)
resultado
5) Limpando informações de autorização da sessão e redirecionando o usuário para a página inicial
imagem
6) Uma tentativa de um usuário não autorizado de acessar a página com informações de autenticação de sessão
imagem


O fim


O projeto está em desenvolvimento, “colaboradores” e idéias originais são bem-vindas, pois é difícil fazer esse projeto sozinho.
Repositório do projeto .
Contexto
Fábrica de ORM
Fábrica da Web
Exemplos
Exemplo atual do artigo
Também no repositório há exemplos de uso de todas as funcionalidades no módulo 'examples' e, como se costuma dizer: "Boa sorte, divirta-se", obrigado a todos pela atenção.

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


All Articles