C# 名稱空間
基本概念
在java中,動態資源開發的技術稱為javaweb
web開發
- web,網頁的意思
- 靜態web
- html css
- 提供給所有人看的資料一樣
- 動態web
- 淘寶,幾乎所有的網站
- 提供所有人看的資料始終會發生變化,每個人在不同時間,不同地點看的資訊各不相同
- 技術棧:Servlet/JSP ASP PHP
web應用程式
可以提供瀏覽器訪問的程式
- a.html b.html ....多個web資源,這些web資源可以被外界訪問,對外界提供服務
- URL
- 一個web應用由多部分組成(靜態web,動態web)
- html css
- jsp servlet
- java程式
- jar包
- 配置檔案(properties)
- web應用程式編寫完畢,若想提供給外界訪問,需要一個伺服器來統一管理
Tomcat
安裝
安裝tomcat,之前需要先安裝一下jdk,用java -version
檢查
官網目前已經更新到tomcat10了
下載壓縮包之後,直接解壓
啟動
如果你直接點選bin目錄下的startup.bat,可能會出現一閃而過
你需要在控制檯中輸入
之後在網頁上輸入localhost:8080
,就會顯示
但是,執行結果可能會出現亂碼
修改conf目錄下的logging.properties檔案
將檔案中原有的配置修改
#原有 java.util.logging.ConsoleHandler.encoding = UTF-8 #修改成GBK,因為windows預設是gbk java.util.logging.ConsoleHandler.encoding = GBK
訪問測試:localhost:8080
資料夾對應作用
--webapps Tomcat伺服器的web目錄
-ROOT
-project 網站的目錄名
-WEB-INF
-classes java程式
-lib web應用所依賴的jar包
-web.xml 網站配置檔案
- index.html 預設的首頁
- static
-css
-style.css
-js
-img
-....
HTTP
什麼是HTTP
HTTP(超文字傳輸協議)是一個簡單的請求—響應協議,它通常是執行在TCP上
-
文字:html,字串
-
超文字:圖片,音樂,視訊,地圖,定位...
-
80埠
Https:安全的
- 443埠
HTTP請求
- 客戶端——發請求(Request)——伺服器
百度的例子
Request URL: https://www.baidu.com/?tn=78040160_14_pg&ch=8 請求地址
Request Method: GET get/post
Status Code: 200 OK 狀態碼:200
Remote Address: 163.177.151.110:443 遠端地址
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
- 請求行
- 請求方式:GET,POST
- get:請求能攜帶的引數比較少,大小有限制,不安全但高效
- post:請求能攜帶的引數沒有限制,大小沒有限制,安全但不高效
- 請求方式:GET,POST
- 請求頭
Accept: 告訴瀏覽器,它支援的資料型別
Accept-Encoding: 支援哪種編碼格式 GBK,UTF-8,GB312 ..
Accept-Language: 告訴瀏覽器,他的語言環境
Cache-Control: no-cache 快取控制
Connection: 告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機
HTTP響應
- 伺服器——響應——客戶端
百度的例子
Cache-Control: private 快取控制
Connection: keep-alive 連線
Content-Type: text/html;charset=utf-8
- 響應體
Accept: 告訴瀏覽器,它支援的資料型別
Accept-Encoding: 支援哪種編碼格式 GBK,UTF-8,GB312 ..
Accept-Language: 告訴瀏覽器,他的語言環境
Cache-Control: no-cache 快取控制
Connection: 告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機
Refrush:告訴客戶端,多久重新整理一次
Location讓網頁重新定位
- 響應狀態碼
響應狀態碼 | 描述 |
---|---|
200 | 請求成功 |
3** | 請求重定向 |
4** | 找不到 |
5** | 伺服器錯誤 |
502 | 閘道器錯誤 |
面試題
當你的瀏覽器中輸入地址並回車的一瞬間到頁面能夠展示回來,經歷了什麼
- DNS解析
- 瀏覽器的DNS快取
- 系統的DNS快取
- 路由器的DNS快取
- 網路運營商的DNS快取(中國移動,中國電信)
- 上述都沒有找到,則會採用遞迴的方式,向根服務器進行查詢,根伺服器告訴本地DNS伺服器域的伺服器地址,本地DNS向域伺服器發出請求,域伺服器告訴本地伺服器域名解構伺服器的地址,本地伺服器向域名解構伺服器發出請求,收到域名和IP的關係,本地伺服器再返回給瀏覽器並將對應關係儲存在快取中,以下一次使用
- DNS優化
- DNS快取
- DNS存在很多級快取,從離瀏覽器的距離排序,(瀏覽器快取,系統快取,路由器快取,IPS伺服器快取,根域名伺服器快取,頂級域名伺服器快取,主域名伺服器快取)
- DSN負載均衡
- DNS可以返回一個合適的機器的IP給使用者,例如可以根據每臺機器的負載量,該機器離使用者地理位置的距離等等
- DNS快取
- 當瀏覽器拿到IP後,就向伺服器傳送http連線請求,三次握手
- 傳送請求
- 接受響應
- 瀏覽器頁面渲染
- 處理HTML標記並構建DOM樹
- 處理CSS標記並構建CSSDOM樹
- 將DOM和CSSDOM合併為一棵渲染樹
- 根據渲染樹來佈局,以計算每個節點的幾何資訊(重排)
- 將各個節點繪製到螢幕(重繪)
- 如果DOM和CSSDOM被修改,以上過程需要重複執行,才能計算出哪些畫素需要在螢幕上進行重新渲染
- 斷開連線“TCP四次揮手"
Maven
為什麼學習Maven?
在javaWeb開發中,需要大量的jar包,我們需要手動匯入。Maven就是為了方便匯入jar包
安裝Maven
下載完成後解壓
配置環境變數
在我們系統環境變數中
配置如下環境變數
名稱 | 具體含義 |
---|---|
M2_HOME | maven目錄下的bin目錄 |
MAVEN_HOME | maven目錄 |
在系統變數PATH中配置MAVEN_HOME | %MAVEM_HOME%\bin |
測試Maven 是否安裝成功mvn -version
修改setting.xml
路徑:D:\Environment\maven\apache-maven-3.5.4\conf\settings.xml
在setting.xml中配置映象(為了下載依賴的速度變快)和本地倉庫(設定依賴的下載位置)
阿里雲映象
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
本地倉庫
配置好之後,在本地需要新建一個資料夾soft(資料夾名可以自己設定。比如repo,repository)
<!-- 本地倉庫位置 -->
<localRepository>D:/Environment/maven/soft</localRepository>
在Maven中建立一個帶模板專案
在IDEA中啟用使用Maven
建立專案
在專案建立成功後,檢查一下是否正確(看一眼,萬一依賴下載到C盤要炸,越來越多後面電子會“炸”)
補充資料夾
補充資料夾java和resources,標記資料夾功能
- java ——>Sources Root
- resources——>Resources Root
- resources資料夾是給java檔案讀取的
修改web.xml
使用模板新建的專案,web.xm
l太舊了
使用下載的tomcat中的web.xml
路徑:D:\Environment\apache-tomcat-9.0.37\webapps\ROOT\WEB-INF
<?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"
metadata-complete="true">
</web-app>
在Maven中建立一個普通專案
在New Project中不選擇模板,直接點選Next
WEB-INF使用者不可見的,所以,如果你將jquery的包放在WEB-INF中,html中是拿不到的
pom.xml
maven由於他的約定大於配置,我們之後可能遇到的問題,無法匯入或者生效的問題
Maven手動匯入jar
下載jar包
匯入jar
Add as Library
右鍵lib資料夾
在IDEA中配置Tomcat
配置Tomcat
沒有配置Deployment
,會碰到如下警告
碰到的問題
啟動tomcat
解決碰到的問題
- Maven 3.6.2
解決方法:降級為3.6.1
- iDEA中每次都要重複配置Maven
解決方法:在IDEA中全域性預設配置去配置
- ,maven預設專案中web.xml版本問題
解決方法:在Tomcat目錄下的webapps/ROOT/WEB-INF
中複製(將一些沒用的刪除),替換為webapp4.0版本和tomcat一致
<?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"
metadata-complete="true">
</web-app>
Servlet
Servlet簡介
- servlet是sun公司開發動態web的一門技術
- sun公司在這些API中提供了一個介面叫做Servlet,如果你想開發一個servelt,只需要完成2個步驟
- 編寫好一個類,實現servlet介面
- 把開發好的java類部署到web伺服器中
把實現了servlet介面的java程式叫做Servlet
HelloServlet
-
構建一個普通的Maven專案是,刪除裡面的src目錄,以後就在這個專案中建立一個Moudel,這個空的工程就是Maven的主工程
-
Maven父子工程的理解
父專案中會有
<modules> <module>servlet-01</module> </modules>
子專案會有(如果沒有的話下面這段,自己加一個)
比如我建立的一個Moudle就沒有自動生成,就需要自己寫,還有刪除一些自帶的
<modelVersion>4.0.0</modelVersion> <parent> <artifactId>javaweb-servlet-01</artifactId> <groupId>com.study</groupId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>servlet01</artifactId> <packaging>war</packaging>
優點:父專案中的jar包可以在子專案中使用
-
Maven環境優化
-
修改web.xml為最新的
-
將Maven的結構搭建 java resource
-
編寫一個Servlet程式
- 編寫一個普通類
- 實現Servlet介面,直接繼承HttpServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
//由於get 和 post 只是請求實現的不同的方式 可以相互呼叫 業務邏輯都一樣
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();//響應流
writer.println("hello servlet !");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 編寫Servlet的對映
- 為什麼需要對映:因為我們寫的是java程式,但是要通過瀏覽器訪問,而瀏覽器需要連線web伺服器,所以我們需要在web服務中註冊我們寫的servlet,還需要給他一個能夠訪問的路徑
<!-- 註冊servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<!-- servlet的請求路徑-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置tomcat
- 啟動測試,OK!
Mapping
一般是用一個servlet可以指定一個對映路徑
- 一個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>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</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>*.do</url-pattern>
</servlet-mapping>
ServletContext上下文
web容器在啟動的時候,他會為每一個web程式都建立一個對應的ServletContext物件,他代表當前的web應用
共享資料
我們在HelloServlet中儲存資料,可以在另外一個servlet中拿到
儘量不要用ServletContext來共享資料,資料一多會炸,可以使用session
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");
System.out.println(username);
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().print("名字:"+username);
}
}
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello");
ServletContext context = this.getServletContext();
String username = "DJ";
context.setAttribute("username",username);//將一個數據儲存在servletContext中
}
}
讀取資原始檔
ProPerties
- 在java目錄下新建properties
- 在resources目錄下新建propertites
發現都被打包到同一個路徑下:classes,我們俗稱這個路徑是classpath
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//這個路徑主要是針對target生成的
InputStream is= context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(username+" "+ password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpServletResponse
使用例子
向瀏覽器輸出訊息
(上面一直提到)
下載檔案
- 要獲取下載的檔案的路徑
- 設定下載的檔名
- 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
- 獲取下載檔案的輸入流
- 建立緩衝區
- 獲取OutputStream物件
- 獲取OutputStream流寫入到buffer緩衝區
- 使用OutputStream將緩衝區中的資料輸出到客戶端
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要獲取下載的檔案的路徑
String realPath="D:\\Project\\javawebservlet01\\response\\target\\classes\\圖片.png";
System.out.println("下載檔案的路徑"+realPath);
// 2. 設定下載的檔名
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
System.out.println("檔名"+fileName);
// 3. 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
//web下載檔案的頭資訊 URLEncoder.encode 處理檔名亂碼
resp.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
// 4. 獲取下載檔案的輸入流
FileInputStream in = new FileInputStream(realPath);
// 5. 建立緩衝區
int length=0;
byte[] buffer = new byte[1024];
// 6. 獲取OutputStream物件
ServletOutputStream out = resp.getOutputStream();
// 7. 獲取OutputStream流寫入到buffer緩衝區 使用OutputStream將緩衝區中的資料輸出到客戶端
while((length=in.read(buffer))>0){
out.write(buffer,0,length);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
定時重新整理驗證碼
採用的其實是重新整理整個頁面
package com.study.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//讓瀏覽器3s自動重新整理一次
resp.setHeader("refresh","3");
//在記憶體中建立一張圖片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到圖片
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//給圖片寫資料
g.setColor(Color.green);
g.setFont(new Font(null,Font.BOLD,20));
String num = makeNum();
System.out.println(num);
g.drawString(num,0,20);
//告訴瀏覽器,這個請求用圖片的方式開啟
resp.setContentType("image/jpeg");
//把圖片寫到瀏覽器 jpg表示檔案格式名
ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String num = random.nextInt(1000000)+"";//[0,100000)
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0;i<6-num.length();i++){
stringBuffer.append("0");
}
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
重定向
URL會發生變化
一個web資源收到客戶端A請求後,B通知客戶端A去訪問另外一個web資源C,這個過程叫重定向
void sendRedirect(String var1) throws IOException;
常見的例子:登入狀態
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定後臺傳給前臺的資料不是亂碼
resp.setCharacterEncoding("UTF-8");//不然頁面顯示會亂碼
resp.sendRedirect("/response_war/img");
}
<form action="${pageContext.request.contextPath}/redi" method="get">
username:<input type="text" name="username" /><br/>
password:<input type="text" name="password" /><br/>
<input type="submit">
</form>
面試題:重定向和請求轉發的區別
- 相同點
- 頁面都會發生跳轉
- 不同點
- 請求轉發的時候URL不會發生變化 307
- 重定向的時候,URL發生後變化 302
HttpServletRequest
//常用方法
//1. 獲得前臺的引數
//設定前臺傳給後臺的資料不是亂碼
req.setCharacterEncoding("UTF-8");
req.getParameter("username");
req.getParameterValues("hobbys");
//2. 通過請求轉發
// /success.jsp /代表當前的web應用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
Cookie,Session
會話
會話:使用者開啟一個瀏覽器,點選瀏覽很多連結,訪問了多個web資源,關閉瀏覽器,這個過程就是會話
有狀態會話:
一個網站,怎麼證明你來過?
客戶端 服務端
- 服務端給客戶端一個信件,客戶端下次訪問服務端就帶上一個信件就可以了 cookie
- 伺服器登記你來過了,下次你來的時候我來匹配你:session
儲存會話的兩種技術
Cookie
cookie:一般會儲存在本地的使用者目錄下 appdata
//從請求中拿到cookie拿到cookie的資訊
//伺服器響應給客戶端cookie
Cookie[] cookies = req.getCookies(); //獲得cookie
cookie.getName();//獲得cookie的key
cookie.getValue();//獲得cookie的value
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一個cookie
cookie.setMaxAge(24*60*60); //設定cookie的有效期,若沒有設定,關閉瀏覽器cookie就失效
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
//儲存使用者上一次訪問的時間
public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//伺服器 告訴你 你來的時間, 把這個時間封裝成一個信件,你下次帶來,我就知道了
//解決中文亂碼
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
PrintWriter out = resp.getWriter();
//Cookie 伺服器從客戶端獲取
Cookie[] cookies = req.getCookies();
if(cookies!=null){
//如果存在,遍歷陣列
out.write("你上一次訪問的時間是");
for(Cookie cookie:cookies){
if("lastLoginTime".equals(cookie.getName())){
//獲取cookie的值
System.out.println(cookie.getValue());//String
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.write("這是第一次訪問本站");
System.out.println("這是第一次訪問本站");
}
//伺服器給客戶端響應一個cookie
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
//有效期為一天 s
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Session(重點)
什麼是Session
- 伺服器會給每一個使用者(瀏覽器)建立一個Session物件
- 一個Session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就一直存在
- 使用者登入之後,整個網站都可訪問
//建立session 並且給屬性賦值,也是可以存放一個物件的
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class CookieDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決中文亂碼
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
//得到session
HttpSession session = req.getSession();
//給Session中存在東西
session.setAttribute("name","張三");
//獲得session的ID
String id = session.getId();
//判斷Session 是不是新建立的
if(session.isNew()){
resp.getWriter().write("session建立成功ID"+id);
}else{
resp.getWriter().write("session已經建立成功ID"+id);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
//取出session的值
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class CookieDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決中文亂碼
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf-8");
//得到session
HttpSession session = req.getSession();
//取Session中存在東西
resp.getWriter().write(session.getAttribute("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
設定session的失效時間
在web.xml
<!-- 設定session的失效時間 單位:分鐘-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
在程式碼中
session.removeAttribute("name");
session.invalidate();
Session和Cookie的區別
- session儲存在伺服器端,cookie儲存在瀏覽器。
- session比較安全,cookie用某些手段可以修改,不安全。
- cookie的儲存量有限、只允許存入4KB,而session是無限量的
使用場景:
- 儲存一個登入使用者的資訊
- 購物車資訊
- 在整個網站中經常使用的資料,將他儲存在session
JSP
什麼是jsp
java server pages :java伺服器頁面,也和servlet一樣,使用者動態web技術
最大的特點
- 寫JSP就像在寫HTML
- 區別
- HTML只給使用者提供靜態的資料
- jsp頁面可以嵌入java程式碼,為使用者提供動態資料
JSP原理
思路 JSP是怎麼執行的
- 程式碼層面沒有任何問題,和html程式碼很像
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
- 伺服器內部工作
tomcat 中有一個work目錄
IDEA中使用Tomcat的會在IDEA生成一個work目錄
D:\Environment\apache-tomcat-9.0.37\work\Catalina\localhost\ROOT\org\apache\jsp
發現頁面變成了java程式,jsp最終會被轉換成一個java類
- 瀏覽器向伺服器傳送請求,不管訪問什麼資源,其實都是在訪問Servlet
- JSP本質上就是一個servlet
final javax.servlet.jsp.PageContext pageContext;//頁面上下文
javax.servlet.http.Httpsession session=null;//Session
final javax.servlet.Servletcontext application;//application
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out=null;//out
final java.lang.Object page = this;//pag e當前頁
HttpServletRequest request;//請求
HttpServletReponse reponse ;//響應
在JSP頁面中
只要是JAVA程式碼就會原封不動的輸出
如果是HTML程式碼,就會被轉換為
out.writer("<html>\r\n")
JSP基礎語法
jsp表示式
<%=new java.util.Date()%>
jsp指令碼片段
<%for(int i = 0;i<10;i++){%>
<p>123</p>
<%}%>
jsp宣告
<%!
static {
system. out. println(" Loading Servlet! ");
}
private int globalvar =0;
public void f(){
system. out printIn("進入了方法 ");
}
%>
JSP宣告:會被編譯到JSP生成ava的類中!其他的,就會被生成到 jspService方法中
<!--我是Html註釋->
<%--我是JSP註釋--%>
jsp的註釋不會在客戶端顯示,html的註釋可以看到
九大內建物件
- PageContext 存東西
- Request 存東西
- Response
- Session 存東西
- Application【ServeltContext】存東西
- config【ServletConfig】
- out
- page 不用瞭解
- exception
request:客戶端向伺服器傳送請求,產生的資料,使用者看完就沒用了,比如:新聞,使用者看完沒用了
session:客戶端向伺服器傳送請求,產生的資料,使用者用完一會還有用,比如:購物車
application:客戶端向伺服器傳送請求,產生的資料,一個使用者用完,其他使用者還可以使用,比如:聊天記錄
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--http://localhost:8080/jsp01_war_exploded/pageContextDemo01.jsp--%>
<%--內建物件--%>
<%
pageContext.setAttribute("name1","張三");// 儲存的資料只在一個頁面中有效,在另外一個頁面就請求不到了
request.setAttribute("name2","李四");//儲存的資料只有在一次請求中有效,請求轉發會攜帶這個資料
session.setAttribute("name3","王五");//儲存的資料只在一次會話中有效,從開啟瀏覽器到關閉瀏覽器
application.setAttribute("name4","小李");//儲存的資料只在伺服器中有效,從開啟伺服器到關閉伺服器
%>
<%
// 通過pageContext取出我們儲存的值
//pageContext取出,我們通過尋找的方式來
//從底層到高層(作用域)page->request->session->application
String name1=(String)pageContext.findAttribute("name1");
String name2=(String)pageContext.findAttribute("name2");
String name3=(String)pageContext.findAttribute("name3");
String name4=(String)pageContext.findAttribute("name4");
//pageContext.forward("/pageContextDemo02.jsp"); 測試request請求轉發的作用域
%>
<%--使用EL表示式輸出 ${}--%>
<%--一般取值就用EL表示式,比%=好,因為會自動過濾null的值--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
</body>
</html>
JSTL標籤、EL表示式(${})
JSTL標籤庫的使用為了彌補HTML標籤不足;它自定義了許多標籤,可以供我們使用,標籤的功能和java程式碼一樣
核心標籤
標籤 | 描述 |
---|---|
<c:out> |
用於在JSP中顯示資料,就像<%= ... > |
<c:set> |
用於儲存資料 |
<c:remove> |
用於刪除資料 |
<c:if> |
與我們在一般程式中用的if一樣 |
<c;choose> |
本身只當做<c:when>和<c:otherwise>的父標籤 |
<c:when> |
<c:choose>的子標籤,用來判斷條件是否成立 |
<c:otherwise> |
<c:choose>的子標籤,接在<c:when>標籤後,當<c:when>標籤判斷為false時被執行 |
<cLforeach> |
基礎迭代標籤,接受多種集合型別 |
<c:url> |
使用可選的查詢引數來創造一個URL |
JSTL標籤使用步驟
- 引入對應的taglib
- 使用其中的方法
- 在Tomcat也需要引入jstl的包,否則會出現500
- lib目錄下
D:\Environment\apache-tomcat-9.0.37\lib
- lib目錄下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if測試</h4>
<form action="coreif.jsp" method="get">
<%-- EL表示式獲取表單中資料--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登入">
</form>
<%--判斷如果提交的是使用者名稱是admin就登入成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理員歡迎你"/>
</c:if>
<c:out value="${isAdmin}"/>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:set var="score" value="55" />
<c:choose>
<c:when test="${score>=90}">
優秀
</c:when>
<c:when test="${score>=80}">
良好
</c:when>
<c:when test="${score>=60}">
合格
</c:when>
<c:otherwise >
不及格
</c:otherwise>
</c:choose>
</body>
</html>
JavaBean
javaBean有特定的寫法
- 必須有一個無參構造
- 屬性必須私有化
- 必須有對應的get/set方法
一般和資料庫的欄位做對映
ORM 物件關係對映
- 表——>類
- 欄位——>屬性
- 行記錄——>物件
注意:一定要每一個欄位都和實體類的屬性對應
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--stu = new Test();--%>
<jsp:useBean id="test" class="com.jmu.vo.Test" scope="page"/>
<jsp:setProperty name="test" property="id" value="1018" />
<jsp:setProperty name="test" property="name" value="大東" />
<jsp:getProperty name="test" property="id"/>
<jsp:getProperty name="test" property="name"/>
</body>
</html>
MVC三層結構
Filter
Filter:過濾器,用來過濾網站的資料
- 處理中文亂碼
- 登入驗證
Filter開發步驟:
-
編寫過濾器
- 匯入不要錯
import javax.servlet.*;
- 匯入不要錯
package com.jmu.fiter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web伺服器啟動,就一起初始化,隨時等待過濾物件出現
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("執行前");
filterChain.doFilter(servletRequest,servletResponse);//讓我們的請求繼續走,如果不行,程式執行到這裡就被攔截
System.out.println("執行後");
}
//銷燬 web伺服器關閉的時候,過濾會銷燬
public void destroy() {
System.out.println("銷燬");
}
}
- 在web.xml中配置filter
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>com.jmu.fiter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<!-- 只要是/filter/*的任何請求就執行過濾器-->
<url-pattern>/filter/*</url-pattern>
</filter-mapping>
例子
使用者登入之後,才能進入主頁,使用者登出後就不能進入主頁
- 使用者登入之後,向session放入使用者的資料,並且重定向到主頁
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");//重定向
- 登出
if(req.getSession().getAttribute("USER_SESSION")!=null){
req.getSession().removeAttribute("USER_SESSION");
}
resp.sendRedirect("/login.jsp");
- 將主頁放在sys資料夾中,當session("USER_SESSION")為空的時候,就跳轉到登入頁面
package com.jmu.fiter;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//如果沒有強轉 ServletRequest沒有getSession方法
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
if((req.getSession().getAttribute("USER_SESSION"))==null){
resp.sendRedirect("/login.jsp");
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
xml
<filter>
<filter-name>sysFilter</filter-name>
<filter-class>com.jmu.fiter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
練習登入
專案搭建
- 搭建一個maven web專案
- 配置tomcat
- 修改web.xml
- 測試專案是否能夠跑起來(localhost:8080/)He
- 匯入專案中會遇到的jar
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- Servlet依賴-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP依賴-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!-- jstl表示式的依賴-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- standar標籤庫-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
-
建立專案結構 java main(com.jmu.dao/filter/vo/servlet/service/util) resources
- dao層用來和資料庫互動並返回結果
- service業務層(判斷使用者是否登入成功)
- servlet呼叫控制層
- filter過濾器
- util工具類
-
編寫實體類vo
-
編寫基礎公共類
- resources中db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=true
username = root
password = 123456
-
編寫資料庫工具類
-
編寫字元編碼過濾器filter(上面有寫過的)
-
在webapp匯入靜態資源css js image等等 在webapp下新建static再放
登入功能實現
- 登入頁面(在jsp資料夾下新建一個主頁home.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--login.jsp--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login.do" method="post">
使用者名稱 <input type="text" name="username"/><br/>
密碼 <input type="password" name="password"/><br/>
<input type="submit" value="登入" />
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--home.jsp--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>主頁</h1>
<a href="${pageContext.request.contextPath}/logout.do">登出</a>
</body>
</html>
- 在web.xml中將登入頁面設為首頁,不是index.jsp
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
- 編寫介面UserDao
package com.jmu.dao;
import com.jmu.vo.User;
public interface UserDao {
//通過username得到登入的使用者
public User getLoginUser(String username);
}
- 編寫介面UserDao的實現類UserDaoImpl
package com.jmu.dao;
import com.jmu.util.JdbcUtil;
import com.jmu.vo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDaoImpl implements UserDao{
@Override
public User getLoginUser(String username) {
Connection conn = null;
PreparedStatement pst =null;
User user = null;
try {
conn = JdbcUtil.getConnection();
String sql = "select * from user where username = ?";
pst = conn.prepareStatement(sql);//預編譯
//傳遞引數
Object[] params = {username};
for(int i = 0;i<params.length;i++){
pst.setObject(i+1,params[i]);
}
ResultSet rs = pst.executeQuery();
while(rs.next()){
int auto_id=rs.getInt("auto_id");
String password=rs.getString("password");
int age=rs.getInt("age");
user = new User(auto_id,username,password,age);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtil.release(conn,pst,null);
}
return user;
}
}
- 編寫業務層介面UserService
package com.jmu.service;
import com.jmu.vo.User;
public interface UserService {
//使用者登入
public User login(String username, String password);
}
- 業務層實現類UserServiceImpl
package com.jmu.service;
import com.jmu.dao.UserDao;
import com.jmu.dao.UserDaoImpl;
import com.jmu.vo.User;
import org.junit.Test;
public class UserServiceImpl implements UserService {
//業務層都會呼叫dao層,所以我們要引入Dao層
private UserDao userDao;
public UserServiceImpl(){
userDao = new UserDaoImpl();
}
@Override
public User login(String username, String password) {
User user = null;
user = userDao.getLoginUser(username);
//對比密碼
if(user!=null&&user.getPassword().equals(password)){
return user;
}else{
return null;
}
}
@Test
public void test(){
System.out.println(new UserServiceImpl().login("user02","122").toString());
}
}
- 編寫servlet
登入servlet
package com.jmu.servlet;
import com.jmu.service.UserService;
import com.jmu.service.UserServiceImpl;
import com.jmu.util.Constants;
import com.jmu.vo.User;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username=req.getParameter("username");
String password=req.getParameter("password");
//和資料庫中的密碼進行對比 呼叫業務層
UserService userService=new UserServiceImpl();
User user =userService.login(username,password);
if(user!=null){
//將使用者資訊儲存到session裡面
req.getSession().setAttribute(Constants.USER_SESSION,user);
//跳轉到主頁
resp.sendRedirect(req.getContextPath()+"/jsp/home.jsp");
}else{
//跳轉到ERROR
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 註冊servlet
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.jmu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
- 執行測試