Javaweb03-servlet&filter
1、什麼是servlet
第一個servlet應用程式,實現servlet介面
定義:凡是實現了servlet api介面(或者繼承servlet api介面的實現類)的類就是servlet應用程式;
命周期:
- 創建servlet應用程式的實例:只會執行一次,在首次通過url-pattern映射訪問時,創建實例;
- 初始化init方法:只會執行一次,在創建完servlet應用程式的實例後,立刻調用,一般都是用戶初始化servlet應用程式;
- 業務處理service方法:執行多次,每當訪問請求映射到servlet應用程式時,都會調用service方法,進行請求處理;
- 銷毀destroy方法:只會執行一次,在web應用程式卸載時,統一調用,多用戶釋放伺服器資源;
2、創建Servlet的三種方式
2.1 實現 servlet介面
public class HelloServlet implements Servlet {
// 空參構造
public HelloServlet() {
System.out.println("---------HelloServlet 空參構造--------------");
}
@Override
public void destroy() {
System.out.println("---------HelloServlet destroy--------------");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("---------HelloServlet getServletConfig--------------");
return null;
}
@Override
public String getServletInfo() {
System.out.println("---------HelloServlet getServletInfo--------------");
return null;
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("---------HelloServlet init--------------");
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("---------HelloServlet service--------------");
}
}
2.1.1 servlet的生命周期
//第一次訪問映射路徑:
---------HelloServlet 空參構造---------
---------HelloServlet init-----------(//如果配置了load-on-startup 項目啟動前面兩步就會立刻執行)
---------HelloServlet service--------(//每次訪問映射路徑都會調用此方法)
---------HelloServlet destroy--------(//關閉服務才會調用)
2.2 繼承 GenericServlet
public class HelloServlet2 extends GenericServlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
}
}
2.3 繼承 HttpServlet
public class StudentInfoServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 一般直接在get請求處理方法中,直接調用post方法,實現兩種請求統一處理
//doPost(request, response);
}
}
3、Servlet 的註冊配置
3.1 註冊
<!-- 註冊第一個 servlet應用程式 -->
<servlet>
<!-- servlet應用程式的別名 -->
<servlet-name>helloServlet</servlet-name>
<!-- servlet應用程式的全類名 -->
<servlet-class>com.kgc.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 映射第一個servlet應用程式 -->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
3.2 模糊映射
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<!-- 匹配方法 前匹配 /user/* 等等 -->
<!-- <url-pattern>/*</url-pattern> -->
<!-- 匹配方法 後匹配 -->
<!--<url-pattern>*.do</url-pattern>-->
<!-- 不能 /*.xx 兩種一起使用 -->
</servlet-mapping>
3.3 初始化參數
3.3.1 單個servlet內部初始化參數
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.kgc.servlet.HelloServlet</servlet-class>
<!-- 指定servlet內部初始化參數,必須在load-on-startup之前 -->
<init-param>
<param-name>key</param-name>
<param-value>value</param-value>
</init-param>
</servlet>
3.3.2 獲取單個servlet內部初始化參數
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("---------HelloServlet init--------------");
//獲取當前servelt初始化參數
//通過 config 對象獲取
String encoding = config.getInitParameter("encoding");
System.out.println("******* servlet內部初始化參數 encoding = "+encoding+"******");
}
3.3.3 全局servlet初始化參數
<context-param>
<param-name> key </param-name>
<param-value> value </param-value>
</context-param>
3.3.4 獲取全局servlet初始化參數
//獲取全局servelt初始化參數
//通過ServletContext 對象獲取
String encodingContext = config.getServletContext().getInitParameter("encoding");
System.out.println("**** servlet全局初始化參數 encodingContext = "+encodingContext+"*****");
3.3.5 servlet 的啟動優先順序
默認情況下,啟動是不會創建實例和初始化;
配置了load-on-startup,servlet應用程式就會在伺服器啟動時,創建實例並初始化 ;
允許值為正整數(可以為0)負數不可以,一般為1,值的作用是指定servlet應用程式的創建時機,值越小優先順序,越高,越早創建實例並初始化;
<load-on-startup>1</load-on-startup>
3.3.6 歡迎頁面
<!-- 歡迎頁面可以設計多個,在web.xml中越靠上優先順序越高 -->
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
3.3.7錯誤頁面
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
4、相對路徑和絕對路徑
通過servlet的跳轉使用相對路徑,容易出錯,會導致缺少部分路徑,而找不到資源;
一般使用絕對路徑,進行跳轉;
//獲取項目跟路徑
<%=request.getContextPath()%> //獲取跟路徑後再根據實際情況進行路徑拼接
5、filter
5.1 創建過濾器
實現Filter的應用就是過濾器;
public class MyFirstFilter implements Filter{
public MyFirstFilter() {
System.out.println("-----MyFirstFilter 空參構造 ------");
}
@Override
public void destroy() {
System.out.println("-----MyFirstFilter destroy ------");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
System.out.println("-----MyFirstFilter doFilter ------");
//FilterChain 是決定請i去是否放行的操作對象,如果請求放行,必須要調用FilterChain的請求過濾方法doFilter
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("-----MyFirstFilter init ------");
}
}
5.2 filter 註冊與映射
<!-- 註冊過濾器first:配置內容和servlet基本一樣,就是標籤不一樣 -->
<filter>
<filter-name>myFirstFilter</filter-name>
<filter-class>com.kgc.filter.MyFirstFilter</filter-class>
</filter>
<!-- 過濾器first映射 -->
<filter-mapping>
<filter-name>myFirstFilter</filter-name>
<url-pattern>/filter01.jsp</url-pattern>
<!-- filter的映射也可以模糊匹配 /* 等等 -->
</filter-mapping>
5.3 filter 的初始化參數
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
獲取參數:
//一些配置的初始化參數可以通過 filterConfig.getInitParameter(key) 獲取
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
System.out.println("獲取字符集過濾器中的初始化編碼:"+this.encoding);
}
5.4 filter 的執行順序
web.xml中映射順序,越上面的越先執行;
MySecondFilter
public class MySecondFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
System.out.println("-----1.MySecondFilter doFilter before ------");
chain.doFilter(request, response);
System.out.println("-----2.MySecondFilter doFilter after ------");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
MyThridFilter
public class MyThridFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
System.out.println("-----3.MyThridFilter doFilter before ------");
chain.doFilter(request, response);
System.out.println("-----4.MyThridFilter doFilter after ------");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
filterTarget.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
System.out.println("-----5.Filter Target Page-----");
%>
<h2>Filter Target Page</h2>
</body>
</html>
web.xml
<!-- second -->
<filter>
<filter-name>mySecondFilter</filter-name>
<filter-class>com.kgc.filter.MySecondFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>mySecondFilter</filter-name>
<url-pattern>/web3filter01/filterTarget.jsp</url-pattern>
</filter-mapping>
<!-- third -->
<filter>
<filter-name>myThridFilter</filter-name>
<filter-class>com.kgc.filter.MyThridFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myThridFilter</filter-name>
<url-pattern>/web3filter01/filterTarget.jsp</url-pattern>
</filter-mapping>
運行結果順序:
//執行順序
-----1.MySecondFilter doFilter before ----
-----3.MyThridFilter doFilter before ------
-----5.Filter Target Page-----
-----4.MyThridFilter doFilter after -------
-----2.MySecondFilter doFilter after ------
5.5 編碼過濾器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//this.encoding 編碼名可以存放在過濾器初始化參數中,通過filterConfig.getInitParameter("encoding");獲取
//poet請求亂碼處理
request.setCharacterEncoding(this.encoding);
//響應編碼
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding(this.encoding);
//請求放行
chain.doFilter(request, response);
}