1. 程式人生 > 遊戲資訊 >夢幻西遊:普陀山進入3燈時代,二狗買爆總服戰號打幫戰?

夢幻西遊:普陀山進入3燈時代,二狗買爆總服戰號打幫戰?

**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請求,否則伺服器就應該返回一個解釋當前錯誤狀況的實體,以及這是臨時的還是永久性的狀況。這些狀態碼適用於任何請求方法。瀏覽器應當向用戶顯示任何包含在此類錯誤響應中的實體內容。

Http狀態碼 Http Status Code Http狀態碼含義中文說明
400 400 Bad Request 請求錯誤,通常是訪問的域名未繫結引起
401 401 Unauthorized 需要身份認證驗證
402 402 Payment Required -
403 403 Forbidden 禁止訪問
404 404 Not Found 請求的內容未找到或已刪除
405 405 Method Not Allowed 不允許的請求方法
406 406 Not Acceptable 無法響應,因資源無法滿足客戶端條件
407 407 Proxy Authentication Required 要求通過代理的身份認證
408 408 Request Timeout 請求超時
409 409 Conflict 存在衝突
410 410 Gone 資源已經不存在(過去存在)
411 411 Length Required 無法處理該請求
412 412 Precondition Failed 請求條件錯誤
413 413 Payload Too Large 請求的實體過大
414 414 Request-URI Too Long 請求的URI過長
415 415 Unsupported Media Type 無法處理的媒體格式
416 416 Range Not Satisfiable 請求的範圍無效
417 417 Expectation Failed 無法滿足的Expect
418 418 I'm a teapot 愚人節笑話
421 421 There are too many connections from your internet address 連線數超限
422 422 Unprocessable Entity 請求的語義錯誤
423 423 Locked 當前資源被鎖定
424 424 Failed Dependency 當前請求失敗
425 425 Unordered Collection 未知
426 426 Upgrade Required 請切換到TLS/1.0
428 428 Precondition Required 請求未帶條件
429 429 Too Many Requests 併發請求過多
431 431 Request Header Fields Too Large 請求頭過大
449 449 Retry With 請重試
451 451 Unavailable For Legal Reasons 訪問被拒絕(法律的要求)
499 499 Client Closed Request 客戶端主動關閉了連線

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伺服器呼叫

在收到請求之後,伺服器會進行如下工作:

**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請求,否則伺服器就應該返回一個解釋當前錯誤狀況的實體,以及這是臨時的還是永久性的狀況。這些狀態碼適用於任何請求方法。瀏覽器應當向用戶顯示任何包含在此類錯誤響應中的實體內容。

