一.設計模式
1.單例模式
A.懶漢式
- 單例模式最簡單的實現發現,但是不支持多線程,線程不安全
- 如果想線程安全,在方法上加上synchronized就可以,不過這樣效率低下,99%情況都不會用到
public class Singleton {
private static Singleton instance;
public static Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
private Singleton() {
}
}
B.餓漢式
- 線程安全,沒有加鎖所以效率高,但是類一加載就初始化,浪費內存
public class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
private Singleton() {
}
}
C.雙重鎖
- 安全且在多線程情況下能保持高性能
public class Singleton {
private volatile static Singleton instance;
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
private Singleton() {
}
}
- 爲什麼加雙重驗證?
因爲如果只有第一重驗證,線程A,B都通過第一重驗證,無論線程A,B哪個獲取到了鎖對象,對對象進行實例化,釋放鎖之後,另外一個線程也獲取鎖對象,也對對象進行實例化,此時,對象就不是單例的了。所以要加雙重驗證
- 爲什麼用要volatile修飾?
volatile主要是保證有序性,禁止重排序的,重排序是指編譯器和處理器爲了優化程序性能而對指令序列進行重新排序的一種手段,在創建對象的時候,也就是new對象的時候,是有三步的,分別是:
1.分配對象內存空間
2.初始化對象
3.設置instance指向剛分配的內存地址
不用volatile禁止重排序,順序就可能會變成
1.分配對象內存空間
3.設置instance指向剛分配的內存地址(此時對象還未初始化)
2.最後才初始化對象
當線程A獲取鎖因爲重排序執行順序變成1,3,2時,執行到3後instance就不爲null了,如果此時線程B判斷instance!=null,就直接返回了一個沒有初始化的對象了,這樣線程B有可能會造成程序崩潰
2.工廠模式
- 步驟:創建一個接口和實現幾個接口的實體類,再定義工廠類,之後就可以編寫測試類了,相較於抽象工廠模式簡單點
- Color
public interface Color {
void draw();
}
- Green
public class Green implements Color {
@Override
public void draw() {
System.out.println("Green...");
}
}
- Yellow
public class Yellow implements Color {
@Override
public void draw() {
System.out.println("Yellow...");
}
}
- Red
public class Red implements Color {
@Override
public void draw() {
System.out.println("Red...");
}
}
- ColorFactory
public class ColorFactory {
public Color getColor(String type){
if(type==null){
return null;
}
else if(type.equalsIgnoreCase("Yellow")){
return new Yellow();
}else if(type.equalsIgnoreCase("Red")){
return new Red();
}else if(type.equalsIgnoreCase("Green")){
return new Green();
}
return null;
}
}
- 測試類
public class ColorFactoryDemo {
public static void main(String[] args) {
ColorFactory factory = new ColorFactory();
Color yellow = factory.getColor("yellow");
yellow.draw();
}
}
3.抽象工廠模式
- 相較於工廠模式,較爲複雜點
- 步驟:定義多個接口以及接口的實現類,編寫抽象工廠類,再編寫工廠類,工廠類都是擴展於抽象工廠類,然後再創建一個工廠生成器,之後就可以編寫測試類了
- shape
public interface Shape {
void draw();
}
- Color
public interface Color {
void fill();
}
- Red
public class Red implements Color {
@Override
public void fill() {
System.out.println("Red...");
}
}
- Rectangle
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle...");
}
}
- AbstractFactory
public abstract class AbstractFactory {
public abstract Shape getShape(String type);
public abstract Color getColor(String type);
}
- ColorFactory
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String type) {
return null;
}
@Override
public Color getColor(String type) {
if(type==null){
return null;
}else if(type.equalsIgnoreCase("Red")){
return new Red();
}else if(type.equalsIgnoreCase("Green")){
return new Green();
}else if(type.equalsIgnoreCase("Yellow")){
return new Yellow();
}
return null;
}
}
- ShapeFactory
public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String type) {
if(type==null){
return null;
}else if(type.equalsIgnoreCase("Square")){
return new Square();
}else if(type.equalsIgnoreCase("Circle")){
return new Circle();
}else if(type.equalsIgnoreCase("Rectangle")){
return new Rectangle();
}
return null;
}
@Override
public Color getColor(String type) {
return null;
}
}
- FactoryProduct
public class FactoryProduct {
public static AbstractFactory getFactory(String factoryname){
if(factoryname.equalsIgnoreCase("Shape")){
return new ShapeFactory();
}else if(factoryname.equalsIgnoreCase("Color")){
return new ColorFactory();
}
return null;
}
}
- 測試類
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractFactory shapeFactory = FactoryProduct.getFactory("Shape");
Shape rectangle = shapeFactory.getShape("Rectangle");
rectangle.draw();
AbstractFactory colorFactory = FactoryProduct.getFactory("Color");
Color red = colorFactory.getColor("Red");
red.fill();
}
}
二.網絡基礎
1.OSI七層模式從下到上哪七層
物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層
2.TCP協議、ip協議、Http協議分別在哪一層
傳輸層(tcp、udp協議)
網絡層(ip協議)
應用層(Http協議)
3.TCP協議的3次握手過程
- 第一次握手:客戶端給服務器發送一個SYN報文
- 第二次握手:服務端收到客戶端發送的SYN報文,會迴應一個SYN+ACK報文
- 第三次握手:客戶端收到SYN+ACK報文後,會迴應一個ACK報文
服務端收到ACK報文後,三次握手建立完成,三次握手目的就是爲了建立可靠的通信信道
4.TCP協議的4次揮手過程
- 假如是客戶端先發起關閉請求
- 第一次揮手:客戶端發送一個FIN報文,報文會指定一個序列號
- 第二次揮手:服務端收到FIN報文,會發送一個ACK報文,且把從客戶端接收到的序列號+1作爲ACK報文的序列號,表明收到了客戶端的報文
- 第三次揮手:如果服務端也想斷開連接,和客戶端第一次揮手一樣,發送FIN報文,且指定一個序列號
- 第四次揮手:客戶端收到FIN報文後,一樣發送一個ACK報文作爲應答,且把從服務端接收到的序列號+1作爲自己ACK報文的序列號
- 服務端收到ACK報文後,就處於關閉狀態了
5.TCP和UDP區別
TCP面向連接 UDP面向無連接的
TCP傳輸可靠 UDP傳輸不可靠
TCP傳輸速度慢 UDP傳輸速度快
TCP偏重量級 UDP偏輕量級
TCP面向字節流 UDP面向報文(數據包)
當對網絡通信質量有要求時,比如:整個數據要準確無誤的傳遞給對方,傳輸文本等
對當前網絡通訊質量要求不高的時候,要求網絡通訊速度儘量的快,這時就使用UDP,比如QQ語音,QQ視頻
6.http請求狀態碼
- 200 成功
- 302 重定向
- 304:告訴瀏覽器可以從緩存中獲取請求的資源
- 404 請求資源不存在
- 4xx 客戶端錯誤
- 5xx 服務端錯誤
- 502:無效網關
- 504:網關超時
7.http和https區別
- http是超文本傳輸協議,信息是明文傳輸
- https是具有安全性的SSL加密傳輸協議
- HTTP端口是80,HTTPS是443
- HTTP是無狀態的連接,HTTPS是SSL+HTTP協議構建的可進行加密傳輸,比HTTP協議安全
8.簡述瀏覽器第一次訪問網頁情況
瀏覽器A在第一次請求服務器B的時候,服務器B會在服務端創建一個session,併爲該瀏覽器A創建一個Cookie,並在響應時候把這個Cookie一同返回給瀏覽器A,這樣A在請求數據不變的情況下再次請求服務器B的時候會帶着這個Cookie,cookie中包含了sessionid,與服務端的session對應
9.cookie和session區別
- 兩者都是爲了解決http協議無狀態的情況
- cookie是存放在瀏覽器上的,session放在服務器上的
- session依賴sessionid,而sessionid是存在cookie中的
- cookie放在本地,別人可以分析存放在本地的cookie進行cookie欺騙,所以安全性不如cookie
- 單個cookie保存數據不能超過4k,很多瀏覽器都限制一個站點最多保存20個cookie
10.get和post區別
- get請求在URL中傳送參數有長度限制,post則沒有
- get請求參數在URL可見,post請求參數不可見
- 從可見性上來看,post請求比起get請求安全的多
- get請求是可以緩存的,post請求不可以緩存(get一般是信息獲取之類的,post是信息修改添加之類的,所以get不需要每次獲取都去找數據庫)
11.重定向和轉發區別
- 重定向瀏覽器URL地址欄改變,轉發瀏覽器URL地址欄不變
- 重定向是兩次請求,轉發是一次請求
- 重定向後傳輸的信息會丟失(request),轉發傳輸的信息不會丟失
- 重定向速度不如轉發
轉發一般用於用戶登陸,根據角色轉發到相應的模塊
重定向一般用於用戶註銷登陸時返回主頁面和跳轉到其它的網站等
- 爲什麼說重定向是兩次請求,轉發是一次請求?
轉發過程:
用戶首先發送一個請求到服務端,服務端執行servlet後,調用getRequestDispacther方法,把請求轉發給指定的xxx,整個流程都在服務端完成的,所以說轉發是一次請求
重定向過程:
用戶首先發送一個請求到服務端,服務端執行servlet後,調用sendRedirect方法,這個方法是response,所以是向客戶端返回這個響應,響應告訴客戶端需要再發送一個請求,緊接着客戶端收到這個請求立即發出一個新的請求,去請求新的地址,這裏兩個請求互不干擾,相互獨立,所以request會失效,所以說重定向是兩次請求
12.servlet和jsp區別
- jsp經過編譯後就成爲了Servlet
- jsp是java和html組成成一個擴展名爲jsp的文件,所以jsp側重視圖
- servlet完全從表示層的html裏分離開的,servlet側重控制邏輯(Servlet類似於Controller,用來做控制)
13.簡述下servlet生命週期
初始化階段->執行階段->銷燬階段
-
當客戶端向 Servlet 容器發出 HTTP 請求要求訪問 Servlet 時,Servlet 容器首先會解析請求,檢查內存中是否已經有了該 Servlet 對象,如果有,則直接使用該 Servlet 對象,如果沒有,則創建 Servlet 實例對象,然後通過調用 init() 方法實現 Servlet 的初始化工作。需要注意的是,在 Servlet 的整個生命週期內,它的 init() 方法只能被調用一次
-
這是 Servlet 生命週期中最重要的階段,在這個階段中,Servlet 容器會爲這個請求創建代表 HTTP 請求的 ServletRequest 對象和代表 HTTP 響應的 ServletResponse 對象,然後將它們作爲參數傳遞給 Servlet 的 service() 方法。
service() 方法從 ServletRequest 對象中獲得客戶請求信息並處理該請求,通過 ServletResponse 對象生成響應結果。
在 Servlet 的整個生命週期內,對於 Servlet 的每一次訪問請求,Servlet 容器都會調用一次 Servlet 的 service() 方法,並且創建新的 ServletRequest 和 ServletResponse 對象,也就是說,service() 方法在 Servlet 的整個生命週期中會被調用多次。 -
當服務器關閉或 Web 應用被移除出容器時,Servlet 隨着 Web 應用的關閉而銷燬。在銷燬 Servlet 之前,Servlet 容器會調用 Servlet 的 destroy() 方法,以便讓 Servlet 對象釋放它所佔用的資源。在 Servlet 的整個生命週期中,destroy() 方法也只能被調用一次
14.傳統api和restful api區別
傳統api是用URL來描述行爲的(看URL就知道要幹啥),不管成功失敗都會返回200和一段json,只是可能表示是錯誤的json
restfulapi是用HTTP方法描述行爲,用URL描述資源,使用json交互數據,使用HTTP狀態碼來表示不同的結果
15.jsp九大內置對象和四大作用域
九大內置對象:request、response、session、application、out、config、page、exception、pageContext
四大作用域:page(當前頁面有效)、request(當前請求有效)、session(當前會話有效)、application(當前應用有效)
16.講一下瀏覽器從接收到一個URL到最後展示出頁面,經歷了哪些過程
- 當我們要訪問某個網站的時候,我們在瀏覽器中輸入網址的地址,這個時候瀏覽器會找到對應的DNS服務器,解析出IP地址,拿到IP地址後瀏覽器開始發送報文,對應的IP地址的服務器開始響應報文,以及把請求的資源發送給瀏覽器,瀏覽器在接受相應的資源後便會開始解析,常見的便是HTML,CSS,JavaScript
17.說下你知道的會話跟蹤技術
- URL重寫
URL(統一資源定位符)是Web上特定頁面的地址,URL地址重寫的原理是將該用戶Session的id信息重寫 到URL地址中,以便在服務器端進行識別不同的用戶。URL重寫能夠在客戶端停用cookies或者不支持cookies的時候仍然能夠發揮作用。 - 隱藏表單域
將會話ID添加到HTML表單元素中提交到服務器,此表單元素並不在客戶端顯示,瀏覽時看不到,源代碼中有 - Cookie
Cookie是Web服務器發送給客戶端的一小段信息,客戶端請求時可以讀取該信息發送到服務器端,進而進行用戶的識別。對於客戶端的每次請求,服務器都會將Cookie發送到客戶端,在客戶端可以進行保存,以便下次使用。 服務器創建保存於瀏覽器端,不可跨域名性,大小及數量有限。客戶端可以採用兩種方式來保存這個Cookie對象,一種方式是 保存在 客戶端內存中,稱爲臨時Cookie,瀏覽器關閉後 這個Cookie對象將消失。另外一種方式是保存在 客戶機的磁盤上,稱爲永久Cookie。以後客戶端只要訪問該網站,就會將這個Cookie再次發送到服務器上,前提是 這個Cookie在有效期內。 這樣就實現了對客戶的跟蹤。Cookie是可以被禁止的。 - Session
每一個用戶都有一個不同的session,各個用戶之間是不能共享的,是每個用戶所獨享的,在session中可以存放信息。 保存在服務器端。需要解決多臺服務器間共享問題。如果Session內容過於複雜,當大量客戶訪問服務器時可能會導致內存溢出。因此,Session裏的信息應該儘量精簡。在服務器端會創建一個session對象,產生一個sessionID來標識這個session對象,然後將這個sessionID放入到Cookie中發送到客戶端,下一次訪問時,sessionID會發送到服務器,在服務器端進行識別不同的用戶。Session是依賴Cookie的,如果Cookie被禁用,那麼session也將失效。