主頁 > 後端開發 > JavaWeb

JavaWeb

2023-05-31 07:50:35 後端開發

JavaWeb

1、基本概念

1.1、前言

web開發:

  • web,網頁的意思
  • 靜態web
    • html,css
    • 提供給所有人看的資料始終不會發生變化
  • 動態web
    • 幾乎所有的網站都是動態的
    • 提供給所有人看的資料始侄訓發生變化,每個人在不同的時間,不同的地點看到的資訊各不相同
    • 技術堆疊:Servlet/JSP,ASP,PHP

在Java中,動態web資源開發的技術統稱為JavaWeb

1.2、web應用程式

web應用程式:可以提供瀏覽器訪問的程式

  • index.html、login.html......多個web資源,這些web資源可以唄外界訪問,對外界提供服務
  • 我們能訪問到的任何一個頁面或者資源,都存在于這個世界的某個角落的計算機上
  • URL
  • 這個統一的web資源會被放在同一個檔案夾下,web應用程式-->Tomcat:服務器
  • 一個web應用由多部分組成(靜態web、動態web)
    • html、css、js
    • jsp、Servlet
    • Java程式
    • jar包
    • 組態檔(Properties)

web應用程式撰寫完畢后,若想要提供給外界訪問,需要一個服務器來統一管理

1.3、靜態web

  • *.htm,*.html,這些都是網頁的后綴,如果服務器上一直存在存在這些東西,我們就可以直接進行讀取,通信

    flowchart LR c[客戶端]--一次請求:Request-->s[web Service]--一次回應:Response-->c subgraph 服務器 s-->I(((index.html)))-->s end subgraph 客戶端 c end
  • 靜態web存在的缺點

    • web頁面無法動態更新,所有用戶看到都是同一個頁面
      • 輪播圖,點擊特效:偽動態
      • JavaScript【實際開發中,它用的最多】
      • VBScript
    • 它無法和資料庫互動(資料無法持久化,用戶無法互動)

1.4、動態web

頁面會動態展示:“web的頁面展示的效果因人而異”

flowchart c[客戶端]--一次請求:Request-->w[Web Server Plugin] ws[Web Server]--一次回應:Response-->c subgraph 服務器 w--動態資源-->動態web資源JSP/Servlet-->ws-->fs[File System] end subgraph 客戶端 c end

缺點:

  • 假如服務器的動態web資源出現了錯誤,我們需要重新撰寫我們的后臺程式,重新發布
    • 停機維護

優點:

  • Web頁面可以動態更新,所有用戶看都都不是同一個頁面
  • 它可以與資料庫互動(資料持久化:注冊,商品資訊,用戶資訊.....)
flowchart c[客戶端]--一次請求:Request-->w[Web Server Plugin] ws[Web Server]--一次回應:Response-->c subgraph 服務器 w--動態資源-->source[動態web資源JSP/Servlet]-->ws-->fs[File System] end source--JDBC-->db[(資料庫)] subgraph 客戶端 c end

2、web服務器

2.1、技術講解

ASP

  • 微軟:國內最早流行的就是ASP
  • 在HTML中嵌入了VB腳本,ASP+COM
  • 在ASP開發中,基于一個頁面都有幾千行的業務代碼,頁面極其混亂
  • 維護成本高
  • C#
  • IIS

PHP

  • PHP開發速度很快,功能很強大,跨平臺,代碼很簡單(國內70%)
  • 無法承載大量訪問的情況(局限性)

JSP/Servlet

B/S:瀏覽器和服務器

C/S:客戶端和服務器

  • sun公司主推的B/S架構
  • 基于Java語言(所有的大公司,或者一些開源組件,都是用Java寫的)
  • 可以承載三高問題帶來的影響(高并發、高可用、高性能)
  • 語法像ASP,ASP轉JSP,加強市場強度

2.2、wen服務器

服務器是一種被動的操作,用來處理用戶的一些請求和給用戶一些回應資訊

IIS

微軟的,ASP...Windows中自帶

Tomcat

Tomcat是Apache 軟體基金會(Apache Software Foundation)的Jakarta 專案中的一個核心專案,最新的Servlet 和JSP 規范總是能在Tomcat 中得到體現,因為Tomcat 技術先進、性能穩定,而且免費,因而深受Java 愛好者的喜愛并得到了部分軟體開發商的認可,成為比較流行的Web 應用服務器,

Tomcat 服務器是一個免費的開放源代碼的Web應用服務器,屬于輕量級應用服務器,在中小型系統和并發訪問用戶不是很多的場合下被普遍使用,是開發和除錯JSP 程式的首選,對于一個初學者來說,它是最佳的選擇

Tomcat 實際上運行JSP 頁面和Servlet,

3、Tomcat

3.1、安裝Tomcat

Tomcat官網??https://tomcat.apache.org/

下載——>解壓

  • Core:
    • zip (pgp, sha512)
    • tar.gz (pgp, sha512) Linux安裝包
    • 32-bit Windows zip (pgp, sha512)
    • 64-bit Windows zip (pgp, sha512) 64位安裝包
    • 32-bit/64-bit Windows Service Installer (pgp, sha512)

3.2、Tomcat啟動和配置

檔案夾目錄下??apache-tomcat-9.0.55

??bin 啟動、關閉的腳本檔案夾

??conf 組態檔夾

??lib 依賴的jar包

??logs 日志

??webapps 存放網址的

啟動,關閉Tomcat

??bin目錄下的

startup.bat檔案

shutdown.bat檔案

訪問測驗:http://localhost:8080

可能遇到的問題:

  1. Java環境變數沒有配置
  2. 閃退問題:需要配置兼容性
  3. 亂碼問題:組態檔中設定

3.3、配置

??conf目錄下的

