SpringBoot配置自定義攔截器實(shí)現(xiàn)過(guò)程詳解
1. HttpServletRequest包裝類
因?yàn)镠ttpServletRequest只能讀取一次,所以需要對(duì)request進(jìn)行包裝,變成可重復(fù)讀的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.*;
/**
* 由于流只能讀取一次,所以使用此包裝類對(duì)HttpServletRequest對(duì)象進(jìn)行包裝,讀取完之后再將
* 內(nèi)容塞回去,不影響后續(xù)springmvc的參數(shù)處理。
*/
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傳遞下去
因?yàn)閒ilter是在request前邊執(zhí)行的,所以我們需要使用一個(gè)filter將我們包裝好的request傳遞下去,讓后邊使用的request都是我們包裝好的,防止出現(xiàn)流已經(jīng)被讀取的錯(cuò)誤出現(xiàn)
package net.lesscoding.filter;
import net.lesscoding.interceptor.RequestWrapper;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @apiNote 傳遞request的過(guò)濾器
*/
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. 添加攔截器
這里我們添加一個(gè)判斷用戶登錄狀態(tài)的攔截器,從 request中獲取token信息,查詢r(jià)edis如果redis存在則用戶已經(jīng)登錄,否則就返回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失效,請(qǐng)重新登錄");
}
// 這里為了方便 成功之后就刷新在redis中的時(shí)間
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. 全局異常處理器
使用全局異常處理器捕獲攔截器拋出的異常信息,做統(tǒng)一返回
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. 配置攔截器
對(duì)攔截器進(jìn)行注冊(cè),指定攔截哪些url請(qǐng)求
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 對(duì)項(xiàng)目進(jìn)行配置攔截器
*/
@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)
// 攔截所有請(qǐng)求
.addPathPatterns("/**")
// 排除登錄注冊(cè)修改密碼等接口
.excludePathPatterns("/oauth/**","/login/**","logout/**","/common/**", "options","/try/**","/user/updatePwd")
// 判處swagger等接口
.excludePathPatterns("/doc.html","/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**","/favicon.ico")
;
}
}到此這篇關(guān)于SpringBoot配置自定義攔截器實(shí)現(xiàn)過(guò)程詳解的文章就介紹到這了,更多相關(guān)SpringBoot自定義攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式
這篇文章主要介紹了JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot整合Retry實(shí)現(xiàn)錯(cuò)誤重試過(guò)程逐步介紹
重試的使用場(chǎng)景比較多,比如調(diào)用遠(yuǎn)程服務(wù)時(shí),由于網(wǎng)絡(luò)或者服務(wù)端響應(yīng)慢導(dǎo)致調(diào)用超時(shí),此時(shí)可以多重試幾次。用定時(shí)任務(wù)也可以實(shí)現(xiàn)重試的效果,但比較麻煩,用Spring Retry的話一個(gè)注解搞定所有,感興趣的可以了解一下2023-02-02
java遠(yuǎn)程連接調(diào)用Rabbitmq的實(shí)例代碼
本篇文章主要介紹了java遠(yuǎn)程連接調(diào)用Rabbitmq的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
IDEA創(chuàng)建web項(xiàng)目出現(xiàn)404錯(cuò)誤解決方法
今天先來(lái)搭建一個(gè)web工程,工程搭建好運(yùn)行時(shí)發(fā)現(xiàn)404,本文主要介紹了IDEA創(chuàng)建web項(xiàng)目出現(xiàn)404錯(cuò)誤解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
Java Spring開(kāi)發(fā)環(huán)境搭建及簡(jiǎn)單入門示例教程
這篇文章主要介紹了Java Spring開(kāi)發(fā)環(huán)境搭建及簡(jiǎn)單入門示例,結(jié)合實(shí)例形式分析了spring環(huán)境搭建、配置、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-11-11
Intellij IDEA的一些調(diào)試技巧(小結(jié))
本篇文章主要介紹了Intellij IDEA的一些調(diào)試技巧(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
JPA?通過(guò)Specification如何實(shí)現(xiàn)復(fù)雜查詢
這篇文章主要介紹了JPA?通過(guò)Specification如何實(shí)現(xiàn)復(fù)雜查詢,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11

