1. 程式人生 > 實用技巧 >C# 名稱空間

C# 名稱空間

基本概念

在java中,動態資源開發的技術稱為javaweb

web開發

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

web應用程式

可以提供瀏覽器訪問的程式

  • a.html b.html ....多個web資源,這些web資源可以被外界訪問,對外界提供服務
  • URL
  • 一個web應用由多部分組成(靜態web,動態web)
    • html css
    • jsp servlet
    • java程式
    • jar包
    • 配置檔案(properties)
  • web應用程式編寫完畢,若想提供給外界訪問,需要一個伺服器來統一管理

Tomcat

安裝

安裝tomcat,之前需要先安裝一下jdk,用java -version檢查

官網目前已經更新到tomcat10了

下載壓縮包之後,直接解壓

啟動

如果你直接點選bin目錄下的startup.bat,可能會出現一閃而過

你需要在控制檯中輸入

之後在網頁上輸入localhost:8080,就會顯示

但是,執行結果可能會出現亂碼

修改conf目錄下的logging.properties檔案

將檔案中原有的配置修改

#原有
java.util.logging.ConsoleHandler.encoding = UTF-8
#修改成GBK,因為windows預設是gbk
java.util.logging.ConsoleHandler.encoding = GBK

訪問測試:localhost:8080

資料夾對應作用

--webapps Tomcat伺服器的web目錄
	-ROOT
	-project	網站的目錄名
		-WEB-INF
			-classes	java程式
			-lib	web應用所依賴的jar包
			-web.xml	網站配置檔案
        - index.html	預設的首頁
        - static
        	-css
        		-style.css
            -js
            -img
        -....

HTTP

什麼是HTTP

HTTP(超文字傳輸協議)是一個簡單的請求—響應協議,它通常是執行在TCP上

  • 文字:html,字串

  • 超文字:圖片,音樂,視訊,地圖,定位...

  • 80埠

Https:安全的

  • 443埠

HTTP請求

  • 客戶端——發請求(Request)——伺服器

百度的例子

Request URL: https://www.baidu.com/?tn=78040160_14_pg&ch=8 請求地址
Request Method: GET	get/post
Status Code: 200 OK	狀態碼:200
Remote Address: 163.177.151.110:443 遠端地址
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
  • 請求行
    • 請求方式:GET,POST
      • get:請求能攜帶的引數比較少,大小有限制,不安全但高效
      • post:請求能攜帶的引數沒有限制,大小沒有限制,安全但不高效
  • 請求頭
Accept:  告訴瀏覽器,它支援的資料型別
Accept-Encoding: 支援哪種編碼格式 GBK,UTF-8,GB312 ..
Accept-Language: 告訴瀏覽器,他的語言環境
Cache-Control: no-cache	快取控制
Connection: 告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機

HTTP響應

  • 伺服器——響應——客戶端

百度的例子

Cache-Control: private 快取控制
Connection: keep-alive	連線
Content-Type: text/html;charset=utf-8
  • 響應體
Accept:  告訴瀏覽器,它支援的資料型別
Accept-Encoding: 支援哪種編碼格式 GBK,UTF-8,GB312 ..
Accept-Language: 告訴瀏覽器,他的語言環境
Cache-Control: no-cache	快取控制
Connection: 告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機
Refrush:告訴客戶端,多久重新整理一次
Location讓網頁重新定位
  • 響應狀態碼
響應狀態碼 描述
200 請求成功
3** 請求重定向
4** 找不到
5** 伺服器錯誤
502 閘道器錯誤

面試題

