JSP文件和AXPX文件相似,路徑和URL一一對應,都會被動態編譯爲單獨class。Java Web和ASP.NET的核心是分別是Servlet和IHttpHandler接口,所以不管是基礎的Page文件(JSP、ASPX)方式仍是後來發展的MVC方式(Spring MVC、ASP.NET MVC)都是基於核心接口的基礎上再次封裝和擴展(DispatcherServlet、MvcHandler)。html
除JSP文件外,其餘所有文件部署在應用目錄的WEB-INF子目錄下,WEB-INF目錄能夠認爲是ASP.NET中將web.config文件、bin目錄和App_開頭的運行時目錄存放在了一個統一的根目錄中。java
Java Web的配置文件web.xml也存放在WEB-INF目錄下,而ASP.NET的配置文件web.config通常直接存放在應用目錄下(ASP.NET其餘目錄一樣能夠有web.config文件)。ASP.NET將全部的引用和代碼生成的dll都部署在bin中,而Java Web的引用jar和生成的class分別存放在WEB-INF的子目錄lib和classes中(參考1)。git
綜上,相似ASP.NET中的web.config、bin、App_Data等,Java Web中的WEB-INF、web.xml、lib和classes是咱們必須瞭解和掌握的。github
|--Assembly Root |---WEB-INF/ |--web.xml |--lib/ |--classes/
Eclipse Dynamic Web Project項目web
(1)能夠配置須要編譯的源碼目錄和輸出目錄,默認編譯src目錄下的源文件到build\classes目錄下。apache
(2)能夠配置WEB-INF的根目錄,默認爲WebContent。設計模式
(3)能夠選擇是否生成默認web.xml文件。api
咱們建立一個命名爲DynamicWP的默認生成web.xml的Dynamic Web Proejct項目。文件結構以下:安全
|--DynamicWP |--.settings/ |--build/ |--classes/ |--src/ |--WebContent/ |--META-INF/ |--MANIFEST.MF |--WEB-INF/ |--web.xml |--lib/
在Eclipse的項目資源管理器中DyanmicWP項目的視圖以下:服務器
|--DynamicWP |--Deployment Desciptor |--JAX-WS Web Services |--Java Resources |--JavaScript Resources |--build |--WebContent |--META-INF/ |--MANIFEST.MF |--WEB-INF/ |--web.xml |--lib/
鑑於目前Java IDE衆多而且都有必定的擁泵,Eclipse的Java Web項目不具備可移植性。Maven即解決了項目結構的規範問題又提供了強大引用處理等強大的功能,在項目佈局等方面已是目前事實上的標準。Maven項目的主要結構以下(參考2):
|--root |--pom.xml |--src/ |--main/ |--java/ |--resources/ |--webapp/ |--test/ |--java/ |--resources |--target/
Eclipse中新建一個Maven web app項目。文件結構以下:
|--MavenWP |--pom.xml |--.project |--.classpath |--.settings/ |--src/ |--target/ |--classes/ |--m2e-wtp/
Eclipse4.5.1中對應的項目資源管理視圖
|--MavenWP |--Deployment Desciptor/ |--Java Resources/ |--JavaScript Resources/ |--Deployed Resources/ |--src |--target |--pom.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
Maven的配置文件pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>me.test</groupId> <artifactId>MavenWP</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>MavenWP Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> </dependencies> <build> <finalName>MavenWP</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
正如ASP.NET的核心是IHttpHandler同樣,Java Web的核心是Servlet接口,位於javax.servlet命名空間中。Filter的概念能夠參考ASP.NET的HttpModule,Servlet中的各類Listener能夠參考ASP.NET HttpApplicaiton中相似的event。不管是Java仍是.NET的Web技術,都是基於HTTP協議的具體實現。Java Web和ASP.NET中的一些核心項對應以下:
Java 參考3 | .NET | 備註 | |
Core | javax.servlet.Servlet | System.Web.IHttpHandler | |
HTTP Request | javax.servlet.ServletRequest | System.Web.HttpRequest | |
HTTP Response | javax.servlet.ServletResponse | System.web.HttpResponse | |
Cookie | javax.servlet.http.Cookie | System.Web.HttpCookie | |
Session | javax.servlet.http.HttpSession | System.Web.HttpSessionState | |
Application | javax.servlet.ServletContext | System.Web.HttpApplication | |
Begin Request | javax.servlet.Servlet.RequestDispatcher | System.Web.HttpApplication.BeginRequest | event |
Begin\End Request | javax.servlet.Servlet.ServletRequestListener | System.Web.HttpApplication.BeginRequest\EndRequest | event |
Filter | javax.servlet.Filter | System.Web.IHttpModule | |
Application Event | javax.servlet.ServletContextListener | System.Web.HttpApplication.Application_Start\Application_End | method |
Servlet和ASP.NET的簡化示意圖:
用於簡化web.xml配置的Servlet的註解(3.0開始支持,在ASP.NET中沒有對應項):
(1)WebServlet:做用在javax.servlet.http.HttpServlet的實現類上。
(2)WebFilter:做用在javax.servlet.Filter的實現類上。
(3)WebListener:做用在Listener的實現類上(javax.servlet.ServletContextListener、javax.servlet.ServletContextAttributeListener、javax.servlet.ServletRequestListener、javax.servlet.ServletRequestAttributeListener、javax.servlet.http.HttpSessionListener、javax.servlet.http.HttpSessionAttributeListener)。
(4)WebInitParam:結合WebServlet和WebFilter註解用來配置屬性。
(5)MultipartConfig:做用在javax.servlet.http.HttpServlet的實現類上。標註請求是mime/multipart類型。
用於Servlet容器初始化的ServletContainerInitializer(可實現無web.xml,3.0開始支持,可類比ASP.NET的Application_Start方法):
(1)Servlet容器啓動時查找ServletContainerInitializer的實例。
(2)ServletContainerInitializer實例使用HandlesTypes標註一個或多個類型,Servlet容器將在啓動時掃描classpath,獲取這些類型的實例。
(3)Servlet容器在啓動時調用ServletContainerInitializer實現類的onStartup方法,該方法能夠獲取HandlesTypes標註的全部類型對象。
Session在存儲安全性要求較高的會話信息方面是必不可少的,Session固然絕對不是用來存儲用戶登陸狀態的,但相似驗證碼等敏感信息卻必須存儲在Session中。對於分佈式Web應用自定義Session支持獨立的狀態服務器或集羣是必須的。
ASP.NET經過SessionStateModule經過配置文件配置實際的Session提供程序,Session提供程序實現了SessionStateStoreProviderBase,所以在ASP.NET中實現自定義Session是經過繼承SessionStateStoreProviderBase實現,配置Session是經過Web.config。ASP.NET自定義session的代碼參考github上的開源項目SQLiteSessionStateStore。
同理,Java Servlet中使用自定義Session經過Filter能夠實現。因爲不一樣的servlet容器對Session的實現不一樣,因此通用性最好的方式是繼承HttpServletRequestWrapper重寫getSession方法返回自定義的Session對象。Filter採用了職責鏈模式(chain of responsibility),HttpServletRequestWrapper採用了裝飾模式(Decorator),能夠經過《Head First 設計模式》閱讀模式的相關內容。
(1)首先自定義繼承HttpSession的MySession(爲了便於演示,僅包裝了容器的session並轉發調用)。
import java.util.Enumeration; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; public class MySession implements HttpSession { private HttpSession _containerSession; public MySession(HttpSession session) { this._containerSession = session; } @Override public long getCreationTime() { return this._containerSession.getCreationTime(); } @Override public String getId() { return this._containerSession.getId(); } @Override public long getLastAccessedTime() { return this._containerSession.getLastAccessedTime(); } @Override public ServletContext getServletContext() { return this._containerSession.getServletContext(); } @Override public void setMaxInactiveInterval(int interval) { this._containerSession.setMaxInactiveInterval(interval); } @Override public int getMaxInactiveInterval() { return this._containerSession.getMaxInactiveInterval(); } @SuppressWarnings("deprecation") @Override public HttpSessionContext getSessionContext() { return this._containerSession.getSessionContext(); } @Override public Object getAttribute(String name) { return this._containerSession.getAttribute(name); } @SuppressWarnings("deprecation") @Override public Object getValue(String name) { return this._containerSession.getValue(name); } @Override public Enumeration<String> getAttributeNames() { return this._containerSession.getAttributeNames(); } @SuppressWarnings("deprecation") @Override public String[] getValueNames() { return this._containerSession.getValueNames(); } @Override public void setAttribute(String name, Object value) { this._containerSession.setAttribute(name, value); } @SuppressWarnings("deprecation") @Override public void putValue(String name, Object value) { this._containerSession.putValue(name, value); } @Override public void removeAttribute(String name) { this._containerSession.removeAttribute(name); } @SuppressWarnings("deprecation") @Override public void removeValue(String name) { this._containerSession.removeValue(name); } @Override public void invalidate() { this._containerSession.invalidate(); } @Override public boolean isNew() { return this._containerSession.isNew(); } }
(2)自定義繼承HttpServletRequestWrapper的MyRequest
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; public class MyRequest extends HttpServletRequestWrapper { public MyRequest() { super(null); } public MyRequest(HttpServletRequest request) { super(request); // TODO 自動生成的構造函數存根 } @Override public HttpSession getSession(boolean create) { return new MySession(super.getSession(create)); } @Override public HttpSession getSession() { return new MySession(super.getSession()); } }
(3)自定義Filter將Request包裝爲MyRequest
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; @WebFilter("/*") public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO 自動生成的方法存根 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new MyRequest((HttpServletRequest) request), response); } @Override public void destroy() { // TODO 自動生成的方法存根 } }
經過註解配置了Filter,也能夠經過原始的web.xml方式配置。
1.https://docs.oracle.com/javaee/7/tutorial/packaging003.htm
2.http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
3.https://docs.oracle.com/javaee/7/tutorial/webapp005.htm
你至少應該知道的:
(1)配置文件:ASP.NET的web.config和Java的web.xml
(2)Web核心:ASP.NET的IHttpHandler接口和Java的Servlet接口
(3)攔截器:ASP.NET的HttpModule和Java的Filter
(4)應用程序事件:ASP.NET的HttpApplication event和Java的各類Listener
(5)啓動器:ASP.NET的Application_Start和Java的ServletContainerInitializer
(6)引用管理:ASP.NET的Nuget和Java的Maven
感想:
ASP.NET的核心對象不像Java Servlet同樣,從一開始就基於接口,這是缺點。但Java Servlet的核心對象全靠容器實現,就連HttpSession一樣如此,這也是缺點。好比自定義個Session十分麻煩,沒有像ASP.NET同樣簡單配置便可。另外Servlet的一些抽象定義有點過頭了,不夠簡潔。