SpringBoot實現(xiàn)任意位置獲取HttpServletRequest對象
任意位置獲取HttpServletRequest對象
方法一
//獲取RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); //從獲取RequestAttributes中獲取HttpServletRequest的信息 HttpServletRequest request = (HttpServletRequest)requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
方法二
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest();
HttpServletRequest只能讀取一次的解決
業(yè)務(wù)邏輯,通過filter讀取請求的request,獲取token,并將token傳遞后面流程使用
BodyReaderHttpServletRequestWrapper:
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8")); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } }
RepeatReadFilter:
/** * 封裝HttpServletRequest為可重復(fù)讀取請求 **/ public class RepeatReadFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; // 防止流讀取一次后就沒有了, 所以需要將流繼續(xù)寫出去 ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest); //獲取用戶憑證 String token = httpServletRequest.getHeader(Constants.USER_TOKEN); if(StringUtils.isBlank(token)){ token = httpServletRequest.getParameter(Constants.USER_TOKEN); } //=================獲取json格式的token字段========================= String body = HttpHelper.getBodyString(requestWrapper); if (StringUtils.isNotBlank(body)) { JSONObject jsonObject = JSONObject.parseObject(body); Object obj = jsonObject.get("token"); if (null != obj) { token = obj.toString(); } } requestWrapper.setAttribute(Constants.USER_TOKEN,token); chain.doFilter(requestWrapper, response); } @Override public void destroy() { } }
FilterConfig:
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean registFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new RepeatReadFilter()); registration.addUrlPatterns("/app/*"); registration.setName("UrlFilter"); registration.setOrder(1); return registration; } }
AuthorizationInterceptor:
@Component public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { AuthIgnore annotation; if(handler instanceof HandlerMethod) { annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class); }else{ return true; } //如果有@AuthIgnore注解,則不驗證token if(annotation != null){ return true; } //獲取用戶憑證 String token = request.getHeader(Constants.USER_TOKEN); if(StringUtils.isBlank(token)){ token = request.getParameter(Constants.USER_TOKEN); } if(StringUtils.isBlank(token)){ Object obj = request.getAttribute(Constants.USER_TOKEN); if(null!=obj){ token=obj.toString(); } } //token憑證為空 if(StringUtils.isBlank(token)){ throw new AuthException(Constants.USER_TOKEN + "不能為空", HttpStatus.UNAUTHORIZED.value()); } return true; } }
WebMvcConfig:
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Autowired private AuthorizationInterceptor authorizationInterceptor; // @Autowired // private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**"); super.addInterceptors(registry); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { //argumentResolvers.add(loginUserHandlerMethodArgumentResolver); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { } }
在filter中讀取token,在interceptor中進(jìn)行讀取判斷使用
HttpHelper:
public class HttpHelper { /** * 獲取請求Body * * @param request * @return */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- 在 Spring Boot 中使用異步線程時的 HttpServletRequest 復(fù)用問題記錄
- SpringBoot異步線程父子線程數(shù)據(jù)傳遞的5種方式
- Spring?Boot異步線程間數(shù)據(jù)傳遞的四種方式
- springboot?正確的在異步線程中使用request的示例代碼
- SpringBoot?異步線程間傳遞上下文方式
- SpringBoot獲取HttpServletRequest的3種方式總結(jié)
- SpringBoot詳細(xì)講解異步任務(wù)如何獲取HttpServletRequest
- Spring Boot 中正確地在異步線程中使用 HttpServletRequest的方法
相關(guān)文章
java并發(fā)編程專題(八)----(JUC)實例講解CountDownLatch
這篇文章主要介紹了java CountDownLatch的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07SpringBoot如何獲取application.properties中自定義的值
這篇文章主要介紹了SpringBoot獲取application.properties中的自定義的值,目錄結(jié)構(gòu)文件代碼給大家列舉的非常詳細(xì),需要的朋友可以參考下2021-09-09MyBatis-plus使用lambda條件構(gòu)造器報錯問題及解決
這篇文章主要介紹了MyBatis-plus使用lambda條件構(gòu)造器報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問題
這篇文章主要介紹了解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07