javaweb


基本概念

在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了,但是tomcat10和idea一起使用還是存在問題,所以推薦使用tomcat9

image-20200801215346895

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

啟動

如果你直接點擊bin目錄下的startup.bat,可能會出現界面一閃而過,如果沒有一閃而過就可以跳過下面的辦法了

你需要在控制台中輸入

image-20200801220158691

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

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

image-20200801220709545

修改conf目錄下的logging.properties文件

將文件中原有的配置修改

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

訪問測試:localhost:8080

亂碼的本質:讀取二進制的時候采用的編碼和最初將字符轉換成二進制時的編碼不一致

將"我們是中國人"以UTF-8編碼轉換成byte數組(byte數組其實就相當於二進制序列了,此過程即編碼),再以GBK編碼和byte數組創建新的字符串(此過程即以GBK編碼去解碼byte數組,得到字符串),就產生亂碼了

文件夾對應作用

image-20200815183735144

--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 網關錯誤

面試題

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

鏈接

Maven

為什么學習Maven?

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

安裝Maven

官網

image-20200811074029645

下載完成后解壓

配置環境變量

在我們系統環境變量

配置如下環境變量

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

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

image-20200811074634340

修改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

創建項目

image-20200811075848800

image-20200811080102213

image-20200811080231222

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

image-20200811232328681

標記文件夾

補充文件夾java和resources,標記文件夾功能

  • java ——>Sources Root
  • resources——>Resources Root
    • resources文件夾是給java文件讀取的

image-20200811233121704

修改web.xml

使用模板新建的項目,web.xml太舊了

image-20200812075515411

使用下載的tomcat中的中D:\Environment\apache-tomcat-9.0.37\webapps\ROOT\WEB-INF\web.xml

<?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

image-20200811232706548

image-20200811232926496

image-20200813212321470

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

pom.xml

maven由於他的約定大於配置,我們之后可能遇到的問題,無法導入或者生效xml、properties文件的問題

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

Maven手動導入jar

下載jar包

image-20200815073827912

Apache Commons IO » 2.4

導入jar

image-20200815131019491

Add as Library

右鍵lib文件夾

image-20200815074243289

碰到的問題

  • Maven 3.6.2(無法導入maven項目)

image-20200812074838920

解決方法:降級為3.6.1

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

解決方法:在IDEA中全局默認配置去配置

image-20200821084822603

image-20200821084922284

在IDEA中配置Tomcat

配置Tomcat

image-20200811233642239

image-20200811233811032

image-20200811235431844

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

image-20200811235725339

image-20200811235559454

image-20200811234446348

碰到的問題

參考鏈接

啟動tomcat

image-20200812000049930

image-20200812000018899

Servlet

Servlet簡介

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

把實現了servlet接口的java程序叫做Servlet

HelloServlet

第一個Servlet程序

  • 構建一個普通的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工程添加servlet依賴

  • 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會發生變化

image-20200813074631411

一個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

image-20200813075516958

HttpServletRequest

請求轉發

req.getRequestDispatcher("/success.jsp").forward(req,resp);
//常用方法
//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是無限量的
  • image-20200813142213120

image-20200813142250640

使用場景:

  • 保存一個登錄用戶的信息
  • 購物車信息
  • 在整個網站中經常使用的數據,將他保存在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

image-20200813144454542

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

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

image-20200813144729176

image-20200813172109605

  • 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

image-20200813231040262

<%@ 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工具類
    6. image-20200814192445303
  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. 運行測試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM