Une implémentation Java de la technologie Bigpipe de Facebook.
Jpipe est implémenté via des balises personnalisées, il n'a donc aucune intrusion dans le code backend.
HTML est une fonction qui complète la page de premier plan, tandis que les balises personnalisées peuvent effectuer certaines opérations en arrière-plan.
Principalement applicable à:
| taper | Nombre de demandes | Pression côté serveur | Expérience utilisateur | Vitesse de chargement de la page Web | Ordre de chargement du module | Difficulté à réaliser | Difficulté de post-maintenance |
|---|---|---|---|---|---|---|---|
| ordinaire | 1 | Petit | Différence | lent | Ordre de flux de documents | Simple | en général |
| Ajax | beaucoup | grand | bien | rapide | incertain | difficulté | difficulté |
| Bigpipe unique | 1 | Petit | bien | lent | Personnaliser | en général | en général |
| Bigpipe multithread | 1 | Général (causé par la piscine de fil) | bien | Le plus rapide | incertain | Le plus difficile | en général |
| propriété | taper | Est-ce nécessaire | Valeur par défaut | illustrer | décrire |
|---|---|---|---|---|---|
| de base | int | Non | -1 | Nombre de threads de base | Nombre minimum de threads inactifs, nombre minimum de threads qui survivront de toute façon |
| taille maximale | int | Non | 1024 | Nombre maximum de threads | Jpipe peut créer le nombre maximum de threads utilisés pour traiter les pagelets |
| file d'attente | int | Non | 1024 | Compte de co-colonne d'attente maximale | Demander la concurrence est supérieure à la taille maximale, et il sera mis dans la file d'attente et attendre. |
| Gardien | long | Non | 60000 | Temps inactive maximum (MS) | Si le nombre de threads dépasse la taille des noyaux, il sera recyclé jusqu'à ce que le nombre de threads équivaut à la taille de base. |
| pré-démarrer | booléen | Non | FAUX | Pool de fil de préchauffage | S'il faut pré-démarrer les fils de taille de base |
| propriété | taper | Est-ce nécessaire | Valeur par défaut | illustrer | décrire |
|---|---|---|---|---|---|
| asynchrone | booléen | Non | vrai | S'il faut exécuter des tâches de paglet de manière asynchrone |
| propriété | taper | Est-ce nécessaire | Valeur par défaut | illustrer | décrire |
|---|---|---|---|---|---|
| dominant | chaîne | Oui | ID de document HTML | ||
| haricot | chaîne | Oui | nom de haricot de printemps | ||
| var | chaîne | Oui | paramètres variables | ||
| Uri | chaîne | Non | paramètres URI | ||
| jsmethod | chaîne | Non | Jp.view | Fonction JS qui enveloppe les données |
JpipeThreadPoolFactoryBean class <? xml version = " 1.0 " encoding = " UTF-8 " ?>
< beans xmlns = " http://www.springframework.org/schema/beans "
xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance "
xsi : schemaLocation = " http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd " >
< bean class = " top.ylonline.jpipe.spring.JpipeSpringFactoryBean " />
< bean id = " pool-1 " class = " top.ylonline.jpipe.threadpool.common.Pool " >
< property name = " coreSize " value = " -1 " />
< property name = " maxSize " value = " 20 " />
< property name = " preStartAllCoreThreads " value = " false " />
< property name = " keepAlive " value = " 12000000 " />
< property name = " queueSize " value = " 500 " />
</ bean >
<!-- 工场模式 -->
< bean class = " top.ylonline.jpipe.threadpool.util.JpipeThreadPoolFactoryBean " >
< property name = " pool " ref = " pool-1 " />
</ bean >
<!-- 或者
<bean class="top.ylonline.jpipe.threadpool.util.JpipeThreadPoolFactoryBean">
<property name="pool">
<bean class="top.ylonline.jpipe.threadpool.common.Pool">
<property name="coreSize" value="4"/>
<property name="maxSize" value="10"/>
<property name="preStartAllCoreThreads" value="true"/>
<property name="keepAlive" value="60000"/>
<property name="queueSize" value="500"/>
</bean>
</property>
</bean>
-->
</ beans >JpipeThreadPoolBuilder classe <? xml version = " 1.0 " encoding = " UTF-8 " ?>
< beans xmlns = " http://www.springframework.org/schema/beans "
xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance "
xsi : schemaLocation = " http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd " >
< bean class = " top.ylonline.jpipe.spring.JpipeSpringFactoryBean " />
<!-- builder 模式 -->
< bean id = " jpipeThreadPoolBuilder " class = " top.ylonline.jpipe.threadpool.util.JpipeThreadPoolBuilder " >
< property name = " pool " >
< bean class = " top.ylonline.jpipe.threadpool.common.Pool " >
< property name = " coreSize " value = " 1 " />
< property name = " maxSize " value = " 1 " />
< property name = " preStartAllCoreThreads " value = " true " />
< property name = " keepAlive " value = " 1 " />
< property name = " queueSize " value = " 1 " />
</ bean >
</ property >
</ bean >
< bean id = " jpipeThreadPool-3 " factory-bean = " jpipeThreadPoolBuilder " factory-method = " build " />
</ beans > @ Bean
public JpipeSpringFactoryBean jpipeSpringFactoryBean (){
return new JpipeSpringFactoryBean ();
}
@ Bean
public JpipeThreadPoolExecutor jpipeThreadPoolExecutor () {
Pool pool = new Pool ();
pool . setCoreSize ( 10 );
pool . setMaxSize ( 1024 );
pool . setPreStartAllCoreThreads ( true );
pool . getKeepAlive ( 60000 );
pool . getQueueSize ( 512 );
// return new EagerThreadPool().getExecutor(pool);
return new JpipeThreadPoolBuilder ( pool ). build ();
}via le démarreur de la botte de printemps
< dependency >
< groupId >top.ylonline.jpipe</ groupId >
< artifactId >jpipe-spring-boot-starter</ artifactId >
< version >${version}</ version >
</ dependency > jpipe :
# enabled: true
pool :
pre-start-all-core-threads : true
core-size : -1
max-size : 20
queue-size : 10
keep-alive : 10000 Utilisez @Service de Spring pour définir un paglet pour implémenter la méthode DOEXEC de l'interface PageletBean
@ Service ( "testPagelet1" )
public class PageletServiceTest implements PageletBean {
@ Override
public Map < String , Object > doExec ( final Map < String , String > params ) {
Map < String , Object > data = new HashMap <>( params );
try {
TimeUnit . MILLISECONDS . sleep ( new Random (). nextInt ( 5000 ));
} catch ( InterruptedException e ) {
e . printStackTrace ();
}
return data ;
}
}jpipe.core.js
; ( function ( root , factory ) {
if ( typeof exports === 'object' ) {
module . exports = exports = factory ( ) ;
} else if ( typeof define === 'function' && define . amd ) {
define ( [ ] , factory ) ;
} else {
root . JP = factory ( ) ;
}
} ( this , function ( ) {
var JP = JP || ( function ( window ) {
return {
view : function ( json ) {
var id = json [ 'id' ] ;
document . getElementById ( id ) . innerHTML = json [ 'html' ] ;
}
} ;
} ( window ) ) ;
return JP ;
} ) ) ;<%@ taglib prefix="jp" uri="http://java.yl-online.top/jsp/jpipe" %></body> afin que le rendu du premier écran ne soit pas bloqué. < %@ page contentType="text/html;charset=UTF-8" trimDirectiveWhitespaces="true" % >
< %@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" % >
< %@ taglib prefix="jp" uri="http://java.yl-online.top/jsp/jpipe" % >
< c:set var =" ctx " value =" ${pageContext.request.contextPath} " />
< html lang =" en " >
< head >
< title > index </ title >
< meta http-equiv =" Content-Type " content =" text/html; charset=UTF-8 " />
< meta name =" viewport " content =" width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no " >
< script type =" text/javascript " src =" ${ctx}/resources/jpipe.core.js " > </ script >
</ head >
< body >
< h1 > index </ h1 >
< div id =" pagelet1 " > </ div >
< div id =" pagelet2 " > </ div >
< jp:pipe >
< jp:pagelet domid =" pagelet1 " bean =" testPagelet1 " var =" item " uri =" id=123&name=forever杨" >
< h1 > jspbody support </ h1 >
< p > ${item.id} </ p >
</ jp:pagelet >
< jp:pagelet domid =" pagelet2 " bean =" testPagelet2 " var =" item2 " uri =" id=456&name=forever杨2 " >
< h1 > jspbody support </ h1 >
< p > ${item2.name} </ p >
</ jp:pagelet >
</ jp:pipe >
</ body >
</ html >Non: Déployer dans des conteneurs tels que Tomcat et Je jetée
@ Configuration
public class MvcWevConfig {
@ Resource
private freemarker . template . Configuration configuration ;
@ PostConstruct
public void setConfiguration () {
Version version = freemarker . template . Configuration . getVersion ();
DefaultObjectWrapper wrapper = new DefaultObjectWrapperBuilder ( version ). build ();
this . configuration . setSharedVariable ( "jp" , new FmHashModel ( wrapper ));
}
} < #-- < #assign pipe="top.ylonline.jpipe.freemarker.tag.PipeTag"?new() /> -- >
< #-- < #assign pagelet="top.ylonline.jpipe.freemarker.tag.PageletTag"?new() /> -- >
< html lang =" en " >
< head >
< title > index </ title >
< meta http-equiv =" Content-Type " content =" text/html; charset=UTF-8 " />
< meta name =" viewport " content =" width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no " >
< script type =" text/javascript " src =" jpipe.core.js " > </ script >
</ head >
< body >
< h1 > index </ h1 >
< div id =" pagelet1 " > </ div >
< div id =" pagelet2 " > </ div >
< @jp.pipe >
< @jp.pagelet domid="pagelet1" bean="testPagelet1" var="item" uri="id=123&name=forever杨" >
< h1 > testPagelet1 jspbody support </ h1 >
< p > ${item.id} </ p >
</ @jp.pagelet >
< @jp.pagelet domid="pagelet2" bean="testPagelet2" var="item2" uri="id=456&name=forever杨2" >
< h1 > testPagelet2 jspbody support </ h1 >
< p > ${item2.name} </ p >
</ @jp.pagelet >
</ @jp.pipe >
</ body >
</ html > < #assign pipe="top.ylonline.jpipe.freemarker.tag.PipeTag"?new() />
< #assign pagelet="top.ylonline.jpipe.freemarker.tag.PageletTag"?new() />
< html lang =" en " >
< head >
< title > index </ title >
< meta http-equiv =" Content-Type " content =" text/html; charset=UTF-8 " />
< meta name =" viewport " content =" width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no " >
< script type =" text/javascript " src =" jpipe.core.js " > </ script >
</ head >
< body >
< h1 > index </ h1 >
< div id =" pagelet1 " > </ div >
< div id =" pagelet2 " > </ div >
< @jp.pipe >
< @jp.pagelet domid="pagelet1" bean="testPagelet1" var="item" uri="id=123&name=forever杨" >
< h1 > testPagelet1 jspbody support </ h1 >
< p > ${item.id} </ p >
</ @jp.pagelet >
< @jp.pagelet domid="pagelet2" bean="testPagelet2" var="item2" uri="id=456&name=forever杨2" >
< h1 > testPagelet2 jspbody support </ h1 >
< p > ${item2.name} </ p >
</ @jp.pagelet >
</ @jp.pipe >
</ body >
</ html >FTL prend en charge l'utilisation des balises JSP. Si votre projet n'utilise pas de modèles JSP, cela n'est pas recommandé. Étant donné que les balises JSP personnalisées sont écrites et exploitées dans l'environnement JSP, les conteneurs de servlet qui prennent en charge JSP 1.1 ou JSP 1.2 doivent être introduits (des déploiements de conteneurs de servlet tels que Tomcat et Jetty), et FTL peuvent être utilisés dans des environnements non servants et d'autres environnements Web.
Une explication plus précise est: bien que le conteneur servlet n'ait pas de support JSP local, vous pouvez également utiliser la bibliothèque de balises JSP dans Freemarker. Assurez-vous simplement que le package javax.servlet.jsp. * Pour JSP version 1.2 (ou plus récent) est disponible dans l'application Web. Si votre conteneur de servlet ne prend en charge que JSP 1.1, vous devez copier les six classes suivantes (telles que vous pouvez extraire du package JAR de Tomcat 5.x ou Tomcat 4.x) au Web-inf / Classes / ... Répertoire de l'application Web: Javax.Servlet.jsp.tagext.iterationtag, javax.servlet.jsp.tagext.TAGEXT. javax.servlet.servletContextListener, javax.servlet.servletContextAttutTributleListener, javax.servlet.http.httpSessionAttributeListener, javax.servlet.http.httpSessionListener. Cependant, sachez que parce que le conteneur ne prend en charge que JSP 1.1, en utilisant généralement des versions antérieures avant Servlet 2.3, les écouteurs d'événements peuvent ne pas être pris en charge, de sorte que la bibliothèque de balises JSP 1.2 pour enregistrer les écouteurs d'événements fonctionnera normalement.
Au moment de la presse: JSP a été publié à la version 2.3
Utilisez <#assign jp=JspTaglibs["http://java.yl-online.top/jsp/jpipe"] /> pour introduire des balises JSP personnalisées
< #assign jp=JspTaglibs["http://java.yl-online.top/jsp/jpipe"] />
< html lang =" en " >
< head >
< title > index </ title >
< meta http-equiv =" Content-Type " content =" text/html; charset=UTF-8 " />
< meta name =" viewport " content =" width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no " >
< script type =" text/javascript " src =" jpipe.core.js " > </ script >
</ head >
< body >
< h1 > index </ h1 >
< div id =" pagelet1 " > </ div >
< div id =" pagelet2 " > </ div >
< @jp.pipe >
< @jp.pagelet domid="pagelet1" bean="testPagelet1" var="item" uri="id=123&name=forever杨" >
< h1 > testPagelet1 support </ h1 >
< p > ${item.id} </ p >
</ @jp.pagelet >
< @jp.pagelet domid="pagelet2" bean="testPagelet2" var="item2" uri="id=456&name=forever杨2" >
< h1 > testPagelet2 support </ h1 >
< p > ${item2.name} </ p >
</ @jp.pagelet >
</ @jp.pipe >
</ body >
</ html > Dépendance Maven
<!-- undertow 部署 -->
< dependency >
< groupId >org.springframework.boot</ groupId >
< artifactId >spring-boot-starter-undertow</ artifactId >
</ dependency >
<!-- undertow 部署 -->
< dependency >
< groupId >javax.servlet.jsp</ groupId >
< artifactId >javax.servlet.jsp-api</ artifactId >
< version >2.3.3</ version >
</ dependency >Étant donné que les conteneurs tels que Undertow n'ont pas d'environnement JSP-API, ils doivent s'appuyer sur le package javax.servlet.jsp-API, et en même temps, ils doivent configurer les ClassPathTlds de Freemarker via TaglibFactory. Sans cette configuration, une erreur sera signalée: freemarker.ext.jsp.taglibfactory $ taglibgettingException: aucun tld n'a été trouvé pour le "http://java.yl-online.top/jsp/jpipe" jsp taglib uri. (TLD-S sont recherchés en fonction de la spécification JSP 2.2. Dans les paramètres de développement et de service de service embarqué, vous pouvez également avoir besoin des "metainftldsources" et "classpathtlds" freemarker.ext.servlet.freMarkerServlet init-Params ou les propriétés du système similaires.).
Configuration
@ Configuration
public class MvcWevConfig {
@ Resource
private FreeMarkerConfigurer freeMarkerConfigurer ;
@ PostConstruct
public void loadClassPathTlds () {
List < String > classpathTlds = new ArrayList <>();
classpathTlds . add ( "/META-INF/Jpipe.tld" );
freeMarkerConfigurer . getTaglibFactory (). setClasspathTlds ( classpathTlds );
}
}Dépendance Maven
<!-- 外部 Tomcat 部署 -->
< dependency >
< groupId >javax.servlet</ groupId >
< artifactId >javax.servlet-api</ artifactId >
< scope >provided</ scope >
</ dependency >
< dependency >
< groupId >org.springframework.boot</ groupId >
< artifactId >spring-boot-starter-tomcat</ artifactId >
< scope >provided</ scope >
</ dependency >
< dependency >
< groupId >org.apache.tomcat.embed</ groupId >
< artifactId >tomcat-embed-jasper</ artifactId >
< scope >provided</ scope >
</ dependency >
<!-- 外部 Tomcat 部署 -->Puisqu'il y a déjà un environnement JSP-API à Tomcat et à Jetty, il n'est plus nécessaire de compter sur le package javax.servlet.jsp-api ici