W tej części stworzymy pierwszy kontroler, który zwróci prosty widok. Widok będziemy mogli wyświetlić klikając na odpowiedni link w menu systemowym (wtyczka doda odpowiedni link).
Wymagane moduły:
Deklaracja tych modułów odbywa się w deskryptorze wtyczki:
<?xml version="1.0" encoding="UTF-8"?> <plugin key="com.suncode.plugin-tutorial" name="Tutorial Plugin"> <plugin-details> <description> <localized language="en">Description</localized> <localized language="pl">Opis</localized> </description> <author>Suncode</author> </plugin-details> <!-- I18N --> <i18n key="i18n-bundle" location="locale/messages" /> <!-- Web MVC --> <web-mvc key="mvc" /> </plugin> |
Kontroler odpowiedzialny jest za przyjęcie żądania HTTP i zwrócenie widoku albo innej odpowiedzi (np. json).
Nasz kontroler będzie wyświetlał widok w odpowiedzi na żądanie /hello oraz odpowiadał obiektem json w odpowiedzi na /api/hello.
package com.suncode.plugin.tutorial; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class HelloController { @RequestMapping( value = "/hello", method = RequestMethod.GET ) public String showHelloView( Model model ) { // dodajemy do modelu atrybut "date" model.addAttribute( "date", new Date() ); // wyświetlamy widok "/views/hello.ftl" return "hello"; } @RequestMapping( value = "/api/hello", method = RequestMethod.GET, produces = "application/json" ) @ResponseBody public Map<String, Object> sayHello() { Map<String, Object> result = new HashMap<String, Object>(); result.put( "say", "hello" ); result.put( "date", new Date() ); // zwracamy mapę, która zostanie przetworzona na obiekt json return result; } } |
Widok wyświetli prosty tekst i przesłaną z kontrolera datę:
<p>Hello World</p> <p>Current date: ${date?datetime}</p> |
Widoki muszą być wykonane w technologii Freemarker. Wszystkie widoki muszą znajdować się w katalogu /views i mieć rozszerzenie .ftl (katalog i rozszerzenie są automatycznie dodawane do nazwy zwróconego widoku). |
Standardowo Eclipse nie posiada wbudowanego edytora szablonów Freemarker. Taki edytor wchodzi w skład jBoss Tools. |
Struktura projektu jest następująca:
Po zainstalowaniu/aktualizacji wtyczki możemy wypróbować działanie naszego kontrolera. W tym celu należy wysłać żądanie na odpowiedni adres URL:
Wszystkie adresy URL wtyczki poprzedzone są prefixem składającym się z /plugin/{identyfikator wtyczki}/ (np. /plugin/com.suncode.plugin-tutorial/) |
Wszystkie widoki zwracane przez wtyczkę są domyślnie dekorowane (za wyjątkiem żądań z nagłówkiem X-Requested-With: XMLHTTPREQUEST. Jeżeli nie chcemy dekorować naszej strony, musimy dodać parametr: decorator=none (np: /plugin/com.suncode.plugin-tutorial/hello?decorator=none) dzięki czemu otrzymamy czystą stronę: Wszystkie dostępne dekoratory opisane są Tworzenie widoków Freemarker - Dekoratory widoków |
/plugin/com.suncode.plugin-tutorial/api/hello
{"say":"hello","date":1399446110308} |
Wtyczki mogą serwować dowolne zasoby statyczne (skrypty, zdjęcia etc.). Zasoby takie muszą znajdować się w katalogu /resources:
Zasoby statyczne mogą być pobierane przy użyciu 2 adresów URL (różniących się polityką cache):
gdzie:
Ze względów wydajnościowych, należy zawsze dążyć do wykorzystywania URL z datą ostatniej aktualizacji, ze względu na politykę cache'owania. |
Dynamiczny link do zasobów tworzony jest poprzez dodanie do adresu URL daty ostatniej aktualizacji wtyczki. W widokach Freemarker można ułatwić sobie pobieranie gotowego linku:
Wykorzystany niżej obiekt i makro są opisane w dokumentacji tworzenia widoków Freemarker. |
<!-- Pomocnicze makro --> <#import "/plugin.ftl" as plugin/> <!-- Wykorzystując obiekt pluginContext --> <script src="${pluginContext.pluginResourcesPath}/data.js"></script> <!-- Wykorzystując pomocnicze makro --> <script src="<@plugin.resourceUrl 'data.js'/>"></script> |