spring|spring boot 添加自定义监听器、过滤器、拦截器

场景1:需要项目启动的时候把数据加载到缓存中去 使用:监听器
1.自定义listenner类 添加@WebListener 实现ServletContextListener

spring|spring boot 添加自定义监听器、过滤器、拦截器
文章图片
一个注解 一个实现
2.重写contextInitialized方法

@Override public void contextInitialized(ServletContextEvent sce) {//当服务启动时候的业务逻辑}

3.在启动类添加注解扫描
@EnableScheduling
@ServletComponentScan

spring|spring boot 添加自定义监听器、过滤器、拦截器
文章图片
指定扫描类 场景2:在Rest接口中,在拦截器位置判断请求体的参数是否签名符合规范,符合放行在handler中进行业务逻辑的处理,不符合直接不进行响应 使用:过滤器+拦截器
这类功能有一些点还是需要注意的
  • 过滤器请求被处理前调用一次,拦截器可以调用多次
  • 过滤器无法直接响应请求
  • 过滤器和拦截器中httpServletRequest中getInputStream()只可读取一次,无法重复读取
想要在拦截器中读取输入流之后,handler依旧可以再次读取输入流需要在过滤器中读取inputStream,之后缓存起来,然后包装httpServletRequest;重写其中getInputStream()方法去拿缓存数据,就可以满足在拦截器处理getInputStream之后,handler依旧可以从httpServletRequest中拿到数据
1.过滤器处理
//过滤顺序 @Order(1) //过滤器配置 @WebFilter(filterName = "xxxRequestFilter", urlPatterns = "/path/*") public class xxxRequestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { }@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {if (!(request instanceof ApiRequestWrapper)) { //XXXRequestWrapper是HttpServletRequest包装类 XXXRequestWrapper xxxRequestWrapper = new XXXRequestWrapper((HttpServletRequest) request); chain.doFilter(xxxRequestWrapper, response); return; } chain.doFilter(request,response); } @Override public void destroy() {} }

2.XXXRequestWrapper包装HttpServletRequest 缓存数据
public class XXXRequestWrapper extends HttpServletRequestWrapper {private byte[] rawData; private HttpServletRequest request; private ResettableServletInputStream servletStream; public XXXRequestWrapper(HttpServletRequest request) { super(request); this.request = request; this.servletStream = new ResettableServletInputStream(); }public void resetInputStream() { servletStream.stream = new ByteArrayInputStream(rawData); }@Override public ServletInputStream getInputStream() throws IOException { if (rawData =https://www.it610.com/article/= null) { rawData = readBytes(request).getBytes(Charset.forName("UTF-8")); servletStream.stream = new ByteArrayInputStream(rawData); } return servletStream; }@Override public BufferedReader getReader() throws IOException { if (rawData =https://www.it610.com/article/= null) { rawData = readBytes(request).getBytes(Charset.forName("UTF-8")); servletStream.stream = new ByteArrayInputStream(rawData); } return new BufferedReader(new InputStreamReader(servletStream)); }private class ResettableServletInputStream extends ServletInputStream {private InputStream stream; @Override public int read() throws IOException { return stream.read(); }@Override public boolean isFinished() { return false; }@Override public boolean isReady() { return false; }@Override public void setReadListener(ReadListener listener) {} } private String readBytes(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(); }public String getBodyString() { try { return new String(rawData, "UTF-8"); } catch (UnsupportedEncodingException ex) { return new String(rawData); } } }

3.拦截器Interceptor
@Component public class XXXRequestInterceptor implements HandlerInterceptor { protected Logger log = LoggerFactory.getLogger(getClass()); @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {if (httpServletRequest instanceof XXXRequestWrapper) { XXXRequestWrapper xxxRequestWrapper = (XXXRequestWrapper) httpServletRequest; //使用getInputStream 不影响后续的处理器获取请求体中的数据 xxxRequestWrapper.getInputStream(); log.info("校验成功 "); }catch (Exception e) { log.error("请求校验失败 "); return false; } 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 {} }

4.其他配置 【spring|spring boot 添加自定义监听器、过滤器、拦截器】拦截器不需要单独添加注解,在类上添加@Component即可
过滤器需要在启动类上配置
@ServletComponentScan(basePackageClasses={xxx.xxxRequestFilter.class})

    推荐阅读