Servlet (1)

Servlet 的 HelloWorld

1.創建一個 Servlet 接口的實現類. 

public class HelloServlet implements Servlet {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("destroy");
	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		System.out.println("getServletConfig");
		return null;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		System.out.println("getServletInfo");
		return null;
	}

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("init");
	}

	@Override
	public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("service");
	}

	public HelloServlet() {
		super();
		// TODO Auto-generated constructor stub
		System.out.println("HelloServlet ...Constructor");
	}

}

2.在 web.xml 文件中配置和映射這個 Servlet

	<!-- 配置和映射 Servlet -->
	<servlet>
		<!-- Servlet 註冊的名字 -->
		<servlet-name>helloServlet</servlet-name>
		<!-- Servlet 的全類名 -->
		<servlet-class>com.javaweb.HelloServlet</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<!-- 需要和某一個 servlet 節點的 serlvet-name 子節點的文本節點一致 -->
		<servlet-name>helloServlet</servlet-name>
		<!-- 映射具體的訪問路徑: / 代表當前 WEB 應用的根目錄. -->
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>

啓動Tomcat,瀏覽器訪問http://localhost:8080/項目名/hello

控制檯打印

HelloServlet ...Constructor
init
service

3.Servlet 生命週期

第一次訪問http://localhost:8080/項目名/hello,結果如上

之後再訪問只輸出

...
service
service
service
...

stop tomcat後打印

destroy
1). 構造器: 只被調用一次. 只有第一次請求 Servlet 時, 創建 Servlet 的實例. 調用構造器. 這說明 Serlvet 的單實例的!
2). init 方法: 只被調用一次. 在創建好實例後立即被調用. 用於初始化當前 Servlet. 
3). service: 被多次調用. 每次請求都會調用 service 方法. 實際用於響應請求的. 
4). destroy: 只被調用一次. 在當前 Servlet 所在的 WEB 應用被卸載前調用. 用於釋放當前 Servlet 所佔用的資源. 

4. load-on-startup 參數:

  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.javaweb.HelloServlet</servlet-class>
	<!-- 可以指定 Servlet 被創建的時機 -->
     <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet>
	  <servlet-name>secondServlet</servlet-name>
	  <servlet-class>com.javaweb.SecondServlet</servlet-class>
	  <load-on-startup>2</load-on-startup>
  </servlet>


2). load-on-startup: 可以指定 Serlvet 被創建的時機. 若爲負數, 則在第一次請求時被創建.若爲 0 或正數, 則在當前 WEB 應用被
Serlvet 容器加載時創建實例, 且數值越小越早被創建


5. 關於 serlvet-mapping

1). 同一個Servlet可以被映射到多個URL上,即多個 <servlet-mapping> 元素的<servlet-name>子元素的設置值可以是同一個
Servlet的註冊名。

例如

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.javaweb.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>hello</servlet-name>
   <url-pattern>/hello</url-pattern>
</servlet-mapping>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
即  HelloServlet 可以 通過 /hello 訪問,也可以通過/hello2來訪問

