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的“非商業”方面不會影響您的應用程序。