server.xml 服務器核心組態檔

可以配置啟動的埠號

  • Tomcat的默認埠號為:8080
  • MySQL的默認埠號為:3306
  • http的默認埠號為:80
  • https的默認埠號為:443
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

可以配置主機的名稱

  • 默認的主機名為:localhost(127.0.0.1)
  • 默認網站應用存放的位置為:webapps
<Host name="www.amusing.com" appBase="webapps"
      unpackWARs="true" autoDeploy="true" />

網站是如何進行訪問的

  1. 輸入一個域名,回車

  2. 檢查本機的C:\Windows\System32\drivers\etc\hosts組態檔下有沒有這個域名映射:

    1. 有:直接回傳對應的IP地址,這個地址中,有我們需要訪問的web程式,可以直接訪問
    2. 沒有:去DNS服務器找,找到的話就回傳,找不到就回傳找不到
    flowchart RL DNS(((DNS:全世界的域名都在這里管理)))--步驟3-->客戶端--步驟1-->hosts配置 客戶端--步驟2-->DNS
  3. 可以配置一下環境變數(可選性)

3.4、發布一個web網站

  • 將自己寫的網站,放到服務器(Tomcat)中指定的web應用的檔案夾(webapps)下,就可以訪問了

網站應該有的結構

--webapps : Tomcat服務器的web目錄
	-ROOT
	-amusingoh : 網站的目錄名
		-WEB-INF
			-classes : Java程式
			-lib : web應用說依賴的jar包
			-web.xml : 網站組態檔
		index.html 默認的首頁
		-static
			-css
				-style.css
			-js
			-img
		-......

4、Http

4.1、什么是HTTP

HTTP(超文本傳輸協議)是一個簡單的請求-回應協議,同通常運行在TCP之上

  • 文本:HTML,字串,....
  • 超文本:圖片、音樂、視頻、定位、地圖....
  • 埠號:80

Https:安全的

  • 埠號:443

4.2、兩個時代

  • http1.0
    • HTTP/1.0:客戶端可以與web服務器連接后,只能獲得一個web資源,然后斷開連接
  • http2.0
    • HTTP/1.1:客戶端可以與web服務器連接后,可以獲得多個web資源

4.3、Http請求

  • 客戶端---發請求(Request)--服務器

請求示例(向百度發起請求)

Request URL:https://www.baidu.com/   請求地址
Request Method:GET		get方法/post方法
Status Code:200 OK		狀態碼:200
Remote(遠程) Address:14.215.177.39:443
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9	語言
Cache-Control:max-age=0
Connection:keep-alive

4.3.1、請求行

  • 請求行中的請求方式:GET
  • 請求方式:Get,Post,HEAD,DELETE,PUT,TRACT....
    • GET:請求能夠攜帶的產生較少,大小有現在,會在瀏覽器的URL地址顯示資料內容,不安全,但高效
    • POST:請求能夠攜帶的產生沒有限制,大小沒有限制,不會再瀏覽器的URL地址欄顯示資料內容,安全,但不高效

4.3.2、訊息頭

Accept:text/html	告訴瀏覽器,它支持的資料型別
Accept-Encoding:gzip, deflate, br	支持的編碼格式 GBK UTF-8 GB2312
Accept-Language:zh-CN,zh;q=0.9	告訴瀏覽器它的語言環境
Cache-Control:max-age=0		快取控制
Connection:keep-alive	告訴瀏覽器,請求完成是否斷開還是保持連接
HOST:	主機....

4.4、Http回應

  • 服務器--回應--客戶端
Cache-Control:private	換成控制
Connection:Keep-Alive	連接
Content-Encoding:gzip	編碼
Content-Type:text/html	型別

4.4.1、回應體

Accept:text/html	告訴瀏覽器,它支持的資料型別
Accept-Encoding:gzip, deflate, br	支持的編碼格式 GBK UTF-8 GB2312
Accept-Language:zh-CN,zh;q=0.9	告訴瀏覽器它的語言環境
Cache-Control:max-age=0		快取控制
Connection:keep-alive	告訴瀏覽器,請求完成是否斷開還是保持連接
HOST:	主機....
Refresh:  告訴客戶端多久重繪一次
Location:  讓網頁重新定位

4.4.2、回應狀態碼

200:請求回應成功

3xx:請求重定向

  • 重定向:你重新到我給你的新地址去

4xx:找不到資源 404

  • 資源不存在

5xx:服務器代碼錯誤 500 502:網關錯誤

5、Maven

在Javaweb開發中,需要使用大量的jar包,我們手動匯入

如何能夠讓一個東西自動幫我們匯入和配置這個jar包

由此,Maven誕生了

5.1、Maven專案結構管理工具

我們目前用來就是方便匯入jar包的

?? Maven的核心思想:約定大于配置

  • 有約束,不要去違反

Maven會規定好你該如何去撰寫我們的Java代碼,必須按照這個規范來

5.2、下載安裝Maven

Maven官網??https://maven.apache.org/

5.3、配置環境變數

在我們的系統環境變數中

配置如下配置:

  • M2_HOME maven目錄下的bin目錄
  • MAVEN_HOME maven的目錄
  • 在系統的path中配置 %MAVEN_HOME%\bin

測驗Maven是否安裝成功,保證必須配置完畢

5.4、配置阿里云鏡像

  • 鏡像:mirrors
    • 作用:加上jar包的下載
  • 國內建議使用阿里云的鏡像
<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共倉庫</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

5.5、本地倉庫

在本地的倉庫

建立一個本地倉庫:localRepository

<localRepository>D:\maven\apache-maven-3.6.3\repository</localRepository>

6、Servlet

