JavaWeb基礎知識點

lingengy發表於2018-03-08

一、Filter過濾器

1、Filter介紹:

Filter也稱之為過濾器,開發人員通過Filter技術,對web伺服器管理的所有web資源:例如 Jsp, Servlet, 靜態圖片檔案或靜態 html 檔案等進行攔截,從而實現一些特殊的功能。例如實現URL級別的許可權訪問控制、過濾敏感詞彙、壓縮響應資訊等一些高階功能。

通過Filter技術,開發人員可以實現使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截。簡單說,就是可以實現web容器對某資源的訪問前截獲進行相關的處理,還可以在某資源向web容器返回響應前進行截獲進行處理。

2、編寫Filter步驟

第一步:建立Filter處理類;

package com.prosay.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * 統一的編碼處理程式
 * @author jame
 * 1.實現Filter介面
 * 2.在Web.xml中配置
 */
public class EncodingFilter implements Filter{
    private String encoding;
    /**
     * 過濾器被執行的核心方法
     * tomcat接收的每一個請求都會建立一個子執行緒處理,子執行緒建立的呼叫Dofilter(request response)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
            System.out.println("編碼過濾器開始………………");
            //在前面設定好編碼
            request.setCharacterEncoding(encoding);
            response.setContentType("text/html;charset="+encoding);
            response.setCharacterEncoding("UTF-8");
            //EncodingWrapper wrapper = new EncodingWrapper((HttpServletRequest)request);
            //chain.doFilter(wrapper, response);
            //執行下一個步驟(另外一個過濾器或者是真實的資源)
            chain.doFilter(request, response);
            System.out.println("編碼過濾器結束………………");

    }
    @Override
    public void init(FilterConfig config){
        encoding = config.getInitParameter("encoding");
        System.out.println("過濾器被初始化!!…………………………");
    }
}
package com.prosay.filter;
/**
 * 使用者的許可權校驗
 * @author jame
 *
 */

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class UserFilter extends HttpFilter{

    @Override
    public void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws IOException, ServletException{
        //request中去獲取session
        HttpSession session = request.getSession();

        ServletContext  application = request.getServletContext();
        String userName = (String)session.getAttribute("userName");
        System.out.println("使用者許可權過濾器開始………………");
        //說明當前會話中存在使用者名稱(表示已經登陸了)
        if(userName!=null){
            chain.doFilter(request, response);
        }else{
            response.sendRedirect("../index.html");
        }
        System.out.println("使用者許可權過濾器結束………………");
        //this.getServletContext();
    }
}

第二步:web.xml檔案中配置Filter。
配置Filter時要宣告filter-name(filter的別名)和filter-class(filter的類路徑),也可以設定屬性,然後在filter類取出來。

<!-- 配置編碼過濾器 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.prosay.filter.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
<!-- 使用者許可權攔截器 -->
  <filter>
    <filter-name>userFilter</filter-name>
    <filter-class>com.prosay.filter.UserFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>userFilter</filter-name>
    <url-pattern>/chatroom/*</url-pattern>
  </filter-mapping>

3、過濾器鏈的形成:

當請求一個資源時,伺服器會查詢web.xml中所有對此資源路徑進行過濾的filter,並根據在web.xml中的先後順序形成一個filter鏈(filterchain)。就是按寫在web.xml中的filter類順序執行。

二、監聽器

1、監聽器介紹:

監聽器也叫Listener,是Servlet的監聽器,它可以監聽客戶端的請求、服務端的操作等。通過監聽器,可以自動激發一些操作,比如監聽線上的使用者的數量。

2、ServletContextListener

ServletContextListener是ServletContext的監聽者,它能夠監聽ServletContext物件的生命週期,也就是監聽Web應用的生命週期。
當Servlet容器啟動或終止Web應用時,會觸發ServletContextEvent事件,該事件
由 ServletContextListener 來處理 。

package com.prosay.listener;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * 配置load-on-starup的Servlet可以跟隨Tomcat的啟動初始化
 * ServletContextListener能夠比他更早啟動
 * @author jame
 * 1.實現ServletContextListener介面
 * 2.實現對應的方法
 * 監聽的是上下文的物件生命週期(初始化和銷燬)
 */
public class InitListener implements ServletContextListener{

    @Override
    public void contextDestroyed(ServletContextEvent event){
        System.out.println("專案從容器中解除安裝了…………");
    }
    @Override
    public void contextInitialized(ServletContextEvent event){
        System.out.println("專案被容器載入…………");
        System.out.println("***********聊天室伺服器初始化開始***********");
        ServletContext application = event.getServletContext();
        //第一次訪問(初始化)建立一個ArrayList用來儲存訊息列表,然後將這個ArrayList例項存入Servlet上下文中
        List<String> msgs = new ArrayList<String>();
        //servletContext存屬性方式 setAttribute(String attrName,Object attr)
        application.setAttribute("msgs",msgs);
        //servletContext  httpSession 物件的儲存 整個應用生命週期中儲存屬性 httpsession 整個會話中的儲存屬性
        //線上使用者列表
        List<String> userList = new ArrayList<String>();
        application.setAttribute("users",userList);
        System.out.println("***********聊天室伺服器初始化完畢***********");
    }

}
package com.prosay.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class SecondListener implements ServletContextListener{

    public void contextInitialized(ServletContextEvent event){
        System.out.println(event.getSource()+"#####");
    }
}
package com.prosay.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

/**
 * 
 * @author jame
 *
 */
public class ApplicationAttrListener implements ServletContextAttributeListener{
        /**
         * 監聽servletContext例項的新新增的屬性
         */
        public  void attributeAdded(ServletContextAttributeEvent scae) {
            System.out.println("上下文中增加了:"+scae.getName()+":"+scae.getValue());
        }
        /**
         * 監聽ServletContext例項移除的屬性
         */
        public  void attributeRemoved(ServletContextAttributeEvent scae) {
            System.out.println("上下文中移除了屬性:"+scae.getName()+":"+scae.getValue());
        }
        /**
         * 監聽ServletContext例項中的屬性被替換時發生
         */
        public  void attributeReplaced(ServletContextAttributeEvent scae) {

            System.out.println("上下文中增加了:"+scae.getName()+":"+scae.getValue());
        }
}
<!-- 上下文監聽器 -->
  <listener>
    <description>上下文監聽器,來替換InitServlet</description>
    <listener-class>com.prosay.listener.InitListener</listener-class>
  </listener>
   <listener>
    <listener-class>com.prosay.listener.SecondListener</listener-class>
  </listener>
 <listener>
    <description>上下文屬性監聽器</description>
    <listener-class>com.prosay.listener.ApplicationAttrListener</listener-class>
  </listener>

web.xml中的listener的這個宣告順序,執行後的輸出為:

專案被容器載入…………
*********** 聊天室伺服器初始化開始***********
上下文中增加了:msgs:[]
上下文中增加了:users:[]
***********聊天室伺服器初始化完畢***********
org.apache.catalina.core.ApplicationContextFacade@4a3631f8#####
過濾器被初始化!!…………………………

如果把SecondListener提到前面輸出結果為:

org.apache.catalina.core.ApplicationContextFacade@4a3631f8#####
專案被容器載入…………
*********** 聊天室伺服器初始化開始***********
上下文中增加了:msgs:[]
上下文中增加了:users:[]
***********聊天室伺服器初始化完畢***********
過濾器被初始化!!…………………………

把ApplicationAttrListener提到前面輸出結果為:

專案被容器載入…………
*********** 聊天室伺服器初始化開始***********
上下文中增加了:msgs:[]
上下文中增加了:users:[]
***********聊天室伺服器初始化完畢***********
過濾器被初始化!!…………………………
org.apache.catalina.core.ApplicationContextFacade@4a3631f8#####

說明,寫在web.xml前面的監聽器先檢測到,程式碼先執行,但是如果寫在前面,監聽的內容沒有觸發的話程式碼也是不會先執行的。

HttpSessionListner

HttpSessionListener監聽HttpSession的操作。
當建立一個Session時,激發session Created(HttpSessionEvent se)方法;
當銷燬一個Session時,激發sessionDestroyed (HttpSessionEvent se)方法。

三、重定向和請求轉發

1、重定向介紹:

伺服器向瀏覽器傳送一個302狀態碼及一個Location訊息頭,瀏覽器在收到後會立即向這個地址傳送請求。
sendRedirect(String location)

2、轉發介紹:

轉發:伺服器將客戶端的請求轉發到另外一個頁面
request.getRequestDispatcher(String path)
forward(HttpServletRequest request, HttpServletResponse response)

3、重定向和轉發的區別:

1) 重定向時,客戶端傳送了兩個請求;而轉發時,客戶端只傳送了一個請求(本質區別)
2) 重定向時,客戶端瀏覽器的位址列有變化,而轉發時,客戶端瀏覽器的位址列沒有變化
3) 重定向發生在客戶端,而轉發是發生在服務端,客戶端不知道

4、重定向與轉發的應用場景:

1) 只是頁面跳轉的話,且沒有業務請求處理引數等,可以使用重定向,也可以使用轉發過去。
2,如果請求跳轉頁面有業務處理,則必須使用轉發,但是有兩點需要處理:
1)如果我們的action請求的jsp頁面的有業務邏輯處理或者請求其他名稱空間的action時,在不同的名稱空間裡面,那麼必須使用”../”來跳出當前的路徑請求,在進入其他的名稱空間+其他的action請求,這樣才會使頁面的其他匯入檔案才不會有丟失的情況;
2)當然,如果要跳轉到註冊,或者表單提交頁面時,最後使用重定向比較好,這樣不會有屬性衝突,造成資料提交異常,但有時候卻要轉發過去,具體看是否需要當前的request請求引數;

相關文章