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