6.1、Servlet 簡介

  • Servlet 就是sun公司開發的動態web的一門技術
  • sun在這些API中提供一個介面叫做:Servlet,如果你想開發一個Servlet程式,只需要完成兩個小步驟:
    • 撰寫一個類,實作Servlet介面
    • 把開發好的Java類部署到web服務器中,

把實作了Servlet介面的Java程式叫做 Servlet

6.2、HelloServlet

Servlet介面Sun公司又有兩個默認的實作類:HttpServlet,

  1. 構建一個普通的Maven專案,刪掉里面的src目錄,以后就在這個專案里面建立Module;這個工程就是Maven主工程

  2. 關于Maven父子工程的理解:

    父專案中會有

    <modules>
        <module>servlet-01</module>
    </modules>
    

    子專案會有

    <parent>
        <artifactId>javaweb-02-servlet</artifactId>
        <groupId>com.amusingoh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    

    父專案中的Java子專案可以直接使用

    son extends father

  3. Maven環境優化

    1. 修改web.xml為最新的
    2. 將Maven的結果搭建完整
  4. 撰寫一個Servlet程式

    1. 撰寫一個普通類

    2. 實作Servlet介面,這里我們直接繼承HttpServlet,GenericServlet

      public class HelloServlet extends HttpServlet {
      	//由于get或者post只是請求實作的不同方式,可以互相呼叫,業務邏輯都一樣
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //ServletOutputStram outputStream = resp.getOutputStream();
              printWriter writer = resp.getWriter(); //回應流
              writer.print("Hello Servlet");
          }
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      
    3. 撰寫Servlet的映射

      為什么需要映射:我們寫的是Java程式,但是要通過瀏覽器訪問,而瀏覽器需要連接web服務器,所以我們需要在web服務中注冊我們寫的Servlet,還需要給他一個瀏覽器能夠訪問的路徑

      <!--注冊Servlet-->
      <servlet>
          <servlet-name>hello</servlet-name>
          <servlet-class>com.amusingoh.servlet.HelloServlet</servlet-class>
      </servlet>
      <!--Servlet的請求路徑-->
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>
      
    4. 配置Tomcat

      注意:配置專案發布的路徑就ok

    5. 啟動測驗

flowchart Servlet介面--實作Servlet介面-->GenericServlet--繼承GenericServlet類-->HttpServlet--繼承HTTP Servlet類-->我們自己的類只需要繼承HttpServlet即可;

6.3、Servlet

Servlet是由Web服務器呼叫,Web服務器在收到瀏覽器請求之后,會

graph 瀏覽器--發送Http請求-->Web容器--首次訪問-->A[Servlet]; Web容器-->res[請求:請求頭,請求體] & resp[回應:回應頭,回應體]--呼叫Servlet的Service方法-->Servlet-->END[我們自己些寫的實作類,重寫這些方法1.接收并處理請求2.給出回應的資訊]; Web容器--讀取回應資訊-->resp

6.4、Mapping問題

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

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  2. 一個Servlet可以指定多個映射路徑

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
  3. 一個Servlet可以指定通用映射路徑

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
  4. 默認請求路徑

    <!--默認請求路徑-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  5. 指定一些后綴或者前綴等等

    <!--可以自定義后綴實作請求映射
    注意 * 前面不能加專案映射路徑
    hello/ddd.amusin
    -->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.hell</url-pattern>
    </servlet-mapping>
    
  6. 優先級問題

    指定了固有的映射路徑優先級最高,如果找不到就會走默認的處理請求

    <!--404-->
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.amusingoh.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    

6.5、ServletContext

web容器在啟動的時候,他會為每個web程式都創建一個ServletContext物件,它代表了當前的web應用

6.5.1、 共享資料

在這個Servlet中保存的資料,可也在另外的Servlet中拿到

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //this.getInitParameter() //初始化引數
        //this.getServletConfig() //Servlet配置
        //this.getServletContext() //Servlet背景關系
        ServletContext context = this.getServletContext();

        String username = "頂癮喔"; //資料
        //將資料保存在ServletContext中
        context.setAttribute("username", username);
    }
}
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;charset=utf-8");
        resp.getWriter().print("名:  " + username);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.amusingoh.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>getc</servlet-name>
    <servlet-class>com.amusingoh.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>getc</servlet-name>
    <url-pattern>/getc</url-pattern>
</servlet-mapping>

6.5.2、獲取初始化引數

<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
}

6.5.3、請求轉發

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    System.out.println("success");
    RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//轉發的請求路徑
    requestDispatcher.forward(req,resp); //呼叫forward實作請求轉發
}
graph LR a-->b-->c-->b-->a;

6.5.4、讀取資源檔案

Properties

  • 在Java目錄下新建properties
  • 在resources目錄下新建properties

發現:都唄打包到了同一個路徑下:classes,我們俗稱這個路徑為classpath;

思路:需要一個檔案流

db.properties

username= test
password=123456
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
    Properties prop = new Properties();
    prop.load(is);
    String user = prop.getProperty("username");
    String pwd = prop.getProperty("password");

    resp.getWriter().print(user+":"+pwd);
}

6.6、HttpServletResponse

web服務器接收到客戶的http請求,針對這個請求,分別創建一個代表請求的HttpServletRequest物件,代表回應的一個HttpServletResponse

  • 如果由獲取客戶端請求過來的引數:找HttpServletRequest
  • 如果要給客戶端回應一些資訊:找HttpServletResponse

6.6.1、簡單分類

負責向瀏覽器發送資料的方法

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

負責向瀏覽器發送回應頭的方法

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);

void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);

回應的狀態碼

int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

