Uma arquitetura web - O Spring MVC e AngularJs em camadas.

Nota:
Ola, este artigo é um tutorial traduzido do http://blog.jhades.org/ achei interessante suas ideias e formas de integrar o Spring MVC e o AngularJS e sua explicação condiz com o seu real conhecimento. Deixo aqui talvez uma forma simples de tradução e uma sugestão de melhorar suas comparativas finais com outras arquiteturas java.

Segue:


O Spring MVC e o AngularJs juntos fazem aplicações web produtivas e atraentes para o desenvolvimento front-end e para construir formulários intensivos em sua web app.
Neste post de blog nos vamos ver como construir um formulário intensivo (intensive-form) web app, que pode ser construido utilizando estas tecnologias, e comparar com outras opções. As amostra de funções completas e segura de MVC / AngularJS estão disponíveis no repositório github https://github.com/jhades/spring-mvc-angularjs-sample-app.


Nos vamos seguir os tópicos:
  • A arquitetura de uma aplicação Spring MVC + AngularJS em uma aplicação de página.
  • Como estruturar a web UI utilizando Angular.
  • Como Javascript / CSS bibliotecas complementan o Angular?
  • Como construir uma REST API utilizando Spring Security?
  • Como comparar esta aplicação com outras abordagens baseadas em Java?



A arquitetura de uma aplicação Spring MVC + AngularJS em uma aplicação de página.


As aplicações de negócio com formato intensivo são ideais para serem construídas como apps web de páginas únicas. A ideia principal é comparar arquiteturas de servidores tradicionais com a construção de servidores stateless reusable com serviços REST e para a perspectiva MVC devemos pegar o controller na camada backend e mover para o browser.(Veja na Figura 1).

Como o backend é construido?


O backend de uma aplicação frontend é construído naturalmente da mesma forma que uma API REST. A mesma tecnologia utilizada para web services, pode ser utilizada para aplicações terceira. Obviamente que em muitos casos é importante separar as camadas de serviços SOAP.
De uma perspectiva de DDD, o modelo de domínio permanece no backend, ao nível camada de serviço e persistência. Para interligar apenas por DTO’s, mas não o modelo de domínio.


Como estruturar o front-end para uma web-app consumir o AngularJS?


O frontend deveria ser construído em torno de uma especificação de visão de modelo (o qual não é modelo de domínio) e só deve lidar com a lógica de apresentação, mas nenhuma lógica de negócios. Estas são as três camadas da frontend:


  • A camada de visão:



A camada de view é composta por templates HTML, css e diretivas angular que representam os diferentes componentes UI. Este é um exemplo de uma simples de visão de login:


<form ng-submit="onLogin()" name="form" novalidate="" ng-controller="LoginCtrl">
   <fieldset>
   <legend>Log In</legend>
   <div class="form-field">
        <input type="text" ng-model="vm.username" name="username" required="" ng-minlength="6">
   <div class="form-field">
        <input type="password" ng-model="vm.password" name="password" required="" ng-minlength="6" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}">
   </div></div></fieldset>
   <button type="submit">Log In</button>
   <a href="/resources/public/new-user.html">New user?</a>
</form>


  • A camada controladora:



A camada controladora é feita com controladores Angular que fixa os dados recuperados vindos do backend e da visão juntos.
O controlador inicializa o view-model e define como a visão deve reagir com as alterações do model e vice-versa;  


angular.module('loginApp', ['common',  'editableTableWidgets'])
   .controller('LoginCtrl', function ($scope, LoginService) {
       $scope.onLogin = function () {
           console.log('Attempting login with username ' + $scope.vm.username + ' and password ' + $scope.vm.password);
           if ($scope.form.$invalid) {
               return;
           }
           LoginService.login($scope.vm.userName, $scope.vm.password);
       };
   });


Uma das principais responsabilidades do controlador é a validação do front-end. Algunas validações prontas são utilizadas por convenção. Por exemplo os casos em que o campo é requerido.
Algumas validações de front-end precisam ser repetidas no backend e na camada de serviços da visão devido a as reações de segurança. As validações de front-end podem ser facilmente ignoradas.


  • O camada de serviços da visão:

Um conjunto de serviços Angular permite a iteração com o backend que injeta os controladores Angular.
angular.module('frontendServices', [])
   .service('UserService', ['$http','$q', function($http, $q) {
       return {
           getUserInfo: function() {
               var deferred = $q.defer();
               $http.get('/user')
                   .then(function (response) {
                       if (response.status == 200) {
                           deferred.resolve(response.data);
                       }
                       else {
                           deferred.reject('Error retrieving user info');
                       }
               });
               return deferred.promise;
     }


Agora vamos ver quais as bibliotecas nos precisamos para ter um front-end em pé e rodando.


Como estruturar o front-end para uma web-app consumir o AngularJS?


O AngularJs já fornece uma grande parte da funcionalidade necessária para construir a interface do nosso aplicativo. Alguns bons complementos para angular são:


  • Uma biblioteca de CSS facilmente personalizável de apenas 4k do Yahoo é chamado Pure CSS. Esse Skin Builder permite uma fácil geração de temas baseado nas cores primárias. Isso é uma solução BYOJ (Bring Your Own Javascript) (Traga Seu Proprio Javascript), que ajuda a manter as coisas do “Caminho do Angular”.
  • Uma biblioteca de programação funcional para manipular os dados. O mais visto e mais utilizado e que é de fácil manutenção e documentação até os dias de hoje é o Lodash


Com essas duas bibliotecas e o AngularJS, praticamente qualquer aplicação baseada em formulário pode ser construida, nenhuma outra biblioteca é requerida. Algumas outras bibliotecas podem ser utilizadas dependendo do seu projeto que são:


  • Um modulo de sistema parecido com o requirejs é legal possuir, mas por que o módulo de sistema do Angular não manipula arquivos de recuperação, isto introduz alguma duplicação entre as declarações de dependência de RequireJS e os módulos angulares.
  • A CSRF modulo Angular, que previne ataques de cross-site request forgery.
  • Um módulo de internacionalização.


Como construir uma API REST backend usando SpringMVC?


O Backend e construido utilizando as seguintes camadas:
  • Camada de rotas: define a entrada de serviços correspondentes as url HTTP e faz a leitura dos parâmetros para o HTTP request.
  • Camada de serviço: contem as lógicas de negócio tal como suas validações, e define o escopo das transções de negócio.
  • Camada de persistência: faz o mapeamento do banco de dados em memória e domina os objetos.


O Spring MVC é melhor configurado utilizando apenas o Java. O web.xml é raramente utilizado, veja aqui um exemplo de aplicação utilizando apenas configuração JAVA.
A camada de  serviço e a persistência são construidos utilizando a arquitetura DDD, então vamos concentrar a nossa atenção sobre a camada de rotas.


A Camada de Rotas


As mesmas anotações do Spring MVC são utilizadas para construir uma aplicação JSP/Thymeleaf e também pode ser usado para construir uma API REST.
A grande diferença é que os metodos controladores não retornam String que definem os quais os metodos de template que devem ser renderizados. Neste caso utilizamos o @ResponseBody para retornar objeto que será utilizado em tempo de execução.


@ResponseBody
@ResponseStatus(HttpStatus.OK)
@RequestMapping(method = RequestMethod.GET)
public UserInfoDTO getUserInfo(Principal principal) {
   User user = userService.findUserByUsername(principal.getName());
   Long todaysCalories = userService.findTodaysCaloriesForUser(principal.getName());
   return user != null ? new UserInfoDTO(user.getUsername(), user.getMaxCaloriesPerDay(), todaysCalories) : null;
}


Se todos os metodos de sua classe estão anotados com @ResponseBody, então é melhor anotar com as classes com @RestController.
Adicionando a biblioteca JSON Jackson, os métodos retornados devem vir convertidos para JSON sem qualquer configuração adicional. É também posśivel converter XML para outros formatos dependendo do valor que o cabecalho HTTP aceita, especificado para seu cliente.
Veja aqui um exemplo de uma integração de controladores com erro de cabeçalho configurado.


Como proteger ma API REST utilizando Spring Security.


Uma API REST pode ser protegida utilizando o Spring Security configurado com Java. Uma boa prática é utilizar o formulário de login com autenticação fallback HTTP Basic e a inclusão de alguma proteção CSRF, e o possível para forcar todos os metodos do backend a utilizar HTTPS.
Isso significa que o backend irá proporcionar ao usuário um formulário de login e atribuir um cookie de sessão no login bem-sucedido para clientes de navegador, mas para para clientes fora dos navegadores web com suporte fallback HTTP Basic onde as credencias de autorização são passadas via cabeçalho HTTP.
Siga as recomendações do OWASP, os serviços REST podem ser minimamente sem serviços de estados (o único serviço de estado é a sessão de cookie utilizado para autenticação) para retornar sem credenciais sobre as chamadas de cada requisição.
Este é um exemplo de como configurar uma API REST protegida:


http
     .authorizeRequests()
     .antMatchers("/resources/public/**").permitAll()
     .anyRequest().authenticated()
     .and()
     .formLogin()
     .defaultSuccessUrl("/resources/calories-tracker.html")
     .loginProcessingUrl("/authenticate")
     .loginPage("/resources/public/login.html")
     .and()
     .httpBasic()
     .and()
     .logout()
     .logoutUrl("/logout");
 if ("true".equals(System.getProperty("httpsOnly"))) {
     LOGGER.info("launching the application in HTTPS-only mode");
     http.requiresChannel().anyRequest().requiresSecure();
 }       


Essa configuração abrange o aspecto de autenticação de segurança apenas, a escolha de uma estratégia de autorização depende dos requisitos da API de segurança. Se você precisa de um controle muito refinado na autorização, em seguida, verificar Spring Security ACLs que pode conter os ajustes necessários para o seu uso.
Agora vamos ver esta tecnica de construção de web apps comparada com outras abordagens utilizadas.


Comparando o Spring MVC / AngularJS em camadas com outras abordagens comuns.


Esta abordagem manipula Javascript para o front-end e Java para o backend para fazer um fluxo de trabalho simplificado e desenvolvimento produtivo.
Quando o backend está sendo executado, não são necessárias ferramentas especiais ou plugins para conseguir frontend completo capacidade de hot-deploy: (build or rebuild) apenas publique os recursos do servidor utilizando sua IDE (para exemplo pressione Ctrl + F10 no IntelliJ) e atualize seu navegador.
As classes de backend podem ser atualizadas utilizando o JRabel, mas para o front-end nada de especial pode ser adicionado. Na verdade todo o front-end pode ser construido utilizando por o exemplo o json-server. Essa ferramenta permite que você faça diferentes desenvolvimentos para construir um front-end e um backend em paralelo se necessário.


Os ganhos de produtividade para o desenvolvimento em camadas?
Da minha experiência de ser capaz de editar o HTML e CSS diretamente sem camadas de engano no meio (ver aqui uma comparação angular de alto nível com GWT e JSF) ajuda a reduzir a sobrecarga mental e mantém as coisas simples. O ciclo de desenvolvimento editar-salvar-atualizar é muito rápido e confiável e dá um impulso enorme produtividade.
O ganho principal de produtividade é quando temos o mesmo desenvolvedor que constrói o backend também desenvolve o frontend, porque as mudanças são necessárias muitas vezes simultâneas, tanto para a maioria dos recursos.
A principal desvantagem dessa forma de desenvolvimento é que a equipe precisa saber HTML/CSS e javascript para criar as aplicações. Mas isso tem se tornado comum entre os desenvolvedores.
Na minha experiência, todas as camadas permite implementar um caso de uso  no front-end complexo em uma fração de tempo, enquanto uma solução equivalente em “Java Puro” leva dias, assim o ganho de produção tem curva de aprendizado e definitivamente vale a pena.


Conclusões


Spring MVC e AngularJs realmente combinam e abrem a porta para um novo caminho de construção de formulários intensivos na web. O ganho de produção que está aproximação permite faz isso uma alternativa de trabalho admirável.
A ausência de algum servidor de estados entre as requisições (alem de cookie autenticação) elimina alguns bugs por design de arquitetura.
Para mais detalhes verifique essa aplicação simples e envie suas perguntas e questionamentos nos comentários abaixo.

Comentários

Postagens mais visitadas deste blog

Tutorial HIBERNATE – Gerar Base de Dados a Partir das Entidades