1. 程式人生 > >通過filter過濾器對請求引數進行處理

通過filter過濾器對請求引數進行處理

遇見的問題:前臺把引數通過報文或者使用表單、ajax提交到後臺,如果我們的請求引數是加密的,那麼我們在controller裡面的每一個方法裡都需要進行解密處理。如果方法太多,那就太麻煩了。
設計方案:在一個Filter中將 HttpServletRequest 裡的所有引數都取出來分別進行過濾然後再放回到該HttpServletRequest 中行不行呢?通過測試後發現是不行的,因為HttpServletRequest 只提供了getParameter ,而沒有提供setParameter;所以,我們只能自己寫一個HttpServletRequest 方法繼承HttpServletRequestWrapper,然後覆蓋裡面的方法,並且增加我們自己的setParameters方法,這樣我們就可以為所欲為了,最後再在filter中呼叫該類的方法對引數進行處理(獲取、修改、儲存等等)。

解決方案:在請求引數到達controller之前,在filter裡面進行解密;這樣,通過簡單的過濾器處理,把需要處理的請求都在過濾器裡進行解密操作,這樣就等於實現了自動化處理。
這裡我們針對兩種不同的請求方式進行講解:1.普通的表單、ajax請求;2.json格式的報文請求。(三步搞定)

1.普通的表單、ajax請求;

第一步:新建一個類