Http狀態碼 Http Status Code Http狀態碼含義中文說明
400 400 Bad Request 請求錯誤,通常是訪問的域名未繫結引起
401 401 Unauthorized 需要身份認證驗證
402 402 Payment Required -
403 403 Forbidden 禁止訪問
404 404 Not Found 請求的內容未找到或已刪除
405 405 Method Not Allowed 不允許的請求方法
406 406 Not Acceptable 無法響應,因資源無法滿足客戶端條件
407 407 Proxy Authentication Required 要求通過代理的身份認證
408 408 Request Timeout 請求超時
409 409 Conflict 存在衝突
410 410 Gone 資源已經不存在(過去存在)
411 411 Length Required 無法處理該請求
412 412 Precondition Failed 請求條件錯誤
413 413 Payload Too Large 請求的實體過大
414 414 Request-URI Too Long 請求的URI過長
415 415 Unsupported Media Type 無法處理的媒體格式
416 416 Range Not Satisfiable 請求的範圍無效
417 417 Expectation Failed 無法滿足的Expect
418 418 I'm a teapot 愚人節笑話
421 421 There are too many connections from your internet address 連線數超限
422 422 Unprocessable Entity 請求的語義錯誤
423 423 Locked 當前資源被鎖定
424 424 Failed Dependency 當前請求失敗
425 425 Unordered Collection 未知
426 426 Upgrade Required 請切換到TLS/1.0
428 428 Precondition Required 請求未帶條件
429 429 Too Many Requests 併發請求過多
431 431 Request Header Fields Too Large 請求頭過大
449 449 Retry With 請重試
451 451 Unavailable For Legal Reasons 訪問被拒絕(法律的要求)
499 499 Client Closed Request 客戶端主動關閉了連線

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

      http://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="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>

             
             
             
             
   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檔案中單獨寫頭部。如下圖

  1. 一個Servlet可以指定一個對映路徑

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        </servlet-mapping>
    
  2. 一個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>
    
  3. 一個Servlet可以指定通用對映路徑(/*許可權很高)

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron/*</url-pattern>許可權很高
        </servlet-mapping>
    
  4. 預設請求路徑路徑

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

</servlet-mapping>
  1. 指定一些前後綴

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>*.Aaron</url-pattern>  <!-- 可以自定義字尾請求對映,但是前面*不可加/ -->
        </servlet-mapping>
    
  2. 優先順序問題

    指定了固有的對映路徑優先順序最高,如果找不到就會走預設的請求;

    <!--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="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">
    <!--註冊伺服器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 檔案下載

  1. 向瀏覽器輸出訊息
  2. 下載檔案
    1. 要獲取下載檔案的路徑
    2. 下載的檔名是啥?
    3. 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
    4. 獲取下載檔案的輸入流
    5. 建立緩衝區
    6. 獲取OutputStream物件
    7. 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的資料輸出到客戶端!
    8. 關流
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 驗證碼功能

  1. 驗證怎麼來的?

    • 前端實現

    • 後端實現,需要用到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

  1. 從伺服器請求中拿到Cookie資訊
  2. 伺服器相應給客戶端cookie

1、cookie會話

會話:使用者開啟一個瀏覽器,點選了很多超連結,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話

有狀態會話:訪問網站,下次訪問有記錄的情況

一個網站,怎麼證明你來過?
客戶端 服務端

  1. 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
  2. 伺服器登記你來過了,下次你來的時候我來匹配你;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="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">

    <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標籤

  1. EL表示式:${}
  • 獲取資料
  • 執行運算
  • 獲取Web開發的常用物件
  1. JSP標籤

    <%@ taglib prefix="c" uri="http://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")%>

  1. 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);
            }
        });
    }
}

使用者登入後進入,登出後不能進入主頁,過濾器實現

  1. 使用者登入之後,向Sesison中放入使用者的資料

  2. 進入主頁的時候要判斷使用者是否已經登入;要求:在過濾器中實現!

    @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

      http://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="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>

             
             
             
             
   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檔案中單獨寫頭部。如下圖

  1. 一個Servlet可以指定一個對映路徑

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        </servlet-mapping>
    
  2. 一個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>
    
  3. 一個Servlet可以指定通用對映路徑(/*許可權很高)

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron/*</url-pattern>許可權很高
        </servlet-mapping>
    
  4. 預設請求路徑路徑

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

</servlet-mapping>
  1. 指定一些前後綴

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>*.Aaron</url-pattern>  <!-- 可以自定義字尾請求對映,但是前面*不可加/ -->
        </servlet-mapping>
    
  2. 優先順序問題

    指定了固有的對映路徑優先順序最高,如果找不到就會走預設的請求;

    <!--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="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">
    <!--註冊伺服器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 檔案下載

  1. 向瀏覽器輸出訊息
  2. 下載檔案
    1. 要獲取下載檔案的路徑
    2. 下載的檔名是啥?
    3. 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
    4. 獲取下載檔案的輸入流
    5. 建立緩衝區
    6. 獲取OutputStream物件
    7. 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的資料輸出到客戶端!
    8. 關流
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 驗證碼功能

  1. 驗證怎麼來的?

    • 前端實現

    • 後端實現,需要用到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

  1. 從伺服器請求中拿到Cookie資訊
  2. 伺服器相應給客戶端cookie

1、cookie會話

會話:使用者開啟一個瀏覽器,點選了很多超連結,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話

有狀態會話:訪問網站,下次訪問有記錄的情況

一個網站,怎麼證明你來過?
客戶端 服務端

  1. 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
  2. 伺服器登記你來過了,下次你來的時候我來匹配你;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="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">

    <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標籤

  1. EL表示式:${}
  • 獲取資料
  • 執行運算
  • 獲取Web開發的常用物件
  1. JSP標籤

    <%@ taglib prefix="c" uri="http://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")%>

  1. 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);
            }
        });
    }
}

使用者登入後進入,登出後不能進入主頁,過濾器實現

  1. 使用者登入之後,向Sesison中放入使用者的資料

  2. 進入主頁的時候要判斷使用者是否已經登入;要求:在過濾器中實現!

    @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();
            }
        }
    }
}