6.6.2、下載檔案

  1. 向瀏覽器輸出訊息

  2. 下載檔案

    1??要獲取下載檔案的路徑

    2??下載的檔案名是啥

    3??設定想辦法讓瀏覽器能夠支持下載我們需要的東西

    4??獲取下載檔案的輸入流

    5??創建緩沖區

    6??獲取OutputStream物件

    7??將FileOutputStream流寫入到buffer緩沖區

    8??使用OutputStream將緩沖區中的資料輸出到客戶端

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 1.獲取下載檔案的路徑
    String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/哈哈、.png");
    // String realPath="D:\\Picture\\Receipt4.png";
    System.out.println("路徑:"+realPath);
    // 2.知道下載的檔案名
    String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
    // 3.設定想辦法讓瀏覽器能夠支持(Context-Disposition)下載,中文檔案名要用URLEncoder.encode編碼,否則可能亂碼
    resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"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)) > 0) {
        outputStream.write(buffer,0,len);
    }
    // 8.關閉流
    fileInputStream.close();
    outputStream.close();
}

6.6.3、驗證碼功能

驗證碼怎么來的

  • 前端實作
  • 后端實作,需要用到Java的影像類,產生一個圖片
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //讓瀏覽器3秒自動重繪一次
        resp.setHeader("refresh", "3");
        //在記憶體中創建一個圖片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //得到圖片
        Graphics2D g = (Graphics2D) image.getGraphics();
        //設定圖片的背景顏色
        g.setColor(Color.white);
        g.fillRect(0,0,80,20);
        //給圖片寫資料
        g.setColor(Color.blue);
        g.setFont(new Font(null, Font.BOLD, 20));
        g.drawString(makeNum(),0,20);

        //告訴瀏覽器,這個請求用圖片方式打開
        resp.setContentType("image/jpeg");
        //網站存在快取,不讓瀏覽器快取
        resp.setDateHeader("expires",-1);
        resp.setHeader("cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把圖片寫給瀏覽器
        ImageIO.write(image, "jpg", resp.getOutputStream());

    }
    //生成亂數
    private String makeNum() {
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 7 - num.length(); i++) {
            sb.append("0");
        }
        num=sb.toString()+num;
        return num;
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

請求轉發

graph LR a-->b-->c-->b-->a;

6.6.4、實作重定向

graph LR a--1.向b請求web資源-->b--2.通知a訪問c-->a; a--3.發送請求-->c

一個web資源b收到客戶端a的請求后,b會通知客戶端a去訪問另一個web資源c,這個程序叫重定向

void sendRedirect(String var1) throws IOException;

測驗:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    /*
        resp.setHeader("location", "/response/image");
        resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
        */
    resp.sendRedirect("/response/image"); //重定向
}

重定向和請求轉發的區別:

相同點

  • 頁面都會實作跳轉

不同點

  • 請求轉發時,url 不會產生變化
  • 重定向時,url 地址欄會發生變化

6.6.5、簡單實作登錄重定向

<%--這里提交的路徑,需要尋找到專案的路徑--%>
<%--${pageCentext.request.contextPath}代表當前的專案--%>

<form action="${pageContext.request.contextPath}/login" method="get">
    用戶名:<input type="text" name="username"> <br>
    密碼:<input type="password" name="password"> <br>
    <input type="submit">
</form>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //處理請求
    String username = req.getParameter("username");
    String password = req.getParameter("password");

    System.out.println(username + " : " + password);
    //重定向時一定要注意,路勁問題,否則404,req.getContextPath()獲取當前專案的path
    resp.sendRedirect("/response/success.jsp");
}
<servlet>
    <servlet-name>request</servlet-name>
    <servlet-class>com.amusingoh.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>request</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>success</title>
    </head>
    <body>
        <h1>SUCCESS</h1>
    </body>
</html>

6.7、HttpServletRequest

HttpServletRequest代表客戶端的請求,用戶通過HTTP協議訪問服務器,HTTP請求中的所有資訊會被封裝到HttpServletRequest,通過HttpServletRequest的方法,獲得客戶端的所有資訊

6.7.1、獲取前端傳遞的引數,請求轉發

String getParameter(String var1);

String[] getParameterValues(String var1);

Enumeration getParameterNames();

Map<String, String[]> getParameterMap();

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");

    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobbies = req.getParameterValues("hobbies");
    System.out.println("======================");
    //后臺接受中文亂碼問題
    System.out.println(username);
    System.out.println(password);
    System.out.println(Arrays.toString(hobbies));
    System.out.println("===========================");

    System.out.println(req.getContextPath());
    //通過請求轉發
    //這里的 / 代表當前的web應用
    req.getRequestDispatcher("/success.jsp").forward(req,resp);
}

相同點

  • 頁面都會實作跳轉

不同點

  • 請求轉發時,url 不會產生變化 307
  • 重定向時,url 地址欄會發生變化 302

7、Cookie、Session

7.1、會話

會話:用戶打開一個瀏覽器,點擊了超鏈接,訪問多個web資源,關閉瀏覽器,這個程序稱之為會話

有狀態會話:訪問web資源會留下記錄,記錄用戶訪問過此web資源

一個網站,怎么證明用戶來過
客戶端 服務端

  1. 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了;cookie
  2. 服務器登記用戶來過了,下次用戶再來時服務器匹配用戶;session

7.2、保存會話的兩種技術

cookie

  • 客戶端技術(回應,請求)

session

  • 服務器技術,利用這個技術,可以保存用戶的會話資訊,可以把資訊或資料放在Session中

7.3、Cookie

  1. 從請求中拿到cookie資訊
  2. 服務器回應給客戶端cookie
Cookie[] cookies = req.getCookies(); //獲得Cookie
cookie.getName(); //獲得cookie中的key
cookie.getvalue(); //獲得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMillis() + ""); //新建一個cookie
cookie.setMaxAge(24*60*60); //設定cookie的有效期
resp.addcookie(cookie); //回應給客戶端一個cookie

