SpringBoot中Interceptor和Filter如何避免在多次处理中重复获取Request参数?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1160个文字,预计阅读时间需要5分钟。
拦截器(Interceptor)和过滤器(Filter)通过上方这张图我们可以了解到,在Filter和Interceptor之间有一层Servlet。Servlet是提交request的地方。因此,我们想要重写HttpServletRequest方法,只能在Servlet之前进行。也就是说,只能在filter中进行。
Interceptor、Filter
通过上方这个图我们可以知道,在 Filter 和 Inteceptor 中间有一层Servlet。而Servlet就是提交request的地方。所以我们要重写HttpServletRequest方法只能在Servlet之前。也就是filter 中。
区别:
-
1.servlet请求,顺序:Filter ——> interceptor。
-
2.Filter的作用是对所有进行过滤,包括接口或者静态资源,interceptor 仅拦截 请求。
-
3.Filter对请求或者资源进行过滤,筛选合适的请求或者资源。interceptor,仅对不符合的请求拦截。
-
4.Filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于 java本身的反射机制,这是两者最本质的区别。
-
5.Filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而interceptor与servlet容器无关。
-
filter:目的就是可以以流的方式多次获取请求参数。
-
Interceptor:对回调接口进行统一的验证签名。
回调接口都需要验证签名,而且签名规则一样,所以想拿到拦截器处理。
如果签名或者ip地址不符合条件,直接就返回了。而具体的接口只要专注业务处理,不需要验证签名了。
下面贴一下在springboot中的使用:
一、Filter
如果请求是GET方法,可以直接通过getParameter(String param)方法读取指定参数,可读取多次;
而POST方法的参数是存储在输入流中,只能读一次,不能多次读取。
有时需要在filter里打印请求参数,因而在filter里读取post请求里的输入流后,会导致具体的controller里拿不到请求参数。
解决方法:
-
1、采用ThreadLocal,在filter里把读取到的post参数存入ThreadLocal里,而controller就可以再从ThreadLocal里把请求参数读取出来。
-
2、使用servlet提供的HttpServletRequestWrapper类,重写相关ServletRequest方法,实现多次读取的能力。
1.1 ThreadLocal方法
public class ThreadCache { // ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数 private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); public static String getPostRequestParams{ return threadLocal.get(); } public static void setPostRequestParams(String postRequestParams){ threadLocal.set(postRequestParams); } public static void removePostRequestParams(){ threadLocal.remove(); } }一个简单的filter:
import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.localhost:8111/test/test", param); System.out.println(str); } }DESTools.java
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import org.apache.commons.codec.binary.Base64; public class DESTools { public static DESTools instance; public static DESTools getInstace() { if(instance == null) { instance = new DESTools(); } return instance; } Key key; /** * ** */ private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7, (byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd, (byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28, 0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 }; public DESTools() { setKey(BOSS_SECRET_KEY); } /** * 根据参数生成KEY */ public void setKey(byte[] strKey) { try { DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY); SecretKeyFactory keyFactory; keyFactory = SecretKeyFactory.getInstance("DES"); this.key = keyFactory.generateSecret(dks); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } } /** * 加密String明文输入,String密文输出 */ public String getEncString(String strMing) { byte[] byteMi = null; byte[] byteMing = null; String strMi = ""; Base64 base64en = new Base64(); try { byteMing = strMing.getBytes("UTF8"); byteMi = this.getEncCode(byteMing); strMi = base64en.encodeAsString(byteMi); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { base64en = null; byteMing = null; byteMi = null; } return strMi; } /** * 解密 以String密文输入,String明文输出 * @param strMi * @return */ public String getDesString(String strMi) { Base64 base64De = new Base64(); byte[] byteMing = null; byte[] byteMi = null; String strMing = ""; try { byteMi = base64De.decode(strMi); byteMing = this.getDesCode(byteMi); strMing = new String(byteMing, "UTF8"); } catch (Exception e) { throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e); } finally { base64De = null; byteMing = null; byteMi = null; } return strMing; } /** * 加密以byte[]明文输入,byte[]密文输出 * @param byteS * @return */ private byte[] getEncCode(byte[] byteS) { byte[] byteFina = null; Cipher cipher; try { cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, key); byteFina = cipher.doFinal(byteS); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { cipher = null; } return byteFina; } /** * 解密以byte[]密文输入,以byte[]明文输出 * @param byteD * @return */ private byte[] getDesCode(byte[] byteD) { Cipher cipher; byte[] byteFina = null; try { cipher = Cipher.getInstance("DES"); cipher.init(Cipher.DECRYPT_MODE, key); byteFina = cipher.doFinal(byteD); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { cipher = null; } return byteFina; } }ConfigProperties.java
获取yml文件的值
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Configuration @Component public class ConfigProperties { @Value("${test.test.privateKey}") private String privateKey; @Value("${test.test.requestUrl}") private String requestUrl; public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } }yml文件如图
springboot 2.x 过滤器和拦截器 放行某个路径(静态资源)
import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.www.freesion.com/article/1790501924/blog.csdn.net/liuerchong/article/details/110467532
www.cnblogs.com/endstart/p/6196807.html
本文共计1160个文字,预计阅读时间需要5分钟。
拦截器(Interceptor)和过滤器(Filter)通过上方这张图我们可以了解到,在Filter和Interceptor之间有一层Servlet。Servlet是提交request的地方。因此,我们想要重写HttpServletRequest方法,只能在Servlet之前进行。也就是说,只能在filter中进行。
Interceptor、Filter
通过上方这个图我们可以知道,在 Filter 和 Inteceptor 中间有一层Servlet。而Servlet就是提交request的地方。所以我们要重写HttpServletRequest方法只能在Servlet之前。也就是filter 中。
区别:
-
1.servlet请求,顺序:Filter ——> interceptor。
-
2.Filter的作用是对所有进行过滤,包括接口或者静态资源,interceptor 仅拦截 请求。
-
3.Filter对请求或者资源进行过滤,筛选合适的请求或者资源。interceptor,仅对不符合的请求拦截。
-
4.Filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于 java本身的反射机制,这是两者最本质的区别。
-
5.Filter是依赖于servlet容器的,即只能在servlet容器中执行,很显然没有servlet容器就无法来回调doFilter方法。而interceptor与servlet容器无关。
-
filter:目的就是可以以流的方式多次获取请求参数。
-
Interceptor:对回调接口进行统一的验证签名。
回调接口都需要验证签名,而且签名规则一样,所以想拿到拦截器处理。
如果签名或者ip地址不符合条件,直接就返回了。而具体的接口只要专注业务处理,不需要验证签名了。
下面贴一下在springboot中的使用:
一、Filter
如果请求是GET方法,可以直接通过getParameter(String param)方法读取指定参数,可读取多次;
而POST方法的参数是存储在输入流中,只能读一次,不能多次读取。
有时需要在filter里打印请求参数,因而在filter里读取post请求里的输入流后,会导致具体的controller里拿不到请求参数。
解决方法:
-
1、采用ThreadLocal,在filter里把读取到的post参数存入ThreadLocal里,而controller就可以再从ThreadLocal里把请求参数读取出来。
-
2、使用servlet提供的HttpServletRequestWrapper类,重写相关ServletRequest方法,实现多次读取的能力。
1.1 ThreadLocal方法
public class ThreadCache { // ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数 private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); public static String getPostRequestParams{ return threadLocal.get(); } public static void setPostRequestParams(String postRequestParams){ threadLocal.set(postRequestParams); } public static void removePostRequestParams(){ threadLocal.remove(); } }一个简单的filter:
import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.localhost:8111/test/test", param); System.out.println(str); } }DESTools.java
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import org.apache.commons.codec.binary.Base64; public class DESTools { public static DESTools instance; public static DESTools getInstace() { if(instance == null) { instance = new DESTools(); } return instance; } Key key; /** * ** */ private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7, (byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd, (byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28, 0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 }; public DESTools() { setKey(BOSS_SECRET_KEY); } /** * 根据参数生成KEY */ public void setKey(byte[] strKey) { try { DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY); SecretKeyFactory keyFactory; keyFactory = SecretKeyFactory.getInstance("DES"); this.key = keyFactory.generateSecret(dks); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } } /** * 加密String明文输入,String密文输出 */ public String getEncString(String strMing) { byte[] byteMi = null; byte[] byteMing = null; String strMi = ""; Base64 base64en = new Base64(); try { byteMing = strMing.getBytes("UTF8"); byteMi = this.getEncCode(byteMing); strMi = base64en.encodeAsString(byteMi); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { base64en = null; byteMing = null; byteMi = null; } return strMi; } /** * 解密 以String密文输入,String明文输出 * @param strMi * @return */ public String getDesString(String strMi) { Base64 base64De = new Base64(); byte[] byteMing = null; byte[] byteMi = null; String strMing = ""; try { byteMi = base64De.decode(strMi); byteMing = this.getDesCode(byteMi); strMing = new String(byteMing, "UTF8"); } catch (Exception e) { throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e); } finally { base64De = null; byteMing = null; byteMi = null; } return strMing; } /** * 加密以byte[]明文输入,byte[]密文输出 * @param byteS * @return */ private byte[] getEncCode(byte[] byteS) { byte[] byteFina = null; Cipher cipher; try { cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, key); byteFina = cipher.doFinal(byteS); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { cipher = null; } return byteFina; } /** * 解密以byte[]密文输入,以byte[]明文输出 * @param byteD * @return */ private byte[] getDesCode(byte[] byteD) { Cipher cipher; byte[] byteFina = null; try { cipher = Cipher.getInstance("DES"); cipher.init(Cipher.DECRYPT_MODE, key); byteFina = cipher.doFinal(byteD); } catch (Exception e) { throw new RuntimeException( "Error initializing DESTOOLS class. Cause: " + e); } finally { cipher = null; } return byteFina; } }ConfigProperties.java
获取yml文件的值
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Configuration @Component public class ConfigProperties { @Value("${test.test.privateKey}") private String privateKey; @Value("${test.test.requestUrl}") private String requestUrl; public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } }yml文件如图
springboot 2.x 过滤器和拦截器 放行某个路径(静态资源)
import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.www.freesion.com/article/1790501924/blog.csdn.net/liuerchong/article/details/110467532
www.cnblogs.com/endstart/p/6196807.html