當你的瀏覽器中輸入地址並回車的一瞬間到頁面能夠展示回來,經歷了什麼

  1. DNS解析
    • 瀏覽器的DNS快取
    • 系統的DNS快取
    • 路由器的DNS快取
    • 網路運營商的DNS快取(中國移動,中國電信)
    • 上述都沒有找到,則會採用遞迴的方式,向根服務器進行查詢,根伺服器告訴本地DNS伺服器域的伺服器地址,本地DNS向域伺服器發出請求,域伺服器告訴本地伺服器域名解構伺服器的地址,本地伺服器向域名解構伺服器發出請求,收到域名和IP的關係,本地伺服器再返回給瀏覽器並將對應關係儲存在快取中,以下一次使用
  2. DNS優化
    • DNS快取
      • DNS存在很多級快取,從離瀏覽器的距離排序,(瀏覽器快取,系統快取,路由器快取,IPS伺服器快取,根域名伺服器快取,頂級域名伺服器快取,主域名伺服器快取)
    • DSN負載均衡
      • DNS可以返回一個合適的機器的IP給使用者,例如可以根據每臺機器的負載量,該機器離使用者地理位置的距離等等
  3. 當瀏覽器拿到IP後,就向伺服器傳送http連線請求,三次握手
  4. 傳送請求
  5. 接受響應
  6. 瀏覽器頁面渲染
    1. 處理HTML標記並構建DOM樹
    2. 處理CSS標記並構建CSSDOM樹
    3. 將DOM和CSSDOM合併為一棵渲染樹
    4. 根據渲染樹來佈局,以計算每個節點的幾何資訊(重排)
    5. 將各個節點繪製到螢幕(重繪)
    6. 如果DOM和CSSDOM被修改,以上過程需要重複執行,才能計算出哪些畫素需要在螢幕上進行重新渲染
  7. 斷開連線“TCP四次揮手"

Maven

為什麼學習Maven?

在javaWeb開發中,需要大量的jar包,我們需要手動匯入。Maven就是為了方便匯入jar包

安裝Maven

官網

下載完成後解壓

配置環境變數

在我們系統環境變數

配置如下環境變數

名稱 具體含義
M2_HOME maven目錄下的bin目錄
MAVEN_HOME maven目錄
在系統變數PATH中配置MAVEN_HOME %MAVEM_HOME%\bin

測試Maven 是否安裝成功mvn -version

修改setting.xml

路徑:D:\Environment\maven\apache-maven-3.5.4\conf\settings.xml

在setting.xml中配置映象(為了下載依賴的速度變快)和本地倉庫(設定依賴的下載位置)

阿里雲映象

 <mirror>
	<id>nexus-aliyun</id>
	<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
	<name>Nexus aliyun</name>
	<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

本地倉庫

配置好之後,在本地需要新建一個資料夾soft(資料夾名可以自己設定。比如repo,repository)

<!-- 本地倉庫位置 -->
<localRepository>D:/Environment/maven/soft</localRepository>

在Maven中建立一個帶模板專案

在IDEA中啟用使用Maven

建立專案

在專案建立成功後,檢查一下是否正確(看一眼,萬一依賴下載到C盤要炸,越來越多後面電子會“炸”)

補充資料夾

補充資料夾java和resources,標記資料夾功能

  • java ——>Sources Root
  • resources——>Resources Root
    • resources資料夾是給java檔案讀取的

修改web.xml

使用模板新建的專案,web.xml太舊了

使用下載的tomcat中的web.xml

路徑:D:\Environment\apache-tomcat-9.0.37\webapps\ROOT\WEB-INF

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">
</web-app>

在Maven中建立一個普通專案

在New Project中不選擇模板,直接點選Next

WEB-INF使用者不可見的,所以,如果你將jquery的包放在WEB-INF中,html中是拿不到的

pom.xml

maven由於他的約定大於配置,我們之後可能遇到的問題,無法匯入或者生效的問題

解決方案

Maven手動匯入jar

下載jar包

Apache Commons IO » 2.4

匯入jar

Add as Library

右鍵lib資料夾

在IDEA中配置Tomcat

配置Tomcat

沒有配置Deployment,會碰到如下警告

碰到的問題

參考連結

啟動tomcat

解決碰到的問題

  • Maven 3.6.2

解決方法:降級為3.6.1

  • iDEA中每次都要重複配置Maven

解決方法:在IDEA中全域性預設配置去配置

  • ,maven預設專案中web.xml版本問題

解決方法:在Tomcat目錄下的webapps/ROOT/WEB-INF中複製(將一些沒用的刪除),替換為webapp4.0版本和tomcat一致

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0"
         metadata-complete="true">
</web-app>

Servlet

Servlet簡介

  • servlet是sun公司開發動態web的一門技術
  • sun公司在這些API中提供了一個介面叫做Servlet,如果你想開發一個servelt,只需要完成2個步驟
    • 編寫好一個類,實現servlet介面
    • 把開發好的java類部署到web伺服器中

把實現了servlet介面的java程式叫做Servlet

