软件编程
位置:首页>> 软件编程>> java编程>> SpringBoot配置自定义 * 实现过程详解

SpringBoot配置自定义 * 实现过程详解

作者:是赵敢敢啊  发布时间:2022-11-04 17:24:48 

标签:SpringBoot,自定义,登陆, ,

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")
       ;
   }
}

来源:https://blog.csdn.net/qq_42059717/article/details/127404180

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com