過濾器、監聽器、Servlet3.0註解

一、過濾器

1.介紹

Filter 的完整流程: Filter 對用戶請求進行預處理,接着將請求交給 Servlet 進行處理並生成響應,最後 Filter 再 對服務器響應進行後處理。在一個 web 應用中,可以開發編寫多個Filter,這些 Filter 組合 起來稱之爲一個 Filter 鏈。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wsJrVIMB-1582630865316)(C:\Users\Hello Word\AppData\Roaming\Typora\typora-user-images\1582629150766.png)]

2.實現

init(), doFilter(), destroy()分別在相應的時機執行。後期觀察生命週期。

Filter 的實現只需要兩步:

Step1: 編寫 java 類實現 Filter 接口,並實現其 doFilter 方法。

Step2: 在 web.xml 文件中對編寫的 filter 類進行註冊,並設置它所能攔截的資源

public class Filter01 implements Filter {

	/**
	 * 初始化
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("Filter01 init...");
		
	}

	/**
	 * 處理請求的攔截方法
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		// 處理請求
		System.out.println("Filter01  處理請求...");
		
		// 放行資源
		chain.doFilter(request, response);
		
		// 處理響應
		System.out.println("Filter01  處理響應...");
		
	}

	/**
	 * 銷燬方法
	 */
	@Override
	public void destroy() {
		System.out.println("Filter01 destroy...");
		
	}

}


//web.xml配置
<filter>
  	<filter-name>Filter01</filter-name> <!-- 給服務器看的,與filter-mapping標籤中filter-name保持一致 -->
  	<filter-class>com.shsxt.filter.Filter01</filter-class> <!-- 類的全路徑 -->
  </filter>
  <filter-mapping>
  	<filter-name>Filter01</filter-name> <!-- 給服務器看的,與filter標籤中filter-name保持一致 -->
  	<url-pattern>/Servlet01</url-pattern> <!-- 給瀏覽器看的,需要攔截的資源路徑 -->
  	<!-- <servlet-name>Servlet01</servlet-name> --> <!-- 想要攔截的servlet名稱,與servlet標籤的servlet-name一致 -->
  </filter-mapping>

3.過濾器的執行順序

過濾器

​ 攔截請求到達指定資源之前的請求數據

​ 攔截響應到達客戶端之前的響應數據

​ 放行資源(chain.doFilter(request,response))

過濾器鏈

多個過濾器同時執行

執行順序:web.xml配置文件中,先配置的先執行

攔截順序:按照指定順序攔截,按照相反順序響應

​ 請求:(1 -> 2 -> 3 )

​ 響應:(3 -> 2 -> 1 )

4.過濾器實例

/**
 * 非法訪問攔截
 * 	當用戶訪問登錄狀態才能訪問的資源時,如果用戶未登錄,會被攔截到登錄頁面
 * 	
 * 	攔截的資源:
  		攔截所有資源  /*
  		
  	需要放行的資源:
  		1、指定頁面,放行
  			無需登錄即可訪問的頁面 (例如:登錄頁面、註冊頁面等)
  		2、靜態資源,放行
  			js文件、css文件及圖片(存放在statics目錄下的資源)
  		3、指定操作,放行
  			無需登錄即可執行的操作 (登錄操作、註冊操作等)
  		4、登錄狀態,放行
  			判斷session作用域中是否存在用戶數據(有數據=登錄狀態;無數據=非登錄狀態)
 		
 		當用戶未登錄時訪問資源,攔截跳轉到登錄頁面
 */
public class LoginAccessFilter implements Filter {
    
    public LoginAccessFilter() {
        
    }