HelloServlet

  • 構建一個普通的Maven專案是,刪除裡面的src目錄,以後就在這個專案中建立一個Moudel,這個空的工程就是Maven的主工程

  • Maven父子工程的理解

    父專案中會有

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

    子專案會有(如果沒有的話下面這段,自己加一個)

    比如我建立的一個Moudle就沒有自動生成,就需要自己寫,還有刪除一些自帶的

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>javaweb-servlet-01</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>servlet01</artifactId>
    <packaging>war</packaging>
    

    優點:父專案中的jar包可以在子專案中使用

  • Maven環境優化

  • 修改web.xml為最新的

  • 將Maven的結構搭建 java resource

  • 編寫一個Servlet程式

    • 編寫一個普通類
    • 實現Servlet介面,直接繼承HttpServlet
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    //由於get 和 post 只是請求實現的不同的方式 可以相互呼叫 業務邏輯都一樣
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();//響應流
        writer.println("hello servlet !");
    }

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

  • 編寫Servlet的對映
    • 為什麼需要對映:因為我們寫的是java程式,但是要通過瀏覽器訪問,而瀏覽器需要連線web伺服器,所以我們需要在web服務中註冊我們寫的servlet,還需要給他一個能夠訪問的路徑
<!--    註冊servlet-->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
</servlet>
<!--    servlet的請求路徑-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 配置tomcat
  • 啟動測試,OK!

Mapping

一般是用一個servlet可以指定一個對映路徑

  • 一個servlet可以指定一個對映路徑
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 一個servlet可以指定多個對映路徑
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
  • 一個servlet可以指定通用對映路徑
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  • 指定一些字尾或者字首(但是*前不加/)
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

ServletContext上下文

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

共享資料

我們在HelloServlet中儲存資料,可以在另外一個servlet中拿到

儘量不要用ServletContext來共享資料,資料一多會炸,可以使用session

public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");
        System.out.println(username);
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().print("名字:"+username);
    }

}

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello");
        ServletContext context =  this.getServletContext();

        String username = "DJ";
        context.setAttribute("username",username);//將一個數據儲存在servletContext中
    }

}

讀取資原始檔

ProPerties

  • 在java目錄下新建properties
  • 在resources目錄下新建propertites

發現都被打包到同一個路徑下:classes,我們俗稱這個路徑是classpath

public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //這個路徑主要是針對target生成的
        InputStream is= context.getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        System.out.println(username+" "+ password);
    }

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

HttpServletResponse

使用例子

向瀏覽器輸出訊息

(上面一直提到)

下載檔案

  1. 要獲取下載的檔案的路徑
  2. 設定下載的檔名
  3. 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
  4. 獲取下載檔案的輸入流
  5. 建立緩衝區
  6. 獲取OutputStream物件
  7. 獲取OutputStream流寫入到buffer緩衝區
  8. 使用OutputStream將緩衝區中的資料輸出到客戶端
package com.study.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1. 要獲取下載的檔案的路徑
        String realPath="D:\\Project\\javawebservlet01\\response\\target\\classes\\圖片.png";
        System.out.println("下載檔案的路徑"+realPath);
//        2. 設定下載的檔名
        String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
        System.out.println("檔名"+fileName);
//        3. 設定想辦法讓瀏覽器能夠支援下載我們需要的東西
        //web下載檔案的頭資訊 URLEncoder.encode 處理檔名亂碼
        resp.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
//        4. 獲取下載檔案的輸入流
        FileInputStream in = new FileInputStream(realPath);
//        5. 建立緩衝區
        int length=0;
        byte[] buffer = new byte[1024];
//        6. 獲取OutputStream物件
        ServletOutputStream out =  resp.getOutputStream();
//        7. 獲取OutputStream流寫入到buffer緩衝區 使用OutputStream將緩衝區中的資料輸出到客戶端
        while((length=in.read(buffer))>0){
            out.write(buffer,0,length);
        }
        in.close();
        out.close();

    }

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

定時重新整理驗證碼

採用的其實是重新整理整個頁面

