JavaWeb學習筆記(三)------Servlet
Servlet簡介
- Servlet就是sun公司開發動态web的一門技術,sun公司在這些API中提供了一個接口,叫做Servlet。
- 如果想要開發一個Servlet程式,隻需要完成兩個步驟:
- 編寫一個類,實作Servlet接口
- 把開發好的java類部署到web伺服器中
- 把實作了Servlet接口的Java程式,叫做Servlet
HelloServlet
實作類
- Servlet接口Sun公司有兩個預設的實作類:HttpServlet,GenericServlet
- 建構一個普通的Maven項目,删掉裡面的src目錄,以後的學習在這個項目中建立Module。這個空的工程就是Maven的主工程
關于Maven父子工程的了解
- 在父項目中會有
<modules>
<module>servlet-01</module>
</modules>
- 子項目中會有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.zmt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- 父項目中的jar包,子項目可以直接使用,反過來不信
Maven環境優化
- 修改web.xml為最新的
- 将maven的環境搭建完整
編寫一個Servlet接口
- 編寫一個普通類
- 實作Servlet接口,直接繼承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post隻是請求實作的不同的方式,可以互相調用,因為業務邏輯都一樣
//重寫的post方法調用了get方法,是以直接重寫get方法即可
//用get調post同理
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletInputStream inputStream = req.getInputStream();
//ServletOutputStream outputStream = resp.getOutputStream();
System.out.println("進入doGet方法");
PrintWriter writer = resp.getWriter(); //響應流
writer.print("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
編寫Servlet的映射
- 為什麼需要映射?
- 因為我們寫的是Java程式,但是要通過浏覽器通路,而浏覽器需要連接配接web伺服器,是以我們需要在web服務中注冊我們寫的Servlet,還需要給他一個浏覽器能夠通路的路徑
- 在web.xml中進行配置
<!--注冊Servlet servlet檔案對應的名字-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zmt.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的請求路徑,url-pattern:在位址欄請求的網絡接口 servlet-name:請求的servlet -->
<!--配置url-pattern,一定要在前面加/,不然會出錯 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
配置tomcat
- 注意:配置項目釋出的路徑就可以了
啟動測試
- 成功
- 注意:Tomcat下配置的Artifacts檔案,要和項目檔案名一樣,否則産生的war包有問題
Servlet運作原理
- Servlet是由Web伺服器調用,web伺服器在收到浏覽器請求之後,會:
Mapping問題
- 一個Servlet可以指定一個映射路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一個Servlet可以指定多個映射路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
- 一個Servlet可以指定通用映射路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 可以自定義字尾實作請求映射
注意: *前面不能加項目映射的路徑
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.abc</url-pattern>
</servlet-mapping>
- 預設請求路徑(盡量不用)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
優先級問題
- 指定了固有的映射路徑優先級最高,如果找不到就會走預設的處理請求
ServletContext
web容器在啟動的時候,它會為每個web程式都建立一個對應的ServletContext對象,他代表了目前的web應用:
共享資料
- 我在這個Servlet中儲存的資料,可以在另外一個Servlet中拿到
- 存入資料
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter(); 初始化參數
//this.getServletConfig(); Servlet配置
//this.getServletContext(); Servlet上下文
ServletContext context = this.getServletContext();
String username = "zmt"; //資料
//将一個資料儲存在 ServletContext中,鍵值對形式,
//名字為:username 值zmt
context.setAttribute("username",username);
System.out.println("Hello");
}
}
- 讀出資料
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String)context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- XML檔案
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zmt.servlet.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.zmt.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
</web-app>
- 測試通路結果
擷取初始化參數
- 在web.xml中進行初始化配置
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置一些web應用的初始化參數 -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
</web-app>
- 擷取初始配置
public class ServletDemo03 extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
請求轉發
- 請求轉發,路徑不會發生變化
public class ServletDemo04 extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("進入Demo04");
//請求轉發 /gp為轉發的請求路徑
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
//調用forward實作請求轉發,轉發時,路徑不會變
requestDispatcher.forward(req,resp);
// 合并也可以實作 context.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- XML檔案
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置一些web應用的初始化參數 -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
</web-app>
- 本質上A和B産生練習,由B去C處擷取資訊,是以路徑沒有發生變化
讀取資源檔案
- 在java目錄下,建立proterties
- 在resources目錄下,建立proterties
- 都被打包在同一路徑下:target——servlet-02——WEB-INF——classes
- 俗稱該路徑為:classpath,類路徑
- 思路:需要一個檔案流
- 在build中配置resources,來防止我們資源導出失敗的問題
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 具體實作
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ”/“代表目前web項目,即跳轉到tomcat檔案中webapps中的本項目目錄下
// 本項目名為tomcat中Application Context設定值
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- Properties
username = root
password = 123456
- 測試通路結果