cookie:一般會保存在本地的用戶目錄下appdata


一個網站Cookie是否存在上限

  • 一個cookie只能保存一個資訊;
  • 一個web站點可以給瀏覽器發送多個cookie,最多存放20哥cookie;
  • Cookie大小限制4kb;
  • cookie瀏覽器上限300個

洗掉Cookie

  • 不設定有效期,關閉瀏覽器自動失效
  • 設定有效時間為0

編碼解碼:

URLEncoder.encode("頂癮喔","utf-8")
URLDecoder.decode(cookie.getValue(),"utf-8")

7.4、Session(重點)

什么是Session:

  • 服務器會給每個用戶(瀏覽器)創建一個Session物件;
  • 一個Session獨占一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在;
  • 用戶登錄之后,整個網站它都可以訪問!-->保存用戶的資訊……

Session和Cookie的區別:

image-20220502214919908.png

Session和Cookie的區別:

  • Cookie是把用戶的資料寫給用戶的瀏覽器,瀏覽器保存
  • Session把用戶的資料寫到用戶獨占的Session中,服務器保存(保存重要的資訊,減少服務器資源的浪費)
  • Session物件由服務器創建

使用場景:

  • 保存一個登錄用戶的資訊
  • 購物車資訊
  • 在整個網站中經常會使用的資料,我們將它保存在Session中

使用Session

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //解決亂碼問題
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");

    //得到Session
    HttpSession session = req.getSession();

    //給Session中存東西
    session.setAttribute("name", new Person("頂癮喔",20));

    //獲取Session的Id
    String sessionId = session.getId();

    //判斷Session是不是新創建的
    if (session.isNew()) resp.getWriter().write("session創建成功,ID:"+sessionId);
    else resp.getWriter().write("session已存在于服務器中,ID:"+sessionId);

    //Session創建時做了什么事情
    //        Cookie cookie = new Cookie("JSESSION", "sessionId");
    //        resp.addCookie(cookie);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req,resp);
}


//得到Session
HttpSession session = req.getSession();

Person name = (Person) session.getAttribute("name");
System.out.println(name);


//得到Session
HttpSession session = req.getSession();
session.removeAttribute("name");
//手動注銷Session
session.invalidate();

會話自動過期:web.xml配置

<!--設定Session默認失效時間-->
<session-config>
    <!--1分鐘后Session自動失效,以分鐘為單位-->
    <session-timeout>1</session-timeout>
</session-config>

8、JSP

8.1、什么是JSP

Java Servlet Pages:Java服務器端頁面,也和Servlet一樣,用于動態Web技術

最大特點:

  • 寫JSP就像在寫HTML
  • 區別:
    • HTML只給用戶提供靜態的資料
    • JSP頁面中可以嵌入Java代碼,為用戶提供動態資料

8.2、JSP原理

思路:JSP是如何執行的

  • 代碼層面沒有任何問題
  • 服務器內部作業
    tomcat中有一個work目錄
    IDEA中使用tomcat,會在IDEA的tomcat中產生一個work目錄

瀏覽器向服務器發送請求,不管訪問什么資源,其實都是在訪問Servlet

JSP最終也會轉換成為一個Java類

JSP本質就是Servlet

//初始化
public void _jspInit(){
    
}
//銷毀
public void _jspDestroy(){
    
}
//JSPServlet
public void _jspServlet(.HttpServletRequest request,HttpServletResponse response)
  1. 判斷請求
  2. 內置的一些物件
final javax.servlet.jsp.PageContext pageContext; //頁面背景關系
javax.servlet.http.HttpSession session = null; //Session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page: 當前
HttpServletRequest request	//請求
HttpServletResponse response //回應
  1. 輸出頁面前增加的代碼
response.setContentType("text/html;charset=UTF-8");	//設定回應的頁面型別
pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
  1. 以上的這些物件都可以在JSP頁面中直接使用

image.png

在JSP頁面中:
只要是Java代碼就會原封不動的輸出
如果是HTML代碼,就會被轉換為:

out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("    <title>title</title>\r\n");
out.write("</head>\t\n");
out.write("<body>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");

這樣的格式,輸出到前端

8.3、JSP基礎語法

任何語言都有字跡的語法,JSP作為Java技術的一種應用,它擁有自己的擴充語法(了解即可),Java所以語法都支持

8.3.1、JSP運算式

<%--JSP運算式
    作用:用來將程式的輸出,輸出到客戶端
    <%= 變數或運算式%>
    --%>
<%= new java.util.Date()%>

8.3.2、JSP腳本片段

<%--JSP腳本片段--%>
<%
int num=0;
for (int i = 0; i < 100; i++) {
    num+=i;
}
out.print("<h1>num="+num+"</h1>");
%>

腳本片段的再實作

<%
int x=10;
out.print(x);
%>
<p>this is JSP text</p>
<%
int y=20;
out.print("x="+x);
out.print("y="+y);
%>

<hr>

<%--在代碼嵌入HTML元素--%>
<%
for (int i = 0; i < 3; i++) {
    %>
<h1>Hello world  <%=i%></h1>
<%
}
%>

8.3.3、JSP宣告

<%--JSP宣告--%>
<%!
    static {
    System.out.println("Loading servlet");
}
private int global_var = 0;
public void amu{
    System.out.println("進入了方法amu");
}
%>

JSP宣告:會被編譯到JSP生成Java的類中!其他的,就會被生成到_jspServlet方法中

在JSP嵌入Java代碼即可

<%%>
<%=%>
<%!%>

<%--注釋--%>

JSP的注釋不會在客戶端顯示,HTML就會

8.4、JSP指令

<%--@include 會將兩個頁面合二為一
    頁面之間的變數會受影響
    --%>
