java spring 拦截器和过滤器+过滤器处理数据
- 介绍
- Spring拦截器(Interceptor)
- 导入依赖
- 完整代码
- Java过滤器(Filter)
- 完整代码分为 2 个文件,请看下面
- BodyReaderHttpServletRequestWrapper.java
- MyFilter.java
- Spring过滤器和拦截器的区别
介绍
在Spring框架中,拦截器和过滤器都是用于处理HTTP请求的生命周期中的特定时刻。它们都可以用来拦截请求和响应,并在它们到达目标处理器之前或之后进行一些操作。在本教程中,我们将探讨拦截器和过滤器的区别以及如何使用它们来处理数据。
Spring拦截器(Interceptor)
Spring拦截器是Spring框架特有的,用于在Spring MVC请求处理的前后添加自定义逻辑。拦截器通常用于以下场景:
- 认证和授权
- 日志记录
- 事务管理
- 请求和响应的修改
拦截器的工作流程包括: preHandle
:在请求处理之前调用,可以用来添加额外的验证或修改请求。postHandle
:在请求处理之后,但在视图渲染之前调用,可以用来添加额外的模型数据或修改视图。afterCompletion
:在整个请求结束后调用,可以用来进行资源清理。
拦截器通过Spring的配置文件或注解进行配置。
导入依赖
import org.springframework.stereotype.Component;
导入 Spring的@Component
注解,意味着这个类会被Spring的IoC容器自动识别为一个组件,并将其注册到容器中。拦截器实例会随着容器的启动而被创建。
import org.springframework.web.servlet.HandlerInterceptor;
导入了HandlerInterceptor
接口,这个接口定义了拦截器的三种方法:preHandle()
、postHandle()
和afterCompletion()
,该类将实现这些方法。
import org.springframework.web.servlet.ModelAndView;
导入了ModelAndView
类,它通常在拦截器的postHandle()
方法中被使用,用来访问模型数据和视图信息。
完整代码
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Component
public class Interceptor implements HandlerInterceptor {
/**
* 拦截器
*
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
try {
String requestUrl = httpServletRequest.getRequestURI();
Map<String, String[]> originRequestMap = httpServletRequest.getParameterMap();
System.out.println("拦截器执行,参考 class ActionHandle");
} catch (Exception e) {
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
Java过滤器(Filter)
Java过滤器是Java EE规范的一部分,用于在Servlet容器中处理请求和响应。过滤器通常用于以下场景:
- 认证和授权
- 日志记录
- 事务管理
- 数据压缩
- 缓冲区管理
过滤器的工作流程包括: doFilter
:过滤器的核心方法,对请求和响应进行处理。init
:在过滤器首次使用前调用,可以用来初始化过滤器。destroy
:在过滤器不再使用时调用,可以用来释放资源。
过滤器通过web.xml
配置文件进行配置,或者通过Java配置注解进行配置。
完整代码分为 2 个文件,请看下面
BodyReaderHttpServletRequestWrapper.java
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.net.URLDecoder;
import java.util.*;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> paramsMap;
@Override
public Map getParameterMap() {
return paramsMap;
}
@Override
public String getParameter(String name) {
String[] values = paramsMap.get(name);
if (values == null || values.length == 0) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
return paramsMap.get(name);
}
@Override
public Enumeration getParameterNames() {
return Collections.enumeration(paramsMap.keySet());
}
private String getRequestBody(InputStream stream) {
String line = "";
StringBuilder body = new StringBuilder();
int counter = 0;
// 读取POST提交的数据内容
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
try {
while ((line = reader.readLine()) != null) {
if (counter > 0) {
body.append("rn");
}
body.append(line);
counter++;
}
} catch (IOException e) {
e.printStackTrace();
}
return body.toString();
}
private HashMap<String, String[]> getParamMapFromPost(HttpServletRequest request) {
String body = "";
try {
body = getRequestBody(request.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
HashMap<String, String[]> result = new HashMap<String, String[]>();
if (null == body || 0 == body.length()) {
return result;
}
return parseQueryString(body);
}
// 自定义解码函数
private String decodeValue(String value) {
if (value.contains("%u")) {
return Encodes.urlDecode(value);
} else {
try {
return URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
// 非UTF-8编码
return "";
}
}
}
public HashMap<String, String[]> parseQueryString(String s) {
String valArray[] = null;
if (s == null) {
throw new IllegalArgumentException();
}
HashMap<String, String[]> ht = new HashMap<String, String[]>();
StringTokenizer st = new StringTokenizer(s, "&");
while (st.hasMoreTokens()) {
String pair = (String) st.nextToken();
int pos = pair.indexOf('=');
if (pos == -1) {
continue;
}
String key = pair.substring(0, pos);
String val = pair.substring(pos + 1, pair.length());
if (ht.containsKey(key)) {
String oldVals[] = (String[]) ht.get(key);
valArray = new String[oldVals.length + 1];
for (int i = 0; i < oldVals.length; i++) {
valArray[i] = oldVals[i];
}
valArray[oldVals.length] = decodeValue(val);
} else {
valArray = new String[1];
valArray[0] = decodeValue(val);
}
ht.put(key, valArray);
}
return ht;
}
private Map<String, String[]> getParamMapFromGet(HttpServletRequest request) {
return parseQueryString(request.getQueryString());
}
public String getBody() {
return new String(body);
}
// 报文
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = readBytes(request.getInputStream());
//
/*if ("POST".equals(request.getMethod().toUpperCase())) {
paramsMap = getParamMapFromPost(this);
} else {
paramsMap = getParamMapFromGet(this);
}*/
}
@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();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener arg0) {
}
};
}
private static byte[] readBytes(InputStream in) throws IOException {
BufferedInputStream bufin = new BufferedInputStream(in);
int buffSize = 1024;
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
byte[] temp = new byte[buffSize];
int size = 0;
while ((size = bufin.read(temp)) != -1) {
out.write(temp, 0, size);
}
bufin.close();
byte[] content = out.toByteArray();
return content;
}
}
MyFilter.java
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import 这里填路径.BodyReaderHttpServletRequestWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
@Component
public class MyFilter implements Filter {
@Autowired
public RedisCache redisCache;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 获取配置信息
*/
public String getSysConfig(String configKey) {
return redisCache.getCacheObject(CacheConstants.SYS_CONFIG_KEY + configKey);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
String param = "";
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String method = httpServletRequest.getMethod().toUpperCase();
String type = httpServletRequest.getContentType();
if ("PUT".equals(method) && "application/json;charset=UTF-8".equalsIgnoreCase(type)) {
requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
}
}
if (requestWrapper == null) {
Map<String, String[]> originRequestMap = request.getParameterMap();
Map<String, String> requestMap = new HashMap<String, String>();
for (String key : originRequestMap.keySet()) {
String[] values = originRequestMap.get(key);
requestMap.put(key, values[0]);
}
param = JSON.toJSONString(requestMap);
} else {
// 获取请求中的流,将取出来的字符串,修改字符串,再次转换成流,然后把它放入到新request对象中
param = ((BodyReaderHttpServletRequestWrapper) requestWrapper).getBody();
JSONObject jsonObject = JSONObject.parseObject(param);
for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// 这里可以做判断,把参数修改,实现业务
}
param = jsonObject.toJSONString();
// 将修改后的param重新转换为流,放入新的请求对象中
byte[] bytes = param.getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) request) {
@Override
public ServletInputStream getInputStream() throws IOException {
return new CustomServletInputStream(bis);
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(bis));
}
};
}
System.out.println("过滤器:" + param);
//放行
if (requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
}
private static class CustomServletInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public CustomServletInputStream(ByteArrayInputStream bis) {
this.inputStream = bis;
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public boolean isFinished() {
return inputStream.available() == 0;
}
@Override
public boolean isReady() {
return true; // Always ready to read
}
@Override
public void setReadListener(ReadListener listener) {
// No async support in this example
}
}
}
具体使用的时候参考代码中的注释:“这里可以做判断,把参数修改,实现业务”
这个位置可以通过调试来一步步理解。
Spring过滤器和拦截器的区别
- 配置位置:
- 过滤器通常在
web.xml
中配置。 - 拦截器可以在Spring的配置文件中配置,也可以使用注解进行配置。
- 过滤器通常在
- 应用范围:
- 过滤器可以应用于Servlet层面的所有请求,不仅限于Spring MVC。
- 拦截器仅应用于Spring MVC请求。
- 粒度:
- 过滤器的工作粒度更细,可以处理请求和响应的各个阶段。
- 拦截器的工作粒度稍粗,主要针对请求的处理流程。
- 功能:
- 过滤器主要用于通用的事务管理和安全性控制。
- 拦截器主要用于Spring MVC中的请求处理,如日志记录、权限验证等。