38.1 Filter過濾器(配置、生命週期、路徑配置、攔截方式配置)、登入驗證案例配置過濾器、敏感詞彙過濾、設計模式:裝飾模式
阿新 • • 發佈:2021-02-12
技術標籤:02 javaee
目錄
1 Filter:過濾器
生活中的過濾器:淨水器,空氣淨化器,土匪
web中的過濾器:當訪問伺服器的資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。
過濾器的作用:一般用於完成通用的操作。如:登入驗證、統一編碼處理、敏感字元過濾...
過濾器執行流程:1. 執行過濾器 2. 執行放行後的資源 3. 回來執行過濾器放行程式碼下邊的程式碼
2過濾器配置
2.1web.xml方式實現過濾器
java程式碼實現過濾器介面(import javax.servlet.*;)
import javax.servlet.*; import java.io.IOException; public class FilterDemo1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("FilterDemo1執行了... ..."); filterChain.doFilter(servletRequest,servletResponse);//放行 } @Override public void destroy() { } }
web.xml中書寫程式碼
<filter> <filter-name>demo1</filter-name> <filter-class>cn.lws.demo.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.2註解方式實現過濾器
import javax.servlet.*;
import java.io.IOException;
@WebFilter("/*")//攔截所有資源
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo1執行了... ...");
filterChain.doFilter(servletRequest,servletResponse);//放行
}
@Override
public void destroy() {
}
}
3過濾器生命週期方法
- init:在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源
- doFilter:每一次請求被攔截資源時,會執行。執行多次
- destroy:在伺服器關閉後,Filter物件被銷燬。如果伺服器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
@WebFilter("/*")
public class FilterDemo3 implements Filter {
/**
* 在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源
* @param config
* @throws ServletException
*/
public void init(FilterConfig config) throws ServletException {
System.out.println("init....");
}
/**
* 在伺服器關閉後,Filter物件被銷燬。如果伺服器是正常關閉,則會執行destroy方法。只執行一次。用於釋放資源
*/
public void destroy() {
System.out.println("destroy....");
}
/**
* 每一次請求被攔截資源時,會執行。執行多次
* @param request
* @param response
* @param chain
* @throws ServletException
* @throws IOException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("doFilter。。。 。。。");
chain.doFilter(request, response);
}
}
4 過濾器配置詳解
4.1Filter路徑配置
//@WebFilter("/index.jsp") //只有訪問index.jsp資源時,過濾器才會被執行
//@WebFilter("/user/*") //訪問/user下的所有資源時,過濾器都會被執行
//@WebFilter("/*.jsp") //訪問所有後綴名為jsp資源時,過濾器都會被執行
//@WebFilter("/*") //訪問所有資源時,過濾器都會被執行
public class FilterDemo4 implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo4... ...");
chain.doFilter(request, response);
}
}
4.2Filter攔截方式配置
攔截方式配置: | 資源被訪問的方式 |
註解配置: | 設定dispatcherTypes屬性。如:@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD) 1. REQUEST:預設值。瀏覽器直接請求資源 2. FORWARD:轉發訪問資源 3. INCLUDE:包含訪問資源 4. ERROR:錯誤跳轉資源 5. ASYNC:非同步訪問資源 |
web.xml配置 | 設定<dispatcher></dispatcher>標籤即可 |
4.2.1列:註解方式實現過濾器
//1 瀏覽器請求時會執行此過濾器 預設情況
//@WebFilter(value = "/*",dispatcherTypes = DispatcherType.REQUEST)
//2 瀏覽器轉發時會執行此過濾器
//@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//3 瀏覽器請求或轉發時會執行此過濾器
//@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo5 implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo5執行了。。。 。。。");
chain.doFilter(request, response);
}
}
轉發程式碼:
@WebServlet("/ServletDemo2")
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ServletDemo2 doGet執行了... ...");
request.getRequestDispatcher("index.jsp").forward(request,response);//轉發
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
4.2.2 web.xml方式實現過濾器
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.lws.demo.filter.FilterDemo5</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
5配置多個過濾器
濾器先後順序問題:
1. 註解配置:按照類名的字串比較規則比較,值小的先執行 * 如: AFilter 和 BFilter,AFilter就先執行了。
2. web.xml配置: <filter-mapping>誰定義在上邊,誰先執行
過濾器執行順序:如果有兩個過濾器:過濾器1和過濾器2 。執行順序:過濾器1 - 過濾器2 - 資源執行 - 過濾器2 - 過濾器1
@WebFilter("/*")
public class FilterDemo6 implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo6 執行了... ...");
chain.doFilter(request, response);
System.out.println("FilterDemo6 回來了... ...");
}
}
@WebFilter("/*")
public class FilterDemo7 implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo7 執行了... ...");
chain.doFilter(request, response);
System.out.println("FilterDemo7 回來了... ...");
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
index.jsp... ...
<% out.print("index.jsp執行了。。。 。。。");%> 輸出到jsp頁面中
<% System.out.println("index.jsp執行了。。。 。。。");%> 輸出到控制檯
</body>
</html>
輸入:
http://localhost/day19/index.jsp
6 列:登入驗證案例配置過濾器
參考程式碼:day17_case
需求:
1. 訪問day17_case案例的資源。驗證其是否登入
2. 如果登入了,則直接放行。
3. 如果沒有登入,則跳轉到登入頁面,提示"您尚未登入,請先登入"。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//servletRequest 與req是同一個
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(servletRequest);
HttpServletRequest req = (HttpServletRequest) servletRequest;//1 強制轉換
//2 獲取資源請求路徑
String uri = req.getRequestURI();
System.out.println("uri:"+uri);
//3.判斷是否包含登入相關資源路徑,要注意排除掉 css/js/圖片/驗證碼等資源
if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet") ){
filterChain.doFilter(servletRequest,servletResponse);//放行
}else {
Object user = req.getSession().getAttribute("user");
if(user!=null){
filterChain.doFilter(servletRequest,servletResponse);//放行
}else {
req.setAttribute("login_msg","你尚未登入,請輸入使用者名稱和密碼");
req.getRequestDispatcher("/login.jsp").forward(req,servletResponse);
}
}
}
@Override
public void destroy() {
}
}
7敏感詞彙過濾
src目錄下建立檔案:敏感詞彙.txt(檔案內容可以自行新增)
@WebFilter("/*")
public class FilterDemo8 implements Filter {
private List<String> list=new ArrayList<String>();
public void init(FilterConfig config) throws ServletException {
try{
String realPath =config.getServletContext().getRealPath("/WEB-INF/classes/敏感詞彙.txt");//1 獲取檔案真實路徑
BufferedReader reader = new BufferedReader(new FileReader(realPath));//2 讀取檔案
String line=null;
while ((line=reader.readLine())!=null){
list.add(line);
}
reader.close();
}catch (Exception e){
e.printStackTrace();
}
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//使用了設計模式:裝飾模式
ServletRequest o = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增強getParameter方法 判斷是否是getParameter方法
if(method.getName().equals("getParameter")){
//增強返回值
//獲取返回值
String value = (String) method.invoke(req,args);
if(value != null){
for (String str : list) {
if(value.contains(str)){
value = value.replaceAll(str,"***");
}
}
}
}
return method.invoke(req,args);
}
});
}
}
測試程式碼:
@WebServlet("/ServletDemo2")
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String msg = request.getParameter("msg");
System.out.println(name+":"+msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
驗證方式:輸入
http://localhost/day19/ServletDemo2?name=laowang&msg=sb
過濾後:http://localhost/day19/ServletDemo2?name=laowang&msg=xxx
8設計模式:裝飾模式
- 真實物件:被代理的物件
- 代理物件:
- 代理模式:代理物件代理真實物件,達到增強真實物件功能的目的
8.1實現方式:
8.1.1 靜態代理:有一個類檔案描述代理模式
8.1.2 動態代理:在記憶體中形成代理類
實現步驟: | 1 代理物件和真實物件實現相同的介面 2建立代理物件 = Proxy.newProxyInstance();並增強方法: 3 使用代理物件呼叫方法。 4 增強方法: 增強方式: |
介面:
public interface ProducePc {
int numPc(int pc);//pc總數量
String salePcs(double monkey);//單價
void show();//資訊
}
真實物件:
public class LenovoPc implements ProducePc {
@Override
public int numPc(int pc) {
return pc;
}
@Override
public String salePcs(double monkey) {
String s = String.valueOf(monkey);
return s;
}
@Override
public void show() {
System.out.println("聯想電腦 i7 四核八執行緒 8g 256Gssd");
}
}
代理物件:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
LenovoPc lenovoPc = new LenovoPc();//1.建立真實物件
/* 三個引數: 1. 類載入器:真實物件.getClass().getClassLoader() 2. 介面陣列:真實物件.getClass().getInterfaces() 3. 處理器:new InvocationHandler()*/
//2 動態代理增強LenovoPc物件
ProducePc salePc= (ProducePc) Proxy.newProxyInstance(lenovoPc.getClass().getClassLoader(), lenovoPc.getClass().getInterfaces(),new InvocationHandler() {
//invoke方法:代理物件呼叫的所有方法都會觸發該方法執行。引數:1. proxy:代理物件 2. method:代理物件呼叫的方法,被封裝為的物件 args:代理物件呼叫的方法時,傳遞的實際引數
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("numPc")){
int num = (int) args[0]-1; //1 增強引數
Object obj = method.invoke(lenovoPc, num);
return obj;
}else if (method.getName().equals("salePcs")){
double monkey=(double)args[0]*0.85;
System.out.println("價格:"); //2 增強方法體
Object obj =method.invoke(lenovoPc, monkey);
return obj+"元,_ 送一個滑鼠墊"; //3增強返回值
}else{
Object obj = method.invoke(lenovoPc, args);
return obj;
}
}
});
int i = salePc.numPc(100);
String s = salePc.salePcs(6000);
System.out.println(i);
System.out.println(s);
salePc.show();
}
}