FAUXJSP是一个Java服务器页面(JSP)实现,以便在开发过程中使用:JSP懒惰(而不是编译),可减少应用程序和页面启动时间,在JSPS更改并且不需要服务器重新启动时加快页面重新加载。如果规格合规并不关键,则最能使用开发时使用,也可以在生产中使用。
web.xml:
< servlet >
< servlet-name >FauxJsp</ servlet-name >
< servlet-class >fauxjsp.servlet.JspServlet</ servlet-class >
</ servlet >
< servlet-mapping >
< servlet-name >FauxJsp</ servlet-name >
< url-pattern >*.jsp</ url-pattern >
</ servlet-mapping >以下版本(包括)1.2.3在Maven Central中:
pom.xml:
< dependency >
< groupId >com.github.ggeorgovassilis</ groupId >
< artifactId >fauxjsp</ artifactId >
< version >1.2.3</ version >
</ dependency >1.2.3之后的版本需要一个存储库:
< repositories >
< repository >
< id >fauxjsp-repo</ id >
< url >https://github.com/ggeorgovassilis/fauxjsp/raw/gh-pages/</ url >
< snapshots >
< enabled >true</ enabled >
< updatePolicy >always</ updatePolicy >
</ snapshots >
</ repository >
</ repositories >1.2.7-Snapshot(未在Maven Central上发布)
1.2.3
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
trimDirectiveWhiteSpaces , c:set实现的身体内容0.0.9
0.0.5-snapshot
0.0.4-snapshot
是的。简而言之:
对于你们中的大多数人来说,JSP酷时都非常过时,但是我喜欢将其用于原型和标记。令人遗憾的是,令人惊讶的是,尽管Tagfiles是一种能够创建可重复使用的Web UI组件的良好和成熟的技术,但并没有多少人知道他们。
启动JSP繁重的应用程序很慢,因为其他JSP实现将首先将JSP和TagFiles编译到Java源代码,然后将其汇编为字节代码,然后转到机器代码。同样,在更改JSP文件时,必须重复整个过程,这会减慢开发。在某个时候,您甚至会出现无法解释的编译错误,类加载错误,内存等内容,您会知道您已经受够了,并且会重新启动Servlet容器。
FAUXJSP实现了JSP解释器和JSP Servlet,该解释器会读取JSP文件并随机解释它们,从而完全跳过汇编。这带来了即时页面重新加载,快速应用程序的启动时间和稳健性的好处(没有类载荷器!),但是显然,生成的JSP页面在负载下的负载较慢,而标准实现可能是生产中的问题。
当前实现的功能:
约束和缺失功能:
c:out这样的核心Taglib会起作用,但是除非您重新实现FAUXJSP,否则诸如DisplayTag之类的第三方Taglibs不会。classpath:在类路径中解决标语和JSP的前缀。不支持解决集体路径资源的标准方式。因为:
奖金:
< dependency >
< groupId >com.github.ggeorgovassilis</ groupId >
< artifactId >fauxjsp</ artifactId >
< version >1.1.0</ version >
</ dependency >或者
下载资源并编译
git clone https://github.com/ggeorgovassilis/fauxjsp.git
cd fauxjsp
mvn install< servlet >
< servlet-name >FauxJsp</ servlet-name >
< servlet-class >fauxjsp.servlet.JspServlet</ servlet-class >
<!-- optionally specify a root for resource lookup, defaults to "/"
<init-param>
<param-name>base-path</param-name>
<param-value>/WEB-INF/jsp/</param-value>
</init-param>
-->
</ servlet >
< servlet-mapping >
< servlet-name >FauxJsp</ servlet-name >
< url-pattern >*.jsp</ url-pattern >
</ servlet-mapping > Servlet API,JSTL,EL被provided ,因为Servlet容器或Web应用程序贡献了这些依赖性
log4j,beanshell被provided ,因为它们是可选的
CONSONS-LANG被范围为compile ,因为它是强制性的
有关最新详细信息,请参阅POM。
当您找到错误或需要实现功能时,请提交错误报告。现在,在真实的(项目)生活中,您可能会紧迫,不想等待正式解决方案。 FAUXJSP是模块化的,易于扩展。因此,请查看有关FAUXJSP的体系结构的下一章,该章节将帮助您了解各种相当简单的组件,如何修改它们并实现新功能。
JspServlet接受HTTP请求并呈现请求的JSP。整个序列看起来像这样:
ServletRequest获取请求的JSP文件的名称jspbase (请参阅JspServlet的Javadocs)JspParserFactory询问新的JspParserJspPage JspParserRenderSessionJspRenderer询问JspRendererFactoryJspPage和RenderSession给JspRenderer呈现JspServlet具有一堆受保护的方法,这些方法构建了前面提到的各种工厂。如果您需要特殊的设置,然后覆盖这些构造方法,则可以指定自己的工厂,该工厂可以返回经过修改或全新的解析器和渲染器实现。
JspParser ,更具体地说,其唯一的实现JspParserImpl是一个JSP文件位置,将其呈现并返回分析结果。详细:
JspParser.parse(path)被赋予JSP文件的路径ResourceResolver实例的路径( JspParserFactory集合一个up),该实例将JSP文件返回为字符串。JspNode s的树。TagLibDefinitionCache中,该声明确保在每个请求中仅读取一次Taglibs。JspParserFactory递归解析Tagfile的新解析器。不幸的是,目前不可能在Tagfiles以外加载Taglibs。但是,可以通过为FauxjSP自己提供特殊实现来使用缺少的Taglibs。根据Taglib的不同,您要模拟这可能会或可能不是一项劳动密集型任务。有关一些示例,请看一下JstlCoreTaglib*类。 DefaultJspParserFactoryImpl工厂将其设置为特殊名称空间,每个taglib方法一个。
<%@ taglib prefix uri tagdir %>
<@ include file %>
<%@ attribute name required rtexprvalue type %>
< jsp : attribute name = " ... " >...</ jsp : attribute >
< jsp : body >...</ jsp : body >
< jsp : doBody />< c : out value = " ... " />
< c : choose test = " ... " >...</ c : choose >
< c : when test = " ... " >...</ c : when >
< c : otherwise >...</ c : otherwise >
< c : forEach var = " ... " items = " ... " varStatus = " ... " begin = " ... " end = " ... " >...</ c : forEach >
< c : if test = " ... " >...</ c : if >
< c : set var = " ... " value = " ... " />
< fmt : message key = " ... " />
< fmt : setBundle basename = " ... " />
< fmt : formatNumber value = " ... " .../>
< fmt : formatDate value = " ... " .../>
< fmt : setLocale value = " ... " />
FAUXJSP代表应用程序服务器使用的标准JSTL函数实现,因此所有内容都应开箱即用。
如果您需要更多功能taglibs,请不要忘记在Web.xml中声明它们:
< jsp-config >
< taglib >
< taglib-uri >http://java.sun.com/jstl/core-rt</ taglib-uri >
< taglib-location >META-INF/c-1_0-rt.tld</ taglib-location >
</ taglib >
</ jsp-config >Taglib-Location可以是服务器或类Path的资源路径。
如前所述,FauxJSP不能使用Taglibs,而必须效仿它们,这意味着某人必须编程模仿。
步骤1 :创建TAGLIB实现。只需找到一个已经模拟的Taglibs之一
public class TaglibAdd extends TaglibDefinition {
protected void runAdd ( RenderSession session , JspTaglibInvocation invocation ) {
String xExpression = invocation . getArguments (). get ( "x" );
if ( xExpression == null )
throw new RuntimeException ( "Missing x argument" );
Object x = session . elEvaluation . evaluate ( xExpression , session );
String yExpression = invocation . getArguments (). get ( "y" );
if ( yExpression == null )
throw new RuntimeException ( "Missing y argument" );
Object y = session . elEvaluation . evaluate ( yExpression , session );
try {
int ix = ( Number ) x ;
int iy = ( Number ) y ;
String s = "" +( ix + iy );
session . response . getOutputStream (). write (( s ). getBytes ( session . response . getCharacterEncoding ()));
} catch ( Exception e ) {
throw new JspRenderException ( invocation , e );
}
}
@ Override
public void render ( RenderSession session , JspTaglibInvocation invocation ) {
runAdd ( session , invocation );
}
public TaglibAdd () {
this . name = "add" ;
this . attributes . put ( "x" , new AttributeDefinition ( "x" , Integer . class . getName (), true , true ));
this . attributes . put ( "y" , new AttributeDefinition ( "y" , Integer . class . getName (), true , true ));
}
}
步骤2 :扩展DefaultJspparserFactoryImpl并覆盖setup方法。在这里您可以注册您写的新的Taglib
public class MyJspParserFactory extends DefaultJspParserFactoryImpl {
protected void setup ( JspParserImpl parser ) {
super . setup ( parser );
parser . registerTaglibDefinition (
"http://mytaglibs/add" ,
new TaglibAdd ());
}
}步骤3 :扩展Jspservlet并覆盖getJspParserFactory ,以便返回您的新工厂
public class MyJspServlet extends JspServlet {
protected JspParserFactory getJspParserFactory ( ServletConfig config ){
ResourceResolver location = new ServletResourceResolver ( jspBase , getServletContext ());
DefaultJspParserFactoryImpl factory = new MyJspParserFactory ( location );
return factory ;
}
}步骤4 :在web.xml中使用新的JSPSERVLET实现,而不是旧的Jspservlet
< servlet >
< servlet-name >FauxJsp</ servlet-name >
< servlet-class >MyJspServlet</ servlet-class >
</ servlet >
< servlet-mapping >
< servlet-name >FauxJsp</ servlet-name >
< url-pattern >*.jsp</ url-pattern >
</ servlet-mapping > JspServlet通过log4j登录,如果在类路径上找到,则可以通过标准的JDK日志记录机构进行登录。 log4j.properties中可能的日志记录设置可能看起来像:
log4j.rootLogger=INFO, stdout
log4j.logger.fauxjsp=INFO, stdout
log4j.additivity.fauxjsp.impl.parser.JspParserImpl=false
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
使用Beanshell实现了脚本,因此可以期待与标准脚本行为的某些偏差。除非在类路径上找到beanshell解释器,否则不会启用脚本。当前限制是:
理想情况下,您会找到一种在生产JSP环境和FAUXJSP中都起作用的方法。一个示例是我们之前谈论的脚本中使用的varargs的情况。 FAUXJSP Parser可能会被EL表达式和脚本中出现的字符串混淆,这些字符串用作其他地方用作<,>,>,{,}等的定界符等。
用例是您的tagfiles或jsps引用位于classPath中的其他标签文件或JSP(例如,JAR文件)。不要使用tagdir ,而是在包括资源时使用uri ,例如:
<%@ taglib prefix = " cp " uri = " classpath:/tagfiles " %>您可能注意到JstlView和InternalViewResolver不起作用,Spring找不到您的JSP。在引擎盖下,弹簧应将模型(MVC中的M)填充到HttpServletRequest属性中,并将请求转发到fauxjsp,但事实并非如此。我们可以实现这样的简单转发机制:
import java . util . Locale ;
import org . springframework . stereotype . Component ;
import org . springframework . web . servlet . View ;
import org . springframework . web . servlet . ViewResolver ;
@ Component
public class ForwardingViewResolver implements ViewResolver {
@ Override
public View resolveViewName ( String viewName , Locale locale ) throws Exception {
ForwardingView view = new ForwardingView ();
view . setUrl ( "classpath:/jsp/" + viewName + ".jsp" );
return view ;
}
} import java . util . Map ;
import javax . servlet . RequestDispatcher ;
import javax . servlet . http . HttpServletRequest ;
import javax . servlet . http . HttpServletRequestWrapper ;
import javax . servlet . http . HttpServletResponse ;
import org . springframework . web . servlet . view . InternalResourceView ;
public class ForwardingView extends InternalResourceView {
@ SuppressWarnings ( "unchecked" )
@ Override
public void render ( Map < String , ?> model , HttpServletRequest request , HttpServletResponse response )
throws Exception {
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper ( request ) {
@ Override
public String getServletPath () {
return getUrl ();
}
};
exposeModelAsRequestAttributes (( Map < String , Object >) model , wrapper );
exposeHelpers ( wrapper );
RequestDispatcher rd = request . getServletContext (). getNamedDispatcher ( "FauxJsp" );
rd . forward ( wrapper , response );
}
}Web应用程序上下文中这两个组件的简单存在应该足以使它们被拾取并激活。
可以将JspServlet配置为缓存解析的JSP。这是一个较小的性能改进,因为通常渲染速度比解析要慢。
< servlet >
< servlet-name >FauxJsp</ servlet-name >
< servlet-class >fauxjsp.servlet.JspServlet</ servlet-class >
< init-param >
< param-name >cachePages</ param-name >
< param-value >true</ param-value >
</ init-param >
</ servlet >指定servlet init参数trimDirectiveWhiteSpaces
< servlet >
< servlet-name >FauxJsp</ servlet-name >
< servlet-class >fauxjsp.servlet.JspServlet</ servlet-class >
< init-param >
< param-name >trimDirectiveWhiteSpaces</ param-name >
< param-value >true</ param-value >
</ init-param >
</ servlet >功能即将到来在附近将来的某个时候:
科幻小说(我有一个大概的想法如何实施但需要锻炼,并且可能永远不会出现):
JSP教程的Ross Studtman启发了许多出色的单位测试。
FAUXJSP在GPL下可用。由于FAUXJSP是一种开发工具,因此您通常不会将其用应用程序二进制文件部署到生产中,因此GPL的“非商业”方面不会影响您的应用程序。