业务需要,得对特定的请求进行拦截,判断能不能满足状态,满足后才放行,不满足的话就抛出异常,过程主要分为四部分,首页是webMvcConfg配置,如何是拦截器的拦截逻辑编写,然后是对于json类型的消息头需要重写HttpServletRequestWrapper方法,实现多次对流的读取,不然拦截器读取后,放行请求路径对应的方法就获取不到请求体了,因为流只能读一次,所以还需要过滤器将对应的请求再塞回去
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Resource
    private IRecSealService iRecSealService;
    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器,并且指定需要拦截的请求路径
        registry.addInterceptor(new URLInterceptor(iRecSealService))
                .addPathPatterns("/recMrIndex/aaa"
                        , "/recMrIndex/bbb"
                        , "/recMrIndex/ccc"
                        , "/recUpperShelf/ddd"
                );
        WebMvcConfigurer.super.addInterceptors(registry);
    }
    /**
     * 对指定请求的 HttpServletRequest 进行重新注册返回
     *
     */
    @Bean
    public FilterRegistrationBean setLogServiceFilter() {
        //使用过滤器将请求体塞回去避免流只能读一次造成的错误
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        RequestBodyFilter requestBodyFilter = new RequestBodyFilter();
        registrationBean.setFilter(requestBodyFilter);
        registrationBean.setName("interceptor filter body params");
        registrationBean.addUrlPatterns("/recMrIndex/aaa"
                        , "/recMrIndex/bbb"
                        , "/recMrIndex/ccc"
                        , "/recUpperShelf/ddd"
        );
        registrationBean.setOrder(1);
        return registrationBean;
    }
}
java
/**
 *
 * <p>
 *     对特定的url进行拦截, 按添加的路径进行拦截,获取 各种参数,进行验证
 * </p>
 *
 * @author lihaowei
 * @since: 2023/11/6 15:23
 *
 */
@Component
public class URLInterceptor implements HandlerInterceptor {
    @Resource
    private IRecSealService iRecSealService;
    public URLInterceptor(private IRecSealService iRecSealService) {
        this.iRecSealService = iRecSealService;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String contentType="application/json";
        if (request.getContentType().contains(contentType)){
            String methodName = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
            RequestReaderHttpServletRequestWrapper requestWrapper=new RequestReaderHttpServletRequestWrapper(request);
            String body = requestWrapper.inputStream2String(requestWrapper.getInputStream());
            switch (methodName) {
                //aaa
                case "aaa":
                    ObjectRequest receiveRequest = JSON.parseObject(body,ObjectRequest.class);
                    if (ObjectUtil.isNull(receiveRequest)) {
                        return  true;
                    }
                    
                    return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
                //bbb
                case "bbb":
                    List<ObjectRequest> sends = JSON.parseArray(body, ObjectRequest.class);
                   
                    return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
                 //ccc
                case "ccc":
                    List<ObjectRequest> bindRequest = JSON.parseArray(body, ObjectRequest.class);
                   
                    return getSealPatientStatusByList(receiveRequest.getList,ObjectRequest.class);
                //ddd
                case "ddd":
                    ObjectRequest onShelf = JSON.parseObject(body, ObjectRequest.class);
                    if (ObjectUtil.isEmpty(onShelf)) {
                        return  true;
                    }
                    List<patientRequest> patients=new ArrayList<>();
                    .....
                    return getSealPatientStatus(patients);
            }
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
    public  boolean getSealPatientStatus(List<PatientRequest> patients){
        
        for (PatientRequest request : patients) {
            QueryWrapper<RecSealEntity> queryWrapper=new QueryWrapper<>();
            .....
            RecSealEntity recSeal = iRecSealService.getOne(queryWrapper);
            if (ObjectUtil.isNull(recSeal)){
                return true;
            }
            if () {
            //判断业务逻辑
        } else {
            //判断业务逻辑
            }
        }
        return true;
    }
    
     public <T> boolean getSealPatientStatusByList(List<T> list,Class<T> clazz)  {
        if (CollUtil.isEmpty(list)) {
            return  true;
        }
        List<PatientRequest> patients= new ArrayList<>();
        try {
            for (T t:list){
                PatientRequest patient=new PatientRequest();
                Field patientId=clazz.getDeclaredField("patientId");
                Field visitNo=clazz.getDeclaredField("visitNo");
                //允许访问私有属性值
                patientId.setAccessible(true);
                visitNo.setAccessible(true);
                patient.setPatientId((String) patientId.get(t));
                patient.setVisitNo((String) visitNo.get(t));
                patients.add(patient);
            }
        }catch (NoSuchFieldException e) {
            e.printStackTrace();
            throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"拦截器获取属性出错属性值为空:"+e.getMessage());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new BusinessException(ResultCodeEnum.ERR_0x1000.getCode(),"拦截器获取属性出错");
        }
        if (CollUtil.isEmpty(patients)){
            return true;
        }
        return getSealPatientStatus(patients);
    }
}
java
/**
 * 解决拦截器从流中获取完整的 body 请求参数后,无法再次调用流中数据的问题,否则报以下错误信息
 * <p>
 * I/O error while reading input message; nested exception is java.io.IOException: Stream closed
 */
public class RequestReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
    private final byte[] body;
    public RequestReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = inputStream2String(request.getInputStream()).getBytes(Charset.forName("UTF-8"));
    }
    @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 readListener) {
            }
        };
    }
    /**
     * 将 inputStream 里的数据读取出来并转换成字符串
     *
     * @param inputStream inputStream
     * @return String
     */
    public String inputStream2String(InputStream inputStream) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            sb.append("get body params fail");
            LOGGER.error(e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage());
                }
            }
        }
        return sb.toString();
    }
}
java
/**
 *
 * <p>
 *      重新组装 HttpServletRequest 返回, 解决拦截器中从流中获取完 post 请求中的 body 参数,controller 层无法再次获取的问题
 * </p>
 *
 * @author lihaowei
 * @since: 2023/11/6 15:21
 *
 */
public class RequestBodyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            String method = httpServletRequest.getMethod();
            String contentType = httpServletRequest.getContentType() == null ? "" : httpServletRequest.getContentType();
            // 如果是POST请求并且不是文件上传
            if (HttpMethod.POST.name().equals(method) && !contentType.equals(MediaType.MULTIPART_FORM_DATA_VALUE)) {
                // 重新生成ServletRequest  这个新的 ServletRequest 获取流时会将流的数据重写进流里面
                requestWrapper = new RequestReaderHttpServletRequestWrapper((HttpServletRequest) request);
            }
        }
        if (requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!