A partire ormai dalla versione 4.3.0, Liferay supporta nativamente (issues.liferay.com/browse/LEP-1630) il protocollo Sitemaputilizzato da Google (e da altri motori di ricerca) per indicizzare le pagine di un sito; in pratica si tratta di fornire a Google un file XML con l'elenco di tutte le URL da indicizzare, con relativa priorità e frequenza di aggiornamento.
Liferay è già in grado di produrre questo file XML, attraverso la URL /sitemap.xml
di uno qualsiasi dei siti configurati sul portale; questa URL non è altro che il mapping di una servlet (la classeSitemapServlet
) che, al suo interno, invoca la action Struts SitemapAction
.
Purtroppo però gli unici dati esposti nel file XML sono le pagine ed i web content e non c'è un modo per aggiungere ulteriori dati.
Vdiamo quindi come fare per integrare i dati di una portlet custom all'interno del file sitemap.xml
di Liferay; in pratica quello che vogliamo fare è aggiungere delle URL custom nella mappa del sito.
Come detto, non c'è un modo elegante per estendere la mappa del sito; pertanto dovremo andare a sostituire la classe di portale SitemapAction
con una nostra classe, attraverso il seguente hook:
<hook>
<struts-action>
<struts-action-path>/layouts_admin/sitemap</struts-action-path>
<struts-action-impl>it.dvel.sitemap.action.SitemapAction</struts-action-impl>
</struts-action>
</hook>
A questo punto andiamo a definire la nostra classe nel modo seguente:
public class SitemapAction implements StrutsAction {
@Override
public String execute(
HttpServletRequest request, HttpServletResponse response)
throws Exception {
// Qui va copia/incollato il codice sorgente
// della classse SitemapAction di portale...
[...]
String sitemap = SitemapUtil.getSitemap(
layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
themeDisplay);
// Qui va aggiunto il proprio codice custom
ServletResponseUtil.sendFile(
request, response, null, sitemap.getBytes(StringPool.UTF8),
ContentTypes.TEXT_XML_UTF8);
}
@Override
public String execute(
StrutsAction originalStrutsAction, HttpServletRequest request,
HttpServletResponse response) throws Exception {
return execute(request, response);
}
}
In pratica la classe SitemapAction
esegue una serie di controlli ed alla fine richiama il metodoSitemapUtil.getSitemap()
per generare la mappa; viene restituita una stringa (che rappresenta il blocco XML del file) ed indirizzata poi al browser mediante il metodo ServletResponseUtil.sendFile()
.
Tra le 2 chiamate è necessario inserire il proprio codice custom che, ahimè, dovrà ricostruire il documento XML a partire dalla stringa e successivamente aggiungere le URL custom:
// Recupero del documento XML e del suo elemento radice
Document document = SAXReaderUtil.read(sitemap);
document.setXMLEncoding(StringPool.UTF8);
Element rootElement = document.getRootElement();
// Questo blocco di codice va ripetuto per ogni URL da inserire nella sitemap
Element urlElement = rootElement.addElement("url");
Element locElement = urlElement.addElement("loc");
locElement.addText(url_custom);
Element changefreqElement = urlElement.addElement("changefreq");
changefreqElement.addText(PropsUtil.get(PropsKeys.SITES_SITEMAP_DEFAULT_CHANGE_FREQUENCY));
Element modifiedDateElement = urlElement.addElement("lastmod");
DateFormat iso8601DateFormat = DateUtil.getISO8601Format();
modifiedDateElement.addText(iso8601DateFormat.format(data_ultima_modifica));
// Se fosse necessario gestire URLin lingua, bisogna aggiungere tutte
// le possibili "traduzioni" come alternative
for (Locale availableLocale : availableLocales) {
Element alternateURLElement =
urlElement.addElement("xhtml:link", "http://www.w3.org/1999/xhtml");
alternateURLElement.addAttribute("href", url_alternativa_in_lingua);
alternateURLElement.addAttribute(
"hreflang", LocaleUtil.toW3cLanguageId(availableLocale));
alternateURLElement.addAttribute("rel", "alternate");
}
Element alternateURLElement =
urlElement.addElement("xhtml:link", "http://www.w3.org/1999/xhtml");
alternateURLElement.addAttribute("rel", "alternate");
alternateURLElement.addAttribute("hreflang", "x-default");
alternateURLElement.addAttribute("href", url_custom);
// Fine blocco da ripetere
// Aggiornamento della sitemap da inviare al browser
sitemap = document.asXML();
Buona mappatura!
E non dimenticate che, facendo copia/incolla, qualche elemento del codice andrà sistemato per farlo compilare; ma ve lo lascio come divertimento.