JavaWeb知識梳理(可收藏)
- 2022 年 4 月 6 日
- 筆記
**JavaWeb相關知識 **
1、Servlet
1.1 Status Code(Http狀態碼)
1、1xx 請求資訊
Http狀態碼 | Http Status Code | Http狀態碼含義中文說明 |
---|---|---|
100 | 100 Continue | 請繼續請求 |
101 | 101 Switching Protocols | 請切換協議 |
102 | 102 Processing | 將繼續執行請求 |
2、2xx 成功狀態
這一組狀態碼錶明客戶端的請求已經被伺服器端成功接收並正確解析。
Http狀態碼 | Http Status Code | Http狀態碼含義中文說明 |
---|---|---|
200 | 200 OK | 請求成功 |
201 | 201 Created | 請求已被接受,等待資源響應 |
202 | 202 Accepted | 請求已被接受,但尚未處理 |
203 | 203 Non-Authoritative Information | 請求已成功處理,結果來自第三方拷貝 |
204 | 204 No Content | 請求已成功處理,但無返回內容 |
205 | 205 Reset Content | 請求已成功處理,但需重置內容 |
206 | 206 Partial Content | 請求已成功處理,但僅返回了部分內容 |
207 | 207 Multi-Status | 請求已成功處理,返回了多個狀態的XML消息 |
208 | 208 Already Reported | 響應已發送 |
226 | 226 IM Used | 已完成響應 |
3、3xx 重定向狀態
這一組狀態碼錶示客戶端需要採取更進一步的行動來完成請求。通常,這些狀態碼用來重定向,後續的請求地址(重定向目標)在本次響應的Location域中指明。
Http狀態碼 | Http Status Code | Http狀態碼含義中文說明 |
---|---|---|
300 | 300 Multiple Choices | 返回多條重定向供選擇 |
301 | 301 Moved Permanently | 永久重定向 |
302 | 302 Found | 臨時重定向 |
303 | 303 See Other | 當前請求的資源在其它地址 |
304 | 304 Not Modified | 請求資源與本地快取相同,未修改 |
305 | 305 Use Proxy | 必須通過代理訪問 |
306 | 306 (已廢棄)Switch Proxy | (已廢棄)請切換代理 |
307 | 307 Temporary Redirect | 臨時重定向,同302 |
308 | 308 Permanent Redirect | 永久重定向,且禁止改變http方法 |
4、4xx 客戶端錯誤
這一組狀態碼錶示客戶端的請求存在錯誤,導致伺服器無法處理。除非響應的是一個HEAD請求,否則伺服器就應該返回一個解釋當前錯誤狀況的實體,以及這是臨時的還是永久性的狀況。這些狀態碼適用於任何請求方法。瀏覽器應當向用戶顯示任何包含在此類錯誤響應中的實體內容。
5、5xx 伺服器錯誤狀態
這一組狀態碼說明伺服器在處理請求的過程中有錯誤或者異常狀態發生,也有可能是伺服器意識到以當前的軟硬體資源無法完成對請求的處理。除非這是一個HEAD請求,否則伺服器應當包含一個解釋當前錯誤狀態以及這個狀況是臨時的還是永久的解釋資訊實體。瀏覽器應當向用戶展示任何在當前響應中被包含的實體。
Http狀態碼 | Http Status Code | Http狀態碼含義中文說明 |
---|---|---|
500 | 500 Internal Server Error | 伺服器端程式錯誤 |
501 | 501 Not Implemented | 伺服器不支援的請求方法 |
502 | 502 Bad Gateway | 網關無響應 |
503 | 503 Service Unavailable | 伺服器端臨時錯誤 |
504 | 504 Gateway Timeout | 網關超時 |
505 | 505 HTTP Version Not Supported | 伺服器不支援的HTTP版本 |
506 | 506 Variant Also Negotiates | 伺服器內部配置錯誤 |
507 | 507 Insufficient Storage | 伺服器無法存儲請求 |
508 | 508 Loop Detected | 伺服器因死循環而終止操作 |
509 | 509 Bandwidth Limit Exceeded | 伺服器頻寬限制 |
510 | 510 Not Extended | 獲取資源策略未被滿足 |
511 | 511 Network Authentication Required | 需驗證以許可連接 |
599 | 599 Network Connect Timeout Error | 網路連接超時 |
1.2 web伺服器調用
在收到請求之後,伺服器會進行如下工作:
1.3 servlet註冊
<!--註冊伺服器name = "HelloServet"-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的請求路徑 urlPatterns = "/Aason",loadOnStartup = 15-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Aaron</url-pattern>
</servlet-mapping>
2.1web.xml匹配文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
//www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee
//xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
pom依賴
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
2.2 Mapping問題
如果啟動Tomcat後文件運行正常,但是單獨運行文件JSP顯示程式碼,那麼就是xml文件配置了Servlet,可以在Java文件中單獨寫頭部。如下圖
-
一個Servlet可以指定一個映射路徑
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron</url-pattern> </servlet-mapping>
-
一個Servlet可以指定多個個映射路徑
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron1</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron2</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron3</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron4</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron5</url-pattern> </servlet-mapping>
-
一個Servlet可以指定通用映射路徑(/*許可權很高)
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron/*</url-pattern>許可權很高 </servlet-mapping>
-
默認請求路徑路徑
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
-
指定一些前後綴
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>*.Aaron</url-pattern> <!-- 可以自定義後綴請求映射,但是前面*不可加/ --> </servlet-mapping>
-
優先順序問題
指定了固有的映射路徑優先順序最高,如果找不到就會走默認的請求;
<!--Error錯誤伺服器註冊-->
<servlet>
<servlet-name>ErrorServlet</servlet-name>
<servlet-class>com.Aaron.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ErrorServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
2、 ServletContext
2.3.1 共享數據
web容器在啟動的時候,他會為每個web程式都創建一個對應的ServletContext對象,它代表了當前的web容器;
- 共享數據,保存數據,達到共享;
2.3.2 setAttribute轉發
測試訪問結果,先訪問set ,獲取值後在訪問get,強轉換String
String username = (String)context.getAttribute(“username”);
package com.Aaron.servlet; /**
* @Author: Alskaboo
* @Date: 2022-03-29 19:40
**/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
//@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// this.getInitParameter();初始化值
// this.getServletConfig();servlet配置
// this.getServletContext();servlet上下文銜接對象
ServletContext context = this.getServletContext();
String username = "菜菜";//數據
context.setAttribute("username", username);//鍵值對的形式,將數據保存在了ServletContext中,名字叫username;與後面的key名必須相同
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.Aaron.servlet;
import sun.security.timestamp.HttpTimestamper;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: Alskaboo
* @Date: 2022-03-29 21:13
**/
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 {
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee //xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<!--註冊伺服器name = "HelloServet"-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的請求路徑 urlPatterns = "/Aason",loadOnStartup = 15-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Aaron</url-pattern>
</servlet-mapping>
<!--Error錯誤伺服器註冊-->
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.Aaron.servlet.getServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
</web-app>
2.3.3 請求轉發
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/Demo_02").forward(req,resp);//請求轉發的路徑並且調用forward實現請求轉發
}
重定向:A找B要東西,B沒有,但是B告訴A,C那裡有你需要的,那麼A直接根據路徑找C(路徑改變);
2.3.4 讀取資源文件
properties類:
生成在classpath路徑中
<!--在build中配置resources,來防止我們資源導出失敗的問題-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3、 HttpServletResponse
web伺服器接收到客戶端的http請求,針對這個請求,分別創建一個代表請求的HttpServletRequest對象,代表響應的一個HttpServletResponse;
- 如果要獲取客戶端請求過來的參數:找HttpServletRequest
- 如果要給客戶端響應一些資訊:找HttpservletResponse
2.4.1. 簡單分類
負責向瀏覽器發送數據的方法
servletoutputstream getoutputstream() throws IOException;
Printwriter getwriter() throws IOException;
Http相應
Cache-Control: private 快取控制
Connection:Keep-Alive 連接
Content-Encoding:gzip 編碼
Content-Type:text/html 類型
2.4.2 文件下載
- 向瀏覽器輸出消息
- 下載文件
- 要獲取下載文件的路徑
- 下載的文件名是啥?
- 設置想辦法讓瀏覽器能夠支援下載我們需要的東西
- 獲取下載文件的輸入流
- 創建緩衝區
- 獲取OutputStream對象
- 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的數據輸出到客戶端!
- 關流
package com.Aaron;
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.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
/**
* @Author: Alskaboo
* @Date: 2022-03-30 17:39
**/
public class FileServelet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 要獲取下載文件的路徑,realpath是用來將參數path所指的相對路徑轉換成絕對路徑,然後存於參數resolved_path所指的字元串數組或指針中的一個函數
// String realPath = this.getServletContext().getRealPath("/ycCity.jpg");
String realPath = "F:\\Code\\ideacode\\JavaClassWeb\\Maven02\\response_01\\src\\main\\resources\\ycCity.jpg";
System.out.println("下載文件路徑:" + realPath);
//2. 下載的文件名是啥?
String fielname = realPath.substring(realPath.lastIndexOf("\\") + 1);//直接截取字元串,截取最後一個"/"的下一個就是那個文件名
//3. 設置想辦法讓瀏覽器能夠支援下載我們需要的東西
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fielname,"UTF-8"));
//4. 獲取下載文件的輸入流
FileInputStream fileInputStream = new FileInputStream(realPath);
//5. 創建緩衝區
int len = 0;
byte[] buffer = new byte[1024];
//6. 獲取OutputStream對象
ServletOutputStream outputStream = resp.getOutputStream();
//7. 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的數據輸出到客戶端
while ((len = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
//8.關閉流
fileInputStream.close();
outputStream.close();
}
<servlet>
<servlet-name>filedown</servlet-name>
<servlet-class>com.Aaron.FileServelet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/filedown</url-pattern>
</servlet-mapping>
2.4.3 驗證碼功能
-
驗證怎麼來的?
-
前端實現
-
後端實現,需要用到Java的圖片類,生產一個圖片
-
package com.Aaron;
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;
/**
* @Author: Alskaboo
* @Date: 2022-03-30 22:06
**/
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何讓瀏覽器5秒自動刷新一次
resp.setHeader("refresh", "3");
//在記憶體中創建一個圖片
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到一張圖片
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
//設置圖片顏色
graphics.setColor(Color.white);
graphics.fillRect(0, 0, 80, 20);
//給圖片寫數據
graphics.setColor(Color.RED);
graphics.setFont(new Font(null, Font.BOLD, 20));//BOLD粗體
graphics.drawString(setRandom(), 0, 20);
//告訴瀏覽器這個請求用圖片的形式打開
resp.setContentType("image/jpg");
//網站是有快取的,不讓瀏覽器快取
resp.setDateHeader("expires", -1);
resp.setHeader("Cache-Control", "no-Cache");
resp.setHeader("Pragma", "no-Cache");
//把圖片寫給瀏覽器
boolean write = ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
//生成隨機數
private String setRandom() {
Random random = new Random();
String num = random.nextInt(999_9999) + " ";
StringBuffer stringBuffer = new StringBuffer();//StringBuffer 字元串拼接
for (int i = 0; i < 7 - num.length(); i++) {
stringBuffer.append("0");//保證輸出七位數,不足用0填充
}
String s = stringBuffer.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.Aaron.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
2.4.4 重定向
定義:B一個web資源收到客戶端A請求後,B他會通知A客戶端去訪問另外一個web資源,這個過程叫重定向
常見場景:
- 用戶登錄
測試
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
resp.setHeader("Location","/response/img");
resp.setStatus(302);
*/
resp.sendRedirect("/response/img");
}
面試題
重定向和轉發的區別:
相同點:
- 頁面都會跳轉
不同點:
- 請求轉發的時候,URL不會發生變化
- 重定向的時候,URL會發生變化
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("進入這個請求了");
//處理請求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
//重定向一定要注意路徑問題
resp.sendRedirect("/response/LoginSuccess.jsp");
}
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<title>主頁</title>
</head>
<body>
<h1>Login Success!</h1>
</body>
</html>
<servlet>
<servlet-name>RequestText</servlet-name>
<servlet-class>com.Aaron.send.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestText</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
2.5 HttpServletRequest
HttpServletRequest代表客戶端的請求,用戶通過Http協議訪問伺服器,HTTP請求中的所有資訊會被封裝到HttpServletRequest,通過這個HttpServletRequest的方法,獲得客戶端的所有資訊.
2.5.1 獲取前端的參數,並且請求轉發
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//後台接收亂碼問題
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String[] hobbies = request.getParameterValues("hobbies");
//打出
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
//請求轉發
request.getRequestDispatcher("success.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
面試題
重定向和轉發的區別:
相同點:
- 頁面都會跳轉
不同點:
- 請求轉發的時候,URL不會發生變化;307
- 重定向的時候,URL會發生變化;302
4、 Cookie和Session(重點)
1、Cookie
- 從伺服器請求中拿到Cookie資訊
- 伺服器相應給客戶端cookie
1、cookie會話
會話:用戶打開一個瀏覽器,點擊了很多超鏈接,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話
有狀態會話:訪問網站,下次訪問有記錄的情況
一個網站,怎麼證明你來過?
客戶端 服務端
- 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
- 伺服器登記你來過了,下次你來的時候我來匹配你;session
2、保存會話的兩種技術
cookie
- 客戶端技術(響應、請求)
session
- 伺服器技術,利用這個技術,可以保存會話的資訊,我們把它保存到Session中
//Cookie,伺服器端從客戶端獲取呀;
Cookie[] cookies = req.getCookies();//這裡返回數組,說明cookie可能存在多個
cookie.getName();//獲得cookie
cookie.getValue();//獲得cookie中的Value
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");//新建一個cookie
cookie.setMaxAge(24 * 62 * 60); //cookie有效期
resp.addCookie(cookie);//響應給客戶端一個cookie
一個網站的cookie是否存在上限?
- 一個cookie只能保存一個資訊
- 一個web站點可以給瀏覽器發布多個cookie,最多存放20個cookie
- 大小限制為4KB
- 300個cookie瀏覽器上限制
刪除Cookie:
- 不設置有效期,關閉瀏覽器,自動失效;
- 設置有效期時間為0;
解決cookie亂碼
編碼解碼
Cookie cookie = new Cookie("name", URLEncoder.encode("秦疆", "UTF-8"));
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
相關源碼
package com.Aaron.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;
import static java.lang.System.out;
/**
* @Author: Alskaboo
* @Date: 2022-04-01 19:35
**/
//保存 用戶上一次訪問的時間
public class CookieDemo01 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();//這裡返回數組,說明cookie可能存在多個
//判斷Cookie是否存在
if (cookies != null) {
//如果存在怎麼辦
out.write("您上一次訪問本站的時間是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//獲取cookie的名字
if (cookie.getName().equals("lastLoginTime")) {
//獲取cookie中的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
} else {
out.write("這是您第一次訪問本站");
}
//服務給客戶端響應一個cookie;
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
//cookie有效期為一天
cookie.setMaxAge(24 * 62 * 60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.Aaron.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;
/**
* @Author: Alskaboo
* @Date: 2022-04-01 21:01
**/
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//創建和剛才的cookie名字一樣
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee
//xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>CookieDemo01</servlet-name>
<servlet-class>com.Aaron.Servlet.CookieDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo01</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CookieDemo02</servlet-name>
<servlet-class>com.Aaron.Servlet.CookieDemo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo02</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
</web-app>
2、Session(重點)含銷毀時間
會話:用戶打開一個瀏覽器,點擊了很多超鏈接,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話
什麼是session:
- 伺服器會給每一個用戶(瀏覽器)創建一個Seesion對象;
- 一個Seesion獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在;
- 用戶登錄之後,整個網站都可以訪問它;–>保存用戶資訊
使用場景:
- 保存一個登錄用戶的資訊
- 購物車資訊
- 整個網站中經常使用的資訊
相關程式碼:
//得到Session
HttpSession session = req.getSession();
//給Session存東西
Person person = new Person("秦疆",10);
session.setAttribute("name", person);
//得到Session
HttpSession session = req.getSession();
//給Session存東西
Person name = (Person) session.getAttribute("name");
System.out.println(name);
//關閉會話
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
// 手動註銷Session
session.invalidate();
}
會話關閉web配置文件
<!--設置Session默認的失效時間-->
<session-config>
<!--設置Session失效時間,以分鐘為單位 24*60-->
<session-timeout>1440</session-timeout>
</session-config>
cookie和session的區別
- Cookie是把用戶的數據寫給用戶的瀏覽器,瀏覽器保存(可以保存多個)
- Session把用戶的數據寫到用戶獨佔Session中,伺服器端保存(保存重要的資訊,減少伺服器資源的浪費)
- Session對象由服務創建;
5、JSP
1、什麼是JSP
Java Server Pages : Java伺服器端頁面,也和Servlet一樣,用於動態Web技術!
最大的特點:寫JSP就像在寫HTML
HTML和JSP最大的區別:
- HTML只給用戶靜態的
- JSP頁面中可以嵌入java程式碼,為用戶提供動態數據
2、JSP原理
思路:JSP怎麼運行?
-
程式碼層面沒有問題
-
伺服器內部工作
Tomcat中的work目錄
瀏覽器向伺服器發送請求,不管訪問什麼資源,其實都是在訪問Servlet!
JSP最終也會被轉換成JAVA類
JSP本質上就是一個Servlet
在JSP中:
只要是Java程式碼就會原封不動的輸出;
如果是HTML程式碼,就會被轉換
out.write("<html>\r\n");
這樣的格式輸出到前端。
3、JSP基礎語法
任何語言都有自己的語法,JSP作為java技術的一種應用,它擁有一些自己擴充的語法(了解),Java所有語法都支援
JSP表達式
<%--JSP表達式
作用:用來將程式的輸出,輸出到客戶端
<%= 變數或者表達式 %>
--%>
<%= new java.util.Date()%>
jsp腳本片段
<%--腳本片段--%>
<%
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
}
out.println("<h1>Sum=" + sum + "</h1>");
%>
<%
for (int i = 0; i < 5; i++) {
%>
<h2>Hello,World! <%=i%>//${i}
</h2>
<%
}
%>
JSP指令
1.錯誤頁面
<%@ page errorPage= "路徑" %>
或者單獨創建圖片
<img src="路徑" alt="500">
或者配置文件
<error-page>
<error-code>404</error-code>
<location> /error/404.jsp</ location></error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
網站主體:拼接頁面
jsp注釋
1.隱藏注釋
下面介紹一種隱藏注釋,注釋格式如下:
<%--注釋內容--%>
2.HTML中的注釋
JSP 文件是由 HTML 標記和嵌入的 Java 程式段組成的,所以在 HTML 中的注釋同樣可以在 JSP 文件中使用。這種注釋雖然在客戶端瀏覽頁面時不會看見,但它卻存在於源程式碼中,可通過在客戶端查看源程式碼看到被注釋的內容。所以嚴格來說,這種注釋並不安全。注釋格式如下:
<!--注釋內容-->
3.<% %>腳本片段
其中寫的內容會翻譯在Servlet的Service方法中,顯然我們可以在Service方法中定義局部變數或者調用其他方法,但是不能
在Service中再定義其他的方法,也就是我們可以在<%%>中定義局部變數或者調用方法,但不能定義方法。在jsp頁面可以有多個腳本片段,但是多個腳本片段之間要保證結構完整。
4.<%!%>聲明
其中寫的內容將來會直接翻譯在Servlet類中,因為我們可以在類中定義方法和屬性以及全局變數,所以我們可以在<%!%>中聲
明方法、屬性、全局變數。
5.<%=%>稱作jsp表達式,用於將已經聲明的變數或者表達式輸出到網頁上面。
4、9大內置對象
- PageContext 存東西
- Request 存東西
- esponse
- Session 存東西
- Application 【SerlvetContext】存東西
- config【serlvetConfig】
- out
- page
- exception
<%
pageContext.setAttribute("name1", "秦疆1號");//保存的數據只在一個頁面中有效
request.setAttribute("name2", "秦疆2號");//保存的數據只在一次請求中有效,請求轉發會攜帶這個數據
//跨頁面
session.setAttribute("name3", "秦疆3號");//保存的數據只在一次會話中有效,打開到關閉瀏覽器
application.setAttribute("name4", "秦疆4號");//保存的數據只在伺服器有效,從打開到關閉伺服器
%>
作用域:
request:客戶端向伺服器發送請求,產生的數據,用戶看完就沒用了,比如:新聞,用戶看完沒用的!
session:客戶端向伺服器發送請求,產生的數據,用戶用完一會還有用,比如:購物車;
application:客戶端向伺服器發送請求,產生的數據,一個用戶用完了,其他用戶還可能使用,比如:聊天數據;
5、JSP標籤、JSTL標籤、EL標籤
- EL表達式:${}
- 獲取數據
- 執行運算
- 獲取Web開發的常用對象
-
JSP標籤:
<%@ taglib prefix="c" uri="//java.sun.com/jsp/jstl/core"%>
轉發攜帶參數
<%--
http: //localhost:8e80/jsptag.jsp?name=kuangshen&age=12
--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"></jsp:param>
<jsp: param name="age" value="12"></jsp:param>
</jsp:forward>
取到參數
<%--取出參數--%>
名字:<%=request.getParameter( name: "name")%>年齡:<%=request.getParameter("age")%>
- JSTL表達式
JSTL標籤庫的使用就是為了彌補HTML標籤的不足;它自定義許多標籤,可以供我們使用,標籤的功能和ava程式碼一樣!
JSTL標籤庫使用步驟:
- 引入對應的taglib
- 使用其中的方法
- 在Tomcat也需要引入jstl的包,否則會報錯:JSTL解析錯誤
<h4>if測試</ h4>
<hr>
<form action=" coreif.jsp" method="get">
<%--
EL表達式獲取表單中的數據
${param.參數名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登錄">
</form>
<%--判晰斷如果提交的用戶名是管理員,則登錄成功--%>
<c:if test="${param.username==' admin' }" var="isAdmin">
<c:out value="管理員歡迎您!"/>
</c:if>
<%--自閉he--%>
<c:out value="${isAdmin}"/>
6、JavaBean
實體類
JavaBean有特定的寫法:
- 必須要有一個無參構造
- 屬性必須私有化
- 必須有對應的get/set方法;
一般用來和資料庫的欄位做映射ORM
ORM:對象關係映射
- 表—>類
- 欄位–>屬性
- 行記錄–>對象
6、MVC三層架構
什麼是MVC: Model模型、 view視圖、Controller 控制器
1、早些年
用戶直接訪問控制層,控制器直接操作資料庫
servlet--CRUD-->資料庫
弊端:程式十分臃腫,不利於維護
servlet的程式碼中:處理請求、響應、視圖跳轉、處理DBc、處理業務程式碼、處理邏輯程式碼
架構:沒有什麼是加一層解決不了的!
2、現在三層架構
Model
- 業務處理:業務邏輯(Service)
- 數據持久層:CRUD (Dao)
View展示數據
- 提供鏈接發起Servlet請求(a,form,img…)
controller (Servlet)
- 接收用戶的請求: (req:請求參數、Session資訊….)
- 交給業務層處理對應的程式碼
- 控制視圖的跳轉
登錄--->接收用戶的登錄請求--->處理用戶的請求(獲取用戶登錄的參數,username, password) ---->交給業務層處理登錄業務(判斷用戶名密碼是否正確:事務) --->Dao層查 詢用戶名和密碼是否正確-->資料庫
3、過濾器重點(Filter)
- 解決中文亂碼
- 登陸驗證
JAVA程式碼:實現介面、重寫方法
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web伺服器啟動就開始初始化,隨時等待更新過濾對象
public void init(FilterConfig config) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//銷毀:伺服器關閉
public void destroy() {
System.out.println("CharacterEncodingFilter銷毀");
}
@Override
//Chain: 鏈
/*
1.過濾器中的所有程式碼,在過濾特定請求的時候都會執行
2.必須讓過濾器繼續同行
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter執行前");
chain.doFilter(request, response);//讓程式繼續走
System.out.println("CharacterEncodingFilter執行後");
}
}
xml中配置過濾器程式碼
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.Aaron.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.Aaron.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
4、監聽器
實現一個監聽器的介面;(有N種)
1.編寫一個監聽器
實現監聽器的介面
//監聽網站人數
public class onlineListener implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
/* Session is created. */
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(1);
} else {
int count = onlineCount.intValue();
onlineCount = new Integer(count + 1);
}
servletContext.setAttribute("OnlineCount", onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
/* Session is destroyed. */
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(0);
} else {
int count = onlineCount.intValue();
onlineCount = new Integer(count - 1);
}
servletContext.setAttribute("OnlineCount", onlineCount);
/*
Session銷毀:
1.手動銷毀 getSession().invalidate();
2.自動銷毀
*/
}
}
2.web.xml中註冊監聽器
<listener>
<listener-class>com.Aaron.OnlineListener.onlineListener</listener-class>
</listener>
5、過濾器和監聽器應用
監聽器:GUI編程中經常使用;
package com.Aaron;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 12:45
**/
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("管理");
Panel panel = new Panel(null);
frame.setLayout(null);
frame.setBounds(500, 300, 500, 700);
frame.setBackground(new Color(0, 0, 255));
panel.setBounds(50, 50, 200, 100);
panel.setBackground(new Color(0, 255, 0));
frame.add(panel);
frame.setVisible(true);
//監聽事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
}
}
用戶登錄後進入,註銷後不能進入主頁,過濾器實現
-
用戶登錄之後,向Sesison中放入用戶的數據
-
進入主頁的時候要判斷用戶是否已經登錄;要求:在過濾器中實現!
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if(request.getSession().getAttribute(constant.USER_SESSION) == null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(req, resp);
}
7、JDBC
1、導入依賴
<!--連接資料庫-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
2、JDBC固定步驟
1.載入驅動
2.連接資料庫,代表資料庫
3.向資料庫發送SQL的對象Statement : CRUD
4.編寫SQL(根據業務,不同的SQL)
5.執行SQL
6.關閉連接
package com.Aaron.test;
import java.sql.*;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 16:32
**/
public class TestJDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
//1.載入驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.向資料庫發送SQL的對象Statement
Statement statement = connection.createStatement();
//4.編寫SQL
try {
String sql = "select * from users";
//5.執行查詢操作,返回一個結果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
System.out.println("id=" + rs.getInt("id"));
System.out.println("name=" + rs.getString("name"));
System.out.println("password=" + rs.getString("password"));
System.out.println("birthday=" + rs.getString("birthday"));
}
//6.關閉連接,釋放資源* 先開後關
rs.close();
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
預編譯程式碼
package com.Aaron.test;
import java.sql.*;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 17:06
**/
public class TestJDBC2 {
public static void main(String[] args) throws Exception {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
//1.載入驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.編寫SQL
try {
String sql = "insert into users(id,name,password,email,birthday)values (?,?,?,?,?);";
//4.預編譯
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 5);
preparedStatement.setString(2, "小菜");
preparedStatement.setString(3, "123");
preparedStatement.setString(4, "[email protected]");
preparedStatement.setString(5, "2001-03-17");
//5.執行SQL
int i = preparedStatement.executeUpdate();
if (i > 0) {
System.out.println("插入成功");
}
//6.關閉連接,釋放資源* 先開後關
preparedStatement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3、事務
要麼都成功,要麼都失敗!
ACID原則:保證數據的安全。
開啟事務
事務提交 commit()
事務回滾 ro11back()
關閉事務
轉賬:
A :1000
B :1000
A(900)--100-->B(1100)
junit單元測試
依賴
<!--單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
簡單使用
@Test註解只有在方法上有效,只要加了這個註解的方法,就可以直接運行
package com.Aaron.test;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 17:35
**/
public class TestJDBC3 {
@Test
public void hello() {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
Connection connection = null;
//1.載入驅動
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
connection = DriverManager.getConnection(url, username, password);
//3.通知資料庫開啟事務,false開啟
connection.setAutoCommit(false);
String sql = "update account set money = money - 100 where name = 'A'";
connection.prepareStatement(sql).executeUpdate();
//製造錯誤
// int i = 1 / 0;
String sql1 = "update account set money = money + 100 where name = 'B'";
connection.prepareStatement(sql1).executeUpdate();
connection.commit();
System.out.println("success");
} catch (Exception e) {
try {
//如果異常資料庫回滾事務
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
1.3 servlet註冊
<!--註冊伺服器name = "HelloServet"-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的請求路徑 urlPatterns = "/Aason",loadOnStartup = 15-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Aaron</url-pattern>
</servlet-mapping>
2.1web.xml匹配文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
//www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee
//xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
pom依賴
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
2.2 Mapping問題
如果啟動Tomcat後文件運行正常,但是單獨運行文件JSP顯示程式碼,那麼就是xml文件配置了Servlet,可以在Java文件中單獨寫頭部。如下圖
-
一個Servlet可以指定一個映射路徑
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron</url-pattern> </servlet-mapping>
-
一個Servlet可以指定多個個映射路徑
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron1</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron2</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron3</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron4</url-pattern> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron5</url-pattern> </servlet-mapping>
-
一個Servlet可以指定通用映射路徑(/*許可權很高)
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Aaron/*</url-pattern>許可權很高 </servlet-mapping>
-
默認請求路徑路徑
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
-
指定一些前後綴
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>*.Aaron</url-pattern> <!-- 可以自定義後綴請求映射,但是前面*不可加/ --> </servlet-mapping>
-
優先順序問題
指定了固有的映射路徑優先順序最高,如果找不到就會走默認的請求;
<!--Error錯誤伺服器註冊-->
<servlet>
<servlet-name>ErrorServlet</servlet-name>
<servlet-class>com.Aaron.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ErrorServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
2、 ServletContext
2.3.1 共享數據
web容器在啟動的時候,他會為每個web程式都創建一個對應的ServletContext對象,它代表了當前的web容器;
- 共享數據,保存數據,達到共享;
2.3.2 setAttribute轉發
測試訪問結果,先訪問set ,獲取值後在訪問get,強轉換String
String username = (String)context.getAttribute(“username”);
package com.Aaron.servlet; /**
* @Author: Alskaboo
* @Date: 2022-03-29 19:40
**/
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
//@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// this.getInitParameter();初始化值
// this.getServletConfig();servlet配置
// this.getServletContext();servlet上下文銜接對象
ServletContext context = this.getServletContext();
String username = "菜菜";//數據
context.setAttribute("username", username);//鍵值對的形式,將數據保存在了ServletContext中,名字叫username;與後面的key名必須相同
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.Aaron.servlet;
import sun.security.timestamp.HttpTimestamper;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: Alskaboo
* @Date: 2022-03-29 21:13
**/
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 {
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee //xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<!--註冊伺服器name = "HelloServet"-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的請求路徑 urlPatterns = "/Aason",loadOnStartup = 15-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Aaron</url-pattern>
</servlet-mapping>
<!--Error錯誤伺服器註冊-->
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.Aaron.servlet.getServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
</web-app>
2.3.3 請求轉發
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/Demo_02").forward(req,resp);//請求轉發的路徑並且調用forward實現請求轉發
}
重定向:A找B要東西,B沒有,但是B告訴A,C那裡有你需要的,那麼A直接根據路徑找C(路徑改變);
2.3.4 讀取資源文件
properties類:
生成在classpath路徑中
<!--在build中配置resources,來防止我們資源導出失敗的問題-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3、 HttpServletResponse
web伺服器接收到客戶端的http請求,針對這個請求,分別創建一個代表請求的HttpServletRequest對象,代表響應的一個HttpServletResponse;
- 如果要獲取客戶端請求過來的參數:找HttpServletRequest
- 如果要給客戶端響應一些資訊:找HttpservletResponse
2.4.1. 簡單分類
負責向瀏覽器發送數據的方法
servletoutputstream getoutputstream() throws IOException;
Printwriter getwriter() throws IOException;
Http相應
Cache-Control: private 快取控制
Connection:Keep-Alive 連接
Content-Encoding:gzip 編碼
Content-Type:text/html 類型
2.4.2 文件下載
- 向瀏覽器輸出消息
- 下載文件
- 要獲取下載文件的路徑
- 下載的文件名是啥?
- 設置想辦法讓瀏覽器能夠支援下載我們需要的東西
- 獲取下載文件的輸入流
- 創建緩衝區
- 獲取OutputStream對象
- 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的數據輸出到客戶端!
- 關流
package com.Aaron;
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.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
/**
* @Author: Alskaboo
* @Date: 2022-03-30 17:39
**/
public class FileServelet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 要獲取下載文件的路徑,realpath是用來將參數path所指的相對路徑轉換成絕對路徑,然後存於參數resolved_path所指的字元串數組或指針中的一個函數
// String realPath = this.getServletContext().getRealPath("/ycCity.jpg");
String realPath = "F:\\Code\\ideacode\\JavaClassWeb\\Maven02\\response_01\\src\\main\\resources\\ycCity.jpg";
System.out.println("下載文件路徑:" + realPath);
//2. 下載的文件名是啥?
String fielname = realPath.substring(realPath.lastIndexOf("\\") + 1);//直接截取字元串,截取最後一個"/"的下一個就是那個文件名
//3. 設置想辦法讓瀏覽器能夠支援下載我們需要的東西
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fielname,"UTF-8"));
//4. 獲取下載文件的輸入流
FileInputStream fileInputStream = new FileInputStream(realPath);
//5. 創建緩衝區
int len = 0;
byte[] buffer = new byte[1024];
//6. 獲取OutputStream對象
ServletOutputStream outputStream = resp.getOutputStream();
//7. 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的數據輸出到客戶端
while ((len = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
//8.關閉流
fileInputStream.close();
outputStream.close();
}
<servlet>
<servlet-name>filedown</servlet-name>
<servlet-class>com.Aaron.FileServelet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/filedown</url-pattern>
</servlet-mapping>
2.4.3 驗證碼功能
-
驗證怎麼來的?
-
前端實現
-
後端實現,需要用到Java的圖片類,生產一個圖片
-
package com.Aaron;
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;
/**
* @Author: Alskaboo
* @Date: 2022-03-30 22:06
**/
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何讓瀏覽器5秒自動刷新一次
resp.setHeader("refresh", "3");
//在記憶體中創建一個圖片
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到一張圖片
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
//設置圖片顏色
graphics.setColor(Color.white);
graphics.fillRect(0, 0, 80, 20);
//給圖片寫數據
graphics.setColor(Color.RED);
graphics.setFont(new Font(null, Font.BOLD, 20));//BOLD粗體
graphics.drawString(setRandom(), 0, 20);
//告訴瀏覽器這個請求用圖片的形式打開
resp.setContentType("image/jpg");
//網站是有快取的,不讓瀏覽器快取
resp.setDateHeader("expires", -1);
resp.setHeader("Cache-Control", "no-Cache");
resp.setHeader("Pragma", "no-Cache");
//把圖片寫給瀏覽器
boolean write = ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
//生成隨機數
private String setRandom() {
Random random = new Random();
String num = random.nextInt(999_9999) + " ";
StringBuffer stringBuffer = new StringBuffer();//StringBuffer 字元串拼接
for (int i = 0; i < 7 - num.length(); i++) {
stringBuffer.append("0");//保證輸出七位數,不足用0填充
}
String s = stringBuffer.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.Aaron.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
2.4.4 重定向
定義:B一個web資源收到客戶端A請求後,B他會通知A客戶端去訪問另外一個web資源,這個過程叫重定向
常見場景:
- 用戶登錄
測試
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
resp.setHeader("Location","/response/img");
resp.setStatus(302);
*/
resp.sendRedirect("/response/img");
}
面試題
重定向和轉發的區別:
相同點:
- 頁面都會跳轉
不同點:
- 請求轉發的時候,URL不會發生變化
- 重定向的時候,URL會發生變化
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("進入這個請求了");
//處理請求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
//重定向一定要注意路徑問題
resp.sendRedirect("/response/LoginSuccess.jsp");
}
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
<title>主頁</title>
</head>
<body>
<h1>Login Success!</h1>
</body>
</html>
<servlet>
<servlet-name>RequestText</servlet-name>
<servlet-class>com.Aaron.send.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestText</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
2.5 HttpServletRequest
HttpServletRequest代表客戶端的請求,用戶通過Http協議訪問伺服器,HTTP請求中的所有資訊會被封裝到HttpServletRequest,通過這個HttpServletRequest的方法,獲得客戶端的所有資訊.
2.5.1 獲取前端的參數,並且請求轉發
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//後台接收亂碼問題
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String[] hobbies = request.getParameterValues("hobbies");
//打出
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
//請求轉發
request.getRequestDispatcher("success.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
面試題
重定向和轉發的區別:
相同點:
- 頁面都會跳轉
不同點:
- 請求轉發的時候,URL不會發生變化;307
- 重定向的時候,URL會發生變化;302
4、 Cookie和Session(重點)
1、Cookie
- 從伺服器請求中拿到Cookie資訊
- 伺服器相應給客戶端cookie
1、cookie會話
會話:用戶打開一個瀏覽器,點擊了很多超鏈接,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話
有狀態會話:訪問網站,下次訪問有記錄的情況
一個網站,怎麼證明你來過?
客戶端 服務端
- 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
- 伺服器登記你來過了,下次你來的時候我來匹配你;session
2、保存會話的兩種技術
cookie
- 客戶端技術(響應、請求)
session
- 伺服器技術,利用這個技術,可以保存會話的資訊,我們把它保存到Session中
//Cookie,伺服器端從客戶端獲取呀;
Cookie[] cookies = req.getCookies();//這裡返回數組,說明cookie可能存在多個
cookie.getName();//獲得cookie
cookie.getValue();//獲得cookie中的Value
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");//新建一個cookie
cookie.setMaxAge(24 * 62 * 60); //cookie有效期
resp.addCookie(cookie);//響應給客戶端一個cookie
一個網站的cookie是否存在上限?
- 一個cookie只能保存一個資訊
- 一個web站點可以給瀏覽器發布多個cookie,最多存放20個cookie
- 大小限制為4KB
- 300個cookie瀏覽器上限制
刪除Cookie:
- 不設置有效期,關閉瀏覽器,自動失效;
- 設置有效期時間為0;
解決cookie亂碼
編碼解碼
Cookie cookie = new Cookie("name", URLEncoder.encode("秦疆", "UTF-8"));
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
相關源碼
package com.Aaron.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;
import static java.lang.System.out;
/**
* @Author: Alskaboo
* @Date: 2022-04-01 19:35
**/
//保存 用戶上一次訪問的時間
public class CookieDemo01 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();//這裡返回數組,說明cookie可能存在多個
//判斷Cookie是否存在
if (cookies != null) {
//如果存在怎麼辦
out.write("您上一次訪問本站的時間是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//獲取cookie的名字
if (cookie.getName().equals("lastLoginTime")) {
//獲取cookie中的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
} else {
out.write("這是您第一次訪問本站");
}
//服務給客戶端響應一個cookie;
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
//cookie有效期為一天
cookie.setMaxAge(24 * 62 * 60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.Aaron.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;
/**
* @Author: Alskaboo
* @Date: 2022-04-01 21:01
**/
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//創建和剛才的cookie名字一樣
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="//xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//xmlns.jcp.org/xml/ns/javaee
//xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>CookieDemo01</servlet-name>
<servlet-class>com.Aaron.Servlet.CookieDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo01</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CookieDemo02</servlet-name>
<servlet-class>com.Aaron.Servlet.CookieDemo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo02</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
</web-app>
2、Session(重點)含銷毀時間
會話:用戶打開一個瀏覽器,點擊了很多超鏈接,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話
什麼是session:
- 伺服器會給每一個用戶(瀏覽器)創建一個Seesion對象;
- 一個Seesion獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在;
- 用戶登錄之後,整個網站都可以訪問它;–>保存用戶資訊
使用場景:
- 保存一個登錄用戶的資訊
- 購物車資訊
- 整個網站中經常使用的資訊
相關程式碼:
//得到Session
HttpSession session = req.getSession();
//給Session存東西
Person person = new Person("秦疆",10);
session.setAttribute("name", person);
//得到Session
HttpSession session = req.getSession();
//給Session存東西
Person name = (Person) session.getAttribute("name");
System.out.println(name);
//關閉會話
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
// 手動註銷Session
session.invalidate();
}
會話關閉web配置文件
<!--設置Session默認的失效時間-->
<session-config>
<!--設置Session失效時間,以分鐘為單位 24*60-->
<session-timeout>1440</session-timeout>
</session-config>
cookie和session的區別
- Cookie是把用戶的數據寫給用戶的瀏覽器,瀏覽器保存(可以保存多個)
- Session把用戶的數據寫到用戶獨佔Session中,伺服器端保存(保存重要的資訊,減少伺服器資源的浪費)
- Session對象由服務創建;
5、JSP
1、什麼是JSP
Java Server Pages : Java伺服器端頁面,也和Servlet一樣,用於動態Web技術!
最大的特點:寫JSP就像在寫HTML
HTML和JSP最大的區別:
- HTML只給用戶靜態的
- JSP頁面中可以嵌入java程式碼,為用戶提供動態數據
2、JSP原理
思路:JSP怎麼運行?
-
程式碼層面沒有問題
-
伺服器內部工作
Tomcat中的work目錄
瀏覽器向伺服器發送請求,不管訪問什麼資源,其實都是在訪問Servlet!
JSP最終也會被轉換成JAVA類
JSP本質上就是一個Servlet
在JSP中:
只要是Java程式碼就會原封不動的輸出;
如果是HTML程式碼,就會被轉換
out.write("<html>\r\n");
這樣的格式輸出到前端。
3、JSP基礎語法
任何語言都有自己的語法,JSP作為java技術的一種應用,它擁有一些自己擴充的語法(了解),Java所有語法都支援
JSP表達式
<%--JSP表達式
作用:用來將程式的輸出,輸出到客戶端
<%= 變數或者表達式 %>
--%>
<%= new java.util.Date()%>
jsp腳本片段
<%--腳本片段--%>
<%
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
}
out.println("<h1>Sum=" + sum + "</h1>");
%>
<%
for (int i = 0; i < 5; i++) {
%>
<h2>Hello,World! <%=i%>//${i}
</h2>
<%
}
%>
JSP指令
1.錯誤頁面
<%@ page errorPage= "路徑" %>
或者單獨創建圖片
<img src="路徑" alt="500">
或者配置文件
<error-page>
<error-code>404</error-code>
<location> /error/404.jsp</ location></error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
網站主體:拼接頁面
jsp注釋
1.隱藏注釋
下面介紹一種隱藏注釋,注釋格式如下:
<%--注釋內容--%>
2.HTML中的注釋
JSP 文件是由 HTML 標記和嵌入的 Java 程式段組成的,所以在 HTML 中的注釋同樣可以在 JSP 文件中使用。這種注釋雖然在客戶端瀏覽頁面時不會看見,但它卻存在於源程式碼中,可通過在客戶端查看源程式碼看到被注釋的內容。所以嚴格來說,這種注釋並不安全。注釋格式如下:
<!--注釋內容-->
3.<% %>腳本片段
其中寫的內容會翻譯在Servlet的Service方法中,顯然我們可以在Service方法中定義局部變數或者調用其他方法,但是不能
在Service中再定義其他的方法,也就是我們可以在<%%>中定義局部變數或者調用方法,但不能定義方法。在jsp頁面可以有多個腳本片段,但是多個腳本片段之間要保證結構完整。
4.<%!%>聲明
其中寫的內容將來會直接翻譯在Servlet類中,因為我們可以在類中定義方法和屬性以及全局變數,所以我們可以在<%!%>中聲
明方法、屬性、全局變數。
5.<%=%>稱作jsp表達式,用於將已經聲明的變數或者表達式輸出到網頁上面。
4、9大內置對象
- PageContext 存東西
- Request 存東西
- esponse
- Session 存東西
- Application 【SerlvetContext】存東西
- config【serlvetConfig】
- out
- page
- exception
<%
pageContext.setAttribute("name1", "秦疆1號");//保存的數據只在一個頁面中有效
request.setAttribute("name2", "秦疆2號");//保存的數據只在一次請求中有效,請求轉發會攜帶這個數據
//跨頁面
session.setAttribute("name3", "秦疆3號");//保存的數據只在一次會話中有效,打開到關閉瀏覽器
application.setAttribute("name4", "秦疆4號");//保存的數據只在伺服器有效,從打開到關閉伺服器
%>
作用域:
request:客戶端向伺服器發送請求,產生的數據,用戶看完就沒用了,比如:新聞,用戶看完沒用的!
session:客戶端向伺服器發送請求,產生的數據,用戶用完一會還有用,比如:購物車;
application:客戶端向伺服器發送請求,產生的數據,一個用戶用完了,其他用戶還可能使用,比如:聊天數據;
5、JSP標籤、JSTL標籤、EL標籤
- EL表達式:${}
- 獲取數據
- 執行運算
- 獲取Web開發的常用對象
-
JSP標籤:
<%@ taglib prefix="c" uri="//java.sun.com/jsp/jstl/core"%>
轉發攜帶參數
<%--
http: //localhost:8e80/jsptag.jsp?name=kuangshen&age=12
--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"></jsp:param>
<jsp: param name="age" value="12"></jsp:param>
</jsp:forward>
取到參數
<%--取出參數--%>
名字:<%=request.getParameter( name: "name")%>年齡:<%=request.getParameter("age")%>
- JSTL表達式
JSTL標籤庫的使用就是為了彌補HTML標籤的不足;它自定義許多標籤,可以供我們使用,標籤的功能和ava程式碼一樣!
JSTL標籤庫使用步驟:
- 引入對應的taglib
- 使用其中的方法
- 在Tomcat也需要引入jstl的包,否則會報錯:JSTL解析錯誤
<h4>if測試</ h4>
<hr>
<form action=" coreif.jsp" method="get">
<%--
EL表達式獲取表單中的數據
${param.參數名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登錄">
</form>
<%--判晰斷如果提交的用戶名是管理員,則登錄成功--%>
<c:if test="${param.username==' admin' }" var="isAdmin">
<c:out value="管理員歡迎您!"/>
</c:if>
<%--自閉he--%>
<c:out value="${isAdmin}"/>
6、JavaBean
實體類
JavaBean有特定的寫法:
- 必須要有一個無參構造
- 屬性必須私有化
- 必須有對應的get/set方法;
一般用來和資料庫的欄位做映射ORM
ORM:對象關係映射
- 表—>類
- 欄位–>屬性
- 行記錄–>對象
6、MVC三層架構
什麼是MVC: Model模型、 view視圖、Controller 控制器
1、早些年
用戶直接訪問控制層,控制器直接操作資料庫
servlet--CRUD-->資料庫
弊端:程式十分臃腫,不利於維護
servlet的程式碼中:處理請求、響應、視圖跳轉、處理DBc、處理業務程式碼、處理邏輯程式碼
架構:沒有什麼是加一層解決不了的!
2、現在三層架構
Model
- 業務處理:業務邏輯(Service)
- 數據持久層:CRUD (Dao)
View展示數據
- 提供鏈接發起Servlet請求(a,form,img…)
controller (Servlet)
- 接收用戶的請求: (req:請求參數、Session資訊….)
- 交給業務層處理對應的程式碼
- 控制視圖的跳轉
登錄--->接收用戶的登錄請求--->處理用戶的請求(獲取用戶登錄的參數,username, password) ---->交給業務層處理登錄業務(判斷用戶名密碼是否正確:事務) --->Dao層查 詢用戶名和密碼是否正確-->資料庫
3、過濾器重點(Filter)
- 解決中文亂碼
- 登陸驗證
JAVA程式碼:實現介面、重寫方法
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web伺服器啟動就開始初始化,隨時等待更新過濾對象
public void init(FilterConfig config) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//銷毀:伺服器關閉
public void destroy() {
System.out.println("CharacterEncodingFilter銷毀");
}
@Override
//Chain: 鏈
/*
1.過濾器中的所有程式碼,在過濾特定請求的時候都會執行
2.必須讓過濾器繼續同行
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("CharacterEncodingFilter執行前");
chain.doFilter(request, response);//讓程式繼續走
System.out.println("CharacterEncodingFilter執行後");
}
}
xml中配置過濾器程式碼
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.Aaron.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.Aaron.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
4、監聽器
實現一個監聽器的介面;(有N種)
1.編寫一個監聽器
實現監聽器的介面
//監聽網站人數
public class onlineListener implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
/* Session is created. */
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(1);
} else {
int count = onlineCount.intValue();
onlineCount = new Integer(count + 1);
}
servletContext.setAttribute("OnlineCount", onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
/* Session is destroyed. */
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null) {
onlineCount = new Integer(0);
} else {
int count = onlineCount.intValue();
onlineCount = new Integer(count - 1);
}
servletContext.setAttribute("OnlineCount", onlineCount);
/*
Session銷毀:
1.手動銷毀 getSession().invalidate();
2.自動銷毀
*/
}
}
2.web.xml中註冊監聽器
<listener>
<listener-class>com.Aaron.OnlineListener.onlineListener</listener-class>
</listener>
5、過濾器和監聽器應用
監聽器:GUI編程中經常使用;
package com.Aaron;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 12:45
**/
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("管理");
Panel panel = new Panel(null);
frame.setLayout(null);
frame.setBounds(500, 300, 500, 700);
frame.setBackground(new Color(0, 0, 255));
panel.setBounds(50, 50, 200, 100);
panel.setBackground(new Color(0, 255, 0));
frame.add(panel);
frame.setVisible(true);
//監聽事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
}
}
用戶登錄後進入,註銷後不能進入主頁,過濾器實現
-
用戶登錄之後,向Sesison中放入用戶的數據
-
進入主頁的時候要判斷用戶是否已經登錄;要求:在過濾器中實現!
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if(request.getSession().getAttribute(constant.USER_SESSION) == null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(req, resp);
}
7、JDBC
1、導入依賴
<!--連接資料庫-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
2、JDBC固定步驟
1.載入驅動
2.連接資料庫,代表資料庫
3.向資料庫發送SQL的對象Statement : CRUD
4.編寫SQL(根據業務,不同的SQL)
5.執行SQL
6.關閉連接
package com.Aaron.test;
import java.sql.*;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 16:32
**/
public class TestJDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
//1.載入驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.向資料庫發送SQL的對象Statement
Statement statement = connection.createStatement();
//4.編寫SQL
try {
String sql = "select * from users";
//5.執行查詢操作,返回一個結果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
System.out.println("id=" + rs.getInt("id"));
System.out.println("name=" + rs.getString("name"));
System.out.println("password=" + rs.getString("password"));
System.out.println("birthday=" + rs.getString("birthday"));
}
//6.關閉連接,釋放資源* 先開後關
rs.close();
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
預編譯程式碼
package com.Aaron.test;
import java.sql.*;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 17:06
**/
public class TestJDBC2 {
public static void main(String[] args) throws Exception {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
//1.載入驅動
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
Connection connection = DriverManager.getConnection(url, username, password);
//3.編寫SQL
try {
String sql = "insert into users(id,name,password,email,birthday)values (?,?,?,?,?);";
//4.預編譯
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 5);
preparedStatement.setString(2, "小菜");
preparedStatement.setString(3, "123");
preparedStatement.setString(4, "[email protected]");
preparedStatement.setString(5, "2001-03-17");
//5.執行SQL
int i = preparedStatement.executeUpdate();
if (i > 0) {
System.out.println("插入成功");
}
//6.關閉連接,釋放資源* 先開後關
preparedStatement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3、事務
要麼都成功,要麼都失敗!
ACID原則:保證數據的安全。
開啟事務
事務提交 commit()
事務回滾 ro11back()
關閉事務
轉賬:
A :1000
B :1000
A(900)--100-->B(1100)
junit單元測試
依賴
<!--單元測試-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
簡單使用
@Test註解只有在方法上有效,只要加了這個註解的方法,就可以直接運行
package com.Aaron.test;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* @Author: Alskaboo
* @Date: 2022-04-05 17:35
**/
public class TestJDBC3 {
@Test
public void hello() {
//配置資訊
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String username = "root";
String password = "root";
Connection connection = null;
//1.載入驅動
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.連接資料庫
connection = DriverManager.getConnection(url, username, password);
//3.通知資料庫開啟事務,false開啟
connection.setAutoCommit(false);
String sql = "update account set money = money - 100 where name = 'A'";
connection.prepareStatement(sql).executeUpdate();
//製造錯誤
// int i = 1 / 0;
String sql1 = "update account set money = money + 100 where name = 'B'";
connection.prepareStatement(sql1).executeUpdate();
connection.commit();
System.out.println("success");
} catch (Exception e) {
try {
//如果異常資料庫回滾事務
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}