<%@include file="common/header.jsp" %>
<h1>網頁主體</h1>
<%@include file="common/footer.jsp" %>

<hr>

<%--jsp標簽
    jsp:include  拼接頁面,本質還是三個頁面
        頁面之間的變數不受影響
        --%>
<jsp:include page="common/header.jsp"/>
<h1>網頁主體</h1>
<jsp:include page="common/footer.jsp"/>

8.5、四大作用域,九大內置物件

  • PageContext 存東西
  • Request 存東西
  • Response
  • Session 存東西
  • Application 【ServletContext】 存東西
  • Config 【ServletConfig】
  • Out
  • Page 不用了解
  • Exception
pageContext.setAttribute("name1","頂癮喔1"); //保存的資料只在一個頁面中有效
request.setAttribute("name2","頂癮喔2"); //保存的資料只在一次請求中有效,請求轉發會攜帶這個資料
session.setAttribute("name3","頂癮喔3"); //保存的資料只在一次會話中有效,從打開瀏覽器到關閉瀏覽器
application.setAttribute("name4","頂癮喔4"); //保存的資料只在服務器中有效,從打開服務器到關閉服務器

request:客戶端向服務器發送請求,產生的資料,用戶看完就沒用了,比如:新聞、用戶看完沒用的

session:客戶端向服務器發送請求,產生的資料,用戶用完有會兒還有用,比如:購物測

application:客戶端向服務器發送請求,產生的資料,一個用戶用完了,其他用戶還可能使用,比如:聊天資料

8.6、JSP標簽、JSTL標簽、EL標簽

<!--JSTL運算式的依賴-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!--standard標簽庫-->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

EL運算式: ${}

  • 獲取資料
  • 執行運算
  • 獲取web開發的常用物件
  • 呼叫Java方法

jsp標簽

<%--jsp:include--%>

<%--
http://localhost:8080/jsptag.jsp?name=頂癮喔&age=20
--%>
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/頂癮喔"/>
    <jsp:param name="age" value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/20"/>
</jsp:forward>

JSTL運算式

JSTL標簽庫的使用就是為了彌補HTML標簽的不足,它自定義了許多標簽來提供使用,標簽的功能和和Java代碼一樣

格式化標簽

SQL標簽

XML標簽

核心標簽(掌握部分)

image.png

JSTL標簽庫使用步驟

  • 引入對應的 taglib
  • 使用其中的方法
  • 在Tomcat中也需要引入 jstl 的包,否則會報錯:JSTL決議希錯誤

c:if

<body>
    <h4>if測驗</h4>

    <hr>
    <form action="coreif.jsp" method="get">
    <%--
    EL運算式獲取表單中的資料
    ${param.引數名}
    --%>
        <input type="text" name="username" value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/${param.username}">
        <input type="submit" value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/登錄">
    </form>

    <%--判斷如果提交的用戶是管理員,著登錄成功--%>
    <c:if test="${param.username=='admin'}" var="isAdmin">
        <c:out value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/管理員welcome"/>
    </c:if>
    <c:out value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/${isAdmin}"/>

</body>

c:choose c:when

<body>
<%--定義一個變數score,值為84--%>
<c:set var="score" value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/84"/>

<c:choose>
    <c:when test="${score>=90}">
        優秀
    </c:when>
    <c:when test="${score>=80}">
        良好
    </c:when>
    <c:when test="${score>=70}">
        一般
    </c:when>
    <c:when test="${score>=60}">
        及格
    </c:when>
    <c:when test="${score<60}">
        no及格
    </c:when>
</c:choose>

</body>

c:forEach

<body>
<%
    ArrayList<String> people = new ArrayList<>();
    people.add(0, "張三");
    people.add(1, "李四");
    people.add(2, "王五");
    people.add(3, "趙六");
    people.add(4, "田七");
    request.setAttribute("list",people);
%>
<%--
var, 每次遍歷出來的變數
items, 要遍歷的物件
begin, 開始位置
end, 結束位置
step, 步長
--%>
<c:forEach var="people1" items="${list}">
    <c:out value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/${people1}"/> <br>
</c:forEach>
<hr>
<c:forEach var="people1" items="${list}" begin="2" end="4" step="2">
    <c:out value="https://www.cnblogs.com/amusingoh/archive/2023/05/30/${people1}"/> <br>
</c:forEach>

</body>

9、JavaBean

物體類

JavaBean有特定的寫法:

  • 必須要有一個無參構造
  • 屬性必須私有化
  • 必須有對應的 get/set 方法

一般用來和資料庫的欄位做映射 ORM;

ORM:物件關系映射

  • 表-->類
  • 欄位-->屬性
  • 行記錄-->物件
id name age address
1 頂癮喔1 10 城中
2 頂癮喔2 20 魚峰
3 頂癮喔3 30 柳東
class People{
    private int id;
    private String name;
    private in age;
    private String address;
}
class A{
    new People(1,"頂癮喔1",10,"城中");
    new People(2,"頂癮喔2",20,"魚峰");
    new People(3,"頂癮喔3",30,"柳東");
}
  • 過濾器
  • 檔案上傳
  • 郵件發送
  • JDBC復習:如何使用JDBC,JDBC crud,jdbc事務

10、MVC三層架構

什么是MVC:Model View Controller 模型、試圖、控制器

10.1、早些年

image.png

用戶直接訪問控制層,控制層就可以直接操作資料庫

servlet--CRUD-->資料庫
弊端:程式十分臃腫,不利于維護
servlet的代碼中:處理請求、回應、試圖跳轉、處理JDBC、處理業務代碼、處理邏輯代碼

架構:沒有什么是加已成解決不了的

10.2、MVC三層架構

image.png

Model

  • 業務處理:業務邏輯(Service)
  • 資料持久層:CRUD(Dao)

View

  • 展示資料
  • 提供鏈接發起Servlet請求(a,form,img...)

Controller (Servlet)

  • 接收用戶的請求:(req:請求引數、Session資訊...)

  • 交給業務層處理對應的代碼

  • 控制視圖的跳轉

    登錄--->接收用戶的登錄請求--->處理用戶的請求(獲取用戶登錄的引數,username,password)--->交給業務層處理登錄業務(判斷用戶名密碼是否正確:事務)--->Dao層查詢用戶名和密碼是否正確--->資料庫

11、Filter(重點)

Filter:過濾器,用來過濾網站的資料

  • 處理中文亂碼
  • 登錄驗證

image.png

Filter開發步驟:

  1. 導包

    導包不要導錯

    import javax.servlet.Filter
    
  2. 撰寫過濾器

    public class CharacterEncodingFilter implements Filter {
        //初始化:web服務器啟動,就已經初始化了,隨時等待過濾物件的出現
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter初始化");
        }
    
        /**
         * Chain: 鏈
         * 過濾中的所有代碼,在過濾特定請求的時候都會執行
         * 必須要讓過濾器繼續同行
         */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletResponse.setContentType("text/html;charset=utf-8");
            System.out.println("CharacterEncodingFilter執行前,,,");
            //讓我們的請求繼續走,如果不屑,程式到這里就會被攔截停止
            filterChain.doFilter(servletRequest,servletResponse);
            System.out.println("CharacterEncodingFilter執行后,,,");
        }
    
        //銷毀:web服務器關閉時,過濾器會銷毀
        @Override
        public void destroy() {
            System.out.println("CharacterEncodingFilter銷毀");
        }
    }
    
  3. 在web.xml中配置Filter

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.amusingoh.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是/servlet的任何請求,會經過這個過濾器-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
    

12、監聽器

實作一個監聽器的介面

  1. 撰寫一個監聽器

    實作監聽器的介面

    public class OnlineCounterListener implements HttpSessionListener {
        /**
         * 創建session監聽
         * 一旦創建Session就會觸發一次這個事件
         */
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext servletContext = se.getSession().getServletContext();
            System.out.println(se.getSession().getId());
    
            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);
        }
    
        /**
         * 銷毀session監聽
         * 一旦銷毀Session就會觸發一次這個事件
         * Session銷毀:
         * 1.手動銷毀 getSession().invalidate();
         * 2.自動銷毀
         */
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            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);
        }
    }
    
  2. web.xml中注冊監聽器

    <!--注冊監聽器-->
    <listener>
        <listener-class>com.amusingoh.listener.OnlineCounterListener</listener-class>
    </listener>
    
  3. 查看使用情況

13、過濾器、監聽器常見應用

監聽器:GUI編程中經常使用

用戶登錄之后才能進入主頁,用戶注銷后就不能進入主頁了

  1. 用戶登錄之后,向session中放入用戶的資料
  2. 進入主頁的時候要判斷用戶是否已經登錄, 要求:在過濾器中實作
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

if (request.getSession().getAttribute(Constant.USER_SESSION) == null) {
    response.sendRedirect("/javaweb_filter/error.jsp");
}
filterChain.doFilter(servletRequest,servletResponse);

14、JDBC

什么是JDBC:Java連接資料庫

220527

需要jar的包支持

  • java.sql
  • javax.sql
  • mysql-conneter-java...連接驅動(必須要匯入)

建表陳述句

use test;

create table users(
    id int primary key,
    `name` varchar(30),
    `password` varchar(40),
    email varchar(40),
    birthday date
) engine=innodb, character set =utf8,collate=utf8_general_ci;

insert into users(id, `name`, `password`, email, birthday)
values (1, '張三', '123456', '[email protected]', '2000-01-01'),
       (2, '李四', '123456', '[email protected]', '2000-01-02'),
       (3, '王五', '123455', '[email protected]', '2000-01-03');

select * from users;

匯入資料庫依賴

<!--mysql的驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>

JDBC固定操作

  1. 加載驅動
  2. 連接資料庫
  3. 向資料庫發送SQL的物件Statement:CRUD
  4. 撰寫SQL(根據業務,不同的SQL)
  5. 執行生氣了
  6. 關閉連接

資源檔案 db.properties

driver=com.mysql.cj.jdbc.Driver
# useUnicode=true&characterEncoding=utf-8 解決中文亂碼問題
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username=test
password=123456

JDBC工具類JdbcUtils.java

