Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

UrlRewriteFilter: emulare mod_rewrite in Java

UrlRewriteFilter: emulare mod_rewrite in Java
UrlRewriteFilter: emulare mod_rewrite in Java
Link copiato negli appunti

UrlRewriteFilter è una libreria nata con l'intento di emulare le funzionalità del modulo mod_rewrite di Apache: è stata utilizzata in molte applicazioni ed integrata anche in framework più complessi, ad esempio Appfuse e Spring.

Ecco alcune delle sue caratteristiche più evidenti:

  • ridotto consumo di risorse: l'archivio jar pesa poco meno di 200k, e non ha dipendenze verso altre librerie di terze parti;
  • focalizzazione su poche funzionalità;
  • documentazione piuttosto completa e semplice da comprendere.

Il principale punto a suo favore è chiaramente che moltissimi sviluppatori web hanno conoscenze pregresse dell'utilissimo mod_rewrite

Vediamo come utilizzare questa libreria per i nostri progetti.

Installazione

L'installazione di UrlRewriteFilter è molto semplice:

  • si scarica la libreria dal sito ufficiale. Alla data di stesura di questo articolo (Luglio 2011) l'ultima versione disponibile è la 3.2.0;
  • si copia la libreria nella directory /WEB-INF/lib
  • si crea il file di configurazione /WEB-INF/urlrewrite.xml

Ecco il codice sorgente di urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
        "http://tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
</urlrewrite>

Nei prossimi paragrafi esploreremo alcune regole icolarmente utili per il rewrite definibili all'interno di urlrewrite.xml.

Clean URLs

Le clean URLs sono uno stratagemma molto utilizzato nelle web application, soprattutto nei CMS (Content Management Systems), per via della facile fruibilità per gli utenti umani e per i crawler dei motori dei ricerca.

Di fatto si tratta di creare una versione "amichevole" di URL altrimenti anonime, eccone un esempio:

  • abbiamo un articolo dal titolo "Tutorial: impariamo a programmare in Java"
  • sul database l'ID dell'articolo è 42;
  • l'articolo è stato scritto in data 30/07/2011;
  • attualmente per accedere all'articolo è sufficiente utilizzare la URL:
    http://www.example.com/show_article.jsp?article_id=42
    

Per il momento non ci interessa l'implementazione reale della pagina show_article.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
  <title>show_article.jsp</title>
</head>
<body>
  Mostra articolo con ID = <%=request.getParameter("article_id")%>
</body>
</html>

Utilizzare una URL del genere ha diversi problemi, primo fra tutti il fatto che il percorso per arrivare ai contenuti è completamente anonimo, trattandosi di un semplice numero.

Avere una URL più leggibile porta diversi vantaggi:

  • comprensibilità
  • statistiche
  • indicizzazione

Ecco gli accorgimenti più utilizzati per rendere le URL più facili da comprendere:

  • inserimento del titolo
    tutorial-impariamo-a-programmare-in-java.html
  • inserimento della data di pubblicazione
    /2011/07/tutorial-impariamo-a-programmare-in-java.html

Questi elementi della URL vengono chiamati in gergo "slug", la cui traduzione italiana è "lumacone" (!); in effetti il loro compito è allungare le URL, per guidare l'utente verso i contenuti facendogli seguire una "traccia" facilmente visibile...

Un miglioramento ulteriore può essere costituito dall'eliminazione dei parametri (o almeno dalla loro riduzione): in questo modo i contenuti apparirebbero agli utenti e ai motori di ricerca come un insieme strutturato e ordinato, facilitandone la fruizione e la ricerca.

Vediamo quindi alcuni esempi, di complessità crescente:

Decisamente meglio, non trovate? Possiamo inserire le regole necessarie nel file di configurazione /WEB-INF/urlrewrite.xml <urlrewrite>

<rule>
  <from>^/article/(d+).html</from>
  <to>/show_article.jsp?article_id=$1</to>
</rule>
<rule>
  <from>^/article/(d+)/.*.html</from>
  <to>/show_article.jsp?article_id=$1</to>
</rule>
<rule>
  <from>^/(d+)/(d+)/article/(d+)/.*.html</from>
  <to>/show_article.jsp?article_id=$3</to>
</rule>

Ecco qualche dettaglio sul funzionamento:

  • ogni regola è contenuta in un elemento <rule>
  • l'elemento <from> regular expression
  • l'elemento <to> "$1" back reference <from>
  • il metodo di redirezione di default (per i cui dettagli rimandiamo alla documentazione ufficiale di UrlRewriteFilter) è un FORWARD, quindi il client non si accorge di questa "traduzione".
  • Un mapping migliore per le servlet

    Il servlet mapping serve per indicare al container quando richiamare una certa servlet; il meccanismo standard, che viene configurato dall'elemento <servlet-mapping> nel file web.xml, è sempre stato piuttosto carente, ed una delle principali lamentele (rimasta purtroppo inascoltata anche nella versione 3.0 delle specifiche) è il fatto che sia impossibile eseguire dei mapping complessi in web.xml; le possibilità infatti sono molto limitate:

    • se inizia con uno slash
      • /miopath1/* /miopath1/
      • /miopath2 esattamente /miopath2
    • se inizia con un asterisco, è utilizzato per mappare delle estensioni di file: .html .do .pincopallino

    Chiaramente una delle possibili migliorie sarebbe poter utilizzare le regular expression, ed è qui che UrlRewriteFilter ci vene in aiuto; possiamo infatti delegare l'esecuzione di una chiamata HTTP ad un metodo di una classe, che non deve essere per forza una servlet ma basta che il metodo in questione sia pubblico e che abbia i parametri HttpServletRequest e HttpServletResponse:

    Nell'esempio che segue vogliamo intercettare tutte le chiamate a pagine con estensione *.html in un qualsiasi sotto-path di /app/, e di far gestire la richiesta alla classe it.html.examples.MiaServlet. Ecco la regola da inserire in urlrewrite.xml:

    <rule>
      <from>/app/.*.html</from>
      <run class="it.html.examples.MiaServlet" method="mioMetodo" />
    </rule>

    mentre questo è il codice della "servlet" (come viene impropriamente definita sulla documentazione):

    package it.html.examples;
    import java.io.IOException;
    
    import javax.servlet.http.*;
    public class MiaServlet {
        public void mioMetodo(HttpServletRequest req, HttpServletResponse resp) throws IOException {
            resp.getWriter().println("MiaServlet.mioMetodo() invocato!");
        }
    }

    Ecco alcune URL che vengono correttamente intercettate:

Ti consigliamo anche