目录
1. HttpServletRequest包装类2. 使用Filter将request传递下去3. 添加拦截器4. 全局异常处理器5. 配置拦截器
1. HttpServletRequest包装类
因为HttpServletRequest只能读取一次,所以需要对request进行包装,变成可重复读的request. - package net.lesscoding.interceptor;
- import javax.servlet.ReadListener;
- import javax.servlet.ServletInputStream;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- import java.io.*;
- /**
- * 由于流只能读取一次,所以使用此包装类对HttpServletRequest对象进行包装,读取完之后再将
- * 内容塞回去,不影响后续springmvc的参数处理。
- */
- public class RequestWrapper extends HttpServletRequestWrapper {
- private String body;
- public RequestWrapper(HttpServletRequest request) {
- super(request);
- if (request.getHeader("Content-Type") != null
- && request.getHeader("Content-Type").contains("multipart/form-data")){
- try{
- request.getParts();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- StringBuilder stringBuilder = new StringBuilder();
- try (InputStream inputStream = request.getInputStream();
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))){
- char[] charBuffer = new char[128];
- int bytesRead = -1;
- while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
- stringBuilder.append(charBuffer, 0, bytesRead);
- }
- }catch (NullPointerException ex){
- stringBuilder.append("");
- } catch (Exception ex) {
- }
- body = stringBuilder.toString();
- }
- @Override
- public ServletInputStream getInputStream() throws IOException {
- final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
- ServletInputStream servletInputStream = new ServletInputStream() {
- @Override
- public boolean isFinished() {
- return false;
- }
- @Override
- public boolean isReady() {
- return false;
- }
- @Override
- public void setReadListener(ReadListener readListener) {
- }
- @Override
- public int read() throws IOException {
- return byteArrayInputStream.read();
- }
- };
- return servletInputStream;
- }
- @Override
- public BufferedReader getReader() throws IOException {
- return new BufferedReader(new InputStreamReader(this.getInputStream()));
- }
- public String getBody() {
- return body;
- }
- public void setBody(String body) {
- this.body = body;
- }
- }
复制代码 2. 使用Filter将request传递下去
因为filter是在request前边执行的,所以我们需要使用一个filter将我们包装好的request传递下去,让后边使用的request都是我们包装好的,防止出现流已经被读取的错误出现 - package net.lesscoding.filter;
- import net.lesscoding.interceptor.RequestWrapper;
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import java.io.IOException;
- /**
- * @apiNote 传递request的过滤器
- */
- public class RepeatedlyReadFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- ServletRequest requestWrapper = null;
- if(request instanceof HttpServletRequest){
- requestWrapper = new RequestWrapper((HttpServletRequest) request);
- }
- chain.doFilter( requestWrapper == null ? request : requestWrapper,response );
- }
- @Override
- public void destroy() {
- }
- }
复制代码 3. 添加拦截器
这里我们添加一个判断用户登录状态的拦截器,从 request中获取token信息,查询redis如果redis存在则用户已经登录,否则就返回false - package net.lesscoding.interceptor;
- import cn.hutool.core.util.StrUtil;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.util.concurrent.TimeUnit;
- /**
- * @apiNote 登录拦截器
- */
- @Configuration
- public class LoginInterceptor implements HandlerInterceptor {
- @Autowired
- private RedisTemplate redisTemplate;
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- String token = request.getHeader("AccessToken");
- String redisToken = String.valueOf(redisTemplate.opsForValue().get(token));
- if(StrUtil.isBlank(redisToken)){
- throw new RuntimeException("token失效,请重新登录");
- }
- // 这里为了方便 成功之后就刷新在redis中的时间
- redisTemplate.opsForValue().set("token",redisToken,30, TimeUnit.MINUTES);
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- }
- }
复制代码 4. 全局异常处理器
使用全局异常处理器捕获拦截器抛出的异常信息,做统一返回 - package net.lesscoding.config;
- import lombok.extern.slf4j.Slf4j;
- import net.lesscoding.common.Result;
- import net.lesscoding.common.ResultFactory;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.RestControllerAdvice;
- /**
- * @apiNote 全局异常处理器
- */
- @RestControllerAdvice
- @Slf4j
- public class GlobalExceptionHandler {
- @ExceptionHandler(value = RuntimeException.class)
- public Result runtimeExceptionHandler(RuntimeException e){
- e.printStackTrace();
- log.error("{}", e.getMessage());
- return ResultFactory.buildThrowable(e);
- }
- @ExceptionHandler(value = Exception.class)
- public Result exceptionHandler(Exception e){
- e.printStackTrace();
- log.error("{}", e.getMessage());
- return ResultFactory.buildThrowable(e);
- }
- @ExceptionHandler(value = Throwable.class)
- public Result exceptionHandler(Throwable t){
- t.printStackTrace();
- log.error("{}", t.getMessage());
- return ResultFactory.buildThrowable(t);
- }
- }
复制代码 5. 配置拦截器
对拦截器进行注册,指定拦截哪些url请求 - package net.lesscoding.config;
- import net.lesscoding.filter.RepeatedlyReadFilter;
- import net.lesscoding.interceptor.LoginInterceptor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.web.servlet.FilterRegistrationBean;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
- /**
- * @apiNote 对项目进行配置拦截器
- */
- @Configuration
- public class LoginConfiguration implements WebMvcConfigurer {
- @Autowired
- private LoginInterceptor loginInterceptor;
- @Bean
- public FilterRegistrationBean repeatedlyReadFilter(){
- FilterRegistrationBean registration = new FilterRegistrationBean();
- RepeatedlyReadFilter repeatedlyReadFilter = new RepeatedlyReadFilter();
- registration.setFilter(repeatedlyReadFilter);
- registration.addUrlPatterns("/*");
- return registration;
- }
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(loginInterceptor)
- // 拦截所有请求
- .addPathPatterns("/**")
- // 排除登录注册修改密码等接口
- .excludePathPatterns("/oauth/**","/login/**","logout/**","/common/**", "options","/try/**","/user/updatePwd")
- // 判处swagger等接口
- .excludePathPatterns("/doc.html","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**","/favicon.ico")
- ;
- }
- }
复制代码到此这篇关于SpringBoot配置自定义拦截器实现过程详解的文章就介绍到这了,更多相关SpringBoot自定义拦截器内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟! |