Servlet基礎知識
1.Servlet是什麼?
(1)執行在伺服器端的java程式
(2)作用:
++ 1.處理接收客戶端的請求
++ 2.處理請求後呼叫java程式中的程式碼,並給客戶端做出響應
++ 響應:HTML程式碼段、JSON 機制:IO輸出流,將服務端的資料輸出到客戶端
(1)HTML: 輸出的就是HTML程式碼段
(2) 使用json引入:阿里 fast-json
<!-- Fastjoson JSON處理工具 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency>
告訴客戶端我是什麼資料/客戶端傳送給服務端的資料型別: Content-type (mime型別)
(3)實時執行的容器(隨時監聽客戶端傳送的請求,隨時準備給客戶端傳送響應)
2.瞭解兩個JAVA WEB(J2EE)開發中常用的元件
(1)Maven
作用:
++管理專案包
++構建專案,打包專案
++管理專案之間程式碼的依賴
安裝方法:
1.官網下載軟體,地址:http://maven.apache.org/download.cgi
2.解壓
3.配置環境變數”MAVEN_HOME”為maven解壓的根目錄路徑
4.環境變數”path”新增,%MAVEN_HOME%\bin
5.測試maven配置是否成功,cmd>mvn - v ,有版本輸出則安裝配置完成
結構解析:
++ conf: 配置檔案路徑
(1)settings.xml : maven構建目錄配置檔案
```xml
```
<!-- 配置阿里雲倉庫 --> <mirror> <id>nexus-aliyun</id> <mirrorOf>*,!jeecg,!jeecg-snapshots,!getui-nexus</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
(2)Tomcat
是一個輕量的伺服器端WEB程式容器
作用:
++ 在伺服器端執行一個服務用於接收所有客戶端的請求轉發給Java容器程式碼(Servlet)
++ 可以部署多個java程式在服務端執行,且提供埠號和專案名進行訪問
++ 可以配置請求相關的內容,如:https(SSL證書加密的請求)
++ 請求網路相關的策略和Java程式碼解耦
安裝方法:
1.官網下載https://tomcat.apache.org/download-80.cgi
2.解壓
3.執行-》 執行:bin> startup程式(sh檔案:linux執行 bat:windows執行)
4.訪問:在瀏覽器導航窗體中輸入: http://tomcat所在的伺服器ip地址或域名: Tomcat的埠號 / 專案名
-
停止:執行:bin> shutdown程式(sh檔案:linux執行 bat:windows執行)
++ 在開啟的tomcat視窗 按 ctrl+C停止
結構解析:
++bin:Tomcat的執行檔案目錄(啟動 startup、停止 shutdown)
++conf:Tomcat配置檔案路徑
(1)server.xml : 配置容器服務配置項(Tomcat埠、Https配置、專案路徑配置...)
**(2) web.xml : Tomcat啟動專案配置檔案(不要修改,啟動的是Tomcat內建的專案)**
++ webapps : Tomcat要部署的專案資料夾
3.Servlet專案的構建(IDEA)
(1)使用idea構建專案
1.新建專案-》 Java Enterprise -》
++ name: 專案名
++ location: 專案檔案位置
++ Project Template:專案模板(選擇Web Application)
++ Application server:服務執行容器(TomEE)
++ bulid system : Maven
++ Group: 根包結構 (公司域名反寫)
++ Artfiact: 打包的專案名稱
點選OK
2.選擇依賴
++ 只選擇Servlet就可以
點選OK
(2)專案的結構
-
src>main>java: java原始碼目錄
-
src>main>resource :資原始檔夾(配置檔案)
-
src>main>webapp: 包含專案的靜態資原始檔、web動態配置檔案(Servlet執行配置)
++ WEB-INF》 web.xml : Servlet執行配置
- 和SRC目錄同級的pom.xml : maven依賴配置檔案
(3)IDEA 啟動專案的方式
1.在idea下配置Tomcat的方式
注意:idea下選擇服務容器選擇 Tomcat Server
(1)右上角-》找到Tomcat窗體點選-》 Edit Configuration.. 開啟窗體
(2)修改URL,點選Deployment-》Application context : 修改路徑
2.啟動點選Tomcat窗體右側的執行按鈕或者debug按鈕
3.停止點選紅色方塊停止
2.IDEA中maven的配置方式
4.Servlet第一個Demo
(1)編寫Servlet原始檔
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定mime型別為html
resp.setContentType("text/html;charset=UTF-8");
//準備返回給客戶端的html程式碼段
String str = "<span style='color:red;'>你好客戶端,我是伺服器!</span>";
//從響應物件獲取一個輸出流
PrintWriter writer = resp.getWriter();
//輸出客戶端
writer.write(str);
//輸出、關閉流
writer.flush();
writer.close();
}
}
(2)配置Servlet
在webapp資料夾下得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_4_0.xsd"
version="4.0">
<!-- 註冊Servlet類到容器中 -->
<servlet>
<!-- 給Servlet取個名字 -->
<servlet-name>ServletDemo1</servlet-name>
<!-- 註冊的servlet類的全包名路徑位置 -->
<servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
</servlet>
<!-- 配置請求URL路徑與Servlet的對映關係 -->
<servlet-mapping>
<!-- 要給哪個名字的Servlet配置對映 -->
<servlet-name>ServletDemo1</servlet-name>
<!-- url路徑與Servlet對映 -->
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
(3)編譯執行Tomcat
直接執行即可
(4)訪問Servlet
如:在瀏覽器位址列中輸入:
http://localhost:8080/JavaServletDemo/login
其中:
++localhost : Tomcat執行的計算機IP地址
++ 8080 : Tomcat的埠號
++ /JavaServletDemo : 專案名稱
++ /login : Servlet 的對映url-pattern
5.Servlet的生命週期方法
5.1 Servlet初始化-init()方法
定義在Servlet介面中,在GenericServlet類中重寫了這個方法,提供了一個過載的init方法
public void init(ServletConfig config) throws ServletException
在HttpServlet類中就沒有init方法了,我們需要重寫
/**
* Servlet初始化方法
* @throws ServletException
*/
@Override
public void init() throws ServletException {
System.out.println("Servlet初始化");
}
作用:
當請求訪問Servlet容器時,如果沒有建立Servlet例項,就會呼叫init方法,如果有例項則不會呼叫(Servlet單例模式)
5.2 請求響應處理-service()方法
作用:處理請求和響應
注意:如果是繼承了HttpServlet的Servlet例項,不要重寫service方法,因為在HttpServlet類內部已經重寫了該方法
HttpServlet中重寫的方法:
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
if (!(req instanceof HttpServletRequest &&
res instanceof HttpServletResponse)) {
throw new ServletException("non-HTTP request or response");
}
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
service(request, response); // 呼叫了自定義的過載的service方法
}
HttpServlet中過載的方法:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod(); //獲取請求的型別進行判斷
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
5.3 Servlet銷燬-destroy() 方法
作用:
當Servlet容器停止或者Servlet容器覺得你的Servlet例項應該銷燬就會被呼叫,自動化過程
@Override
public void destroy() {
System.out.println("銷燬!");
}
6.HTTP請求、響應
(1)請求組成
請求行/狀態行
頭資訊
實體
請求行:
GET /sample.jsp HTTP/1.1
請求頭:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate
引數:
username=chaidapeng&password=123456
(2)請求狀態碼
200 -》 請求成功
404 -》 請求資源不存在
403 -》請求方式不對
500 -》 後端程式碼異常
501 -》後端不支援RESTful介面
7.Servlet封裝的請求和響應物件
1.請求物件ServletRequest常用方法
(1)getParameter(String parameterName)查詢指定請求引數值
http://localhost:8080/JavaServletDemo/login?name=%E8%80%81%E6%9D%8E&age=18
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
System.out.println("引數name="+name);
System.out.println("引數age="+age);
}
(2)getParameterMap() 獲取請求引數的map集合
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> strings = parameterMap.keySet();
for(String key:strings){
String[] strings1 = parameterMap.get(key);
System.out.println("key:"+key+" value:"+ Arrays.toString(strings1));
}
(3)獲取客戶端請求的mime型別
String contentType = req.getContentType();
System.out.println(contentType);
(4)獲取客戶端的輸入流進行讀取getInputStream
ServletInputStream inputStream = req.getInputStream();
int available = inputStream.available();
byte [] arr = new byte[available];
System.out.println(available);
inputStream.read(arr);
System.out.println(new String(arr));
(5)獲取客戶端的ip、主機名、埠
//客戶端IP地址
String remoteAddr = req.getRemoteAddr();
//返回客戶端主機名
String remoteHost = req.getRemoteHost();
//客戶端埠號
int remotePort = req.getRemotePort();
System.out.println(remoteAddr+" "+remoteHost+" "+remotePort);
(6)獲取請求頭中得引數
請求頭引數如下:
請求頭:
Accept:image/gif,image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/4.0(compatible;MSIE5.01;Windows NT 5.0)
Accept-Encodin:gzip,deflate
String host = req.getHeader("Host");
System.out.println(host);
(7)在請求物件中新增或取得引數值(自定義)
//給請求物件新增引數
req.setAttribute("keyName","123");
//取得請求物件攜帶的引數
Object keyName = req.getAttribute("keyName");
2.響應物件ServletResponse
(1)獲取輸出流,向客戶端輸出資料getOutputStream
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.print("123");
outputStream.println("789");
outputStream.print("456");
outputStream.println("<h1>4444</h1>");//如果不設定contentType則按照字串輸出
outputStream.flush();
outputStream.close();
(2)返回可以向客戶端傳送字元資料的PrintWriter物件
同上,輸出htmldemo 在單元4
(3)設定請求和響應的字元編碼集
//設定請求、響應內容的字符集
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
(4)設定響應的mime型別
//設定請求、響應內容的字符集
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
比如:輸出一個json字串
//設定請求、響應內容的字符集
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter writer = resp.getWriter();
//設定響應的mime型別 json型別
resp.setContentType("application/json;charset=UTF-8");
User u1 = new User("高靖博",28);
//json字串轉換為物件
String u2 = "{name:'王丘',age:18}";
User parse = JSONObject.parseObject(u2,User.class);
System.out.println(parse.name+" "+parse.age);
//java物件轉為json字串
String s = JSON.toJSONString(u1);
System.out.println(s);
writer.print(s);
writer.flush();
writer.close();
8.ServletConfig 配置物件
作用:
++ 在Servlet例項的時候新增一些引數,然後通過servletConfig物件呼叫getInitParameter方法取得初始化引數
(1)配置初始化引數
在web.xml中對應的servlet標籤下配置init-param標籤
<!-- 註冊Servlet類到容器中 -->
<servlet>
<!-- 給Servlet取個名字 -->
<servlet-name>ServletDemo1</servlet-name>
<!-- 註冊的servlet類的全包名路徑位置 -->
<servlet-class>com.huawei.javaservletdemo.ServletDemo1</servlet-class>
<!-- servletConfig初始化配置引數 -->
<init-param>
<param-name>userName</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>pwd</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
(2)獲取servletConfig物件,獲取初始化引數值
方法一:重寫init方法,引數寫上ServletConfig物件引數
/**
* 重寫servlet中的init方法,且要帶上引數(ServletConfig config)
* 初始化方法
* @param config 初始化時例項ServletConfig引數物件
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
System.out.println("初始化");
//獲取servlet初始化引數
String userName = this.config.getInitParameter("userName");
System.out.println("userName:"+userName);
}
方法二:通過Servlet當前物件呼叫getServletConfig()方法獲取物件
ServletConfig servletConfig = this.getServletConfig();
System.out.println(servletConfig.getInitParameter("userName"));
(3)獲取所有的初始化引數名稱
//獲取初始化引數名稱的列舉物件
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
//迭代器遍歷列舉值
String s1 = initParameterNames.nextElement();
9.ServletContext 物件 Servlet上下文物件
獲取方式主要使用兩種:
//1.通過ServletConfig物件獲取
ServletContext servletContext = servletConfig.getServletContext();
//2.通過當前Servlet物件呼叫getServletContext獲取
ServletContext servletContext1 = this.getServletContext();
(1) 給上下文物件新增引數能夠在多個Servlet例項之間共享
如:在Servlet1中給ServletContext物件設定引數
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
System.out.println(servletConfig.getInitParameter("userName"));
//1.通過ServletConfig物件獲取
ServletContext servletContext = servletConfig.getServletContext();
//2.通過當前Servlet物件呼叫getServletContext獲取
ServletContext servletContext1 = this.getServletContext();
//設定引數
servletContext.setAttribute("qqNumber","123456789");
}
在Servlet2中獲取設定的引數
System.out.println("Servlet2被呼叫");
ServletContext servletContext = this.getServletContext();
System.out.println("在Servlet2中獲取:"+servletContext.getAttribute("qqNumber"));
10.Http請求響應
1.請求型別
(1)GET請求:
如:http://192.168.1.100:8080?name=高靖博&age=18
出現的情況:
++ 瀏覽器地址框請求是GET
++ 請求查詢指定伺服器資源是GET(獲取css、js、頁面、圖片、視訊..)
特點:
++ 請求引數是跟在請求url後面的
++ GET請求沒有請求體
(2)POST請求
如:表單提交 <form method="post">
當表單提交時就是POST請求
出現的情況:
++ 需要加密請求引數
++ 請求引數很多很長
特點:
++ 請求引數是在請求體重
++ 請求引數長度不限制
11.HttpServlet提供的請求(HttpServletRequest)和響應物件(HttpServletResponse)
httpservlet提供的請求和響應物件分別都繼承了servlet的請求和響應物件
1.HttpServletRequest 請求物件
(1)獲取客戶端的Cookie
/**
* Cookie客戶端會話儲存技術
*/
//服務端獲取Cookie的方法
Cookie[] cookies = req.getCookies();
if(cookies!=null){
for(int i=0;i< cookies.length;i++){
Cookie cookie = cookies[i];
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("name:"+name);
System.out.println("value"+value);
}
}
(2)獲取客戶端請求的URI和URL
//獲取客戶端請求的URI
String requestURI = req.getRequestURI();
//獲取客戶端請求的URL
StringBuffer requestURL = req.getRequestURL();
// /JavaServletDemo/login
System.out.println("requestURI"+requestURI);
// http://localhost:8080/JavaServletDemo/login
System.out.println("requestURL"+requestURL);
(3) 請求的查詢引數字串
//如請求: http://localhost:8080/JavaServletDemo/login?name=hhh&age=12
String queryString = req.getQueryString();
//name=hhh&age=12
System.out.println(queryString);
(4) 獲取請求的型別
String method = req.getMethod();
// GET
System.out.println(method);
2.HttpServletResponse 響應物件
(1) 給客戶端新增一個Cookie
//伺服器端可以建立一個cookie返回給客戶端
Cookie c = new Cookie("token","123456789");
c.setMaxAge(9999);//設定Cookie過期時間,單位秒
resp.addCookie(c);
(2) 獲取響應頭資訊和設定響應頭資訊
//覆蓋設定
resp.setHeader(“屬性名”,"屬性值");
//追加
resp.addHeader("屬性名","屬性值");
注意:只有響應物件可以取值和賦值,請求物件只能取得請求頭的值,不能設定