spring|spring boot 添加自定义监听器、过滤器、拦截器
场景1:需要项目启动的时候把数据加载到缓存中去 使用:监听器
1.自定义listenner类 添加@WebListener 实现ServletContextListener
文章图片
一个注解 一个实现
2.重写contextInitialized方法
@Override
public void contextInitialized(ServletContextEvent sce) {//当服务启动时候的业务逻辑}
3.在启动类添加注解扫描
@EnableScheduling
@ServletComponentScan
文章图片
指定扫描类 场景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})
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- 2018-07-09|2018-07-09 Spring 的DBCP,c3p0
- 编写字典程序
- spring|spring boot项目启动websocket
- Spring|Spring Boot 整合 Activiti6.0.0
- Spring集成|Spring集成 Mina
- springboot使用redis缓存
- Spring|Spring 框架之 AOP 原理剖析已经出炉!!!预定的童鞋可以识别下发二维码去看了