zoukankan      html  css  js  c++  java
  • springboot拦截器配置、消息头校验、重复请求过滤

      一个一个来,按spring boot的风格,我们不喜欢xml文件,所以使用java类来启用拦截器配置:

    import com.wlf.order.prize.aop.RequestInterceptor;
    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 InterceptorConfig implements WebMvcConfigurer {
    
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**").
                    excludePathPatterns("/jpservice/getSign", "/jpservice/getTimeStamp");
        }
    }

      上面我们拦截了所有的web请求,除了这两个接口:"/jpservice/getSign", "/jpservice/getTimeStamp"

      接着我们进入拦截器里,做消息头校验、重复请求校验:

    import com.wlf.order.prize.javabean.Result;
    import com.wlf.order.prize.util.BeanConvert;
    import com.wlf.order.prize.util.IPUtil;
    import com.wlf.order.prize.util.ThreadLocalUtil;
    import com.wlf.order.prize.util.TimeStampList;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.lang.Nullable;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 拦截器:增加重复请求的过滤、话单记录处理
     *
     * @author wulinfeng
     * @since 2019/12/25
     */
    @Slf4j
    @Component
    public class RequestInterceptor extends HandlerInterceptorAdapter {
    
        private final static SimpleDateFormat SF = new SimpleDateFormat("yyyyMMddHHmmss");
    
        // 话单格式:记录时间|接口名称|接口时延|调用方IP|本地IP|业务参数|结果码|序列号
        private final static String CDR_FORMAT = "{}|{}|{}|{}|{}|{}|{}|{}";
    
        // 时间戳缓存
        private final static TimeStampList cache = new TimeStampList(10000);
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            // 请求头校验
            String timestamp = request.getHeader("timestamp");
            String sign = request.getHeader("sign");
            if (timestamp == null || timestamp.trim().equals("") || sign == null || sign.trim().equals("")) {
                Result result = new Result(1025, "请求头缺失.");
                getResponse(result, response);
                return false;
            }
    
            // 时间戳校验
            if (timestamp.length() != 13) {
                Result result = new Result(1026, "时间戳格式错误.");
                getResponse(result, response);
                return false;
            }
    
            Long requestTime = null;
            try {
                requestTime = Long.parseLong(timestamp);
            } catch (NumberFormatException e) {
                Result result = new Result(1026, "时间戳格式错误.");
                getResponse(result, response);
                return false;
            }
    
            // 重复请求校验
            if (cache.contains(requestTime)) {
                Result result = new Result(1027, "重复请求.");
                getResponse(result, response);
                return false;
            }
    
            cache.add(requestTime);
    
            // 获取请求和本地IP,记录话单
            String beginTime = String.valueOf(System.currentTimeMillis());
            String remoteIp = IPUtil.getRemoteIp(request);
            String localIp = IPUtil.getLocalIp();
    
            Map<String, String> strMap = new HashMap<>();
            strMap.put("beginTime", beginTime);
            strMap.put("remoteIp", remoteIp);
            strMap.put("localIp", localIp);
            strMap.put("sequence", timestamp);
    
            ThreadLocalUtil.setMap(strMap);
    
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               @Nullable ModelAndView modelAndView) throws Exception {
    
            // 计算接口时延
            Map<String, String> strMap = ThreadLocalUtil.getMap();
            long beginTime = Long.parseLong(strMap.get("beginTime"));
            long currentTime = System.currentTimeMillis();
    
            // 获取当前时间
            String currentDate = SF.format(new Date(currentTime));
    
            // 记录话单
            log.error(CDR_FORMAT, currentDate, strMap.get("apiType"), currentTime - beginTime, strMap.get("remoteIp"),
                    strMap.get("localIp"), strMap.get("sequence"), strMap.get("biz"), strMap.get("resultCode"));
        }
    
    
        /**
         * 构造响应消息体
         *
         * @param result
         * @param response
         * @throws IOException
         */
        private void getResponse(Result result, HttpServletResponse response) throws IOException {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
    
            PrintWriter out = null;
            out = response.getWriter();
            out.write(BeanConvert.getResultJson(result));
            out.flush();
            out.close();
        }
    }

      如果你的拦截器需要注入bean,而且失败了,可以参见springboot拦截器注入bean失败实例

  • 相关阅读:
    RabbitMQ(四)
    RabbitMQ(三)
    RabbitMQ(二)
    定位
    响应式布局
    学习前端的一些心得
    css样式大全
    常用标签
    HTML
    app 被拒绝原因
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/12102299.html
Copyright © 2011-2022 走看看