package com.study.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //讓瀏覽器3s自動重新整理一次
        resp.setHeader("refresh","3");
        //在記憶體中建立一張圖片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到圖片
        Graphics2D g = (Graphics2D) image.getGraphics();
        g.setColor(Color.white);
        g.fillRect(0,0,80,20);
        //給圖片寫資料
        g.setColor(Color.green);
        g.setFont(new Font(null,Font.BOLD,20));
        String num = makeNum();
        System.out.println(num);
        g.drawString(num,0,20);
        //告訴瀏覽器,這個請求用圖片的方式開啟
        resp.setContentType("image/jpeg");
        //把圖片寫到瀏覽器 jpg表示檔案格式名
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(1000000)+"";//[0,100000)
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0;i<6-num.length();i++){
            stringBuffer.append("0");
        }
        return num;

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

重定向

URL會發生變化

一個web資源收到客戶端A請求後,B通知客戶端A去訪問另外一個web資源C,這個過程叫重定向

void sendRedirect(String var1) throws IOException;

常見的例子:登入狀態

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //設定後臺傳給前臺的資料不是亂碼
    resp.setCharacterEncoding("UTF-8");//不然頁面顯示會亂碼
    resp.sendRedirect("/response_war/img");
}
<form action="${pageContext.request.contextPath}/redi" method="get">
    username:<input type="text" name="username" /><br/>
    password:<input type="text" name="password" /><br/>
    <input type="submit">
</form>

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

  • 相同點
    • 頁面都會發生跳轉
  • 不同點
    • 請求轉發的時候URL不會發生變化 307
    • 重定向的時候,URL發生後變化 302

HttpServletRequest

//常用方法
//1. 獲得前臺的引數
//設定前臺傳給後臺的資料不是亂碼
req.setCharacterEncoding("UTF-8");
req.getParameter("username");
req.getParameterValues("hobbys");
//2. 通過請求轉發 
// /success.jsp /代表當前的web應用
req.getRequestDispatcher("/success.jsp").forward(req,resp);

Cookie,Session

會話

會話:使用者開啟一個瀏覽器,點選瀏覽很多連結,訪問了多個web資源,關閉瀏覽器,這個過程就是會話

有狀態會話:

一個網站,怎麼證明你來過?

客戶端 服務端

  1. 服務端給客戶端一個信件,客戶端下次訪問服務端就帶上一個信件就可以了 cookie
  2. 伺服器登記你來過了,下次你來的時候我來匹配你:session

儲存會話的兩種技術

cookie:一般會儲存在本地的使用者目錄下 appdata

//從請求中拿到cookie拿到cookie的資訊
//伺服器響應給客戶端cookie
Cookie[] cookies = req.getCookies(); //獲得cookie
cookie.getName();//獲得cookie的key
cookie.getValue();//獲得cookie的value
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一個cookie
cookie.setMaxAge(24*60*60); //設定cookie的有效期,若沒有設定,關閉瀏覽器cookie就失效
package com.study.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

//儲存使用者上一次訪問的時間
public class CookieDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //伺服器 告訴你 你來的時間, 把這個時間封裝成一個信件,你下次帶來,我就知道了
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        PrintWriter out = resp.getWriter();
        //Cookie 伺服器從客戶端獲取
        Cookie[] cookies = req.getCookies();

        if(cookies!=null){
            //如果存在,遍歷陣列
            out.write("你上一次訪問的時間是");
            for(Cookie cookie:cookies){
                if("lastLoginTime".equals(cookie.getName())){
                    //獲取cookie的值
                    System.out.println(cookie.getValue());//String
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        }else{
            out.write("這是第一次訪問本站");
            System.out.println("這是第一次訪問本站");
        }
        //伺服器給客戶端響應一個cookie
        Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
        //有效期為一天 s
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);
    }

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

Session(重點)

什麼是Session

  • 伺服器會給每一個使用者(瀏覽器)建立一個Session物件
  • 一個Session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就一直存在
  • 使用者登入之後,整個網站都可訪問
//建立session 並且給屬性賦值,也是可以存放一個物件的
package com.study.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        //得到session
        HttpSession session = req.getSession();
        //給Session中存在東西
        session.setAttribute("name","張三");
        //獲得session的ID
        String id = session.getId();
        //判斷Session 是不是新建立的
        if(session.isNew()){
            resp.getWriter().write("session建立成功ID"+id);
        }else{
            resp.getWriter().write("session已經建立成功ID"+id);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//取出session的值
package com.study.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CookieDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        //得到session
        HttpSession session = req.getSession();
        //取Session中存在東西
        resp.getWriter().write(session.getAttribute("name"));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
設定session的失效時間
在web.xml
<!--  設定session的失效時間 單位:分鐘-->
<session-config>
	<session-timeout>1</session-timeout>
</session-config>
在程式碼中
session.removeAttribute("name");
session.invalidate();

Session和Cookie的區別

  • session儲存在伺服器端,cookie儲存在瀏覽器。
  • session比較安全,cookie用某些手段可以修改,不安全。
  • cookie的儲存量有限、只允許存入4KB,而session是無限量的

使用場景:

  • 儲存一個登入使用者的資訊
  • 購物車資訊
  • 在整個網站中經常使用的資料,將他儲存在session

JSP

什麼是jsp

java server pages :java伺服器頁面,也和servlet一樣,使用者動態web技術

最大的特點

  • 寫JSP就像在寫HTML
  • 區別
    • HTML只給使用者提供靜態的資料
    • jsp頁面可以嵌入java程式碼,為使用者提供動態資料

JSP原理

思路 JSP是怎麼執行的

  • 程式碼層面沒有任何問題,和html程式碼很像
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
  • 伺服器內部工作

tomcat 中有一個work目錄

IDEA中使用Tomcat的會在IDEA生成一個work目錄

D:\Environment\apache-tomcat-9.0.37\work\Catalina\localhost\ROOT\org\apache\jsp

發現頁面變成了java程式,jsp最終會被轉換成一個java類

  • 瀏覽器向伺服器傳送請求,不管訪問什麼資源,其實都是在訪問Servlet

  • JSP本質上就是一個servlet
final javax.servlet.jsp.PageContext pageContext;//頁面上下文
javax.servlet.http.Httpsession session=null;//Session
final javax.servlet.Servletcontext application;//application
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out=null;//out
final java.lang.Object page = this;//pag	e當前頁
HttpServletRequest  request;//請求
HttpServletReponse  reponse ;//響應    

在JSP頁面中

只要是JAVA程式碼就會原封不動的輸出

如果是HTML程式碼,就會被轉換為

out.writer("<html>\r\n")

JSP基礎語法

jsp表示式

<%=new java.util.Date()%>

jsp指令碼片段

<%for(int i = 0;i<10;i++){%>
    <p>123</p>
<%}%>

jsp宣告

<%!
static {
         system. out. println(" Loading Servlet! ");
}

private int globalvar =0;

public void f(){
         system. out printIn("進入了方法 ");
}
%>

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

<!--我是Html註釋->
<%--我是JSP註釋--%>
jsp的註釋不會在客戶端顯示,html的註釋可以看到

九大內建物件

  • PageContext 存東西
  • Request 存東西
  • Response
  • Session 存東西
  • Application【ServeltContext】存東西
  • config【ServletConfig】
  • out
  • page 不用瞭解
  • exception

request:客戶端向伺服器傳送請求,產生的資料,使用者看完就沒用了,比如:新聞,使用者看完沒用了

session:客戶端向伺服器傳送請求,產生的資料,使用者用完一會還有用,比如:購物車

application:客戶端向伺服器傳送請求,產生的資料,一個使用者用完,其他使用者還可以使用,比如:聊天記錄

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--http://localhost:8080/jsp01_war_exploded/pageContextDemo01.jsp--%>
<%--內建物件--%>
<%
    pageContext.setAttribute("name1","張三");// 儲存的資料只在一個頁面中有效,在另外一個頁面就請求不到了
    request.setAttribute("name2","李四");//儲存的資料只有在一次請求中有效,請求轉發會攜帶這個資料
    session.setAttribute("name3","王五");//儲存的資料只在一次會話中有效,從開啟瀏覽器到關閉瀏覽器
    application.setAttribute("name4","小李");//儲存的資料只在伺服器中有效,從開啟伺服器到關閉伺服器
%>
<%
//    通過pageContext取出我們儲存的值
//pageContext取出,我們通過尋找的方式來
    //從底層到高層(作用域)page->request->session->application
    String name1=(String)pageContext.findAttribute("name1");
    String name2=(String)pageContext.findAttribute("name2");
    String name3=(String)pageContext.findAttribute("name3");
    String name4=(String)pageContext.findAttribute("name4");
    //pageContext.forward("/pageContextDemo02.jsp"); 測試request請求轉發的作用域
%>

<%--使用EL表示式輸出 ${}--%>
<%--一般取值就用EL表示式,比%=好,因為會自動過濾null的值--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>

</body>
</html>

JSTL標籤、EL表示式(${})

JSTL標籤庫的使用為了彌補HTML標籤不足;它自定義了許多標籤,可以供我們使用,標籤的功能和java程式碼一樣

核心標籤

標籤 描述
<c:out> 用於在JSP中顯示資料,就像<%= ... >
<c:set> 用於儲存資料
<c:remove> 用於刪除資料
<c:if> 與我們在一般程式中用的if一樣
<c;choose> 本身只當做<c:when>和<c:otherwise>的父標籤
<c:when> <c:choose>的子標籤,用來判斷條件是否成立
<c:otherwise> <c:choose>的子標籤,接在<c:when>標籤後,當<c:when>標籤判斷為false時被執行
<cLforeach> 基礎迭代標籤,接受多種集合型別
<c:url> 使用可選的查詢引數來創造一個URL

JSTL標籤使用步驟

  • 引入對應的taglib
  • 使用其中的方法
  • 在Tomcat也需要引入jstl的包,否則會出現500
    • lib目錄下D:\Environment\apache-tomcat-9.0.37\lib

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h4>if測試</h4>
<form action="coreif.jsp" method="get">
<%--    EL表示式獲取表單中資料--%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登入">
</form>

<%--判斷如果提交的是使用者名稱是admin就登入成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
    <c:out value="管理員歡迎你"/>
</c:if>
<c:out value="${isAdmin}"/>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:set var="score" value="55" />
<c:choose>
    <c:when test="${score>=90}">
        優秀
    </c:when>
    <c:when test="${score>=80}">
        良好
    </c:when>
    <c:when test="${score>=60}">
        合格
    </c:when>
    <c:otherwise >
        不及格
    </c:otherwise>
</c:choose>
</body>
</html>

JavaBean

javaBean有特定的寫法

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

一般和資料庫的欄位做對映

ORM 物件關係對映

  • 表——>類
  • 欄位——>屬性
  • 行記錄——>物件

注意:一定要每一個欄位都和實體類的屬性對應

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--stu = new Test();--%>
<jsp:useBean id="test" class="com.jmu.vo.Test" scope="page"/>
<jsp:setProperty name="test" property="id" value="1018" />
<jsp:setProperty name="test" property="name" value="大東" />

<jsp:getProperty name="test" property="id"/>
<jsp:getProperty name="test" property="name"/>

</body>
</html>

MVC三層結構

Filter

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

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

Filter開發步驟:

  • 導包

  • 編寫過濾器

    • 匯入不要錯import javax.servlet.*;
package com.jmu.fiter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    //初始化:web伺服器啟動,就一起初始化,隨時等待過濾物件出現
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化");

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        System.out.println("執行前");
        filterChain.doFilter(servletRequest,servletResponse);//讓我們的請求繼續走,如果不行,程式執行到這裡就被攔截
        System.out.println("執行後");
    }
    //銷燬 web伺服器關閉的時候,過濾會銷燬
    public void destroy() {
        System.out.println("銷燬");
    }
}
  • 在web.xml中配置filter
