JavaWeb學習筆記九 過濾器、注解


過濾器Filter

filter是對客戶端訪問資源的過濾,符合條件放行,不符合條件不放行,並且可以對目標資源訪問前后進行邏輯處理。

步驟:

  1. 編寫一個過濾器的類實現Filter接口
  2. 實現接口中尚未實現的方法(着重實現doFilter方法)
  3. 在web.xml中進行配置(主要是配置要對哪些資源進行過濾)

例子,過濾器實現類:

package com.yyb.filter;

import java.io.IOException;
import javax.servlet.*;

/**
 * Created by Administrator on 2017/7/28.
 */
public class FilterDemo implements Filter {
    @Override
    //Filter創建的時候執行init方法
    public void init(FilterConfig filterConfig) throws ServletException {
        //1、獲得web.xml中filter 的名稱<filter-name>FilterDemo</filter-name>
        System.out.println(filterConfig.getFilterName());
        //2、獲得當前filter的初始化參數
        System.out.println(filterConfig.getInitParameter("aaa"));
        //3、獲得servletContext
        filterConfig.getServletContext();

        System.out.println("init ....");
    }

    @Override
    //doFilter是Filter的核心過濾的方法
    /*
     * request: 內部封裝是客戶端http請求的內容
     * response: 代表是響應
     * FilterChain: 過濾器鏈對象
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        System.out.println("quick1 running....");
        //放行請求
        chain.doFilter(request, response);
    }

    @Override
    //Filter對象銷毀的時候執行destory方法
    public void destroy() {
        System.out.println("destroy...");
    }
}

web.xml

<filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.yyb.filter.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Filter的API詳解

filter生命周期及其與生命周期相關的方法,Filter接口有三個方法,並且這個三個都是與Filter的生命相關的方法:

  • init(Filterconfig):代表filter對象初始化方法,filter對象創建時執行。
  • doFilter(ServletRequest,ServletResponse,FilterCha):代表filter執行過濾的核心方法,如果某資源在已經被配置到這個filter進行過濾的話,那么每次訪問這個資源都會執行doFilter方法。
  • destory():代表是filter銷毀方法,當filter對象銷毀時執行該方法。

Filter對象的生命周期

  • Filter何時創建:服務器啟動時就創建該filter對象
  • Filter何時銷毀:服務器關閉時filter銷毀

init(FilterConfig):其中參數config代表該Filter對象的配置信息的對象,內部封裝是該filter的配置信息。

destory()方法:filter對象銷毀時執行。

doFilter方法:doFilter(ServletRequest,ServletResponse,FilterChain),其中的參數ServletRequest/ServletResponse是每次在執行doFilter方法時web容器負責創建一個request和一個response對象作為doFilter的參數傳遞進來。該request與response就是在訪問目標資源的service方法時的request和response。FilterChain是過濾器鏈對象,通過該對象的doFilter方法可以放行該請求。chain對象根據配置的filter-mapping順序依次執行filter。

Filter的配置

<filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.yyb.filter.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

url-pattern配置

  • 完全匹配 

    /Servlet1,只有訪問Servlet1時才執行

  • 目錄匹配 /aaa/bbb/* 

/user/*:訪問前台的資源進入此過濾器

/admin/*:訪問后台的資源時執行此過濾器

  • 擴展名匹配 *.abc *.jsp

注意:url-pattern可以使用servlet-name替代,也可以混用。

 <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <!--<url-pattern>/*</url-pattern>-->
        <servlet-name>FilterTest</servlet-name>
        <servlet-name>FilterTest1</servlet-name>
    </filter-mapping>

dispatcher:訪問的方式

  • REQUEST:默認值,代表直接訪問某個資源時執行filter
  • FORWARD:轉發時才執行filter
  • INCLUDE: 包含資源時執行filter
  • ERROR:發生錯誤時 進行跳轉時執行filter

例子:web.xml

  <filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.yyb.filter.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

在FilterTest中,添加轉發代碼  request.getRequestDispatcher("/index.jsp").forward(request, response); ,此時當訪問FilterTest時,過濾器只會執行依次,而不是兩次。轉發時不會執行過濾器。

但是重定向會執行兩次,在FilterTest中,添加轉發代碼  response.sendRedirect(request.getContextPath()+"/index.jsp"); ,可以看到執行結果。

Filter的作用

  • 公共代碼的提取
  • 可以對request和response中的方法進行增強(裝飾者模式/動態代理)
  • 進行權限控制

使用filter解決參數中文亂碼

package com.ithiema.web.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

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;
import javax.servlet.http.HttpServletRequestWrapper;

public class EncodingFilter implements Filter{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        //request.setCharacterEncoding("UTF-8");
        
        //在傳遞request之前對request的getParameter方法進行增強
        /*
         * 裝飾者模式(包裝)
         * 
         * 1、增強類與被增強的類要實現統一接口
         * 2、在增強類中傳入被增強的類
         * 3、需要增強的方法重寫 不需要增強的方法調用被增強對象的
         * 
         */
        
