Post on 24-Jun-2015
description
Christian Kaltepoth | ingenit GmbH & Co. KG
Beyond PrettyFacesEinführung in Rewrite
URL-Rewriting
Wikipedia
A rewrite engine is software [...] that modifies a web URL's appearance.
This modification is called URL rewriting.
http://en.wikipedia.org/wiki/Rewrite_engine
Beispiel
http://www.onlineshop.de/b/ref=sa_menu_desk3?ie=UTF8&node=2193272340
http://www.onlineshop.de/elektronik
Sprechende RESTful URLs
http://www.javaserverfaces.org/news
http://jax.de/wjax2013/sessions
https://github.com/ocpsoft/rewrite/issues/87
http://stackoverflow.com/questions/tagged/jsf
Wozu das Ganze?
Vorteile
• Adressierbare Informationen– Wo bin ich hier?– "Vertrauen"
• Reload und Bookmarks• Einfache HTML Links
– Lose Kopplung
• Technologieneutralität
SEO
• Keywords in URL• Optimierung des Rankings
http://www.amazon.com/JavaServer-Faces-2-0-Complete-
Reference/dp/0071625097
PrettyFaces• JSF URL-Rewriting De-facto-Standard • RESTful URLs• Page Actions• Einfache Rewrite Engine• Dynamic Views• Integration mit JSF Navigation
Warum Rewrite?
API Abhängigkeiten
Servlet-spezifisch
JSF-spezifisch
Pre
ttyF
aces
Einschränkungen
• Mapping nur via Request Path• Eingeschränkte Konfiguration via XML• Annotation API „verbesserungswürdig“• Konvertierung nur eingeschränkt
möglich• Nicht besonders erweiterbar
Der Neuanfang
Was ist Rewrite?
Key Features
• Servlet basiertes Rewriting auf Basis einer Rule-Engine
• Framework Integration– JSF, CDI, Spring, Shiro, etc.
• Konfiguration: Java DSL + Annotations• Fokus auf Erweiterbarkeit• Open Source (Apache 2.0)
Begriffe
• Configuration:– Sortierte Liste
von Rules
• Rule:– Conditions– Operations– Priority
Rewriting Types
Inbound
Outbound
Inbound
GET /faces/home.xhtml HTTP/1.1Host: www.acme.comConnection: keep-alive[....]
Outbound
<a href="/faces/home.xhtml"> Getting started</a>
Java DSL
Warum?
• Typensichere Konfiguration• Code Assist durch IDE• Geführte Konfiguration• Erweiterbar• „Plain Java“
Java DSL
public class RewriteConfig extends HttpConfigurationProvider {
@Override public Configuration getConfiguration(ServletContext ctx) {
// Konfiguration „bauen“
}
@Override public int priority() { return 10; }
}
ConfigurationBuilder
return ConfigurationBuilder.begin() // Variante 1 .addRule() .when( /* condition */ ) .perform( /* operation */ ) // Variante 2 .addRule( /* rule */ )
;
Initial Redirect
http://www.acme.com/
http://www.acme.com/faces/home.xhtml
Redirect
Beispiel: Initial Redirect
.addRule()
.when( Direction.isInbound().and(Path.matches("/"))).perform( Redirect.permanent("/faces/home.xhtml"))
Der erste Rewrite
http://www.acme.com/faces/home.xhtml
http://www.acme.com/home
Der erste Rewrite
.addRule()
.when(Direction.isInbound().and( Path.matches("/home"))).perform(Forward.to("/faces/home.xhtml"))
.addRule()
.when(Direction.isOutbound().and( Path.matches("/faces/home.xhtml"))).perform(Substitute.with("/home"))
Einfacher: Joins
.addRule( Join.path("/home") .to("/faces/home.xhtml") )
Parameter
/faces/products.xhtml?category=books
/products/books
JSF 2.0 View Parameter
<f:metadata> <f:viewParam name="category" value="#{productListPage.category}" /></f:metadata>
@Named@RequestScopedpublic class ProductListPage {
private String category;
}
Join mit Parametern
.addRule( Join.path("/products/{category}") .to("/faces/products.xhtml"))
Demo
Annotations?
Einfacher Join
@Named@RequestScoped@Join(path = "/home", to = "/faces/home.xhtml")public class HomePage {
/* your code */
}
Parameter
/faces/products.xhtml?category=books
/products/books
Mit View-Parametern@Named@RequestScoped@Join(path = "/products/{category}", to = "/faces/products.xhtml")public class ProductListPage {
// <f:viewParam name=“category“ ...> private String category;
/* ... */
}
Ohne View-Parameter@Named@RequestScoped@Join(path = "/products/{category}", to = "/faces/products.xhtml")public class ProductListPage {
@Parameter private String category;
/* ... */ }
Validierung@Named@RequestScoped@Join(path = "/products/{category}", to = "/faces/products.xhtml")public class ProductListPage {
@Parameter @Matches("[a-zA-Z\\-]+") private String category;
/* ... */ }
JSF Validators@Named@RequestScoped@Join(path = "/products/{category}", to = "/faces/products.xhtml")public class ProductListPage {
@Parameter @Validate(with = CategoryValidator.class) private String category;
/* ... */ }
Request Actions
Request Actions@Named@RequestScoped@Join(path = "/home", to = "/faces/home.xhtml")public class HomePage {
@RequestAction public void init() { /* your code */ }
}
Ignore Postbacks@Named@RequestScoped@Join(path = "/home", to = "/faces/home.xhtml")public class HomePage {
@RequestAction @IgnorePostback public void init() { /* your code */ }
}
Deferral@Named@ViewScoped@Join(path = "/home", to = "/faces/home.xhtml")public class HomePage {
@RequestAction @Deferred public void init() { /* your code */ }
}
Deferral@Named@ViewScoped@Join(path = "/home", to = "/faces/home.xhtml")public class HomePage {
@RequestAction @Deferred(before = Phase.RENDER_RESPONSE) public void init() { /* your code */ }
}
Navigation
Navigation
<h:link outcome="/products.xhtml"> <f:param name="category" value="books"/> Bücher</h:link>
<a href="/products/books"> Bücher </a>
Navigation
public class SomePage {
public String actionMethod() {
/* do something */
return "/products.xhtml?category=books" + "&faces-redirect=true";
}
}
Navigation
public class SomePage {
public Navigate actionMethod() {
/* do something */
return Navigate.to(ProductListPage.class) .with("category", "books");
}
}
Was kann Rewrite noch?
Content Delivery Networks(CDN)
JSF Resources
<h:outputScript name="jquery.js" />
<script type="text/javascript" src="/faces/javax.faces.resource/jquery.js" />
<script type="text/javascript" src="http://dh8sm43.cloudfront.net/jquery.js" />
Erzeugt
Gewünscht
CDN URL Relocation
.addRule( CDN.relocate("/faces/javax.faces.resource/jquery.js") .to("http://dh8sm43.cloudfront.net/jquery.js"))
ResourceTransformation
HTTP Response
RewriteTransformation
Pipeline
Usecases
• Minification – JavaScript, CSS
• Compression – GZIP, Deflate
• Rendering – SASS, SCSS, Markdown, Textile, ...
• Custom Processing
JavaScript Minify
.addRule()
.when( Direction.isInbound().and(Path.matches( "/faces/javax.faces.resource/{*}.js"))).perform( Transform.with(Minify.js()))
Rendering
Beispiel: Sass$blue: #3bbfce;$margin: 16px;
.content-navigation { border-color: $blue; color: darken($blue, 9%);}
.border { padding: $margin / 2; margin: $margin / 2; border-color: $blue;}
.content-navigation { border-color: #3bbfce; color: #2b9eab;}
.border { padding: 8px; margin: 8px; border-color: #3bbfce;}
Beispiel: Sass
.addRule()
.when( Direction.isInbound().and( Path.matches("/styles/{*}.sass"))).perform( Response.setContentType("text/css").and( Transform.with(Sass.compiler())))
Precompile with Maven
<plugin> <groupId>org.jasig.maven</groupId> <artifactId>sass-maven-plugin</artifactId> <version>1.1.1</version> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>update-stylesheets</goal> </goals> </execution> </executions></plugin>
Transform on demand.addRule().when( Direction.isInbound() .and(Path.matches("/styles/{name}.css")) .and(Resource.exists("/styles/{name}.scss")) .and(Not.any( Resource.exists("/styles/{name}.css")))).perform( Forward.to("/styles/{name}.scss") .and(Response.setContentType("text/css")) .and(Transform.with(Sass.compiler())))
Wie migriere ich meine PrettyFaces Anwendung?
Rewrite PrettyFaces Module
<dependency> <groupId>org.ocpsoft.rewrite</groupId> <artifactId>rewrite-config-prettyfaces</artifactId> <version>2.0.8.Final</version></dependency>
• Drop-In Replacement für PrettyFaces• „Sanfte“ Migration
Thank you!
http://ocpsoft.org/rewrite/
Christian Kaltepothchristian@kaltepoth.de @chkal