Una implementación de Java de la tecnología BigPipe de Facebook.
JPIPE se implementa a través de etiquetas personalizadas, por lo que tiene cero intrusión en el código de backend.
HTML es una función que completa la página de primer plano, mientras que las etiquetas personalizadas pueden completar ciertas operaciones en segundo plano.
Principalmente aplicable a:
| tipo | Número de solicitudes | Presión del lado del servidor | Experiencia de usuario | Velocidad de carga de la página web | Orden de carga del módulo | Dificultad para lograr | Dificultad en el mantenimiento |
|---|---|---|---|---|---|---|---|
| común | 1 | Pequeño | Diferencia | lento | Orden de flujo de documentos | Simple | generalmente |
| Ajax | muchos | grande | bien | rápido | incierto | dificultad | dificultad |
| Bigpipe de un solo hilo | 1 | Pequeño | bien | lento | Personalizar | generalmente | generalmente |
| Bigpipe multiproceso | 1 | General (causado por el grupo de hilos) | bien | Lo más rápido | incierto | El mas difícil | generalmente |
| propiedad | tipo | ¿Es requerido? | Valor predeterminado | ilustrar | describir |
|---|---|---|---|---|---|
| tamaño de un núcleo | intencionalmente | No | -1 | Número de hilos centrales | Número mínimo de hilos inactivos, número mínimo de hilos que sobrevivirán de todos modos |
| de tamaño máximo | intencionalmente | No | 1024 | Número máximo de hilos | JPipe puede crear el número máximo de hilos utilizados para procesar pagelets |
| cola | intencionalmente | No | 1024 | Recuento máximo de co-columna de espera | La concurrencia de solicitud es mayor que el tamaño máximo, y se colocará en la cola y esperará. |
| Mantener alivado | largo | No | 60000 | Tiempo de inactividad máximo (MS) | Si el número de subprocesos excede el tamaño del núcleo, se reciclará hasta que el número de hilos sea igual al tamaño del núcleo. |
| Presiones previas al núcleo-core | booleano | No | FALSO | Piscina de hilo de precalentamiento | Si pre-practicar hilos de tamaño de núcleo |
| propiedad | tipo | ¿Es requerido? | Valor predeterminado | ilustrar | describir |
|---|---|---|---|---|---|
| asíncrata | booleano | No | verdadero | Si ejecutar tareas de Pagelet de forma asincrónica |
| propiedad | tipo | ¿Es requerido? | Valor predeterminado | ilustrar | describir |
|---|---|---|---|---|---|
| doméstico | cadena | Sí | ID de documento HTML | ||
| frijol | cadena | Sí | Nombre del frijol de primavera | ||
| varilla | cadena | Sí | Parámetros variables | ||
| Uri | cadena | No | Parámetros de URI | ||
| jsmethod | cadena | No | Jp.view | función js que envuelve datos |
JpipeThreadPoolFactoryBean Clase <? 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 <? 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 ();
}Vía Spring-Boot Starter
< 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 Use @Service de Spring para definir un Pagelet para implementar el método doexec de la interfaz 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> para que la representación de la primera pantalla DOM no se bloquee. < %@ 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 >No: desplegar en contenedores como Tomcat y Jetty
@ 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 admite el uso de etiquetas JSP. Si su proyecto no usa plantillas JSP, esto no se recomienda. Debido a que las etiquetas JSP personalizadas se escriben y operan en el entorno JSP, los contenedores de servlet que admiten JSP 1.1 o JSP 1.2 deben introducirse (implementaciones de contenedores de servlet como Tomcat y Jetty), y FTL se puede utilizar en entornos no servicio y otros entornos web.
Una explicación más precisa es: aunque el contenedor Servlet no tiene soporte JSP local, también puede usar la biblioteca de etiquetas JSP en Freemarker. Solo asegúrese de que el paquete javax.servlet.jsp.* Para JSP versión 1.2 (o más nuevo) esté disponible en la aplicación web. Si su contenedor de servlet solo admite JSP 1.1, entonces debe copiar las siguientes seis clases (como puede extraer del paquete jar de Tomcat 5.x o Tomcat 4.x) a la webinf/classes/... directorio de la aplicación web: javax.servlet.jsp.tagext.iterationtag, javax.servlet.jsp.tagext.trycatchfinally, javax.servlet.servletContextListener, javax.servlet.servletcontextattributeListener, javax.servlet.http.httpsessionAttributeListener, javax.servlet.http.httpsessionListener. Sin embargo, tenga en cuenta que debido a que el contenedor solo admite JSP 1.1, generalmente usando versiones anteriores antes de Servlet 2.3, los oyentes de eventos no pueden ser compatibles, por lo que la biblioteca de etiquetas JSP 1.2 para registrar los oyentes de eventos funcionará normalmente.
A partir de la hora de prensa: JSP ha sido lanzado a la versión 2.3
Use <#assign jp=JspTaglibs["http://java.yl-online.top/jsp/jpipe"] /> para introducir etiquetas JSP personalizadas
< #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 > dependencia de 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 >Dado que los contenedores como Untow no tienen un entorno JSP-API, deben confiar en el paquete javax.servlet.jsp-api, y al mismo tiempo, deben configurar los classpathtlds de freemarker a través de taglibFactory. Sin esta configuración, se informará un error: freemarker.ext.jsp.taglibfactory $ tagLibGettingException: no se encontró TLD para el "http://java.yl-online.top/jsp/jpipe" jsp taglib uri. (TLD-S se buscan de acuerdo con la especificación JSP 2.2. En Configuración de desarrollo de desarrollo de desarrollo e integrado, también puede necesitar los "metainftldsources" y "classpathtlds" freemarker.ext.servlet.freemarkerservlet init-params o las propiedades del sistema similares).
Configuración
@ 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 );
}
}dependencia de 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 部署 -->Dado que ya hay un entorno JSP-API en Tomcat y Jetty, ya no hay necesidad de confiar en el paquete javax.servlet.jsp-api aquí