[JAVA] SpringBoot配置自定义拦截器实现过程详解

2619 0
Honkers 2022-11-9 09:21:32 | 显示全部楼层 |阅读模式
目录

    1. HttpServletRequest包装类2. 使用Filter将request传递下去3. 添加拦截器4. 全局异常处理器5. 配置拦截器


1. HttpServletRequest包装类

因为HttpServletRequest只能读取一次,所以需要对request进行包装,变成可重复读的request.
  1. package net.lesscoding.interceptor;
  2. import javax.servlet.ReadListener;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletRequestWrapper;
  6. import java.io.*;
  7. /**
  8. *  由于流只能读取一次,所以使用此包装类对HttpServletRequest对象进行包装,读取完之后再将
  9. *  内容塞回去,不影响后续springmvc的参数处理。
  10. */
  11. public class RequestWrapper extends HttpServletRequestWrapper {
  12.     private String body;
  13.     public RequestWrapper(HttpServletRequest request) {
  14.         super(request);
  15.         if (request.getHeader("Content-Type") != null
  16.                 && request.getHeader("Content-Type").contains("multipart/form-data")){
  17.             try{
  18.                 request.getParts();
  19.             }catch (Exception e){
  20.                 e.printStackTrace();
  21.             }
  22.         }
  23.         StringBuilder stringBuilder = new StringBuilder();
  24.         try (InputStream inputStream = request.getInputStream();
  25.              BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))){
  26.             char[] charBuffer = new char[128];
  27.             int bytesRead = -1;
  28.             while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
  29.                 stringBuilder.append(charBuffer, 0, bytesRead);
  30.             }
  31.         }catch (NullPointerException ex){
  32.             stringBuilder.append("");
  33.         } catch (Exception ex) {
  34.         }
  35.         body = stringBuilder.toString();
  36.     }
  37.     @Override
  38.     public ServletInputStream getInputStream() throws IOException {
  39.         final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
  40.         ServletInputStream servletInputStream = new ServletInputStream() {
  41.             @Override
  42.             public boolean isFinished() {
  43.                 return false;
  44.             }
  45.             @Override
  46.             public boolean isReady() {
  47.                 return false;
  48.             }
  49.             @Override
  50.             public void setReadListener(ReadListener readListener) {
  51.             }
  52.             @Override
  53.             public int read() throws IOException {
  54.                 return byteArrayInputStream.read();
  55.             }
  56.         };
  57.         return servletInputStream;
  58.     }
  59.     @Override
  60.     public BufferedReader getReader() throws IOException {
  61.         return new BufferedReader(new InputStreamReader(this.getInputStream()));
  62.     }
  63.     public String getBody() {
  64.         return body;
  65.     }
  66.     public void setBody(String body) {
  67.         this.body = body;
  68.     }
  69. }
复制代码
2. 使用Filter将request传递下去

因为filter是在request前边执行的,所以我们需要使用一个filter将我们包装好的request传递下去,让后边使用的request都是我们包装好的,防止出现流已经被读取的错误出现
  1. package net.lesscoding.filter;
  2. import net.lesscoding.interceptor.RequestWrapper;
  3. import javax.servlet.*;
  4. import javax.servlet.http.HttpServletRequest;
  5. import java.io.IOException;
  6. /**
  7. * @apiNote 传递request的过滤器
  8. */
  9. public class RepeatedlyReadFilter implements Filter {
  10.     @Override
  11.     public void init(FilterConfig filterConfig) throws ServletException {
  12.     }
  13.     @Override
  14.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  15.         ServletRequest requestWrapper = null;
  16.         if(request instanceof HttpServletRequest){
  17.             requestWrapper = new RequestWrapper((HttpServletRequest) request);
  18.         }
  19.         chain.doFilter( requestWrapper == null ? request : requestWrapper,response );
  20.     }
  21.     @Override
  22.     public void destroy() {
  23.     }
  24. }
复制代码
3. 添加拦截器

