SpringBoot實(shí)現(xiàn)任意位置獲取HttpServletRequest對(duì)象
任意位置獲取HttpServletRequest對(duì)象
方法一
//獲取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ù)邏輯,通過(guò)filter讀取請(qǐng)求的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ù)讀取請(qǐng)求
**/
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;
// 防止流讀取一次后就沒(méi)有了, 所以需要將流繼續(xù)寫(xiě)出去
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注解,則不驗(yàn)證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 {
/**
* 獲取請(qǐng)求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();
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 在 Spring Boot 中使用異步線程時(shí)的 HttpServletRequest 復(fù)用問(wèn)題記錄
- SpringBoot異步線程父子線程數(shù)據(jù)傳遞的5種方式
- Spring?Boot異步線程間數(shù)據(jù)傳遞的四種方式
- springboot?正確的在異步線程中使用request的示例代碼
- SpringBoot?異步線程間傳遞上下文方式
- SpringBoot獲取HttpServletRequest的3種方式總結(jié)
- SpringBoot詳細(xì)講解異步任務(wù)如何獲取HttpServletRequest
- Spring Boot 中正確地在異步線程中使用 HttpServletRequest的方法
相關(guān)文章
mysql高版本(8.0+)group_by報(bào)錯(cuò)的處理方法
本文主要介紹了mysql高版本(8.0+)group_by報(bào)錯(cuò)的處理方法,這個(gè)錯(cuò)誤一般發(fā)生在mysql 5.7以及 5.7以上的版本中,本文就來(lái)介紹一下兩種解決方法,感興趣的可以了解一下2023-09-09
通過(guò)Java修改游戲存檔的實(shí)現(xiàn)思路
這篇文章主要介紹了通過(guò)Java修改游戲存檔的實(shí)現(xiàn)思路,實(shí)現(xiàn)方法也很簡(jiǎn)單,因?yàn)橹参锎髴?zhàn)僵尸游戲的數(shù)據(jù)文件存儲(chǔ)在本地的存儲(chǔ)位置是已知的,因此我們可以將實(shí)現(xiàn)過(guò)程拆分為三個(gè)步驟,需要的朋友可以參考下2021-10-10
java并發(fā)編程專題(八)----(JUC)實(shí)例講解CountDownLatch
這篇文章主要介紹了java CountDownLatch的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
SpringBoot如何獲取application.properties中自定義的值
這篇文章主要介紹了SpringBoot獲取application.properties中的自定義的值,目錄結(jié)構(gòu)文件代碼給大家列舉的非常詳細(xì),需要的朋友可以參考下2021-09-09
MyBatis-plus使用lambda條件構(gòu)造器報(bào)錯(cuò)問(wèn)題及解決
這篇文章主要介紹了MyBatis-plus使用lambda條件構(gòu)造器報(bào)錯(cuò)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問(wèn)題
這篇文章主要介紹了解決Swagger2返回map復(fù)雜結(jié)構(gòu)不能解析的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07

