新建拦截器: WebFilter
目的:拦截所有请求过滤器,并将请求类型是HttpServletRequest类型的请求替换为自定义{@link com.*.biz.service.common.interceptor.RequestWrapper
import com.biz.service.common.interceptor.RequestWrapper;
import org.springframework.core.annotation.Order;
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 java.io.IOException;
/**
* @Description: 拦截所有请求过滤器,并将请求类型是HttpServletRequest类型的请求替换为自定义{@link com.biz.service.common.interceptor.RequestWrapper}
*/
@Order(-1)
@javax.servlet.annotation.WebFilter(filterName = "webFilter", urlPatterns = "/*")
public class WebFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
ServletRequest request = null;
if (servletRequest instanceof HttpServletRequest) {
request = new RequestWrapper((HttpServletRequest) servletRequest);
}
if (request == null) {
chain.doFilter(servletRequest, servletResponse);
} else {
chain.doFilter(request, servletResponse);
}
}
@Override
public void destroy() {
}
}
拦截器配置
import com.biz.service.common.filter.WebFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Collections;
@Configuration
public class FilterConfig {
@Bean
FilterRegistrationBean myFilterFilterRegistrationBean() {
FilterRegistrationBean bean = new FilterRegistrationBean<>();
bean.setFilter(new WebFilter());
bean.setOrder(-1);
bean.setUrlPatterns(Collections.singletonList("/*"));
return bean;
}
}
新建 RequestWrapper
目的: getInputStream获取流 然后在流中获取数据 但是这个方法只能获取一次;重写httpservletrequestwrapper把request保存下来.用过滤器把保存的request填进去 就可以多次读取了
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
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.InputStream;
import java.io.InputStreamReader;
/**
* getInputStream获取流 然后在流中获取数据 但是这个方法只能获取一次
* 重写httpservletrequestwrapper把request保存下来
* 用过滤器把保存的request填进去 就可以多次读取了
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private String body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {
}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
// 赋值给body字段
public void setBody(String body) {
this.body = body;
}
}
创建过滤器,获取请求的body,处理后,set回请求中;
import cn.hutool.core.util.StrUtil;
import com.biz.api.common.annotations.I18nTimeHandle;
import com.biz.service.utils.DateZoneUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
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.List;
@Slf4j
public class DateHandlerInterceptor implements HandlerInterceptor {
//在请求处理之前进行调用(Controller方法调用之前)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
I18nTimeHandle annotation = handlerMethod.getMethod().getAnnotation(I18nTimeHandle.class);
if (annotation == null) {
return true;
}
/**
* getInputStream获取流 然后在流中获取数据 但是这个方法只能获取一次,重写HttpServletRequestWrapper把request保存下来
* 用过滤器把保存的request填进去 就可以多次读取了
*/
//如果方法上存在 I18nTimeHandle 注解,则进行时间时区处理
if (request instanceof RequestWrapper) {
RequestWrapper requestWrapper = (RequestWrapper) request;
String body = requestWrapper.getBody();
log.info("处理前的请求体:{}", body);
//获取请求json中时间字符串
List jsonStrDateStr = DateZoneUtil.getJsonStrDateStr(body);
for (String originDate : jsonStrDateStr) {
//将前端传入的时间 转换成 东八区的时间
String targetDate = DateZoneUtil.converDateGMT(originDate, "+8", "+6");
body = StrUtil.replace(body, originDate, targetDate);
}
log.info("处理后的请求体:{}", body);
//将处理后的body放回
requestWrapper.setBody(body);
}
return true;
}
//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
过滤器配置
import com.biz.service.common.interceptor.DateHandlerInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 可添加多个,这里选择拦截所有请求地址,进入后判断是否有加注解即可
registry.addInterceptor(new DateHandlerInterceptor()).addPathPatterns("/**");
}
}
工具类代码
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.biz.service.common.exception.BizException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
public class DateZoneUtil {
private static String GMT_8 = "GMT+8";
/**
* 转换时间时区
*
* @param dateStr 需要转的时间字符串
* @param sourceTimeZone 源时间时区 +8
* @param targetTimeZone 目标时间时区 +6
* @return
* @throws ParseException
*/
public static String converDateGMT(String dateStr, String sourceTimeZone, String targetTimeZone) {
sourceTimeZone = StrUtil.isEmpty(sourceTimeZone) ? GMT_8 : converTimeZone(sourceTimeZone);
targetTimeZone = StrUtil.isEmpty(targetTimeZone) ? GMT_8 : converTimeZone(targetTimeZone);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取传入的时间值
Long time = 0L;
try {
time = new Date(sdf.parse(dateStr).getTime()).getTime();
} catch (ParseException pe) {
throw new BizException("时间格式化异常");
}
//获取源时区时间相对的GMT时间
Long sourceRelativelyGMT = time - TimeZone.getTimeZone(sourceTimeZone).getRawOffset();
//GMT时间+目标时间时区的偏移量获取目标时间
Long targetTime = sourceRelativelyGMT + TimeZone.getTimeZone(targetTimeZone).getRawOffset();
Date date = new Date(targetTime);
return cn.hutool.core.date.DateUtil.formatDateTime(date);
}
/**
* timeZone转换 +8->GMT+8
*
* @param timeZone
* @return
*/
private static String converTimeZone(String timeZone) {
if (StrUtil.isEmpty(timeZone)) {
return GMT_8;
}
return "GMT" + timeZone;
}
/**
* 从jsonStr中获取时间字符串(只有符合格式的才会被截取 yyyy-MM-dd HH:mm:ss )
*
* @param jsonStr
* @return
*/
public static List getJsonStrDateStr(String jsonStr) {
//递归获取jsonObject中的时间字符串
return getJsonObjectDateStr(JSONObject.parseObject(jsonStr));
}
/**
* 递归获取jsonObject中的时间字符串
*
* @param jsonObject
* @return
*/
private static List getJsonObjectDateStr(JSONObject jsonObject) {
List resultList = Lists.newArrayList();
jsonObject.entrySet().forEach(v -> {
if (v.getValue() != null && v.getValue().getClass().equals(String.class) && isValidDate(String.valueOf(v.getValue()))) {
resultList.add(/*v.getKey() + "---" +*/ String.valueOf(v.getValue()));
} else if (v.getValue() != null && v.getValue().getClass().equals(JSONObject.class)) {
JSONObject jsonObject1 = (JSONObject) v.getValue();
resultList.addAll(getJsonObjectDateStr(jsonObject1));
} else if (v.getValue() != null && v.getValue().getClass().equals(JSONArray.class)) {
JSONArray jsonArray = (JSONArray) v.getValue();
for (Object o : jsonArray) {
JSONObject jsonObject2 = (JSONObject) o;
resultList.addAll(getJsonObjectDateStr(jsonObject2));
}
}
});
return resultList;
}
public static Boolean isValidDate(String s) {
if (s.length() != 19) {
return Boolean.FALSE;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
dateFormat.parse(s);
return Boolean.TRUE;
} catch (Exception e) {
return Boolean.FALSE;
}
}
}