这里我们添加一个判断用户登录状态的拦截器,从 request中获取token信息,查询redis如果redis存在则用户已经登录,否则就返回false
  1. package net.lesscoding.interceptor;
  2. import cn.hutool.core.util.StrUtil;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.web.servlet.HandlerInterceptor;
  7. import org.springframework.web.servlet.ModelAndView;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import java.util.concurrent.TimeUnit;
  11. /**
  12. * @apiNote 登录拦截器
  13. */
  14. @Configuration
  15. public class LoginInterceptor implements HandlerInterceptor {
  16.     @Autowired
  17.     private RedisTemplate redisTemplate;
  18.     @Override
  19.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  20.         String token = request.getHeader("AccessToken");
  21.         String redisToken = String.valueOf(redisTemplate.opsForValue().get(token));
  22.         if(StrUtil.isBlank(redisToken)){
  23.             throw new RuntimeException("token失效,请重新登录");
  24.         }
  25.         // 这里为了方便 成功之后就刷新在redis中的时间
  26.         redisTemplate.opsForValue().set("token",redisToken,30, TimeUnit.MINUTES);
  27.         return true;
  28.     }
  29.     @Override
  30.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  31.     }
  32.     @Override
  33.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  34.     }
  35. }
复制代码
4. 全局异常处理器

使用全局异常处理器捕获拦截器抛出的异常信息,做统一返回
  1. package net.lesscoding.config;
  2. import lombok.extern.slf4j.Slf4j;
  3. import net.lesscoding.common.Result;
  4. import net.lesscoding.common.ResultFactory;
  5. import org.springframework.web.bind.annotation.ExceptionHandler;
  6. import org.springframework.web.bind.annotation.RestControllerAdvice;
  7. /**
  8. * @apiNote 全局异常处理器
  9. */
  10. @RestControllerAdvice
  11. @Slf4j
  12. public class GlobalExceptionHandler {
  13.     @ExceptionHandler(value = RuntimeException.class)
  14.     public Result runtimeExceptionHandler(RuntimeException e){
  15.         e.printStackTrace();
  16.         log.error("{}", e.getMessage());
  17.         return ResultFactory.buildThrowable(e);
  18.     }
  19.     @ExceptionHandler(value = Exception.class)
  20.     public Result exceptionHandler(Exception e){
  21.         e.printStackTrace();
  22.         log.error("{}", e.getMessage());
  23.         return ResultFactory.buildThrowable(e);
  24.     }
  25.     @ExceptionHandler(value = Throwable.class)
  26.     public Result exceptionHandler(Throwable t){
  27.         t.printStackTrace();
  28.         log.error("{}", t.getMessage());
  29.         return ResultFactory.buildThrowable(t);
  30.     }
  31. }
复制代码
5. 配置拦截器

对拦截器进行注册,指定拦截哪些url请求
  1. package net.lesscoding.config;
  2. import net.lesscoding.filter.RepeatedlyReadFilter;
  3. import net.lesscoding.interceptor.LoginInterceptor;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  9. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  10. /**
  11. * @apiNote 对项目进行配置拦截器
  12. */
  13. @Configuration
  14. public class LoginConfiguration implements WebMvcConfigurer {
  15.     @Autowired
  16.     private LoginInterceptor loginInterceptor;
  17.     @Bean
  18.     public FilterRegistrationBean repeatedlyReadFilter(){
  19.         FilterRegistrationBean registration = new FilterRegistrationBean();
  20.         RepeatedlyReadFilter repeatedlyReadFilter = new RepeatedlyReadFilter();
  21.         registration.setFilter(repeatedlyReadFilter);
  22.         registration.addUrlPatterns("/*");
  23.         return registration;
  24.     }
  25.     @Override
  26.     public void addInterceptors(InterceptorRegistry registry) {
  27.         registry.addInterceptor(loginInterceptor)
  28.                 // 拦截所有请求
  29.                 .addPathPatterns("/**")
  30.                 // 排除登录注册修改密码等接口
  31.                 .excludePathPatterns("/oauth/**","/login/**","logout/**","/common/**", "options","/try/**","/user/updatePwd")
  32.                 // 判处swagger等接口
  33.                 .excludePathPatterns("/doc.html","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**","/favicon.ico")
  34.         ;
  35.     }
  36. }
复制代码
到此这篇关于SpringBoot配置自定义拦截器实现过程详解的文章就介绍到这了,更多相关SpringBoot自定义拦截器内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4004
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行