@ServletComponentScan

 //启动类加上@ServletComponentScan注解

 filter

package com.box.marketing.service.filter;

import com.box.common.core.constant.RequestConstant;
import com.box.common.core.exception.ServiceException;
import com.box.common.core.utils.GatewayUtils;
import com.box.marketing.service.wrapper.MultiReadHttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* 初始化MultiReadHttpServletRequestWrapper类,必须在过滤中初始化,不能拦截器修改值无效
*
* @author yuan.dingwang
* @date 2021年03月03日 11:19
*/
@Slf4j
@Order(0)
@WebFilter(urlPatterns = "/*", filterName = "reqWrapperFilter") //启动类加上@ServletComponentScan注解
public class RequestWrapperFilter implements Filter {


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

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String safetyVal = request.getHeader(RequestConstant.HEADER_SAFETY_LABEL_NAME);
if (!StringUtils.equals(RequestConstant.HEADER_SAFETY_LABEL_VAL, safetyVal)) {
throw new ServiceException(HttpServletResponse.SC_FORBIDDEN, "请通过网关访问资源");
}

String contentType = servletRequest.getContentType();
if (request.getMethod().toUpperCase().equals(HttpMethod.POST.toString()) && (MediaType.APPLICATION_JSON_VALUE.equals(contentType)) ||
(MediaType.APPLICATION_JSON_UTF8_VALUE.equals(contentType))) {
MultiReadHttpServletRequestWrapper requestWrapper = new MultiReadHttpServletRequestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(requestWrapper, servletResponse);
}else{
filterChain.doFilter(servletRequest, servletResponse);
}

//
}

@Override
public void destroy() {

}

}

interceptor

我们可以知道 Filter 依赖于 Servlet,它主要是针对 URL 地址做一个编码的事情、过滤掉没用的参数、简单的安全校验(比如登录不登录之类),而 Interceptor 依赖于 SpringMVC 框架,它是在 service 或者一个方法调用前,调用一个方法,或者在方法调用后,调用一个方法。下面来具体介绍 Interceptor 的用法和使用场景。

package com.box.marketing.service.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.box.common.core.constant.RequestConstant;
import com.box.common.core.utils.StringUtils;
import com.box.marketing.service.wrapper.MultiReadHttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* 文件描述
*
* @author yuan.dingwang
* @date 2021年03月02日 18:00
*/
@Slf4j
@Component
public class ContentTypeInterceptor extends HandlerInterceptorAdapter {


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String httpMethod = request.getMethod();
String contentType = request.getHeader(HttpHeaders.CONTENT_TYPE);
if (httpMethod.equals(HttpMethod.POST.toString()) && MediaType.APPLICATION_JSON_VALUE.equals(contentType)) {
MultiReadHttpServletRequestWrapper requestWrapper = (MultiReadHttpServletRequestWrapper) request;
String body = requestWrapper.getBody();

HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RequestBody requestBody = method.getAnnotation(RequestBody.class);

if (Objects.isNull(requestBody) && StringUtils.isNotBlank(body)) {
JSONObject obj = JSONObject.parseObject(body);
Map<String, String[]> param = new HashMap<>(16);
for (String key : obj.keySet()) {
String[] put = new String[1];
put[0] = obj.getString(key);
param.put(key, put);
}
requestWrapper.setParameterMap(param);
//reflectSetparam(request, "content-type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}
return super.preHandle(requestWrapper, response, handler);
}

return super.preHandle(request, response, handler);
}


/**
* 修改header信息,key-value键值对儿加入到header中
*
* @param request
* @param key
* @param value
*/
private void reflectSetparam(HttpServletRequest request, String key, String value) {
Class<? extends HttpServletRequest> requestClass = request.getClass();
log.info("request实现类=" + requestClass.getName());
try {
Field request1 = requestClass.getDeclaredField("request");
request1.setAccessible(true);
Object o = request1.get(request);
Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
coyoteRequest.setAccessible(true);
Object o1 = coyoteRequest.get(o);
log.info("coyoteRequest实现类=" + o1.getClass().getName());
Field headers = o1.getClass().getDeclaredField("headers");
headers.setAccessible(true);
MimeHeaders o2 = (MimeHeaders) headers.get(o1);
//o2.removeHeader("content-type");
o2.addValue(key).setString(value);
System.out.println(request.getHeader(HttpHeaders.CONTENT_TYPE));
} catch (Exception e) {
e.printStackTrace();
}
}
}

wrapper 包装类

package com.box.marketing.service.wrapper;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
/**
* 重新写请求
*
* @author yuan.dingwang
* @date 2021年03月02日 19:54
*/
public class MultiReadHttpServletRequestWrapper extends HttpServletRequestWrapper {

private String tempBody;

private Map<String, String[]> params; //定义参数集合

public MultiReadHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
tempBody = getBodyString(request);
params = request.getParameterMap();
}

@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(tempBody.getBytes());
return new ServletInputStream() {
@Override
public boolean isReady() {
return false;
}

@Override
public int readLine(byte[] b, int off, int len) throws IOException {
return super.readLine(b, off, len);
}

@Override
public boolean isFinished() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {

}

@Override
public int read() {
return byteArrayInputStream.read();
}
};
}

@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}

public String getBody() {
return this.tempBody;
}

public void setBody(String body) {

this.tempBody = body;
}


private static String getBodyString(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}


@Override
public Enumeration<String> getParameterNames() {
Vector<String> vector = new Vector<String>(params.keySet());
return vector.elements();
}

/**
* 获取指定参数名的值,如果有重复的参数名,则返回第一个的值 接收一般变量 ,如text类型
*
* @param name 指定参数名
* @return 指定参数名的值
*/
@Override
public String getParameter(String name) {
String[] results = params.get(name);
return results[0];
}


/**
* 36 * 获取指定参数名的所有值的数组,如:checkbox的所有数据
* 37 * 接收数组变量 ,如checkobx类型
* 38
*/
@Override
public String[] getParameterValues(String name) {
return params.get(name);
}

@Override
public Map<String, String[]> getParameterMap() {
return params;
}

public void setParameterMap(Map<String, String[]> parameterMap) {
this.params = parameterMap;
}

}


 

小蚊子大人
原文地址:https://www.cnblogs.com/ywsheng/p/14980268.html