        //被增強的對象
        HttpServletRequest req = (HttpServletRequest) request;
        //增強對象
        EnhanceRequest enhanceRequest = new EnhanceRequest(req);
        chain.doFilter(enhanceRequest, response);
    }

    @Override
    public void destroy() {
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

}

class EnhanceRequest extends HttpServletRequestWrapper{
    private HttpServletRequest request;
    public EnhanceRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    
    //對getParaameter增強
    @Override
    public String getParameter(String name) {
        String parameter = request.getParameter(name);//亂碼
        try {
            parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return parameter;
    }
}

注解

注解就是符合一定格式的語法 @xxxx,是jvm看的,給機器看的。注解在目前而言最主流的應用是代替配置文件。

關於配置文件與注解開發的優缺點:

  • 優點:開發效率高成本低
  • 缺點:耦合性大並且不利於后期維護

jdk5提供的注解

@Override:告知編譯器此方法是覆蓋父類的

@Deprecated:標注過時

@SuppressWarnings:壓制警告

不同的注解只能在不同的位置使用(方法上、字段上、類上)

自定義注解

怎樣去編寫一個自定義的注解,使用@interface關鍵字。

public @interface MyAnno {
    //注解的屬性
    String name();
    int age() default 28;
}

怎樣去使用注解

 @MyAnno(name="",age=20)
    public  void  show(){
    }

    @MyAnno(name="")
    public  void  show1(){
    }

注意:如果屬性的名字是value,並且注解的屬性值只有一個,那么在使用注解時可以省略value。注解屬性類型只能是以下幾種:基本類型;String;枚舉類型;注解類型;Class類型 ;以上類型的一維數組類型。

public @interface MyAnno2 {
    //String value();
   String[]value(); }
    //@MyAnno2("aa")
    //public  void  show2(){
    //}
    @MyAnno3({"name","age"})
    public  void  show3(){

    }

怎樣去解析注解-----使用反射知識

介入一個概念,元注解。代表修飾注解的注解,作用是限制定義的注解的特性。
@Retention

  • SOURCE: 注解在源碼級別可見,在字節碼文件中就沒有了。
  • CLASS:注解在字節碼文件級別可見
  • RUNTIME:注解在整個運行階段都可見

@Target 代表注解修飾的范圍:類上使用,方法上使用,字段上使用

  • FIELD:字段上可用此注解
  • METHOD:方法上可以用此注解
  • TYPE:類/接口上可以使用此注解
import java.lang.reflect.Method;

/**
 * Created by Administrator on 2017/7/28.
 */
public class MyAnnoParse {
    public static void main(String[]args) throws NoSuchMethodException {

        //解析show方法上面的@MyAnno
        //直接的目的是 獲得show方法上的@MyAnno中的參數

        //獲得show方法的字節碼對象
        Class clazz = MyAnnoTest.class;
        Method method = clazz.getMethod("show", String.class);
        //獲得show方法上的@MyAnno
        MyAnno annotation = method.getAnnotation(MyAnno.class);
        //獲得@MyAnno上的屬性值
        System.out.println(annotation.name());//zhangsan
        System.out.println(annotation.age());//28

        //根據業務需求寫邏輯代碼
    }
}

注意:要想解析使用了注解的類 ,那么該注解的Retention必須設置成Runtime,注解解析的實質是從注解中解析出屬性值

字節碼對象存在於獲得注解相關的方法

isAnnotationPresent(Class<? extends Annotation> annotationClass) : 判斷該字節碼對象身上是否使用該注解了
getAnnotation(Class<A> annotationClass) :獲得該字節碼對象身上的注解對象

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM