JavaWeb
Java Web
1、基本概念
1.1、前言
web開發:
- web,網頁的意思,例如:www.baidu.com
- 靜態web
- HTML,css
- 提供給所有人看到的資料始終不會發生變化
- 動態web
- 淘寶,幾乎是所有網站
- 提供給所有人看到的資料始終會發生變化,不同的人,在不同時間,不同地點看到的資料都不一樣
- 技術棧:Servlet/JSp,ASP,PHP
在java中,動態web資源開發的技術統稱為Javaweb
1.2、web應用程式
web應用程式:可以提供瀏覽器訪問的程式
- a.HTML 。。。多個web資源,這些web資源可以被外界訪問,對外界提供服務
- 你們能訪問到的任何一個頁面或者資源,都存在於這個世界的某一個角落的計算機上
- URl
- 這個統一的web資源會被放在同一個資料夾下,web應用程式--->Tomcat:伺服器
- 一個web應用由多個程式組成(靜態、動態)
- html、css、js
- jsp、servlet
- java程式
- jar包
- 配置檔案(Properties)
web應用程式編寫完畢後,若想提供給外界訪問,需要一個伺服器來統一管理;
1.3、靜態web
- *.htm 、 *.html 這些都是網頁的字尾,如果伺服器上一直存在這些東西,我們就可以直接進行讀取
-
靜態web存在的缺點
-
web頁面無法動態更新,所有使用者都訪問到同一個頁面
- 輪播圖,點選特效,偽動態
- JavaScript(實際開發用的最多)
- VBScript
-
它無法和資料互動,(資料無法持久化,使用者無法互動)
-
1.4、動態Web
頁面會動態展示:“頁面效果因人而異”
缺點:
- 假如 伺服器的動態web資源出現錯誤,我們需要我們重新編寫我們的後臺程式,重新發布
- 停機維護
優點:
-
web頁面可以動態更新,所有使用者看到的都不是同一個頁面
-
它可以和資料互動,(資料持久化,使用者可以互動)
可以透過JDBC訪問資料庫。
2、web伺服器
2.1、技術講解
ASP:
- 微軟:國內最早流行的就是ASP
- 在HTML中嵌入了VB指令碼,ASP + COM
- 在ASP開發中,基本一個業務就有幾千行程式碼,頁面極其混亂,
- 維護成本高
PHP:
- 開發速度很快,功能很強大,跨平臺,程式碼簡單(70%);
- 無法承載大量訪問量的情況下(侷限性);
JSP/Servlet:
sun公司的主推的B/S
B/S:瀏覽和伺服器
C/S:客戶端和伺服器
- 基於Java語言的(所有的大公司,或者一些開源的元件,都是用Java寫的)
- 可以承載三高問題帶來的影響;(高併發,高可用,高效能)
- 語法有點像ASP
2.2、web伺服器
伺服器是一種被動的操作,用老處理使用者的一些請求和給使用者一些響應資訊
IIS
微軟的,ASP,,,Windows中自帶的
Tomcat:
面向百度程式設計
Tomcat是Apache 軟體基金會(Apache Software Foundation)的Jakarta專案中的一個核心專案,最新的Servlet和$P規範總是能在Tomcat 中得到體現,因為Tomcat技術先進、效能穩定,而且免費,因而深受ava愛好者的喜愛並得到了部分軟體開發商的認可,成為目前比較流行的Web應用伺服器。
Tomcat伺服器是一個免費的開放原始碼的Web應用伺服器,屬於輕量級應用伺服器,在中小型系統和併發訪問使用者不是很多的場合下被普遍使用,是開發和除錯I$P程式的首選。對於一個Java初學web的人來說,它是最佳的選擇
Tomcat 實際上執行JSP 頁面和Servlet。Tomcat最新版本為9.0。
下載Tomcat:
- 安裝 or 解壓
- 瞭解配置檔案及目錄結構
3、Tomcat
3.1、安裝
3.2、Tomcat配置和啟動
啟動:
start.bat
關閉:
可能遇到的問題:
- java環境變數沒有配置
- 閃退問題,需要配置相容性問題
3.3、配置
可以配置啟動的埠號
-
tomcat的預設埠號為:8080.
-
mysql: 3306
-
http: 80.
-
https: 443
- <connector port="8081" protoco1="HTTP/1.1" connectionTimeout="20000" redirectPort="8443”/>
可以配置主機名稱:
-
預設的主機名為: localhost->127.0.0.1
-
預設網站應用存放的位置為: webapps
<Host name="www. qinjiang.com"appBase="webapps"
unpackwARS="true" autoDeploy="true">
高難度面試題:
請你談談網站是如何訪問的!
1.輸入一個域名;回車
⒉.檢查本機的C:\Windows\System32\driversletclhosts配置檔案下有沒有這個域名對映;
-
1.有:直接返回對應的ip地址,這個地址中,有我們需要訪問的web程式,可以直接訪問
127.0.0.1 qinjaing
-
⒉.沒有:去DNS伺服器找,找到的話就返回,找不到就返回找不到;
3、可以配置一下環境變數(可選項)
3.4、釋出一個web網站
不會就先模仿
- 將自己寫的網站,放到伺服器(Tomcat)中指定的web應用的資料夾(webapps)下,就可以訪問網站應該有的結構
--webapps : Tomcat伺服器的web目錄
-ROOT
-kuangstudy :網站的目錄名
-WEB-INF
-classes : java程式
-lib: web應用所依賴的jar包
-web.xm1 :網站配置檔案
- index.htm1 預設的首頁
-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
- http1.1:客戶端與web伺服器連線後,可以獲得多個web資源。
4.3、http請求
- 客戶端-----發請求--------伺服器
百度:
Request URL: https://www.baidu.com/ 請求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 狀態碼:200
Remote(遠端) Address: 220.181.38.149:443
Accept:text/html
Accept-Encoding: gzip, deflate,brAccept-Language :zh-CN,zh;q=0.9 語言
cache-contro7 : max-age=O
connection : keep-alive
1、請求行
- 請求行中的請求方式:GET
- 請求方式:GET、POST、HEAD 、DELETE 、PUT 、TRACT
- get,請求能夠攜帶的引數比較少,大小有限制,會在瀏覽器的URL位址列顯示資料內容,不安全,但高效
- post:請求能夠攜帶的引數沒有限制,大小沒有限制、不會再瀏覽器的URL位址列顯示資料內容,安全,但不高效
2、請求頭
Accept:告訴瀏覽器,它所支援的資料型別
Accept-Encoding:支援哪種編碼格式 GBK、UTF-8、GB2312
Accept-Language:告訴瀏覽器的,它的語言環境
cache-control:快取控制
connection:告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機
4.4、http響應
-
伺服器------響應--------客戶端
百度:
Cache-Control: private 快取控制
Connection: keep-alive 連線
Content-Encoding: gzip 編碼
Content-Type: text/html; 型別
charset=utf-8
1、響應體
Accept:告訴瀏覽器,它所支援的資料型別
Accept-Encoding:支援哪種編碼格式 GBK、UTF-8、GB2312
Accept-Language:告訴瀏覽器的,它的語言環境
cache-control:快取控制
connection:告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機
Refresh:告訴客戶端,多久重新整理一次
location:讓網頁重新定位
2、響應狀態碼
200:請求響應成功
3**:請求重定向
- 重定向,重新去找新的地址
404:請求資源失敗,找不到
- 資源不存在
5**:伺服器程式碼失敗 500
502:閘道器錯誤
常見面試題:
當你的瀏覽器中位址列輸入地址並回車的一瞬間到頁面能夠展示回來,經歷了什麼?
5、Maven
我為什麼要學習這個技術?
1、在Javaweb學習中,我們需要使用大量jar包,我們得手動去匯入
2、如何能夠讓一個東西自動幫我們匯入和配置
由此,maven誕生了
5.1、Maven專案架構管理工具
我們目前就是用來方便匯入jar包的
Maven的核心思想:約定大於配置
Maven會規定我們如何去編寫java程式碼,我們必須按照規定來寫。
5.2、Maven下載
官方下載
5.3、配置環境變數
在我們的系統環境變數中
配置如下配置:
- M2_HOME maven目錄下的bin目錄
- MAVEN_HOME maven的目錄
- 在系統的path中配置 %MAVEN_HOME%\bin
測試maven是否安裝完畢,保證必須配置完畢!
5.4、阿里雲映象
-
映象:mirrors
- 作用:加速我們的下載
-
國內建議使用阿里雲
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
5.5、本地倉庫
在本地的倉庫,遠端倉庫;
建立一個本地倉庫:localRepository
<localRepository>D:\MySQL\apache-maven-3.8.3\maven-repo</localRepository>
5.6、在IDEA中使用Maven
1、建立一個MavenWeb專案
2、等待專案初始化完畢
3、用IDEA設定maven
5.7、在IDEA中配置Tomcat
解決警告問題
為什麼會有這個問題,我們訪問一個網站,需要指定一個資料夾名,
啟動Tomcat
啟動成功彈出:
5.8、pom檔案
pom.xml檔案是Maven的核心配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--這裡是我們剛才配置的GAV-->
<groupId>org.example</groupId>
<artifactId>Javaweb-01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!--專案的打包方式:
jar:java應用
war:Javaweb應用
-->
<packaging>war</packaging>
<name>Javaweb-01-maven Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!--配置-->
<properties>
<!--專案的預設構建編碼-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--編碼版本-->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<!--專案依賴-->
<dependencies>
<!--具體依賴的jar包配置檔案-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--專案構建用的東西-->
<build>
<finalName>Javaweb-01-maven</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Maven由於它的約定大於配置,我們之後可能遇到我們寫的配置檔案,無法被匯出或者生效問題,
解決方案:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
</build>
6、Maven倉庫的使用
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專案,刪掉裡面的scr子目錄,以後我們的學習就在這個專案裡建立moudel,這個空的工程就是Maven的主工程。(我的IDEA版本如果將scr檔案刪除了,建立了父工程後再建立子工程會直接卡死,我這裡沒有刪除scr檔案,其實不刪也無影響)
2、建立maven父子目錄時,先空後webapp,直接卡死,先webapp後空直接成功?(已解決)
3、關於maven父子工程的理解:
父專案會有:
<moudle>
<moudle>servlet-01</moudle>
</moudle>
子專案會有:
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com. kuang</groupId>
<version>1.O-SNAPSHOT</version>
</parent>
父專案中的java子專案可以直接使用:
son extends father
4、Maven環境最佳化:
- 修改web.xml為最新版
- 將Maven的結構搭建完整
5、編寫一個servlet程式
- 編寫一個普通類
- 實現servlet介面,這裡我們是直接繼承HTTPServlet
public class HelloServlet extends HttpServlet {
//由於get 和 post 只是請求的方式不同,可以相互呼叫,業務邏輯都一樣
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter();//響應流
writer.println("Hello Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
6、編寫Servlet的對映
為什麼需要對映:我們寫的是java程式,我們要透過瀏覽器訪問,而瀏覽器需要連線web伺服器,所以我們需要在web服務
中註冊我們寫的servlet,還需要給他一個瀏覽器可以訪問的路徑。
<!--註冊servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liu.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet的請求路徑-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
7、配置Tomcat
注意專案配置的釋出路徑
8、啟動測試
6.3、Servlet執行原理
servlet是由web伺服器呼叫,web伺服器在收到瀏覽器的請求之後,會:
6.4、Mapping
-
一個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-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello4</url-pattern> </servlet-mapping>
使用http://localhost:8080/srevlet_02_war/hello 後加的 1 2 3 4 都可以
-
一個Servlet可以指定通用對映路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
預設請求路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
指定字首或字尾
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.liu</url-pattern> </servlet-mapping>
注意: * 前面不能加專案對映的路徑
-
優先順序問題
指定了固有的對映路徑,優先順序最高,如果找不到就會走預設的請求處理
<!--404--> <servlet> <servlet-name>error</servlet-name> <servlet-class>com.liu.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應用;
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 = "俊";
context.setAttribute("username",username);//將一個資料儲存在了ServletContext中,名字為: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");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字" +username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
配置檔案:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liu.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.liu.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
2、獲取初始化引數
<!--配置一些web應用初始化引數-->
<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);
}
3、請求轉發
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("進入了servletDemo04!!!");
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/gp").forward(req,resp);//轉發的請求路徑,呼叫forward實現請求轉發
}
重定向:
4、讀取檔案資源
properties
- 在java目錄下新建properties
- 在resources目錄下新建properties
發現都被打包到同一個路徑下,classes,我們俗稱這個路徑為類路徑classpath;
思路:需要一個檔案流
@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 username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username + ":" + password);
is.close();
}
<servlet>
<servlet-name>ps</servlet-name>
<servlet-class>com.liu.servlet.PropertiesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ps</servlet-name>
<url-pattern>/ps</url-pattern>
</servlet-mapping>
username=root
password=root
6.6、HttpServletResponse
web伺服器接收到客戶端的http請求,針對這個請求,分別建立一個代表請求的HttpServletRequest的物件,建立一個代表響應的HttpServletResponse物件
- 如果要獲取客戶端請求過來的引數,找HttpServletRequest
- 如果要獲取客戶端響應的一些資訊,找HttpServletResponse
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);
響應的狀態碼
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;
2、下載檔案
-
向瀏覽器輸出資訊
-
下載檔案
1.要獲取下載檔案的路徑2.下載的檔名是啥?
3.設定想辦法讓瀏覽器能夠支援下載我們需要的東西
4.獲取下載檔案的輸入流
5.建立緩衝區
6.獲取OutputStream物件
7.將FileOutputStream流寫入到buffer緩衝區
8.使用OutputStream將緩衝區中的資料輸出到客戶端!
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.要獲取下載檔案的路徑
String realPath = "D:\\IDEAProfessional\\Javaweb-02-maven\\response\\src\\main\\resources\\1.png";
System.out.println("下載檔案的路徑為:" + realPath);
//2.下載的檔名是啥?
String filename = realPath.substring(realPath.lastIndexOf("\\" + 1));
//3.設定想辦法讓瀏覽器能夠支援下載我們需要的東西,中文命名時需要轉碼,URLEncoder.encode,否則有可能會亂碼
//resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(filename,"UTF-8"));
resp.setHeader("Content-Disposition","attachment;filename=" + filename);
//4.獲取下載檔案的輸入流
FileInputStream in = new FileInputStream(realPath);
//5.建立緩衝區
int len = 0;
byte[] buffer = new byte[1024];
//6.獲取OutputStream物件
ServletOutputStream out = resp.getOutputStream();
//7.將FileOutputStream流寫入到buffer緩衝區 //8.使用OutputStream將緩衝區中的資料輸出到客戶端!
while ((len = in.read(buffer))>0){
out.write(buffer,0,len);
}
//9、關閉流
out.close();
in.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>filedown</servlet-name>
<servlet-class>com.liu.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/filedown</url-pattern>
</servlet-mapping>
3、驗證碼功能
驗證碼怎麼來的?
- 前端實現
- 後端實現,需要用到java的圖片類,生產一個圖片
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何讓瀏覽器5秒重新整理一次頁面
resp.setHeader("refresh","3");
//在記憶體中建立一個圖片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到圖片
Graphics g = 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) + "";
StringBuffer sb = new StringBuffer();
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);
}
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.liu.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/imag</url-pattern>
</servlet-mapping>
可以發現數字是3秒重新整理一次
4、實現重定向
一個web資源受到客戶端請求後,它會告訴客戶端去訪問另外一個web資源,這個過程叫重定向。
常見場景:
-
使用者登入
void sendRedirect(String var1) throws IOException;
-
程式碼測試
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("./imag");//重定向 } }
302:重定向,
Location:重定向的位置
面試題:請你聊聊重定向和轉發有什麼區別?
相同點:
- 頁面都會跳轉
不同點:
-
請求轉發的時候,URL位址列不會產生變化 307
-
重定向的時候,URL位址列會產生變化,直接跳轉到你需要重定向的地址。302
首先:寫好你需要的東西
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("進入了這個請求");
//處理請求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+ ":"+ password);
//重定向的時候一定要注意路徑問題。否則404
resp.sendRedirect("./success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
然後,當你啟動Tomcat時,會預設開啟的首頁
<html>
<body>
<h2>Hello World!</h2>
<%@page pageEncoding="UTF-8" %>
<%--這裡提交的路徑,需要尋找到專案的路徑--%>
<%--${pageContext.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>
</body>
</html>
當你輸入好資訊後,提交會重定向到success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>
6.7、HttpServletRequest
HttpServletRequest代表客戶端的請求,使用者透過Http協議訪問伺服器HTTp中所有的資訊都會被封裝到HttpServletRequest,
透過這個HttpServletRequest的方法,獲得客戶端的所有資訊。
1、獲取前端傳遞的引數
2、請求轉發
public class LoginServlet extends HttpServlet {
@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[] hobbys = req.getParameterValues("hobbys");
System.out.println("========================");
//後臺接收中文亂碼問題
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("========================");
//透過請求轉發
//這裡的 / 代表當前的web應用
req.getRequestDispatcher(req.getContextPath() + "/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登入</title>
</head>
<body>
<h1>登入</h1>
<div style="text-align: center">
<form action="${pageContext.request.contextPath}/login" method="post">
使用者名稱:<input type="text" name="username"><br>
密碼:<input type="password" name="password"><br>
愛好:
<input type="checkbox" name="hobbys" value="女孩">女孩
<input type="checkbox" name="hobbys" value="程式碼">程式碼
<input type="checkbox" name="hobbys" value="電影">電影
<input type="checkbox" name="hobbys" value="唱歌">唱歌
<br>
<input type="submit">
</form>
</div>
</body>
</html>
7、專案建立小結
-
首先,建立一個父子工程,由於我的IDEA版本是最新的,不可以刪除scr檔案,否則會卡死
-
在父工程的pom檔案設定好需要的依賴
,子工程可以直接繼承父工程的依賴 -
再就是建立子工程所出現的問題,沒有
標籤,大機率是IDEA版本太新,系統預設沒有parent標籤也可以, 但是在子工程繼承父工程的jar包時無法順利繼承,這就需要手動在子工程的pom檔案中寫
標籤 <parent> <artifactId>Javaweb-02-maven</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent>
artifactId:繼承的父工程的名稱
groupId:建立專案是的分組,預設為org.example,一般都自己重新命名,方便管理
version:版本。預設,一般講前兩個標籤打出來後這個標籤是自動生成
-
修改子工程下scr-main-webapp-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>
-
在main檔案下新增java資料夾和resources資料夾,養成規範
-
每寫一個java檔案,如果將其輸出到瀏覽器客戶端,需要在web-xml檔案中新增對應自己的
<servlet> <servlet-name>filedown</servlet-name> <servlet-class>com.liu.servlet.FileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>filedown</servlet-name> <url-pattern>/filedown</url-pattern> </servlet-mapping>
:
:無特殊含義,一般設定為自己的class檔名或者契合檔案主題的名字
:需要執行的class檔案路徑 :
:對應上面的servlet-name
:瀏覽器訪問路徑 -
常用到的兩個依賴包
servlet <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> jsp <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> </dependency>
8、cookie、session
8.1、會話
會話:使用者開啟一個瀏覽器,點選了很多超連結,訪問了多個web資源,最後關閉瀏覽器,這個過程稱之為會話
**有狀態會話: ** 簡單來說就是,假設你去過一個地方,下次再來的時候,就會有記錄你曾經來過
你能怎麼證明你是太工的學生?
你 太工
1.交了學費的發票 太工給你發票
⒉.學生證 太工標記你來過了
一個網站,怎麼證明你來過?
客戶端 服務端
1.服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
2.伺服器登記你來過了,下次你來的時候我來匹配你;session
8.2、儲存會話的兩種技術
cookie
- 客戶端技術 (響應、請求)
session
- 伺服器技術,利用這個技術,我們可以把資訊或者資料放在session中!
常見例項:網站登入過之後,你下次不用再登入了,第二次訪問直接上去了
8.3、Cookie
- 從請求中拿到cookie資訊
- 伺服器響應給客戶端cookie
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//伺服器,告訴你,你來的時間,把這個時間封裝成一個信件,下次你來的時候帶上信件,就可以識別你來過
//解決中文亂碼
resp.setHeader("Content-Type","text/html");
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
//cookie,服務端從客戶端獲取,
Cookie[] cookies = req.getCookies();
//判斷cookie是否存在
if(cookies!=null){
///如果存在
out.write("你上一次訪問的時間是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if(cookie.getName().equals("LastLoginTime")){
//獲取cookie的值
long LastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(LastLoginTime);
out.write(date.toLocaleString());
}
}
}else {
out.write("這是你第一次訪問");
}
//服務端給客戶端響應一個cookie
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis() + "");
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
步驟:1、從客戶端獲取cookie
2、判斷cookie是否有值,如果有,將其列印
3、如果沒有,將新的cookie賦值
4、響應給客戶端一個cookie
cookie會儲存在本地檔案
一個網站cookie是否存在上線!
-
一個cookie只能儲存一個資訊
-
一個web站點可以給瀏覽器傳送多個cookie ,最多存放20個cookie
-
Cookie大小有限制4kb
-
300個cookie瀏覽器上限
刪除cookie:
- 不設定有限期,關閉瀏覽器,自動失效
- 設定cookie有效期為0
編碼解碼:
URLEncoder.encode("劉","utf-8")
URLDecoder.decoder(cookie.getValue(),"utf-8")
8.4、Session(重點)
什麼是session:
- 伺服器會給每一個使用者(瀏覽器)建立一個session物件
- 一個session獨佔一個瀏覽器,只要瀏覽器沒關,這個session就存在
- 使用者登入之後,整個網站都可以訪問 -- > 儲存使用者的資訊;儲存購物車的資訊
Session和Cookie區別:
- cookie是把使用者的資料寫給使用者的瀏覽器,瀏覽器儲存(最多7個)
- Session是把使用者的資料寫到使用者獨佔的session中,服務端儲存(儲存重要的資訊,減少伺服器資源的浪費)
- session物件由伺服器建立
使用場景:
- 儲存一個使用者登入資訊
- 購物車資訊
- 在整個網站中會經常使用的資料,我們儲存在session中
首先,獲取session,判斷是否存在
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決亂碼問題
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
//得到session
HttpSession session = req.getSession();
//給session存東西
session.setAttribute("name",new Person("俊爺",1));
//獲取session的ID
String sessionId = session.getId();
//判斷session是不是新建立
if (session.isNew()){
resp.getWriter().write("session建立成功,ID為:" + sessionId);
}else{
resp.getWriter().write("session已經存在了,ID為:" + sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
然後,獲取這個session裡面存的值
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決亂碼問題
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
//得到session
HttpSession session = req.getSession();
//給session存東西
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
使用完之後可以消除並且登出session,但是會馬上產生新的session
public class SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手動登出
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml自行配置servlet,此處就不一一列舉。
預設配置session關閉時間,會話自動過期
<!--設定session預設時間-->
<session-config>
<!--1分鐘後失效-->
<session-timeout>1</session-timeout>
</session-config>
9、JSP
9.1、什麼是JSP
Java Servlet Page :Java伺服器端頁面,也和Servlet一樣,用於動態web技術!
最大特點:
- 寫jsp就像在寫HTML
- 區別:
- HTML只給使用者提供靜態資料
- JSP頁面中可以嵌入Java程式碼,為使用者提供動態資料
9.2、JSP原理
瀏覽器向伺服器傳送請求,無論是訪問什麼資源,其實都是在訪問Servlet!!
JSP最終也會被轉化成為Java類
JSP本質是一個servlet
//初始化
pub1ic void _jspInit() {
}
//銷燬
public void _jspDestroy() {
}
//sPservice
public void _jspservice(.HttpServletRequest request,HttpservletResponse response)
-
判斷請求
-
內建一些物件
final javax.servlet.jsp.Pagecontext pagecontext; //頁面上下文 javax.servlet.http.Httpsession session = nu11; //session final javax.servlet.servletcontext application; //app1icationcontext final javax.servlet.servletconfig config; //config javax.servlet.jsp. spwriter out = nu11; // out final java.1ang.object page = this; //page:當前 HttpservletRequest request //請求 Httpserv1etResponse response //響應
-
輸出頁面前增加的程式碼
response. setcontentType("text/htm1"); //設定響應的頁面型別 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;
-
以上的這些物件我們可以直接在JSP頁面中直接使用!
<% String name = "junye"%> name:<%=name%> //將名字取出來
在JSP頁面中,只要是java程式碼就會原封不動的輸出
如果是HTML程式碼,就會被轉換為
out.write("<html>\r\n")
這樣的格式會輸出到前端
9.3、JSP基礎語法
任何語言都有自己的語法,java中有,JSP作為java技術的一種應用,它擁有一些自己擴充的語法,java所有語法都支援
JSP表示式
<%--JSP表示式
作用:用來將程式的輸出,輸出到客戶端
<%= 變數或者表示式 %>
--%>
<%= new java.util.Date()
%>
JSP指令碼片段
<%
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
out.println("<h1>sum=" + sum + "</h1>");
%>
JSP宣告
<%!
static{
System.out.println("Loading Servlet!");
}
private int glob = 0;
public void liu(){
System.out.println("進入了liu這個方法!");
}
%>
Jsp宣告:會被編譯到jsp生成的java類當中,其他的,就會被生成到_jspService方法中
在JSP中嵌入java程式碼即可
JSP的註釋,不會再客戶端顯示,HTML的就會!
9.4、JSP的指令
會將兩個頁面合二為一
<%@include file="" %> 包含的檔案
<jsp:include file="/common/Header.jsp"/>
<h1>網頁主體</h1>
<jsp:include file="/common/Footer.jsp"/>
<%-- JSP標籤 jsp:include:拼接頁面。本質還是三個 --%>
<jsp:include page="/common/Header.jsp"/>
<h1>網頁主體</h1>
<jsp:include page="/common/Footer.jsp"/>
9.5、9大內建物件
- 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號");//儲存的資料只在伺服器中有效,從開啟伺服器到關閉伺服器
%>
<%--指令碼片段中的程式碼,會被原封不動生成到.JSP.java要求:這裡面的程式碼:必須保證Javai語法的正確性
--%>
<%
//從pageContext取出,我們透過尋找的方式來
//從底層到高層(作用域):
string name1 = (String) pageContext.findAttribute( "name1");
string name2 = (string) pageContext.findAttribute( "name2");
string name3 = (String) pageContext.findAttribute( "name3");
string name4 = (string) pageContext.findAttribute( "name4");
string name5 = (string) pageContext.findAttribute("name5");//不存在
%>
<%--使用EL表示式輸出${}--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4]</h3>
<h3><%=name5%></h3>
request:客戶端向伺服器傳送請求,產生的資料,使用者看完就沒用了,比如:新聞,使用者看完沒用的!
session:客戶端向伺服器傳送請求,產生的資料,使用者用完一會還有用,比如:購物車;
application:客戶端向伺服器傳送請求,產生的資料,一個使用者用完了,其他使用者還可能使用,比如:聊天資料;
9.6、JSP標籤、JSTL標籤、EL表示式
需要用到得新的包
<!-- JSTL表示式的依賴 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard標籤庫 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表示式:$
-
獲取資料
-
執行運算
-
獲取web開發的常用物件
JSP標籤
<%--jsp:include--%>
<%-- http://1oca7host:8080/jsptag.jsp?name=kuangshen&age=12--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen "></jsp:param>
<jsp:param name="age" value="12"></jsp:param>
</jsp:forward>
JSTL表示式
JSTL標籤庫的使用就是為了彌補HTML的不足;他自定義許多標籤,可以供我們使用,標籤的功能和java程式碼一樣
格式化標籤
SQL標籤
XML標籤
核心標籤(掌握部分)
<%--引入JSTL核心標籤庫,我們才能使用JSTL標籤core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
JSTL標籤庫使用步驟:
- 引入對應的taglib
- 使用其中的方法
- 在Tomcat中也要引入JSTL的包,
if
<h1>
if判斷
</h1>
<hr>
<form action="coreif.jsp" method="get">
<%-- EL表示式獲取表單中的資料${param.引數名} --%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登入">
</form>
<%--判斷如果提交的使用者名稱是管理員,則登入成功--%>
<c:if test="${param.username== 'admin' }" var="isAdmin">
<c :out value="管理員歡迎您!"/>
</c:if>
<%--自閉合標籤--%>
<c :out value="${isAdmin}" />
forEach
<%
ArrayList<String> people = new ArrayList<>();people.add(e,"張三");
people.add(1,"李四");
people.add(2,"王五");
people.add( 3,"趙六");
people.add(4,"田六");
request.setAttribute( name: "1ist" ,people);
%>
<%-- var ,每一次遍歷出來的變數items,要遍歷的物件 begin,哪裡開始end,到哪裡step,步長 --%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/ >
<br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="$ipeople}"/>
<br>
</c:forEach>
</ body>
</ htm1>
10、JavaBean
實體類
JavaBean有特定的寫法:
- 必須有一個無參構造
- 屬性必須私有化
- 必須有對應的get/set方法
一般用來和資料庫的子段做對映 :ORM
ORM:物件關係對映
- 表 -----> 類
- 欄位 -----> 屬性
- 行記錄 -----> 物件
實體類一般都是和資料庫中表一一對應
People表
id | name | age | address |
---|---|---|---|
1 | 戒愛1號 | 3 | 山西 |
2 | 戒愛2號 | 6 | 山西 |
3 | 戒愛3號 | 9 | 山西 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People(1,"戒愛",3,"山西");
}
<%
//People people = new PeopLe( );
//peopLe.setAddress( );
//people.setId( );
//people. setAge( );people.setName( );
%>
<jsp:useBean id="people" class="com.kuang.pojo.People" scope="page"/>
<jsp:setProperty name="people" property="id" value="1" />
<jsp:setProperty name="people" property="name" value="戒愛"/>
<jsp:setProperty name="people" property="age" value="3"/>
<jsp:setProperty name="people" property="address" value="山西"/>
<%-- <%=people.getAddress( )%> --%>
姓名: <jsp:getProperty name="people" property="name" /><br>
id: <jsp:getProperty name="people" property="id" /><br>
年齡: <jsp:getProperty name="people" property="age" / ><br>
地址: <jsp:getProperty name="people" property="address" /><br>
11、MVC三層架構
什麼是MVC: model view Controller 模型檢視控制器
11.1、早些年的架構
使用者直接訪問控制層,控制層就可以直接運算元據庫;
servlet -- > CRUD ---> 資料庫
弊端:程式十分臃腫,不易於維護
servlet的程式碼中:處理請求,響應,檢視跳轉,處理JDBC,處理業務程式碼處理邏輯程式碼
架構:沒有什麼是加一層解決不了的!
程式設計師呼叫
JDBC
MYSQL
11.2、三層架構
Model
- 業務處理:業務邏輯(Service)
- 資料持久層:CRUD(Dao)
View
- 展示資料
- 提供連結發起Servlet請求(a、form、img)
Controller
-
接收使用者的請求:(req:請求引數、Session資訊)
-
交給業務層處理對應的程式碼
-
控制檢視的跳轉
登入---->接收使用者的登入請求 ---- >處理使用者的請求(獲取使用者登入的引數,username,password)-----> 交給業務層處理登入業務(判斷使用者名稱密碼是否正確:事務) ---- > Dao層查詢使用者名稱和密碼是否正確--->資料庫
12、Filter(重點)
Filter:過濾器,用來過濾網站的資料;
-
處理中文亂碼
-
登入驗證
Filter開發步驟:
-
導包
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
額外新增需要連線資料庫的包
-
編寫過濾器
-
導包不要錯,必須是javax.servlet的包
-
實現Filter介面,重寫對應的方法
public class CharacterEncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化"); } @Override 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("characterEncoding執行前。。。。"); filterChain.doFilter(servletRequest,servletResponse);//讓我們的請求繼續走,如果不寫,我們的程式到這兒就停止了 System.out.println("characterEncoding執行後。。。"); } //銷燬::web伺服器關閉的時候,過濾器會銷燬 @Override public void destroy() { System.out.println("CharacterEncodingFilter銷燬"); } }
-
在web.xml檔案中配置過濾器
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.liu.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <!--只要是servlet下的任何請求都會過濾--> <url-pattern>/Servlet/*</url-pattern> </filter-mapping>
-
在伺服器關閉的時候,過濾器才會銷燬。
13、監聽器
實現一個監聽器的介面;(有N種)
-
編寫一個監聽器
實現監聽器的介面...
//統計網站線上人數:統計session public class OnlineCountListener implements HttpSessionListener { //建立session監聽 @Override public void sessionCreated(HttpSessionEvent se) { ServletContext servletContext = se.getSession().getServletContext(); Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(1); }else{ int count = onlineCount.intValue(); onlineCount = new Integer(count+1); } servletContext.setAttribute("OnlineCount",onlineCount); } //銷燬session監聽 @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); } }
-
web.xml中註冊監聽器
註冊監聽器 <listener> <listener-class>com.liu.listener.OnlineCountListener</listener-class> </listener>
-
看情況是否使用
14、過濾器、監聽器常見應用
監聽器:GUI程式設計中經常使用
public class (TestPanel i
public static void main(String[]args) {
Frame frame = new Frame("中秋節快樂");1/新建一個窗體Panel panel = new Panel(nul1); //皮膚
frame.setLayout(null);//設定窗體的佈局
frame.setBounds ( 300, 300, 500, 5e0);
frame.setBackground(new color(0,0,255));//設定背景顏色
panel.setBounds (50,5e,300, 3ee);
panel.setBackground( new Color(0,255,0));//設定背景顏色frame.add(panel);
frame.setvisible(true) ;/監聽事件,監聽關閉事件
frame .addwindowListener( new windowAdapter();
@override
public void windowclosing(windowEvent e) {
super.windowClosing(e);
}
});
}
使用者登入之後才能進入主頁,使用者登出之後就不能進入主頁了!
1、當使用者啟動伺服器後,自動進入index.jsp
2、然後自己手動跳轉到登入頁面
<h1>登入</h1>
<form action="/Servlet/login" method="post">
<input type="text" name="username">
<input type="submit">
</form>
登入的程式碼
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取前端請求的引數
String username = req.getParameter("username");
if(username.equals("admin")){//登入成功
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
}else{//登入失敗
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
xml配置
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.liu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/Servlet/login</url-pattern>
</servlet-mapping>
登入成功
<%
這個是在登入成功這個頁面直接進行判斷,如果USER_SESSION為空,直接返回登入頁面,這個是在顯示頁面之前就會進行的步驟,所以
不會顯示下面的‘主頁’
--<%
Object userSession = request.getSession().getAttribute("USER_SESSION");
if (userSession==null){
response.sendRedirect("/Login.jsp");
}
%>
--%>
<h1>主頁</h1>
3、登入失敗,登出的部分
<h1>錯誤</h1>
<h3>沒有許可權,使用者名稱錯誤</h3>
<a href="/Login.jsp">返回登入頁面</a>
public class LoginOutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute("USER_SESSION");
if (user_session!=null){
req.getSession().removeAttribute("USER_SESSION");
resp.sendRedirect("/Login.jsp");
}else{
resp.sendRedirect("/Login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>LoginOutServlet</servlet-name>
<servlet-class>com.liu.servlet.LoginOutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginOutServlet</servlet-name>
<url-pattern>/Servlet/loginout</url-pattern>
</servlet-mapping>
4、新增過濾器,在登入頁面時,如果session的ID為空,直接跳轉成功頁面直接進行重定向回到登入頁面,也就是說無法直接到達成功的頁面
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest servletRequest1 = (HttpServletRequest) servletRequest;
HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse;
if (servletRequest1.getSession().getAttribute("USER_SESSION")==null) {
servletResponse1.sendRedirect("/Login.jsp");
}
filterChain.doFilter(servletRequest1,servletResponse1);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.liu.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
Junit測試
依賴
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
簡單使用
@Test註解只在方法上有效,加了這個註解的方法,可以直接測試方法