這個類繼承自HttpServletRequestWrapper

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletRequestWrapper; /** * 重寫 HttpServletRequestWrapper * 處理表單、ajax請求 * @author zhaoheng * */ public class MyHttpServletRequestWrapper1 extends HttpServletRequestWrapper{ // 用於儲存請求引數 private Map<String , String[]> params = new HashMap<String, String[]>(); // 構造方法
public MyHttpServletRequestWrapper1(HttpServletRequest request) throws IOException { super(request); // 把請求引數新增到我們自己的map當中 this.params.putAll(request.getParameterMap()); } /** * 新增引數到map中 * @param extraParams */ public void (Map<String, Object> extraParams) { for (Map.Entry<String, Object> entry : extraParams.entrySet()) { setParameter(entry.getKey(), entry.getValue()); } } /** * 新增引數到map中 * @param name * @param value */ public void setParameter(String name, Object value) { if (value != null) { System.out.println(value); if (value instanceof String[]) { params.put(name, (String[]) value); } else if (value instanceof String) { params.put(name, new String[]{(String) value}); } else { params.put(name, new String[]{String.valueOf(value)}); } } } /** * 重寫getParameter,代表引數從當前類中的map獲取 * @param name * @return */ @Override public String getParameter(String name) { String[]values = params.get(name); if(values == null || values.length == 0) { return null; } return values[0]; } /** * 重寫getParameterValues方法,從當前類的 map中取值 * @param name * @return */ @Override public String[] getParameterValues(String name) { return params.get(name); } }

通過建立這個類我們就能完成向request物件新增我們處理之後的引數了。

第二步:通過實現filter介面建一個過濾器

package com.zhh.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

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 org.apache.log4j.Logger;

import com.zhh.util.request.MyHttpServletRequestWrapper1;

/**
 * 引數處理驗過濾器(針對ajax、表單等請求) 1.獲取請求引數; 2.對獲取到的請求引數進行處理(解密、字串替、請求引數分類擷取等等); 3.把處理後的引數放回到請求列表裡面
 * 
 * @author zhaoheng
 *
 */
public class ValidatorFilter1 implements Filter {

    private static final Logger log = Logger.getLogger(ValidatorFilter1.class);

    /**
     * 需要過濾的地址
     */
    private static List<String> urlList = Arrays.asList("/pastOrder/filterCsF");

    /**
     * 是否不需要過濾
     * 
     * @param requestUrl
     *            請求的url
     * @return
     */
    public boolean isPast(String requestUrl) {
        for (String url : urlList) {
            if (requestUrl.equals(url)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void destroy() {
    }

    @SuppressWarnings("unchecked")
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        log.info("過濾器2執行開始");
        String url = ((HttpServletRequest) request).getRequestURI().substring(((HttpServletRequest)request).getContextPath().length());

        //通過地址對特定的請求進行處理,如果不需要可以不用,如果不用,就會對使用的請求進行過濾
        if (isPast(url)) {
            MyHttpServletRequestWrapper1 requestWrapper1 = new MyHttpServletRequestWrapper1(
                    (HttpServletRequest) request);
            // 1.獲取需要處理的引數
            String email = requestWrapper1.getParameter("email");
            // 2.把處理後的引數放回去(這裡是大小轉小寫處理)
            requestWrapper1.setParameter("email", email.toLowerCase());
            // 3.放行,把我們的requestWrapper1放到方法當中
            chain.doFilter(requestWrapper1, response);
        } else {
            chain.doFilter(request, response);
        }
    }

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

第三步:在web.xml檔案裡面進行簡單的配置

把我們的過濾器在該檔案中註冊

 <!--  配置過濾器  -->
      <filter>  
        <filter-name>ValidatorFilter1</filter-name>  
        <!--  我們寫的過濾的地址   -->
        <filter-class>com.zhh.filter.ValidatorFilter1</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>ValidatorFilter1</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

controller 接收引數程式碼:

    /**
     * 過濾方法測試
     */
    @RequestMapping("/filterCsF2")
    public void filterCs22(String email,String userName){
        System.out.println("處理後的引數:"+userName+"  "+email);
    }

請求示例程式碼:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>請求demo</title>
</head>

<body>

 <form id="userForm" action="#" method="post">
        username:<input type="text" id ="userName" name="userName" value="21088888"/><br/><br>
        email:<input type="text" id ="email" name="email" value="[email protected]"/><br/><br/>
         age:<input type="text" id ="age" name="age" value="18"/><br/><br/>

        <input type="reset" value="重置"/>&nbsp;&nbsp;
        <input type="button" id ="sub" value="提交">
    </form>

</body>
    <script src="jquery.min.js"></script>
<script type="text/javascript">

            $("#sub").click(
    function(){
        var userName = $("#userName").val();   
          var email = $("#email").val(); 
            var age = $("#age").val(); 
         $.ajax({
            type : "POST",
            url:'http://127.0.0.1:8080/merchant_wap/pastOrder/filterCsF2',
            dataType : "json",
            data : {
                    "userName":userName,
                    "age":age,
                    "email":email
            },
            success : function(data) {
            alert("33");
            },
            error : function(data) {
            alert("cccc"+data.email);
            }
        });
        }
            );
</script>
</html>

處理結果:

處理後的引數:21088888  zhaoheng@163.com

從結果可以看出,我們成功的通過過濾器對請求的email進行大寫轉小寫處理

2.json格式的報文請求;

第一步:新建一個類

這個類繼承自HttpServletRequestWrapper

package com.zhh.util.request;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import jodd.io.StreamUtil;

/**
 * 重寫 HttpServletRequestWrapper
 * 處理json報文請求
 * @author zhaoheng
 *
 */
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{  

     private  byte[] body; //用於儲存讀取body中資料   

     public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {    
         super(request);
         //讀取請求的資料儲存到本類當中
         body = StreamUtil.readBytes(request.getReader(), "UTF-8");    
     }
     //覆蓋(重寫)父類的方法
     @Override    
     public BufferedReader getReader() throws IOException {    
         return new BufferedReader(new InputStreamReader(getInputStream()));    
     }    
     //覆蓋(重寫)父類的方法
     @Override    
     public ServletInputStream getInputStream() throws IOException {    
         final ByteArrayInputStream bais = new ByteArrayInputStream(body);    
         return new ServletInputStream() {    
             @Override    
             public int read() throws IOException {    
                 return bais.read();    
             } 
         };    
     }

     /**
      * 獲取body中的資料
      * @return
      */
    public byte[] getBody() {
        return body;
    }
    /**
     * 把處理後的引數放到body裡面
     * @param body
     */
    public void setBody(byte[] body) {
        this.body = body;
    }
}  

通過建立這個類我們就能完成向request物件新增我們處理之後的引數了。

第二步:通過實現filter介面建一個過濾器

package com.zhh.filter;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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 org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhh.util.request.MyHttpServletRequestWrapper;

/**
 * 引數校驗過濾器(針對json報文請求) 1.獲取請求引數; 2.對獲取到的請求引數進行處理(解密、字串替、請求引數分類擷取等等); 3.把處理後的引數放回到請求列表裡面
 * 
 * @author zhaoheng
 *
 */
public class ValidatorFilter implements Filter {

    private static final Logger log = Logger.getLogger(ValidatorFilter.class);

    /**
     * 需要過濾的地址
     */
    private static List<String> urlList = Arrays.asList("/pastOrder/filterCs");
    /**
     * 是否需要過濾
     * 
     * @param requestUrl
     *            請求的url
     * @return
     */
    public boolean isPast(String requestUrl) {
        for (String url : urlList) {
            if (requestUrl.equals(url)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void destroy() {
        log.info("過濾器執行結束");
    }

    @SuppressWarnings("unchecked")
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        log.info("過濾器1執行開始");
        String url0 = ((HttpServletRequest) request).getRequestURI();
        String url1 = ((HttpServletRequest) request).getContextPath();
        System.out.println("完整地址:"+url0);
        System.out.println("返回當前頁面所在的應用的名字:"+url1);
        System.out.println("返回當前頁面所在的應用的名字長度:"+url1.length());

        // 獲取請求地址
        String url = ((HttpServletRequest) request).getRequestURI().substring(((HttpServletRequest)request).getContextPath().length());
        System.out.println("擷取後的地址:"+url);

        if (isPast(url)) {
            //處理json報文請求
            MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(
                    (HttpServletRequest) request);
            // 讀取請求內容
            BufferedReader br;
            br = requestWrapper.getReader();
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            // 將json字串轉換為json物件
            JSONObject jsonObject = JSONObject.parseObject(sb.toString());

            Map<String, Object> map = new HashMap<String, Object>();
            // 把json物件轉換為Map集合
            map = JSON.toJavaObject(jsonObject, Map.class);
            for (Entry<String, Object> entry : map.entrySet()) {
                // 把郵箱地址轉換為小寫
                if (entry.getKey().equals("email")) {
                    map.put(entry.getKey(), entry.getValue().toString()
                            .toLowerCase());
                }
            }

            // 把引數轉換之後放到我們的body裡面
            String json = JSON.toJSONString(map);
            requestWrapper.setBody(json.getBytes("UTF-8"));
            // 放行 
            chain.doFilter(requestWrapper, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}

第三步:在web.xml檔案裡面進行簡單的配置

把我們的過濾器在該檔案中註冊

 <!--  配置過濾器  -->
      <filter>  
        <filter-name>ValidatorFilter</filter-name> 
         <!--  我們寫的過濾的地址   --> 
        <filter-class>com.zhh.filter.ValidatorFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>ValidatorFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

controller 接收引數程式碼:

/**
     * 過濾方法測試
     * @RequestBody User user 該註解用於接收json請求的引數
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/filterCs")
    public User filterCs(@RequestBody User user){
        System.out.println(user.toString());
        return user;
    }

請求報文示例:
我這裡使用的是postman工具進行json引數請求

{
    "email": "[email protected]",
    "userName":"20181100",
    "age":"18"
}

返回結果:

{
    "email": "[email protected]",
    "userName":"20181100",
    "age":"18"
}

通過該過濾器,把email轉換從小寫成功。
通過以上操作,我們就成功的建立了一個過濾器。

相關推薦

通過filter過濾器請求引數進行處理

遇見的問題:前臺把引數通過報文或者使用表單、ajax提交到後臺,如果我們的請求引數是加密的,那麼我們在controller裡面的每一個方法裡都需要進行解密處理。如果方法太多,那就太麻煩了。 設計方案:在一個Filter中將 HttpServletRequest

spring mvc自定義過濾器filter實現請求引數編解碼的程式碼

百度,google了半天即使再萬能的stackoverflow上也沒有得到解答,今天偶然間發現springmvc註解@RequestParam不是通過HttpServletRequest.java的getParameter(String name)方法得到的引數值,而

通過filter過濾器進行中文處理

oid param 過濾器 局限 很多 public ppi 通過 value 一、使用servlet處理的局限性 可以通過: request.setCharacterEncoding("UTF-8"); 正確獲取UTF-8編碼的中文,但是如果有很多servlet都需要

filter 用於請求和響應進行處理操作

filter 用於對請求和響應進行預處理操作 一個 filter 可以針對多個請求做過濾,url mapping 配置為 /* 自定義 filter 需要實現 Filter 介面,預處理工作在 doFilter 中完成 1. 強制轉換 re

javaEE Springmvc,Converter型別轉換器,請求引數自動進行型別轉換/處理(轉成Date日期型別)

src/springmvc.xml(Springmvc核心配置檔案,配置型別轉換器,為介面卡指定轉換器): <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.spring

springmvc 通過異常增強返回給客戶端統一格式 springmvc請求引數異常處理

本文轉載於:http://www.cnblogs.com/nosqlcoco/p/5562107.html  在springmvc開發中,我們經常遇到這樣的問題;邏輯正常執行時返回客戶端指定格式的資料,比如json,但是遇NullPointerException空指標

spring使用Filter過濾器Response返回值進行修改

返回值輸出代理類:這個類主要是為了吧Response裡面的返回值獲取到,因為直接Response沒有提供直接拿到返回值的方法。所以要通過代理來取得返回值 package com.channel.filter; import java.io.ByteArrayOutp

使用filter配合裝飾器模式實現請求引數加密

1、目標 完成對request請求引數的加密 2、設計的知識點 a、filter、servlet、裝飾器模式 3、遇到問題 在寫這個程式的時候遇到一點一點小問題;什麼問題呢? a、就是一個關於HttpServletRequestWrapper和servletRequestW

SpringMVC請求處理方法引數處理

前言 講完了DispatchServlet(也可以說是SpringMVC框架)的初始化之後,我們再接著看DispatchServlet處理請求的原理,也可以說是SpringMVC處理請求的原理。今天就先來看看SpringMVC對方法引數的處理。 我們

java使用Filter過濾器Response返回值進行修改

author tel 過去 ack generate rip read ner extends 練習時只做了對request 的處理,這裏記錄一下,filter 對 response的處理。 原文地址:java使用Filter過濾器對Response返回值進行修改 有時

使用過濾器權限進行過濾,就是訪問的url地址進行判斷

nis res init quest tool resp != oos list /* * To change this license header, choose License Headers in Project Properties. * To change

awk '!arr[$0]++'文件進行處理

linuxawk ‘!arr[$0]++‘後跟文件,可以過濾掉重復的行。如下面的文件經過處理。 [[email protected] ~]# cat fstab # # /etc/fstab # /etc/fstab # /etc/fstab # /etc/fstab # /etc/fstab

[轉載]Python-Pcap檔案進行處理,獲取指定TCP流 https://www.cnblogs.com/sunpudding/p/9538889.html

https://www.cnblogs.com/sunpudding/p/9538889.html   Python-對Pcap檔案進行處理,獲取指定TCP流         通過對TCP/IP協議的學習,本人寫了一個可以實現對PCAP檔

sklearn中自定義轉換器以及使用流水線資料據進行處理

儘管 Scikit-Learn 提供了許多有用的轉換器,你還是需要自己動手寫轉換器執行任務,比如自定義的清理操作,或屬性組合。你需要讓自制的轉換器與 Scikit-Learn 元件(比如流水線)無縫銜接工作,因為 Scikit-Learn 是依賴鴨子型別的(而不是繼承),你所

Java8新特性 利用流和Lambda表示式List集合進行處理

Lambda表示式處理List 最近在做專案的過程中經常會接觸到 lambda 表示式,隨後發現它基本上可以替代所有 for 迴圈,包括增強for迴圈。也就是我認為,絕大部分的for迴圈都可以用 lambda 表示式改寫。 lambda表示式有它自己的優點:(1)簡潔,(2)易平行計算。尤其適用於遍歷結果

陣列filter方法陣列元素進行過濾

Array.prototype.filter對陣列中元素進行過濾/** * @method reduce * @param {number}   item   當前迭代的陣列元素 * @param {number}   index  當前迭代的陣列元素下下標 * @param {array}    array

餐飲資料進行處理基於Python

對餐飲資料進行處理基於Python 餐飲網頁資料來源 #coding:utf-8 # 匯入必要的模組 import pandas as pd import numpy as np import re # 讀取網頁資料來源 df = pd.read_csv(url,deli

java 通過流讀取request請求引數

第一個是TestIOSServlet的內容,通過網路程式設計的方式 public void doPost(HttpServletRequest request, HttpServletResponse response)     throws ServletExcepti

使用PythonEXCEL表格進行處理

前言 用到的模組 import xlrd #用來讀取excel檔案,不能修改資料 import xlwt #建立Excel檔案並對其進行操作,但不能對已有的Excel檔案進行修改 impor

Java方法傳遞引數處理

若引數是物件,則是按引用傳遞,此時,方法內改變物件引數的值將會直接影響到被傳遞進來的引數物件原來的值,類似C++按引用或指標傳遞。這樣的引數包括陣列及陣列中的物件。 若引數為基本資料型別,則是按值