	public void destroy() {
		
	}
	
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {
		
		// 基於HTTP
		HttpServletRequest request = (HttpServletRequest)arg0;
		HttpServletResponse response = (HttpServletResponse)arg1;
		
		// 獲取當前訪問的資源路徑
		String path = request.getRequestURI(); // 從端口號後開始(不包含端口),到"?"前面	/站點名/資源路徑
		System.out.println(path);
		
		// 1、指定頁面,放行       無需登錄即可訪問的頁面 (例如:登錄頁面、註冊頁面等)
		if (path.contains("/login.html")) {
			// 放行資源
			chain.doFilter(request, response);
			return;
		}
		
		// 2、靜態資源,放行         js文件、css文件及圖片(存放在statics目錄下的資源)
		if (path.contains("/statics")) {
			// 放行資源
			chain.doFilter(request, response);
			return;
		}
		
		// 3、指定操作,放行        無需登錄即可執行的操作 (登錄操作、註冊操作等)
		if (path.indexOf("/loginServlet") != -1) {
			// 放行資源
			chain.doFilter(request, response);
			return;
		}
		
		// 4、登錄狀態,放行 	判斷session作用域中是否存在用戶數據(有數據=登錄狀態;無數據=非登錄狀態)
		String user = (String) request.getSession().getAttribute("user");
		if (user != null && !"".equals(user)) {
			// 放行資源
			chain.doFilter(request, response);
			return;
		}
		
		// chain.doFilter(request, response);
		
		// 攔截請求跳轉到登錄頁面
		response.sendRedirect("login.html");
	
	}

	public void init(FilterConfig fConfig) throws ServletException {
		
	}

}


/**
 * 用戶登錄
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("用戶登錄...");
		
		// 接收參數
		System.out.println(request.getParameter("uname"));
		
		// 模擬用戶在登錄狀態
		request.getSession().setAttribute("user", "zhangsan");
		
		// 登錄成功
		response.sendRedirect("index.html");
	}

}

二、監聽器

1.介紹

web 監聽器是一種Servlet 中的特殊的類,ServletContext,HttpSession,ServletRequest 的創建和銷燬;變量的創建、銷燬和修改等。

2.實現

public class Listener01 implements HttpSessionListener,HttpSessionAttributeListener {

	/**
	 * session的創建
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println("Session Create...");
	}

	/**
	 * session的銷燬
	 */
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		System.out.println("Session Destroy...");
	}

	/**
	 * 設置域對象
	 */
	@Override
	public void attributeAdded(HttpSessionBindingEvent se) {
		System.out.println("attributeAdded...");
		
	}

	/**
	 * 刪除域對象
	 */
	@Override
	public void attributeRemoved(HttpSessionBindingEvent se) {
		System.out.println("attributeRemoved...");
		
	}

	/**
	 * 修改域對象
	 */
	@Override
	public void attributeReplaced(HttpSessionBindingEvent se) {
		System.out.println("attributeReplaced...");
		
	}

}

//servlet

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 創建session對象
		HttpSession session  = request.getSession();
		
		// 設置域對象
		session.setAttribute("uname", "zhangsan");
		
		// 修改域對象
		session.setAttribute("uname", "lisi");
		
		// 刪除域對象
		session.removeAttribute("uname");
		
		// session的銷燬
		session.invalidate();
	}

3.監聽器案例

/**
 * 在線人數統計
 * 	當有新的session對象被創建,則在線人數+1;
 * 	有session對象被銷燬,在線人數-1;
 * @author Lisa Li
 *
 */
public class OnlineListener implements HttpSessionListener {
	
	// 默認在線人數
	private Integer onlineNumber = 0;

	/**
	 * 當有新的session對象被創建,則在線人數+1;
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		// 人數+1
		onlineNumber++;
		// 將人數存到session作用域中
		//se.getSession().setAttribute("onlineNumber", onlineNumber);
		// 將人數存到application作用域中
		se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
		
	}

	/**
	 * 有session對象被銷燬,在線人數-1;
	 */
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// 人數-1
		onlineNumber--;
		// 將人數存到session作用域中
		// se.getSession().setAttribute("onlineNumber", onlineNumber);
		// 將人數存到application作用域中
		se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);
		
	}

}

/**
 * 在線人數統計
 */
