Struts2 Convention plugin : e' quasi magia
Oggi mi era una giornata fiacca. Mi sono detto : " Guardiamo un po' di cose che mi ero lasciato da fare" e l'occhio mi e' cascato su Struts2. Intendiamoci, non che non abbia mai visto come funziona questo framwork ( chiunque lavori con Java in ambito Web prima o poi ha a che fare con Struts ), semplicemente non ero mai andato + che tanto a fondo nella versione 2 di Struts.
Ho cominciato a guardare un po' di documentazione ( l'indice ) e l'occhio mi e' caduto su Convention plugin ... e ne sono entusiasta !
Ecco un piccolo diario delle mie prove ...
Per prima cosa, mi sono creato un progetto web dinamico con Eclipse. Poi ho preso tutte le librerie dall'applicazione di esempio "struts2-rest-showcase" ... tanto per non sbagliare o avere dipendenze non risolte ( prima o poi dovro' passare a Maven, ma che ci volete fare ... sono affezionato ad Ant ! ) . Ho quindi velocemente letto la prima parte della pagina linkata prima ( Convention plugin ) e poi ho cominciato a smanettare un po' con i files delle risorse e ... senza una riga di configurazione ( apparte il caricamento del filtro per struts ) mi sono ritrovato per le mani una pagina jsp che ha associato un bean e un file di risorse che risponde in maniera dinamica !!!
Ecco il gioco spiegato in due parole : Per default Convention cerca le pagine in WEB-INF/content, quindi se create una pagina pippo.jsp qui' dentro viene automaticamente creata una azione pippo che risponde sulla root della vostra applicazione ; inoltre, il plugin cerca tutto quello che implementa com.opensymphony.xwork2.Action e lo trasforma in una azione ... o quasi . Tutto quello che si trova all'interno di <un nome package>.action o <un nome package>.actions o <un nome package>.struts diventa un azione e viene mappato a partire dal piu' "anziano" parente. Facciamo un esempio :
com.pippo.action.PippoAction viene mappato in / com.pippo.action.pippo.Paperino ( che implementa com.opensymphony.xwork2.Action ) viene mappato in /pippo/ com.pippo.struts.pippo.paperino.QuackQuackAction viene mappato in /pippo/paperino
e viene fatto senza bisogno che scriviate una riga di configurazione o mappatura !
In piu' il nome dell'azione viene interpretato secondo il camel case e la classe rispondera' a com.pippo.action.PippoAction == /pippo com.pippo.action.pippo.Paperino == /pippo/paperino com.pippo.struts.pippo.paperino.QuackQuackAction == /pippo/paperino/quack-quack
La cosa ancora piu' intrigante e' che, sempre gratis, se create le relative pagine jsp in /WEB-INF/content queste vengono associate alla view dell'azione e automaticamente bindati ai relativi JavaBean !!! E quindi :
com.pippo.action.PippoAction == /pippo == /WEB-INF/content/pippo.jsp com.pippo.action.pippo.Paperino == /pippo/paperino == /WEB-INF/content/pippo/paperino.jsp com.pippo.struts.pippo.paperino.QuackQuackAction == /pippo/paperino/quack-quack == /WEB-INF/content/pippo/paperino/quack-quack.jsp
Ed eccoci all'esempio :
HelloAction.java
package com.fermasoft.prove.convention.action;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {
public String execute(){
return SUCCESS;
}
public String getName(){
return "Goofy";
}
public String getTime(){
SimpleDateFormat formatter = new SimpleDateFormat("HH.mm");
return formatter.format(new Date(System.currentTimeMillis()));
}
}
HelloAction.properties
greeting=Hello ${name} ! It's ${time} o' clock !
testing.param= ${name} you passed me {0}
value=I am string coming from the class resources
package.properties
package.value=I am a string coming from the package wide resources value=I am another string coming from the package wide resources
hello.jsp
<%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>hello convention !</title> </head> <body> <p>Testing the Convention plugin</p>
here's a greeting that takes parameters from a bean I didn't explicitly declare in this page :
<div style="font-style: italic;"> <s:text name="greeting"/> <br /> </div>
here's a parametrized text that comes from a resource bundle I didn't declare either ; the first part in the result of a call the the same bean as above, the second part is a parameter I directly passed from the page :
<div style="font-style: italic;"> <s:text name="testing.param"> <s:param value="'aValue'" /> </s:text> <br /> </div>
here's a text that comes from a package wide bundle :
<div style="font-style: italic;"><s:property value="getText('package.value')" /></div> <br />
here's a text that comes from a Class bundle that overrides the package bundle :
<div style="font-style: italic;"><s:property value="getText('value')" /> </div><br />
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>sanity</display-name> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>struts.devMode</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
e la struttura del progetto :
Hello
├── build
│ └── classes
│ └── com
│ └── fermasoft
│ └── prove
│ └── convention
│ └── action
│ ├── HelloAction.class
│ ├── HelloAction.properties
│ └── package.properties
├── src
│ └── com
│ └── fermasoft
│ └── prove
│ └── convention
│ └── action
│ ├── HelloAction.java
│ ├── HelloAction.properties
│ └── package.properties
└── WebContent
├── META-INF
│ └── MANIFEST.MF
└── WEB-INF
├── content
│ └── hello.jsp
├── lib
│ ├── commons-fileupload-1.2.1.jar
│ ├── commons-io-1.3.2.jar
│ ├── commons-logging-1.0.4.jar
│ ├── freemarker-2.3.16.jar
│ ├── javassist-3.7.ga.jar
│ ├── log4j-1.2.16.jar
│ ├── ognl-3.0.jar
│ ├── struts2-config-browser-plugin-2.2.1.1.jar
│ ├── struts2-convention-plugin-2.2.1.1.jar
│ ├── struts2-core-2.2.1.1.jar
│ └── xwork-core-2.2.1.1.jar
└── web.xml
e questo e' il risultato della pagina :
Testing the Convention plugin here's a greeting that takes parameters from a bean I didn't explicitly declare in this page : Hello Goofy ! Its 17.54 o clock ! here's a parametrized text that comes from a resource bundle I didn't declare either ; the first part in the result of a call the the same bean as above, the second part is a parameter I directly passed from the page : Goofy you passed me aValue here's a text that comes from a package wide bundle : I am a string coming from the package wide resources here's a text that comes from a Class bundle that overrides the package bundle : I am string coming from the class resources
Recent Comments