Uma implementação Java da tecnologia Bigpipe do Facebook.
O JPIPE é implementado por meio de tags personalizadas, por isso não possui intrusão no código de back -end.
O HTML é uma função que completa a página de primeiro plano, enquanto as tags personalizadas podem concluir determinadas operações em segundo plano.
Principalmente aplicável a:
| tipo | Número de solicitações | Pressão do lado do servidor | Experiência do usuário | Velocidade de carregamento da página da web | Pedido de carregamento do módulo | Dificuldade de alcançar | Dificuldade na pós-manutenção |
|---|---|---|---|---|---|---|---|
| ordinário | 1 | Pequeno | Diferença | lento | Documentar o pedido de fluxo | Simples | geralmente |
| Ajax | muitos | grande | bom | rápido | incerto | dificuldade | dificuldade |
| Bigpipe Bigpipe | 1 | Pequeno | bom | lento | Personalizar | geralmente | geralmente |
| Bigpipe multithread | 1 | Geral (causado pelo pool de threads) | bom | Mais rápido | incerto | O mais difícil | geralmente |
| propriedade | tipo | É necessário | Valor padrão | ilustrar | descrever |
|---|---|---|---|---|---|
| tamanho do núcleo | int | não | -1 | Número de tópicos principais | Número mínimo de fios ociosos, número mínimo de fios que sobreviverão de qualquer maneira |
| Max-tamanho | int | não | 1024 | Número máximo de threads | O JPipe pode criar o número máximo de threads usados para processar pagelets |
| tamanho da fila | int | não | 1024 | Contagem máxima de co-coluna de espera | A concorrência de solicitação é maior que o Max-Size e será colocada na fila e aguarda. |
| Manter-se | longo | não | 60000 | Tempo inativo máximo (MS) | Se o número de threads exceder o tamanho do núcleo, ele será reciclado até que o número de threads seja igual ao tamanho do núcleo. |
| pré-iniciar-se-todo-threads | booleano | não | falso | Pré -aqueça o pool de threads | Se deve começar a começar os tópicos do tamanho do núcleo |
| propriedade | tipo | É necessário | Valor padrão | ilustrar | descrever |
|---|---|---|---|---|---|
| assíncrono | booleano | não | verdadeiro | Se deve executar as tarefas de pagelets de forma assíncrona |
| propriedade | tipo | É necessário | Valor padrão | ilustrar | descrever |
|---|---|---|---|---|---|
| DOMID | corda | sim | ID do documento HTML | ||
| feijão | corda | sim | Nome do feijão da primavera | ||
| var | corda | sim | parâmetros variáveis | ||
| Uri | corda | não | Parâmetros URI | ||
| JsMethod | corda | não | JP.View | Função JS que envolve dados |
JpipeThreadPoolFactoryBean <? 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 ();
}via iniciante da Spring-Boot
< 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 um pagelet para implementar o método Doexec da 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> para que a renderização da primeira tela DOM não seja bloqueada. < %@ 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 >Não: implantar para contêineres como Tomcat e cais
@ 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 suporta o uso de tags JSP. Se o seu projeto não usar modelos JSP, isso não será recomendado. Como as tags JSP personalizadas são escritas e operadas no ambiente JSP, os contêineres do servlet que suportam o JSP 1.1 ou o JSP 1.2 precisam ser introduzidos (implantações de contêineres de servlet como Tomcat e Jetty) e o FTL pode ser usado em ambientes não servlet e outros ambientes da Web.
Uma explicação mais precisa é: embora o contêiner do servlet não tenha suporte JSP local, você também pode usar a biblioteca de tags JSP no Freemarker. Apenas certifique -se de que o pacote javax.servlet.jsp.* Para JSP versão 1.2 (ou mais recente) esteja disponível no aplicativo da web. Se o seu contêiner de servlet suportar apenas o JSP 1.1, você deverá copiar as seis classes a seguir (como você pode extrair do pacote JAR de Tomcat 5.x ou Tomcat 4.x) para o Web-Inf/Classes/... Diretório da Web: javax.jspáx.jsp.tagext.iteratytag, javax.servlet.jsplet.jsplet.jSsp. javax.servlet.servletContextListener, javax.servlet.servletContextTtributelistener, javax.servlet.http.httpSessionAttributelistener, javax.servlet.http.httpsionListener. No entanto, esteja ciente de que, como o contêiner suporta apenas o JSP 1.1, geralmente usando versões anteriores antes do Servlet 2.3, os ouvintes do evento podem não ser suportados; portanto, a biblioteca de tags JSP 1.2 para registrar os ouvintes de eventos funcionará normalmente.
Até o momento da imprensa: o JSP foi lançado na versão 2.3
Use <#assign jp=JspTaglibs["http://java.yl-online.top/jsp/jpipe"] /> para introduzir tags 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 > Dependência do 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 >Como os contêineres como a Underlow não possuem um ambiente JSP-API, eles precisam confiar no pacote javax.servlet.jsp-api e, ao mesmo tempo, eles precisam configurar os patrimônios de classe do Freemarker através do TaglibFactory. Sem essa configuração, será relatado um erro: freemarker.ext.jsp.taglibFactory $ taglibgettingException: Nenhum TLD foi encontrado para o "http://java.ylline.top/jsp/jpipe" jsp taglib Uri. (Os TLD-S são pesquisados de acordo com a especificação JSP 2.2. Nas configurações de desenvolvimento e serviço incorporado, você também pode precisar das "metainftldSources" e "ClassThtlds" Freemarker.ext.Extlet.FreemarkerSertlet As propriedades do sistema ou as propriedades do sistema semelhantes.)
Configuração
@ 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 );
}
}Dependência do 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 部署 -->Como já existe um ambiente JSP-API em Tomcat e Jetty, não há necessidade de confiar no pacote javax.servlet.jsp-api aqui