public class OnlineServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	//引入日誌
	//private logger logger=LoggerFactory.getLogger(OnlineServlet.class);
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//得到參數
		String key=request.getParameter("key");
		
		//判斷是否爲空
		if(key==null || "".equals(key)){
			//創建session對象
			HttpSession session=request.getSession();
			//獲取session作用域中人數application
			Integer onlineNumber=(Integer) session.getServletContext().getAttribute("onlineNumber");
			//當前訪問用戶的ip及內容
			String ip=request.getRemoteAddr();
			String content=request.getParameter("content");
			System.out.println(ip);
			System.out.println(content);
			//輸出
			response.setContentType("text/html;charset=UTF-8");
			response.getWriter().write("<h2>在線人數:"+onlineNumber+"</h2><h4><a href='Servlet01?key=logout'>退出</a><h4>");
			
		}else{
			//傳遞了參數,表示要做用戶推出操作
			request.getSession().invalidate();
		}
	}

}

三、Servlet3.0註釋

1.@WebServlet

@WebServlet 註解將一個繼承於javax.servlet.http.HttpServlet 的類標註爲可以處理用戶請求的 Servlet。

//@WebServlet(value="/Servlet01")
//@WebServlet(name="Servlet01",value="/Servlet01")
//@WebServlet(value={"/Servlet01","/Servlet001"})
//@WebServlet(urlPatterns="/s01")
//@WebServlet(urlPatterns={"/Servlet01","/Servlet001"})
@WebServlet("/s01")
public class Servlet01 extends HttpServlet {
	private static final long serialVersionUID = 1L;

	
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("Servlet...");
		
	}

}

2.@WebFilter

使用註解時:過濾器鏈按照類名的字母排序(大部分情況)

@WebFilter("/*")
public class Filter01 implements Filter {

    /**
     * Default constructor. 
     */
    public Filter01() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("Filter01...");
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

3.@WebListener

Servlet3.0 提供@WebListener 註解將一個實現了特定監聽器接口的類定義爲監聽

器。將實現了 ServletContextListener 接口的 MyServletContextListener 標註爲監聽器。

@WebListener
public class Listener01 implements HttpSessionListener {

    /**
     * Default constructor. 
     */
    public Listener01() {
        // TODO Auto-generated constructor stub
    }

	/**
     * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
     */
    public void sessionCreated(HttpSessionEvent se)  { 
         // TODO Auto-generated method stub
    }

	/**
     * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
     */
    public void sessionDestroyed(HttpSessionEvent se)  { 
         // TODO Auto-generated method stub
    }
	
}

4.@MultipartConfig

文件上傳

  • @MultipartConfig 一定要加註解!!!!!

  • 如果前臺的表單類型設置爲enctype=" multipart/form-data",後臺servlet一定要加註解,否則所有的參數都爲null。

    使用註解@MultipartConfig 將一個 Servlet 標識爲支持文件上傳。 Servlet3.0 將 multipart/form-data 的 POST 請求封裝成 Part,通過Part 對上傳的文件進行操作。

    @MultipartConfig
    @WebServlet("/uploadServlet")
    public class UploadServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    
    	
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		// 獲取參數
    		String uname = request.getParameter("uname");
    		System.out.println(uname);
    						
    		
    		
    		// 得到要上傳的文件對象   getPart(name):name代表的是表單元素file文件域的name屬性值
    		Part part = request.getPart("myfile");
    		// 得到文件存放的路徑
    		String path  = request.getServletContext().getRealPath("/");
    		// 得到上傳的文件名
    		String fileName = part.getSubmittedFileName();
    		// 上傳
    		part.write(path +"/"+fileName);
    		
    		
    	}
    
    }
    
    <body>
    
    	<!-- 
    		表單實現文件上傳
    			第一步:設置表單類型 enctype="multipart/form-data" (文件上傳表單)
    			第二步:表單提交類型 method="POST"
    			第三步:文件域file元素設置name屬性值
    	 -->
    	 <form action="uploadServlet" method="POST" enctype="multipart/form-data" >
    	 	姓名:<input type="text" name="uname" /> <br>
    	 	文件:<input type="file" name="myfile" /> <br>
    	 	<button>提交</button>
    	 </form>
    </body>
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章