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
投稿
猜你喜欢
- 线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序
- 个人理解:把一个类里的多个命令分离出来,每个类里放一个命令,实现解耦合,一个类只对应一个功能,在使用命令时由另一个类来统一管理所有命令。缺点
- 一、基本介绍 1、介绍学习很多算法知识,力争做到最优解的学习过程中,很多时候都会遇到PriorityQueue(优先队列)。一个基
- 本文实例讲述了dotNet中的反射用法。分享给大家供大家参考,具体如下:参考MSDN:ms-help://MS.VSCC.2003/MS.M
- clone() 方法麻烦一些,需要将所有涉及到的类实现声明式接口 Cloneable,并覆盖Object类中的clone()方法,并设置作用
- 本文实例为大家分享了C#支付宝新版支付请求接口调用的具体代码,供大家参考,具体内容如下因为支付宝已经集成了完整的SDK,所以可以使用SDK直
- Dotnet中嵌入资源(位图、图标或光标等)有两种方式,一是直接把资源文件加入到项目,作为嵌入资源,在代码中通过Assembly的GetMa
- 问题springcloud 版本 为 Finchley.RELEASEspringboot 版本为 2.0.3.RELEASE现在有需求,/
- 最近的需求有一个自动发布的功能, 需要做到每次提交都要动态的添加一个定时任务代码结构1. 配置类package com.orion.ops.
- C#中Invoke的用法()invoke和begininvoke 区别一直对invoke和begininvoke的使用和概念比较混乱,这两天
- using System;using System.Runtime.InteropServices;using System.Windows
- 本文简单介绍如何动态创建接口interface的实现实例对象,包含两个知识点:1.如何获取接口interface的所有实现实例对象?2.如何
- 注:作者使用IDEA + Gradle注:需要有一定的java SpringBoot and SSM+Springcloud基础程序测试错误
- 概述在以下示例中,将介绍在PDF文档页面设置页面切换按钮的方法。示例中将页面切换按钮的添加分为了两种情况,一种是设置按钮跳转到首页、下页、上
- 前言服务消费者调用服务提供者的时候使用RestTemplate技术存在不便之处:拼接urlrestTmplate.getForObJect这
- 本文实例讲述了Android实现跑马灯效果的方法。分享给大家供大家参考。具体如下:运行效果截图如下:直接在布局里写代码就好了:<Tex
- 首先我们应该清楚的是JDK1.6和JDK1.7中String类的intern方法还是有差别的: JDK1.6中的int
- 一、算术运算符算术运算符的作用和在数学中的作用一样,主要的算术运算符有以下几种1、+加2、-减3、*乘4、/除5、%取余其中加、减、乘、除的
- 1.服务配置中心1.1 服务配置中心介绍首先我们来看一下,微服务架构下关于配置文件的一些问题:1.配置文件相对分散。在一个微服务架构下,配置
- Stream流多字段求和、汇聚实现方法利用Collectors.toMap(Function keyMapper, Function val