Seguindo na sequência de como desenvolver um aplicativo web completo com Java e JSF
Todo o código referente a estes posts estão no github.
Estrutura do banco
Como dito anteriormente, o primeiro passo para se construir um sistema é a definição da estrutura do seu banco de dados, a estrutura escolhida para este passo do sistema está na Figura 1.Figura1: Estrutura do banco de dados |
Foi criada uma tabela separada para a senha do usuário afim de garantir uma maior segurança dos dados. Como a senha está isolada em uma outra tabela, ela só será pesquisada pelo sistema quando o usuário logar, ou quando houver alguma alteração da senha.
Caso a senha estivesse na mesma tabela do usuário, os dados da senha ficariam trafegando pelo aplicativo toda hora em que os dados do usuário fossem requisitados, o que aumenta a possibilidade de alguém coletar esta informação, e mesmo que criptografada, pode ser que esta senha seja descoberta.
Na parte do endereço do usuário, houve uma normalização dos dados de cidades, estados e ruas. Note que nem sempre esta normalização é necessária, poderíamos ter uma tabela de endereço com todos estes dados, mas a normalização deles nos traz a vantagem de não termos que repetir o cadastro de dados que já existam.
Todas estas tabelas estão ligadas a tabela CEP, para que com isso seja possível localizarmos estes dados pelo CEP, assim que o usuário digitar um CEP que já existe no sistema ele deve trazer os valores daqueles campos, facilitando o cadastro das informações do endereço.
Porém isto também levanta um alerta, e se o usuário estiver cadastrando um CEP e aquele valor já existir para uma certa Rua de um município? Bom alguns municípios pequenos possuem apenas um CEP, com isso todas as ruas deles estão em um mesmo valor do CEP, assim podemos ter dados de CEPs que só possuem o estado e a cidade.
Para tratarmos estes casos, devemos ter uma certa lógica de negócios ao utilizarmos o cadastro do CEP. Uma das atitudes que podem ser tomadas é nunca cadastrar todos os dados do CEP, quando ele tiver sendo inserido pela primeira vez em uma cidade. Se uma cidade nunca foi cadastrada no sistema, o CEP só vai conter os valores do estado e da Cidade, e quando houver um segundo cadastro, com a mesma rua, ai sim completa-se a informação do CEP. Mas fazer isso durante o cadastro do endereço do usuário não é uma boa opção, já que o sistema deve fazer algumas queries para realizar estas operações, entõa o ideal é deixar isto para um sistema de batch que rode de tempos em tempos.
E o que fazer quando duas ruas foram cadastradas para um CEP de uma cidade, mas esta cidade não possui CEP único? Neste caso, você pode tentar tratar pela maioria, ou mesmo fazer uma análise manual, isto vai depender da quantidade de dados que a sua base tem neste caso.
Validações e regras de negócio
Existem algumas validações que podemos e devemos fazer durante este cadastro, por exemplo se a senha possui no mínimo 6 caracteres e 2 dígitos. Para fazer este tipo de validação iremos usar uma classe validadora do JSF, para isso deve-se adicionar a tag validator no seu componente, como mostrado a seguir em destaque:<h:inputSecret id="senha"O código de validação será implementado em um bean que implementa a interface Validator do faces. O único método que esta interface define é o validate, como mostrado abaixo:
value="#{usuarioBean.usuarioSenha.password}"
validator="validadorDeSenha"
required="#{not empty param.includeInSalvar}"
pt:placeholder="Qual é a sua senha?" />
public void validate(FacesContext context, UIComponent iuComponent, Object valor)FacesContext é o contexto faces e podemos usar ele para, por exemplo redirecionar o usuário para uma outra página de erro. O componente é o objeto referente ao componente da tela que está sendo validado e finalmente o Objeto será o valor digitado pelo usuário.
throws ValidatorException {
if(!padraoSenha.matcher(valor.toString()).matches()){
MessageFactory msg = new MessageFactory();
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
msg.getMessage("senhaInvalida"), null));
}
}
Neste caso estamos apenas validando o valor digitado, usando REGEX (regular expression), nossa REGEX de validação de senha verifica se os valores digitados estão entre 6 e 20 caracteres de tamanho, e se ela contém pelo menos 2 letras e pelo menos 2 números, abaixo segue a implementação do REGEX:
((?=.{2,}\\d)(?=.{2,}[a-zA-Z]).{6,20})Repare que para o regex a definição de números é dada por \d mas como \ no java é um caracter especial, devemos utilizar o caracter de escape que também é uma \, por isso temos \\d.
(
(?=.{2,}\\d) verifica se contém pelo menos 2 ({2,}) dígitos \\d
(?=.{2,}[a-zA-Z]) verifica se contém pelo menos 2 ({2,}) letras(a-zA-Z) de a a z minúsculo e A a Z maiúsculo
.{6,20} verificacao de tamanho;
)
Para utilizar o regex em java usa-se a classe chamada Pattern:
private Pattern padraoSenha= Pattern.compile("((?=.{2,}\\d)(?=.{2,}[a-zA-Z]).{6,20})");Regex é um tema muito amplo que não cabe ao escopo deste post, por isso não vamos discutí-lo aqui.package br.unip.dsd.bean.validador;
Basicamente a classe validadora segue os mesmos princípios do ManagedBean e para definirmos ele, usamos a anotação @FacesValidator sobre a classe. Com isso ele poderá ser acessado nas suas páginas usando o nome da classe, no mesmo padrão dos beans, primeira letra minúscula e demais de acordo com o nome da classe.
Quando o usuário digitar uma senha que não atende aos padrões do nosso regex, uma mensagem de erro será mostrada para ele ao lado do componente.
Porém esta ação de validação acontece nas ações da tela, por exemplo, quando o usuário clicar no botão de salvar.
Quando a validação falha uma exceção do tipo ValidatorException é disparada, e este é o comportamento padrão dos validadores. Repare que nada deverá ser feito se o valor digitado pelo usuário estiver correto.
Lembre-se que cada pacote de beans adicionado ao projeto, deverá ser adicionado a propriedade basePackages, da anotação @ComponentScan, na classe de configuração, que no nosso caso é a JPAConfig.
Usando enums internacionalizados para os dados tipados
É comum o uso de enumerations para dados tipados, que raramente terão os valores alterados. Os enums basicamente são uma lista de valores introduzidos no código e que são gravados em um campo. Para gravarmos os valores dos enums em um campo existem duas possibilidades:- usar um id no enum, valor numérico
- usar o toString do enum
public List<SelectItem> getEstadoCivil() {O código é bem simples, o primeiro ponto a observar é a utilização de um MessageFactory, que está sendo usado aqui para a internacionalização dos valores do enumeration.
List<SelectItem> estadoCivil = new ArrayList<SelectItem>();
MessageFactory msg = new MessageFactory();
estadoCivil.add(new SelectItem(EstadoCivil.CASADO.toString(), msg.getMessage("casado")));
estadoCivil.add(new SelectItem( EstadoCivil.SOLTEIRO.toString(), msg.getMessage("solteiro")));
estadoCivil.add(new SelectItem(EstadoCivil.DIVORCIADO.toString(), msg.getMessage("divorciado")));
estadoCivil.add(new SelectItem(EstadoCivil.VIUVO.toString(), msg.getMessage("viuvo")));
return estadoCivil;
}
SelectItem é um objeto utilizado para mostrarmos dados como uma lista, em uma combobox, para que o usuário selecione o valor desejado.
Através do SelectItem são enviados dois valores de String para a tela, primeiro o valor do enum internacionalizado, que irá aparecer na lista para o usuário. Depois o valor do enum transformado em String, que será usado para gravarmos no banco.
Nenhum comentário:
Postar um comentário