<filter>
	<filter-name>CharacterEncoding</filter-name>
	<filter-class>com.jmu.fiter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>CharacterEncoding</filter-name>
<!--        只要是/filter/*的任何請求就執行過濾器-->
	<url-pattern>/filter/*</url-pattern>
</filter-mapping>

例子

使用者登入之後,才能進入主頁,使用者登出後就不能進入主頁

  1. 使用者登入之後,向session放入使用者的資料,並且重定向到主頁
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");//重定向
  1. 登出
if(req.getSession().getAttribute("USER_SESSION")!=null){
    req.getSession().removeAttribute("USER_SESSION");
}
resp.sendRedirect("/login.jsp");
  1. 將主頁放在sys資料夾中,當session("USER_SESSION")為空的時候,就跳轉到登入頁面
package com.jmu.fiter;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //如果沒有強轉 ServletRequest沒有getSession方法
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        if((req.getSession().getAttribute("USER_SESSION"))==null){
            resp.sendRedirect("/login.jsp");
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {

    }
}

xml

<filter>
    <filter-name>sysFilter</filter-name>
    <filter-class>com.jmu.fiter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>sysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>

練習登入

專案搭建

  1. 搭建一個maven web專案
  2. 配置tomcat
  3. 修改web.xml
  4. 測試專案是否能夠跑起來(localhost:8080/)He
  5. 匯入專案中會遇到的jar
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
  </dependency>
  <!--        Servlet依賴-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!--        JSP依賴-->
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.3</version>
    <scope>provided</scope>
  </dependency>
  <!--        jstl表示式的依賴-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <!--        standar標籤庫-->
  <dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
  </dependency>
</dependencies>
  1. 建立專案結構 java main(com.jmu.dao/filter/vo/servlet/service/util) resources

    1. dao層用來和資料庫互動並返回結果
    2. service業務層(判斷使用者是否登入成功)
    3. servlet呼叫控制層
    4. filter過濾器
    5. util工具類
  2. 編寫實體類vo

  3. 編寫基礎公共類

    1. resources中db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=true
username = root
password = 123456
  1. 編寫資料庫工具類

  2. 編寫字元編碼過濾器filter(上面有寫過的)

  3. 在webapp匯入靜態資源css js image等等 在webapp下新建static再放

登入功能實現

  1. 登入頁面(在jsp資料夾下新建一個主頁home.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--login.jsp--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login.do" method="post">
    使用者名稱 <input type="text" name="username"/><br/>
    密碼 <input type="password" name="password"/><br/>
    <input type="submit" value="登入" />

</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--home.jsp--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>主頁</h1>
<a href="${pageContext.request.contextPath}/logout.do">登出</a>
</body>
</html>
  1. 在web.xml中將登入頁面設為首頁,不是index.jsp
<welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
</welcome-file-list>
  1. 編寫介面UserDao
package com.jmu.dao;

import com.jmu.vo.User;

public interface UserDao {
    //通過username得到登入的使用者
    public User getLoginUser(String username);
}

  1. 編寫介面UserDao的實現類UserDaoImpl
package com.jmu.dao;

import com.jmu.util.JdbcUtil;
import com.jmu.vo.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDaoImpl implements UserDao{

    @Override
    public User getLoginUser(String username) {
        Connection conn = null;
        PreparedStatement pst =null;
        User user = null;
        try {
            conn  = JdbcUtil.getConnection();
            String sql = "select * from user where username = ?";
            pst = conn.prepareStatement(sql);//預編譯
            //傳遞引數
            Object[] params = {username};
            for(int i = 0;i<params.length;i++){
                pst.setObject(i+1,params[i]);
            }
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                int auto_id=rs.getInt("auto_id");
                String password=rs.getString("password");
                int age=rs.getInt("age");
                user = new User(auto_id,username,password,age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.release(conn,pst,null);
        }
        return user;
    }
}

  1. 編寫業務層介面UserService
package com.jmu.service;

import com.jmu.vo.User;

public interface UserService {
    //使用者登入
    public User login(String username, String password);
}
  1. 業務層實現類UserServiceImpl
package com.jmu.service;

import com.jmu.dao.UserDao;
import com.jmu.dao.UserDaoImpl;
import com.jmu.vo.User;
import org.junit.Test;

public class UserServiceImpl implements UserService {
    //業務層都會呼叫dao層,所以我們要引入Dao層
    private UserDao userDao;
    public UserServiceImpl(){
        userDao = new UserDaoImpl();
    }
    @Override
    public User login(String username, String password) {
        User user = null;
        user = userDao.getLoginUser(username);
        //對比密碼
        if(user!=null&&user.getPassword().equals(password)){
            return user;
        }else{
            return null;
        }

    }

    @Test
    public void test(){
        System.out.println(new UserServiceImpl().login("user02","122").toString());
    }
}
  1. 編寫servlet

登入servlet

package com.jmu.servlet;

import com.jmu.service.UserService;
import com.jmu.service.UserServiceImpl;
import com.jmu.util.Constants;
import com.jmu.vo.User;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        //和資料庫中的密碼進行對比 呼叫業務層
        UserService userService=new UserServiceImpl();
        User user =userService.login(username,password);
        if(user!=null){
            //將使用者資訊儲存到session裡面
            req.getSession().setAttribute(Constants.USER_SESSION,user);
            //跳轉到主頁
            resp.sendRedirect(req.getContextPath()+"/jsp/home.jsp");
        }else{
            //跳轉到ERROR
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 註冊servlet
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.jmu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>
  1. 執行測試