public class JdbcUtils {
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    static {
        try {
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            Properties properties = new Properties();
            properties.load(inputStream);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            System.out.println(url);
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //驅動只用加載一次
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //獲取鏈接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    //釋放鏈接資源
    public static void release(Connection conn, Statement st, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

TestJdbc.java

public class TestJdbc {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            //加載驅動
            //連接資料庫
            conn = JdbcUtils.getConnection();
            //向資料庫發送SQL的物件Statement : CRUD
            st = conn.createStatement();

            //撰寫SQL
            String sql = "select * from users;";

            //執行查詢SQL,回傳一個ResultSet : 結果集
            rs = st.executeQuery(sql);

            while (rs.next()) {
                System.out.println("id="+rs.getObject("id"));
                System.out.println("name="+rs.getObject("name"));
                System.out.println("password="+rs.getObject("password"));
                System.out.println("email="+rs.getObject("email"));
                System.out.println("birthday="+rs.getObject("birthday"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //關閉連接,釋放資源(一定要做) 先開后關
            JdbcUtils.release(conn,st,rs);
        }
    }
}

預編譯SQL

public class TestJdbc2 {
    public static void main(String[] args) throws Exception {
        //配置資訊
        String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
        String username = "test";
        String password = "123456";

        //1.加載驅動
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.連接資料庫
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.撰寫SQL
        String sql = "insert into users(id,`name`,`password`,email,birthday) values(?,?,?,?,?);";

        //4.預編譯
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,4);
        preparedStatement.setString(2,"頂癮喔");
        preparedStatement.setString(3,"123456");
        preparedStatement.setString(4,"[email protected]");
        preparedStatement.setDate(5, new Date(new java.util.Date().getTime()));

        //5.執行SQL
        int i = preparedStatement.executeUpdate();
        if (i > 0) {
            System.out.println("inset success");
        }
        //6.關閉連接
        preparedStatement.close();
        connection.close();
    }
}

事務

要么都成功,要么都失敗

ACID原則:保證資料的安全

開啟事務

事務提交 commit()

事務回滾 rollback()

事務關閉

Junit單元測驗

依賴

<!--單元測驗-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
</dependency>

簡單使用

@Test注解只有在方法上有效,只要加了這個注解的方法,就可以直接運行

@Test
public void test() {
    System.out.println("Hello");
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/553825.html

標籤:其他

上一篇:新版idea快捷鍵總結學習----(用于java開發模式)

下一篇:返回列表

標籤雲
其他(159989) Python(38189) JavaScript(25464) Java(18161) C(15234) 區塊鏈(8268) C#(7972) AI(7469) 爪哇(7425) MySQL(7217) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5344) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4579) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1977) 功能(1967) Web開發(1951) HtmlCss(1950) C++(1927) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1862) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • JavaWeb

    # JavaWeb ## 1、基本概念 ### 1.1、前言 web開發: - web,網頁的意思 - 靜態web - html,css - 提供給所有人看的資料始終不會發生變化 - 動態web - 幾乎所有的網站都是動態的 - 提供給所有人看的資料始侄訓發生變化,每個人在不同的時間,不同的地點看到 ......

    uj5u.com 2023-05-31 07:50:35 more
  • 新版idea快捷鍵總結學習----(用于java開發模式)

    ### 選擇代碼區 1. ctrl w - 如果放到以if開頭的陳述句,可以選擇if判斷條件所在的代碼片段 - 游標在單個單詞下時 選擇單詞 - 在選中多個單詞時,選擇整個字串 - 三次點擊時,如果不在字串單詞下,用于選擇{}內的代碼片段 逐級遞增 如果在單詞下方,用于選擇單詞所在的字串并且向外 ......

    uj5u.com 2023-05-31 07:50:18 more
  • geowebCache 切片不同方式的呼叫

    1.curl 方式 curl -v -u admin:geoserver -H "Content-type: application/json" -d "{'seedRequest':{'name':'NR:tdbp','bounds':{'coords':{ 'double':[ '108.790 ......

    uj5u.com 2023-05-31 07:50:09 more
  • np.bincount方法

    [官方檔案](https://numpy.org/doc/stable/reference/generated/numpy.bincount.html#numpy-bincount) `out = np.bincount(x[, weights, minlength])` **該函式用于統計輸入陣列 ......

    uj5u.com 2023-05-31 07:50:04 more
  • JavaWeb編程面試題——Spring Boot

    面試題==知識點,這里所記錄的面試題并不針對于面試者,而是將這些面試題作為技能知識點來看待。不以刷題進大廠為目的,而是以學習為目的。這里的知識點會持續更新,目錄也會隨時進行調整。 ......

    uj5u.com 2023-05-31 07:50:00 more
  • Python 實作 m3u8 視頻下載

    # Python 實作 m3u8 視頻下載 m3u8 是一種**基于文本的媒體播放串列檔案格式**,通常用于指定流媒體播放器播放在線媒體流。它是一個簡單的文本檔案,其中包含多個由 URI 參考的媒體資源檔案的 URL。m3u8 檔案通常包含多個 ts 檔案的鏈接,這些 ts 檔案是實際的視頻和音頻數 ......

    uj5u.com 2023-05-31 07:49:53 more
  • 一文詳解 Sa-Token 中的 SaSession 物件

    Sa-Token 是一個輕量級 java 權限認證框架,主要解決登錄認證、權限認證、單點登錄、OAuth2、微服務網關鑒權 等一系列權限相關問題。 > Gitee 開源地址:[https://gitee.com/dromara/sa-token](https://gitee.com/dromara/ ......

    uj5u.com 2023-05-31 07:49:45 more
  • 如何用ReadWriteLock實作一個通用的快取中心?

    摘要:在并發場景中,Java SDK中提供了ReadWriteLock來滿足讀多寫少的場景。 本文分享自華為云社區《【高并發】基于ReadWriteLock開了個一款高性能快取》,作者:冰 河。 寫在前面 在實際作業中,有一種非常普遍的并發場景:那就是讀多寫少的場景。在這種場景下,為了優化程式的性能 ......

    uj5u.com 2023-05-31 07:49:34 more
  • 【爬蟲+資料清洗+可視化】用Python分析“淄博燒烤“的評論資料

    [toc] # 一、背景介紹 您好,我是[@馬哥python說](https://mp.weixin.qq.com/s/EuOKLq6ZSgQGnijreylSiA) ,一枚10年程式猿。 自從2023.3月以來,"淄博燒烤"現象持續占領熱搜流量,體現了后疫情時代眾多網友對人間煙火氣的美好向往,本現 ......

    uj5u.com 2023-05-31 07:49:02 more
  • c++11: all_of 、 any_of 和 none_of

    242. 有效的字母異位詞 ```cpp class Solution { public: bool isAnagram(string s, string t) { if(s.size()!=t.size()) return false; int ans[26]={0}; for(auto& ch: ......

    uj5u.com 2023-05-31 07:48:43 more