Há alguns dias eu estava querendo um tempo para estudar um pouco a API do Gravatar, que por sinal funciona muito bem aqui no WordPress. Lendo a documentação de uso, percebi que muito fácil de você obter a imagem de um perfil do Gravatar usando um hash do e-mail do usuário com criptografia MD5.
Primeiramente, como sou um usuário fanático do jQuery, tentei resolver a bronca direto por Javascript, mas acabei empacando na geração do hash MD5, não sei porque, mais aqui nenhuma implementação Javascript para MD5 funcionou, assim parti para o plano B, usando a API Java para gerar o hash MD5, perfeito, funcionou corretamente, tá bom, mas agora eu tenho a implementação lá em uma classe Java, como que eu ligo isto com a minha view HTML/JSP ?
Usando o VRaptor 3.4, fiz uma requisição AJAX/JSON e retornava o hash e fazia o carregamento da imagem via jQuery, assim:
01 $(document).ready(function(){ 02 $('#button').bind('click', function(){ 03 var email = $('#email').attr('value'); 04 05 var url = "<c:url value='/gravatar/get-md5/'/>"; 06 $.post(url, {email: email}, function(data){ 07 var url = "http://www.gravatar.com/avatar/" + data.string + "?s=200"; 08 $('#result').html($("<img/>").attr('src', url)).append('<br/><i>' + data.string + "</i>"); 09 }); 10 }); 11 });
Na minha aplicação Java eu tinha duas classes, uma que implementava o hash MD5 e a outra que era o meu controller da requisição AJAX/JSON:
01 package com.wp.carlos4web.cpropriedades.md5; 02 03 import java.io.UnsupportedEncodingException; 04 import java.security.MessageDigest; 05 import java.security.NoSuchAlgorithmException; 06 07 public class MD5 { 08 public static String hex(byte[] array) { 09 StringBuffer sb = new StringBuffer(); 10 for (int i = 0; i < array.length; ++i) { 11 sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring( 12 1, 3)); 13 } 14 return sb.toString(); 15 } 16 17 public static String md5Hex(String message) { 18 try { 19 MessageDigest md = MessageDigest.getInstance("MD5"); 20 return hex(md.digest(message.getBytes("CP1252"))); 21 } catch (NoSuchAlgorithmException e) { 22 } catch (UnsupportedEncodingException e) { 23 } 24 return null; 25 } 26 } 27 // Controller. 28 package com.wp.carlos4web.cpropriedades.controllers; 29 30 import com.wp.carlos4web.cpropriedades.md5.MD5; 31 32 import br.com.caelum.vraptor.Get; 33 import br.com.caelum.vraptor.Post; 34 import br.com.caelum.vraptor.Resource; 35 import br.com.caelum.vraptor.Result; 36 import br.com.caelum.vraptor.view.Results; 37 38 @Resource 39 public class HomeController 40 { 41 private Result result; 42 43 public HomeController(Result result) { 44 super(); 45 this.result = result; 46 } 47 48 @Get("/") 49 public void index () 50 { 51 52 } 53 54 @Post("/gravatar/get-md5/") 55 public void generateMD5Hash(String email) 56 { 57 String hash = MD5.md5Hex(email); 58 59 this.result.use(Results.json()).from(hash).serialize(); 60 } 61 }
O código é bem simples, e funcionou, atendendo o que eu precisava, só que daí pensei em ‘componentizar’ essa solução, daí acabei refletindo e vi que seria inviável inicialmente, logo então pensei em uma solução alternativa à uma interação/codificação Javascript/AJAX, logo a única saída seria escrever uma tag própria para isso, pronto, encapsula a lógica em uma classe Java e vincula a mesma em uma tag acessível pelo HTML/JSP.
As tag libraries, ou tag support do Java são bem simples de serem utilizadas e implementadas, não sou um grande conhecedor, mas com algumas pesquisas na documentação consegui desenvolver a solução sem muitos problemas. Bom primeiramente precisamos criar a nossa classe que contém a implementação necessária, mais qual implementação ?
A implementação/ligação com a classe que gera o hash e que cria o elemento IMG para ser inserido no corpo da página HTML/JSP, o código da classe está na listagem abaixo e é bem simples, repare que os atributos ‘email’ e ‘imageSize’ são os parâmetros da nossa tag na página HTML/JSP.
01 package com.wp.carlos4web.gravatar; 02 03 import java.io.IOException; 04 05 import javax.servlet.jsp.JspException; 06 import javax.servlet.jsp.tagext.TagSupport; 07 08 import com.wp.carlos4web.cpropriedades.md5.MD5; 09 10 public class GravatarTag extends TagSupport 11 { 12 private static final long serialVersionUID = 1066237315711135837L; 13 14 protected String email; 15 16 protected int imageSize = 200; 17 18 @Override 19 public int doEndTag() throws JspException 20 { 21 if(email != null && !email.isEmpty()) 22 { 23 try 24 { 25 // Gera o hash MD5. 26 String hash = MD5.md5Hex(email); 27 28 // Monta a URL para a imagem remota. 29 String url = "http://www.gravatar.com/avatar/" + hash + "?s=" + imageSize; 30 31 // Monta a tag HTML IMG com a URL remota. 32 String img = "<img src='" + url + "'/>"; 33 34 // Insere no corpo da página onde a tag está sendo chamada. 35 this.pageContext.getOut().write(img); 36 } catch (IOException e) { 37 e.printStackTrace(); 38 } 39 } 40 return super.doEndTag(); 41 } 42 43 public String getEmail() { 44 return email; 45 } 46 47 public void setEmail(String email) { 48 this.email = email; 49 } 50 public void setImageSize(int imageSize) { 51 this.imageSize = imageSize; 52 } 53 54 public int getImageSize() { 55 return imageSize; 56 } 57 }
Como vocês viram o código é bem simples. Não existe regra sobre qual pacote deve ficar a sua classe, somente no arquivo TLD de descrição você deverá informar o caminho dela, exemplo: ‘br.pacote.pacote.SuaClasse’. Não esqueça:
- Declarar que a sua classe estende de javax.servlet.jsp.tagext.TagSupport,
- Criar os métodos setters para os seus atributos, caso falte algum será gerada uma exception na sua aplicação.
Caso contrário não irá funcionar.
O próximo passo e a estruturação da nossa tag, para isso eu segui o padrão do desenvolvimento de tags, no meu diretório WEB-INF, eu criei um diretório tags e dentro dele um diretório com um nome significativo, neste caso ‘gravatar’. Dentro dele, seguindo a convenção, criei um arquivo .TLD com o nome da minha classe, logo ‘gravatar.tld’. Abaixo segue a codificação do mesmo, que também é bem simples e segue um padrão.
01 <?xml version="1.0" encoding="ISO-8859-1" ?> 02 <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> 03 04 <taglib> 05 <tlibversion>1.0</tlibversion> 06 <jspversion>1.1</jspversion> 07 <shortname>gravatar</shortname> 08 <uri>http://carlos4web.wordpress.com/</uri> 09 <info>Insere uma tag IMG com o gravatar de um usuário a partir do seu E-mail.</info> 10 11 <tag> 12 <name>gravatar</name> 13 <tagclass>com.wp.carlos4web.gravatar.GravatarTag</tagclass> 14 <bodycontent>JSP</bodycontent> 15 <info>Say Hi</info> 16 17 <attribute> 18 <name>email</name> 19 <required>true</required> 20 <rtexprvalue>true</rtexprvalue> 21 </attribute> 22 <attribute> 23 <name>imageSize</name> 24 <required>false</required> 25 <rtexprvalue>true</rtexprvalue> 26 </attribute> 27 </tag> 28 </taglib>
O próximo passo é usar a nossa tag, esta é a parte mais fácil da brincadeira, primeiramente, declare o import da nossa tag library:
1 <%@ taglib prefix="carlos" uri="/WEB-INF/tags/gravatar/gravatar.tld" %>
Agora é só chamar quando você precisar:
01 <table> 02 <tr> 03 <td valign="top"> 04 <carlos:gravatar email="carlosjrcabello@gmail.com" imageSize="30"/> 05 </td> 06 <td valign="top"> 07 <carlos:gravatar email="carlosjrcabello@gmail.com" imageSize="50"/> 08 </td> 09 <td valign="top"> 10 <carlos:gravatar email="carlosjrcabello@gmail.com" imageSize="100"/> 11 </td> 12 <td valign="top"> 13 <carlos:gravatar email="carlosjrcabello@gmail.com" imageSize="300"/> 14 </td> 15 </tr> 16 </table>
Lembrando pessoal, que segundo a API do Gravatar, quando a imagem do perfil não é encontrada, é retornado uma imagem padrão com a logo do gravatar. Caso você queira, existem mais parâmetros na API para customizar isso.
Conclusão
Bom pessoal, essa é uma solução do ‘mundo real‘ no desenvolvimento de aplicações WEB, porque? Com esse código, você investe um tempo X para fazê-lo, depois você ganha muito tempo somente reusando ele, lembrem-se dos princípios de agilidade e reusabilidade de código.
Este é um exemplo didático, está bem simples, quem quiser enriquecer esta solução com os outros recursos da API do Gravatar fique a vontade, no final será uma solução muito bacana e utilizável.
Download
Para quem quiser baixar o exemplo da tag, estou deixando disponível lá no Github o código junto da estrutura do projeto, segue o endereço abaixo:
https://github.com/carlosjrcabello/gravatar-tag-support
Referências
http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags6.html – contém exemplos bem claros de como utilizar.
http://stackoverflow.com/questions/224748/jsp-custom-tag-library-unable-to-find-setter-method-for-the-attribute – contém a solução para um problema que uma hora ou outra você irá passar, que é a ordem da declaração dos elementos no arquivo TLD.
http://java.sun.com/developer/technicalArticles/xml/WebAppDev3/ – Mais exemplos de como trabalhar com o arquivo TLD.
http://en.gravatar.com/site/implement/ – informações sobre a API e implementações.
Por enquanto é só pessoal, um abraço e até a próxima.
Dúvidas e comentário usem o espaço de comentários abaixo.
Fonte: Carlos4web