2). 在Servlet映射到的URL中也可以使用 * 通配符,但是隻能有兩種固定的格式:
一種格式是“*.擴展名”,另一種格式是以正斜槓(/)開頭並以“/*”結尾。

<servlet-mapping>
	<servlet-name>secondServlet</servlet-name>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

OR

<servlet-mapping>
	<servlet-name>secondServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

注意: 以下的既帶 / 又帶擴展名的不合法. 

<servlet-mapping>
	<servlet-name>secondServlet</servlet-name>
	<url-pattern>/*.action</url-pattern>
</servlet-mapping>

6. ServletConfig: 封裝了 Serlvet 的配置信息, 並且可以獲取 ServletContext 對象

1). 配置 Serlvet 的初始化參數

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.javaweb.HelloServlet</servlet-class>
	
	<!-- 配置 Serlvet 的初始化參數。 且節點必須在 load-on-startup 節點的前面 -->
    <init-param>
	  <!-- 參數名 -->
      <param-name>user</param-name>
	  <!-- 參數值 -->
      <param-value>root</param-value>
    </init-param>
    <init-param>
      <param-name>password</param-name>
      <param-value>root</param-value>
    </init-param>
	
     <load-on-startup>1</load-on-startup>
 </servlet>

2). 獲取初始化參數,Serlvet 的配置名稱(瞭解),獲取 ServletContext 對象

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("init");
		// 獲取初始化參數
		String user = servletConfig.getInitParameter("user");
		System.out.println("user: " + user);

		Enumeration<String> names = servletConfig.getInitParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String value = servletConfig.getInitParameter(name);
			System.out.println("--" + name + " : " + value);

		}

		//獲取Servlet註冊名稱
		String servletName = servletConfig.getServletName();
		System.out.println(servletName);
		
		//獲取ServletContext
		ServletContext servletContext = servletConfig.getServletContext();

	}

結果

init
user: root
--user : root
--password : root
hello


ServletConfig的4個常用方法:

(1)、public String getInitParameter(String name):返回指定名稱的初始化參數值;

(2)、public Enumeration getInitParameterNames():返回一個包含所有初始化參數名的Enumeration對象;

(3)、public String getServletName():返回在DD文件中<servlet-name>元素指定的Servlet名稱;

(4)、public ServletContext getServletContext():返回該Servlet所在的上下文對象;



7.ServletContext


1). 可以由  SerlvetConfig 獲取:

ServletContext servletContext = servletConfig.getServletContext();

2). 該對象代表當前 WEB 應用: ServletContext,是一個全局的儲存信息的空間,服務器開始,其就存在,服務器關閉,其才釋放。

可以從中獲取到當前 WEB 應用的各個方面的信息.


①. 獲取當前 WEB 應用的初始化參數

設置初始化參數: 可以爲所有的 Servlet 所獲取

  <context-param>
    <param-name>driver</param-name>
    <param-value>com.mysql.jdbc.Driver</param-value>
  </context-param>

方法:

getInitParameter
getInitParameterNames

代碼

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("init");
		
		...

		// 獲取ServletContext
		ServletContext servletContext = servletConfig.getServletContext();

		String contextParam = servletContext.getInitParameter("driver");
		System.out.println(contextParam);
		Enumeration<String> names2 = servletContext.getInitParameterNames();

		while (names2.hasMoreElements()) {
			String name = names2.nextElement();
			String value = servletContext.getInitParameter(name);
			System.out.println("kk" + name + " : " + value);

		}

	}

②. 獲取當前 WEB 應用的某一個文件在服務器上的絕對路徑, 而不是部署前的路徑

		 String realPath = servletContext.getRealPath("/");
		 System.out.println(realPath);
		 String realPath2 = servletContext.getRealPath("/hello.jsp");
		 System.out.println(realPath2);

輸出

D:\workspaces\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\FirstWeb\
D:\workspaces\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\FirstWeb\hello.jsp

③. 獲取當前 WEB 應用的名稱: 

getContextPath()

		 String servletContextName = servletContext.getServletContextName();
		 String contextPath = servletContext.getContextPath();
		 System.out.println(contextPath + "------" + servletContextName);
結果
/FirstWeb------FirstWeb

④. 獲取當前 WEB 應用的某一個文件對應的輸入流. 

getResourceAsStream(String path): path 的 / 爲當前 WEB 應用的根目錄. 

代碼:

		Properties pros = new Properties();
		
		try {
			ClassLoader classLoader = getClass().getClassLoader();
			InputStream is = classLoader.getResourceAsStream("jdbc.properties");
			System.out.println("1. " +  is);
			pros.load(is);
			
			System.out.println(pros.getProperty("name"));  
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		pros = new Properties();
		
		try {
			InputStream is2 = servletContext.getResourceAsStream("/WEB-INF/classes/jdbc.properties");
			System.out.println("2. " + is2);
			pros.load(is2);
			System.out.println(pros.getProperty("name"));  
		} catch (Exception e) {
			e.printStackTrace();
		}

等等。。。


8. GET 請求和 POST 請求:

1). 使用GET方式傳遞參數:

①. 在瀏覽器地址欄中輸入某個URL地址或單擊網頁上的一個超鏈接時,瀏覽器發出的HTTP請求消息的請求方式爲GET。 
②. 如果網頁中的<form>表單元素的 method 屬性被設置爲了“GET”,瀏覽器提交這個FORM表單時生成的HTTP請求消息的請求方式也爲GET。 
③. 使用GET請求方式給WEB服務器傳遞參數的格式:  

http:/localhost:8080/counter.jsp?name=lc&password=123

④. 使用GET方式傳送的數據量一般限制在 1KB 以下。 


2). 使用 POST 方式傳遞參數:


①. POST 請求方式主要用於向 WEB 服務器端程序提交 FORM 表單中的數據: form 表單的 method 置爲 POST
②. POST 方式將各個表單字段元素及其數據作爲 HTTP 消息的實體內容發送給 WEB 服務器,傳送的數據量要比使用GET方式傳送的數據量大得多。  


POST /counter.jsp HTTP/1.1
referer: http://localhost:8080/Register.html
content-type: application/x-www-form-urlencoded
host: localhost:8080
content-length: 43


name=zhangsan&password=123              --請求體中傳遞參數



9. 如何在 Serlvet 中獲取請求信息:

1). Servlet 的 service() 方法用於應答請求: 因爲每次請求都會調用 service() 方法


public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException

ServletRequest: 封裝了請求信息. 可以從中獲取到任何的請求信息.
ServletResponse: 封裝了響應信息, 如果想給用戶什麼響應, 具體可以使用該接口的方法實現. 


這兩個接口的實現類都是服務器給予實現的, 並在服務器調用 service 方法時傳入. 

2). ServletRequest: 封裝了請求信息. 可以從中獲取到任何的請求信息.


①. 獲取請求參數: 

> String getParameter(String name): 根據請求參數的名字, 返回參數值. 
若請求參數有多個值(例如 checkbox), 該方法只能獲取到第一個提交的值. 


> String[] getParameterValues(String name): 根據請求參數的名字, 返回請求參數對應的字符串數組. 

> Enumeration getParameterNames(): 返回參數名對應的 Enumeration 對象, 
類似於 ServletConfig(或 ServletContext) 的 getInitParameterNames() 方法. 


> Map getParameterMap(): 返回請求參數的鍵值對: key: 參數名,  value: 參數值, String 數組類型. 


②. 獲取請求的 URI:


HttpServletRequest httpServletRequest = (HttpServletRequest) request;

String requestURI = httpServletRequest.getRequestURI();
System.out.println(requestURI); //  /day_29/loginServlet


③. 獲取請求方式: 


String method = httpServletRequest.getMethod();
System.out.println(method); //GET

④. 若是一個 GET 請求, 獲取請求參數對應的那個字符串, 即 ? 後的那個字符串


String queryString = httpServletRequest.getQueryString();
System.out.println(queryString); //user=ddf&password=123456&interesting=game&interesting=party&interesting=shopping


⑤. 獲取請求的 Serlvet 的映射路徑 
  
   String servletPath = httpServletRequest.getServletPath();
   System.out.println(servletPath);  //  /loginServlet
   
⑥. 和 attribute 相關的幾個方法:   


3). HttpServletRequest: 是 SerlvetRequest 的子接口. 針對於 HTTP 請求所定義. 裏邊包含了大量獲取 HTTP 請求相關的方法. 
 
4). ServletResponse: 封裝了響應信息, 如果想給用戶什麼響應, 具體可以使用該接口的方法實現. 


①. *getWriter(): 返回 PrintWriter 對象. 調用該對象的 print() 方法, 將把 print() 中的參數直接打印
到客戶的瀏覽器上. 


②. 設置響應的內容類型: response.setContentType("application/msword");


③. void sendRedirect(String location): 請求的重定向. (此方法爲 HttpServletResponse 中定義.)

form表單

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="loginService" method="post">
		用戶名<input name="user" type="text"><br> 密碼<input
			name="password" type="password"><br> <br> <br>
		愛好 : 
		<input type="checkbox" name="interesting" value="reading">reading 
		<input type="checkbox" name="interesting" value="shopping">shopping
		<input type="checkbox" name="interesting" value="sport">sport 
		
		<input type="submit">
	</form>
</body>
</html>


import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class LoginServlet implements Servlet {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void init(ServletConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("請求來了。。。");

		// 獲取請求參數
		String user = request.getParameter("user");
		String password = request.getParameter("password");
		System.out.println("user=" + user + " password=" + password);
		//request.getParameter("interesting") checkbox 只能獲取 第一個被選中的
		String interesting = request.getParameter("interesting");
		System.out.println("request.getParameter(\"interesting\")的值:" + interesting);
		
		//獲取checkbox 全部被選中的值
		String[] intreastinges = request.getParameterValues("interesting");
		for (String str : intreastinges) {
			System.out.println(str);
		}

		//獲取全部請求參數
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String value = request.getParameter(name);
			System.out.println(name + " =" + value);
		}

		Map<String, String[]> map = request.getParameterMap();
		for (Map.Entry<String, String[]> entry : map.entrySet()) {
			System.out.println(entry.getKey() + " " + Arrays.asList(entry.getValue()));
		}

		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		String requestURI = httpServletRequest.getRequestURI();
		System.out.println(requestURI);
		
		//獲取請求參數對應的那個字符串, 即 ? 後的那個字符串
		String queryString = httpServletRequest.getQueryString();
		System.out.println(queryString);

		//獲取請求的 Serlvet 的映射路徑 
		String servletPath = httpServletRequest.getServletPath();
		System.out.println(servletPath);

		//獲取web項目的根路徑
		String contextPath = httpServletRequest.getContextPath();
		System.out.println(contextPath);

		PrintWriter writer = response.getWriter();
		writer.println("helloworld");

	}

}



請問HttpServletRequest和ServletRequest的區別? 


servlet理論上可以處理多種形式的請求響應形式 
http只是其中之一 


所以HttpServletRequest、 HttpServletResponse分別是ServletRequest和ServletResponse的子類 


參考閱讀: 
========== 
HttpServletRequest和ServletRequest都是接口 
HttpServletRequest繼承自ServletRequest 
HttpServletRequest比ServletRequest多了一些針對於Http協議的方法。 
如 
getHeader(String name), 
getMethod() , 
getSession() 
等等。 
他們對應的實現類: 
javax.servlet.ServletRequestWrapper (implements javax.servlet.ServletRequest) 
javax.servlet.http.HttpServletRequestWrapper (implements javax.servlet.http.HttpServletRequest) 












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章