WEB核心技術-1
一個成熟的web需要運用到多種語言的書寫,這裡的資料庫連線我們已經學了使用jdbc以及mybatis的方式完成資料的獲取與修改
HTTP
請求體和i請求頭之間有空格隔開的
對應的引數存放到請求體中
GET/POST的區別
1.GET請求引數放到請求行中,沒用請求體。POST請求引數放到請求體中
2.GET請求請求引數大小有限制,POST 沒有
HTTP響應資料格式
WEB伺服器-Tomcat
這種類似的web伺服器是一個軟體,對http協議操作進行封裝,使程式設計師不必直接對協議進行操作,讓WEB開發更加快捷
可以將web專案部署到伺服器中,對外提供網上瀏覽服務
我們用的tomcat是一個輕量級web伺服器
這是一個綠色軟體直接解壓即安裝,刪除資料夾即解除安裝
開啟方式點開bin start.bat安全開啟,ctrl+c安全關閉
在idea中可以本地部署tomcat
也可以使用pom中新增配置
Servlet
Servlet快速入門
1.在pom檔案裡匯入依賴jar包,直接複製以後都是一樣的
這裡注意一定要定義一個scope為provided
2.寫一個方法完成servlet介面,重寫其方法
3.配置訪問路徑使其能被訪問到
這裡說一下我這裡困擾了一下午的tomcat頁面一直404輸入路徑也無法跳轉,最後我重新以模板的形式生成了maven新的工程,在pom中匯入tomcat就解決了,真是讓人頭疼
這裡我們的service方法裡只是寫了輸出語句,其實這是用來接收以及向伺服器返回資料的方法,之後學習了過後,會具體使用
servlet生命週期
package com.ember.web;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
其他兩個方法在需要使用時檢視javaee api
這裡說一下要在一個方法中使用另一個方法中的成員變數,則直接提升改成與變數的作用域
servlet體系結構
以上程式碼顯示servlet會根據頁面的訪問方式呼叫不同的方法,這裡用一個例子顯示了呼叫的是哪個方法我們通過a.html提交資料到demo3時使用的post方式則會呼叫dopost方法,直接訪問用get方式則使用doget方法
http協議裡一共有七種請求方式,對應了七種方法,用到的時候都是要複寫的
HttpServlet的使用步驟:1.寫類繼承HttpServlet2.重寫doget和dopost方法
使用原理:獲取請求方式,並且根據不同的請求方式,呼叫不同的doxxx方法
servlet urlPattern配置
一個servlet可以配置多個urlPattern,通過這些路徑都可以訪問到servlet
urlPattern的配置規則:
當一個路徑同時符合精確匹配也符和路徑匹配,則精確匹配的優先順序要高一點
一般只用前三種,第四種儘量不要使用
優先順序依次遞減
xml方式編寫servlet(舊方法,現在一般使用註解的方式配置)
1.繼承httpservlet
public class ServletDemo4 extends HttpServlet {
2、在web.xml裡面完成配置
<!-- servlet全類名-->
<servlet>
<servlet-name>renyi</servlet-name>
<servlet-class>com.ember.web.ServletDemo4</servlet-class>
</servlet>
<!-- servlet訪問路徑-->
<servlet-mapping>
<servlet-name>renyi</servlet-name>
<url-pattern>/demo4</url-pattern><!-- 配置可以訪問的路徑-->
</servlet-mapping>
很明顯註解的方式簡單多了
Request/Response
Request:獲取請求資料
Response:設定響應資料
以下程式碼實現以下瀏覽器的互動
當我們在網址後面輸入?name=xxx的時候頁面會根據名字內容更改顯示內容,這就是互動
Request繼承體系:
Tomcat需要解析請求資料,封裝為request物件,並且建立request物件傳遞到service方法中
要使用request物件,直接查閱javaee api文件的httpservletrequest介面
Request獲取請求資料
分為三步:獲取請求行&請求頭&請求體
下面寫一個例子
對於我們要向頁面傳入一些資訊我們可以寫一個表單完成資料傳入(注意這裡要使用get方式,應為我們是在doget方法中寫的測試)
<form name="user" action="/testtomcat2/req1" method="get">
username:<input name="uername">
password:<input name="password">
<input type="submit">
</form>
點選提交後會直接跳轉,資料會返回到控制檯
/*獲取請求頭
* user-agent獲取瀏覽器的版本*/
String agent = req.getHeader("user-agent");
System.out.println(agent);
以上呢get和post都會有,而請求體只有post請求才會有所以要測試請求體的方法則需要寫一個表單
<form action="/testtomcat2/req1" method="post">
使用者名稱: <input type="text" name="username">
密碼:<input type="password" name="password">
<input type="submit">
</form>
通過獲取位元組流或字元流獲得資料
Request通用方式獲取請求引數
因為一個servlet根據請求方式的不同會呼叫不同的方法,但是這兩個方法中只有獲取請求的方式這一段程式碼不同其他的都是差不多的,這就造成了程式碼的重複,所以我們可以使用一種統一的獲取請求引數的方式,從而統一doget和dopost方法內的程式碼
首先我們判斷是哪種請求在呼叫相應的獲取引數的方式,系統將這些引數封裝成一個Map集合,這三個方法就是request物件提供的通用獲取請求引數的方法,以下是對三個方法的實現例子
將doget裡面的程式碼全部複製到doget中也是可以獲取到資料的這就是通用的三個方法
因為裡面的程式碼是完全一樣的,所以我們的dopost方法裡只用呼叫doget就可以了
使用了通用方式之後,遮蔽了get和post的請求方式的不同,則我們可以使用servlet模板來建立servlet
可以根據需要去改造模板
Request post請求引數中文亂碼處理
這是我們寫了一個例子來獲取使用者名稱,並且在html頁面中提交了中文使用者名稱導致的亂碼
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 獲取username
String username = request.getParameter("username");
System.out.println(username);
}
// 解決亂碼 POST.getReader()獲取字元流預設的編碼不是utf-8,所以post請求的中文會亂碼
request.setCharacterEncoding("UTF-8");/*設定字元輸入流的編碼*/
在最上面加入如上程式碼,改變其編碼與html相同
GET請求解決方案
解決中文亂碼 get 亂碼原因:瀏覽器處理資料進行url編碼(UTF-8),伺服器接收資料再進行url解碼(ISO-8859-1),但是編碼解碼使用的字符集不一樣導致亂碼,只能從url編碼底層入手
以下是對get請求傳入中文的username解決辦法
/*1.先對亂碼資料進行編碼,轉為位元組陣列*/
// byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
// /*位元組陣列解碼*/
// username = new String(bytes, StandardCharsets.UTF_8);
username=new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
System.out.println("解決亂碼後"+username);
熟練過後將上面兩行程式碼合併成一行了,這種方式是一種通用的方式同樣可以解決post亂碼
Request請求轉發
一種在伺服器內部的資源跳轉方式
// 請求轉發
request.getRequestDispatcher("/req6").forward(request,response);
將請求轉發給另一個路徑,一般兩個路徑要共享資料
在req5頁面中請求轉發
System.out.println("demo5''''[''");
// 儲存資料
request.setAttribute("msg","hello");
// 請求轉發
request.getRequestDispatcher("/req6").forward(request,response);
在req6中接收請求
獲取資料
Object msg = request.getAttribute("msg");
System.out.println(msg);
System.out.println("demo6'''''''");
}
轉發的特點:
瀏覽器位址列路徑不發生改變
只能轉發到當前伺服器的內部資源
一次請求,可以在轉發資源間使用request共享資料
Response設定響應資料
以下是響應資料的分類以及對應的設定的方法
Response完成重定向
即當不能處理請求的時候返回其他路徑
即分為兩步:
1.返回狀態碼302
2.返回跳轉路徑
實現:
resp.setStatus(302);
resp.setHeader("location","資源b的路徑")
以下例子
resp1
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("resp1..........");
// 重定向
// 1.設定響應資料碼302
response.setStatus(302);
// 2.設定響應頭Location
response.setHeader("Location","/testtomcat2/resp2");//注意資源路徑要寫伺服器的虛擬字首
}
resp2
只要訪問resp1就自動跳轉到resp2
可以發現這個程式碼只有跳轉的路勁會有改變所以以後這樣寫
// 簡化方式完成重定向
response.sendRedirect("/testtomcat2/resp2");
(注意:可以重定向到任意路徑)
對於路徑書寫
瀏覽器使用:需要加虛擬目錄(專案訪問路徑)
服務端使用:不加虛擬目錄(即不需要瀏覽器跳轉頁面訪問)
對於要加虛擬路徑的時候直接寫虛擬目錄,使得耦合性太強了,以後一改路勁就會出錯,所以我們一般採用動態路徑
// 簡化方式完成重定向
// response.sendRedirect("/testtomcat2/resp2");
// 動態獲取虛擬目錄
String contextPath = request.getContextPath();
response.sendRedirect(contextPath+"resp2");
Response響應字元&位元組資料
獲取位元組流就是使用的獲取方法不一樣,用與獲取一些檔案並輸出
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 獲取檔案
FileInputStream fis = new FileInputStream("C://Users//Ember//Desktop//icon//file.png");
// 2.獲取Response位元組輸出流
ServletOutputStream os = response.getOutputStream();
// 3.完成流的Copy
byte[] buff=new byte[1024];
int len=0;
while((len=fis.read(buff))!=-1){
os.write(buff,0,len);
}
fis.close();
}
這種複製方法是javaIO中的知識,我們一般使用工具類來簡化
先去pom裡增加依賴
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
匯入後即可使用IOUtils的方法了
// 3.完成流的Copy
// byte[] buff=new byte[1024];
// int len=0;
// while((len=fis.read(buff))!=-1){
// os.write(buff,0,len);
// }
IOUtils.copy(fis,os);
fis.close();
(注意:這裡選著IOUtils時要注意匯入的包是apache)
案例:使用者登入&使用者註冊
1.使用者登入
首先在我們之前建立了maven外掛以及servlet的工程裡首先配置好mybatis需要的環境
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- junit 單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<!-- 新增slf4j日誌api -->
<dependency>
<groupId>org.slf4j</groupId>