一、Java Web 模組結構
#JSP檔案和AXPX檔案類似,路徑和URL一一對應,都會被動態編譯為單獨class。 Java Web和ASP.NET的核心是分別是Servlet和IHttpHandler接口,因此無論是基礎的Page文件(JSP、ASPX)方式還是後來發展的MVC方式(Spring MVC、ASP.NET MVC)都是基於核心接口的基礎上再次封裝和擴充(DispatcherServlet、MvcHandler)。 (建議:java影片教學)
除JSP檔案外,其他全部檔案部署在應用程式目錄的WEB-INF子目錄下,WEB-INF目錄可以認為是ASP.NET中將web.config檔、bin目錄和App_開頭的運行時目錄存放在了一個統一的根目錄中。
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)。
綜上,類似ASP.NET中的web.config、bin、App_Data等,Java Web中的WEB-INF、web.xml、lib和classes是我們必須了解和掌握的。
|--Assembly Root |---WEB-INF/ |--web.xml |--lib/ |--classes/
1、WEB-INF目錄:Java Web檔案的根目錄。
2、web.xml檔:設定檔(asp.net web.config)。
3、lib目錄:存放類別庫檔案(asp.net bin)。
4、classes目錄:存放class檔案(asp.net bin)。
二、Java Web專案的基本架構[Eclipse Dynamic Web Project]
Eclipse Dynamic Web Project專案
#( 1)可以設定需要編譯的原始碼目錄和輸出目錄,預設編譯src目錄下的原始檔到build\classes目錄下。
(2)可以設定WEB-INF的根目錄,預設為WebContent。
(3)可以選擇是否要產生預設web.xml檔。
我們建立一個命名為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/
1、.settings為Eclipse專案資料夾,存放了Eslipse專案的各種配置。在Eclipse專案視圖中不可見。
2、src目錄存放原始碼。在Eclipse的專案檢視中對應為Java Resources/src。
3、build存放編譯後的檔案。
4、可以在類似的\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\DynamicWP目錄中查看執行時的檔案結構。
三、Maven Web專案的基本結構
#鑑於目前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/
1、pom.xml:maven專案設定檔。
2、.project檔案和.classpath檔案以及.settings目錄和target/m2e-wtp目錄下的檔案為Eclipse專案設定檔。
3、src和target:maven標準專案目錄。
Eclipse4.5.1中對應的專案資源管理檢視
|--MavenWP |--Deployment Desciptor/ |--Java Resources/ |--JavaScript Resources/ |--Deployed Resources/ |--src |--target |--pom.xml
1、認建立的專案會新增一個index.jsp並報錯:使用maven搜尋並新增servlet依賴更新後就可以正常運行。
2、Java建置路徑問題警告:使用maven搜尋並新增compiler外掛程式並設定configuration節點更新就可以消除。
3、牆的問題配置maven鏡像,我採用的是http://maven.oschina.net/content/groups/public/。
4、預設建立的maven webapp缺少的src/main/java、src/test/java和src/test/resources等目錄都需要自己手動新增。
5、修改.settings/org.eclipse.wst.common.project.facet.core.xml,更新
6、web.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>
四、servlet基礎
如ASP.NET的核心是IHttpHandler一樣,Java Web的核心是Servlet接口,位於javax.servlet命名空間中。 Filter的概念可以參考ASP.NET的HttpModule,Servlet中的各種Listener可以參考ASP.NET HttpApplicaiton中類似的event。
無論是Java或.NET的網路技術,都是基於HTTP協定的具體實作。 Java Web與ASP.NET中的一些核心項目對應如下:
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当然绝对不是用来存储用户登录状态的,但类似验证码等敏感信息却必须存储在Session中。对于分布式Web应用自定义Session支持独立的状态服务器或集群是必须的。
ASP.NET通过SessionStateModule通过配置文件配置实际的Session提供程序,Session提供程序实现了SessionStateStoreProviderBase,因此在ASP.NET中实现自定义Session是通过继承SessionStateStoreProviderBase实现,配置Session是通过Web.config。
同理,Java Servlet中使用自定义Session通过Filter可以实现。由于不同的servlet容器对Session的实现不同,所以通用性最好的方式是继承HttpServletRequestWrapper重写getSession方法返回自定义的Session对象。
(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)配置文件: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的一些抽象定义有点过头了,不够简洁。
更多java知识请关注java基础教程栏目。
以上是Java Web專案基礎圖文詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!