Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
1
VÝVOJ PODNIKOVÝCH APLIKACÍ NA PLATFORMĚ JAVA - CVIČENÍ
Zbyněk Šlajchrt Část 9.
2
Program Diskuse nad domácím úkolem Aplikace Fotoalbum Verzování entit
Využití inteceptoru pro synchronizaci keše Využití REST služby pro ruční čištění keše
3
Úklid keše na základě verze
Umožňuje úklid pouze obstarožních ikon Zavedeme verzi do entity Photo Nový atribut private int version; getter JPA automaticky začne po každé modifikaci entity zvyšovat hodnotu v tomto poli Používáno také pro optimistické zamykání Pozn.: Pravděpodobně bude nutné odstranit tabulku PHOTO: DROP TABLE PHOTO
4
Úprava metody cleanCache
Porovnává aktuální verze fotek s verzemi ikon v keši Načte z DB entity všech fotek, které jsou v keši Obrázek se nenačítá, jelikož má fetch=LAZY V dotazu se využívá operátoru IN Zařídí výběr specifikovaných fotek. Ikony, jejichž verze je nižší než aktuální verze, jsou odstraněny z keše Ujistěte se, že PhotoCache je public void cleanCache() { @Schedule(second = "*/10", minute = "*", hour = "*", persistent = false) // Pokud je keš prázdná, není co uklízet if (cache.isEmpty()) { return; } Set<Integer> photoIds = getCachedPhotoIds(); // Vybereme všechny fotky, které jsou v keši. Operátor IN // zařídí výběr specifikovaných fotek. Query query = entityManager.createQuery("select p.name, p.version from Photo p where p.id in :photoIds"); query.setParameter("photoIds", photoIds); // Výsledek je seznam dvojic (name, version) List<Object[]> nameVersionPairs = query.getResultList(); // V cyklu porovnáme aktuální verzi fotky s verzí ikony for (Object[] nameVersionPair : nameVersionPairs) { String photoName = (String) nameVersionPair[0]; int versionInDb = (Integer) nameVersionPair[1]; Photo icon = cache.get(photoName); // Porovnání verzí if (versionInDb > icon.getVersion()) { cache.remove(photoName); logger.info("Icon " + photoName + " removed from the cache"); private Set<Integer> getCachedPhotoIds() { Set<Integer> photoIds = new HashSet<Integer>(); for (Photo photo : cache.values()) { photoIds.add(photo.getId()); return photoIds;
5
Využití interceptoru K synchronizaci keše lze také využít interceptor
Interceptor se nasadí na všechny metody, které modifikují entitu Photo nebo mění jejich počet Výhoda: Odstínění služeb od problematiky kešování Metody na AlbumDAOBean addPhoto(Photo photo) updatePhoto(Photo photo) removePhotos(int[] selectedIds) Metoda PhotoGateway save()
6
CacheSynchronizer V modulu ejb vytvořte třídu interceptoru CacheSynchronizer Interceptor se řídí následující konvencí ohledně hlaviček metod: add* – vytváří novou fotografii, která je v prvním parametru update* – aktualizuje fotografii, která je v prvním parametru remove* – odstraňuje fotografie, jejichž PK jsou v poli int[] předávaném jako první parametr bez parametrů – např. save(), musí se zavolat metoda na beanu, která vrátí ukládanou entitu package cz.vse.javaee.album; import javax.ejb.EJB; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; import java.lang.reflect.Method; /** * Tento interceptor je zavěšen na všech servisních metodách, které * mění stav a počet entit Photo. * <p/> * Created by IntelliJ IDEA. * User: zslajchrt * Date: Apr 13, 2010 * Time: 1:47:39 PM */ public class CacheSynchronizer { @EJB private PhotoCache cache; @AroundInvoke public Object onUpdatePhoto(InvocationContext ic) throws Exception { Object result = ic.proceed(); String methodName = ic.getMethod().getName(); if (methodName.startsWith("add") || ic.getMethod().getName().startsWith("update")) { // U 'add' a 'update' očekává první argument entitu syncWithCache((Photo) ic.getParameters()[0]); } else if (methodName.startsWith("remove")) { // U 'remove' očekává první argument int[] s id entit syncWithCache((Integer[]) ic.getParameters()[0]); } else if (ic.getParameters() == null) { Method getter = ic.getTarget().getClass().getMethod("getCurrent"); Photo photo = (Photo) getter.invoke(ic.getTarget()); syncWithCache(photo); } return result; private void syncWithCache(Photo photo) { System.out.println("Removing " + photo.getName() + " from cache"); cache.cleanCache(); private void syncWithCache(Integer[] photoIds) { System.out.println("Removing " + photoIds.length + " photos from cache");
7
Konfigurace interceptoru na metodách
Na všechny "create/update/delete" metody, které pracují s Photo, umístěte anotaci @Interceptors(CacheSynchronizer.class)
8
Poznámky JBoss může mít problémy s používáním sekvence pro generování ID fotek. Pomůže explicitně určit sekvenci pomocí mapovacích anotací a sekvenci ručně vytvořit v databázi: @SequenceGenerator(name = "PHOTOSEQ", sequenceName = "PHOTOSEQUENCE") použít na třídě Photo @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PHOTOSEQ") použít na getPhoto() CREATE SEQUENCE PHOTOSEQUENCE AS BIGINT START WITH
9
REST Architektonický styl distribuovaných systémů
REpresentational State Transfer Přenos reprezentace zdroje na klienta Dotazem na zdroj identifikovaný URL nahraje klient reprezentační stav zdroje. Tento stav může obsahovat URL odkazy na další zdroje Dotazem na jiné URL přechází klient do dalšího stavu, který odpovídá reprezentaci odkazovaného zdroje. Dodatečná (post-hoc) interpretace HTTP metod GET, POST, PUT, DELETE
10
Příklady REST http://myapp/shop/products
Zdrojem je zde seznam výrobků Reprezentací může být HTML, XML nebo JSON Zdrojem je zde konkrétní výrobek
11
Omezení na REST architekturu
Client-server Stateless – server neudržuje stav klienta Cacheable – klient může kešovat stav Layered – klient neví o přítomnosti mezivrstev Možnost přesunu části kódu serveru na klienta (JavaScript) Jednotné rozhraní pro komunikaci URI ke stavu jsou připojena metadata, např. MIME stav může obsahovat linky na asociované zdroje
12
Ovládání keše pomocí REST
URL zdroje – keše Metoda GET na tomto zdroji vyčistí keš V modulu web vytvoříme třídu CacheResource @Path("cache") – URL fragment pro tento zdroj @Stateless – chování odpovídá bezstavovému EJB @Produces("text/plain") – MIME reprezentace zdroje PhotoCache photoCache Metoda cleanCache deleguje na PhotoCache @GET – specifikuje, že GET bude směrována sem @Path("cache") @Stateless @Produces("text/plain") public class CacheResource { @EJB private PhotoCache photoCache; @GET public String cleanCache() { photoCache.cleanCache(); return "OK"; }
13
Úprava WEB-INF/web.xml
<servlet> <servlet-name>JerseyWebApplication</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>cz.vse.javaee.album</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <url-pattern>/rs/*</url-pattern> </servlet-mapping>
14
Domácí úkol
15
Dodatek: Aplikační vrstva
16
Dodatek: Prezentační vrstva
17
Dodatek: Diagram stránek
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.