@Anysc注解会开启一个新的线程,主线程的Request和子线程是不共享的,所以获取为null
在使用springboot的自定带的线程共享后,代码如下,Request不为null,但是偶发的其中body/head/urlparam内容出现获取不到的情况,是因为异步任务在未执行完毕的情况下,主线程已经返回,拷贝共享的Request对象数据被清空
- ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- //设置子线程共享
- RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);
- HttpServletRequest request = servletRequestAttributes.getRequest();
-
-
com.alibaba -
transmittable-thread-local -
2.11.0 -
requrest共享
通过TransmittableThreadLocal对象进行线程对象共享
- public class CommonUtil {
- public static TransmittableThreadLocal
requestTransmittableThreadLocal = new TransmittableThreadLocal(); -
- public static void shareRequest(HttpServletRequest request){
- requestTransmittableThreadLocal.set(request);
- }
-
- public static HttpServletRequest getRequest(){
- HttpServletRequest request = requestTransmittableThreadLocal.get();
- if(request!=null){
- return requestTransmittableThreadLocal.get();
- }else{
- ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- if(requestAttributes!=null){
- return requestAttributes.getRequest();
- }else{
- return null;
- }
- }
- }
-
- public static void remove(){
- requestTransmittableThreadLocal.remove();
- }
- }
注:系统中所有Request获取需要统一从CommonUtil指定来源,例如token鉴权等
- public class HttpServletRequestReplacedFilter implements Filter, Ordered {
- @Override
- public void destroy() {
-
- }
-
- @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);
- }
- //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。
- // 在chain.doFiler方法中传递新的request对象
- if (requestWrapper == null) {
- chain.doFilter(request, response);
- } else {
- chain.doFilter(requestWrapper, response);
- }
- }
-
- @Override
- public void init(FilterConfig arg0) throws ServletException {
-
- }
-
- @Override
- public int getOrder() {
- return 10;
- }
- }
-
-
- public class RequestWrapper extends HttpServletRequestWrapper{
-
- private final byte[] body;
- private final HashMap
headMap; - private final HashMap
requestParamMap; -
- public RequestWrapper(HttpServletRequest request) throws IOException {
- super(request);
- body = CommonUtil.getBodyString(request).getBytes(Charset.forName("UTF-8"));
-
- headMap = new HashMap();
- Enumeration
headNameList = request.getHeaderNames(); - while (headNameList.hasMoreElements()){
- String key = headNameList.nextElement();
- headMap.put(key.toLowerCase(),request.getHeader(key));
- }
-
- requestParamMap = new HashMap<>();
- Enumeration
parameterNameList = request.getParameterNames(); - while (parameterNameList.hasMoreElements()){
- String key = parameterNameList.nextElement();
- requestParamMap.put(key,request.getParameter(key));
- }
- }
-
- @Override
- public BufferedReader getReader() throws IOException {
- return new BufferedReader(new InputStreamReader(getInputStream()));
- }
-
- @Override
- public ServletInputStream getInputStream() throws IOException {
-
- final ByteArrayInputStream bais = new ByteArrayInputStream(body);
-
- return new ServletInputStream() {
-
- @Override
- public int read() throws IOException {
- return bais.read();
- }
-
- @Override
- public boolean isFinished() {
- return false;
- }
-
- @Override
- public boolean isReady() {
- return false;
- }
-
- @Override
- public void setReadListener(ReadListener readListener) {
-
- }
- };
- }
-
- @Override
- public String getHeader(String name) {
- return headMap.get(name.toLowerCase());
- }
-
- @Override
- public String getParameter(String name) {
- return requestParamMap.get(name);
- }
- }
用于拦截异步任务执行,在任务执前统一进行Request共享操作,且可以定义多个,不影响原有的异步任务代码
- public class CustomTaskDecorator implements TaskDecorator {
- @Override
- public Runnable decorate(Runnable runnable) {
- ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- HttpServletRequest request = requestAttributes.getRequest();
- System.out.println("异步任务共享request");
- return () -> {
- try {
- CommonUtil.shareRequest(request);
- runnable.run();
- } finally {
- CommonUtil.remove();
- }
- };
- }
- }
-
-
- @Configuration
- public class TaskExecutorConfig {
-
- @Bean()
- public Executor taskExecutor() {
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(10);
- executor.setMaxPoolSize(20);
- executor.setQueueCapacity(200);
- executor.setKeepAliveSeconds(60);
- executor.setThreadNamePrefix("taskExecutor-");
- executor.setAwaitTerminationSeconds(60);
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
- executor.initialize();
- return executor;
- }
-
- @Bean("shareTaskExecutor")
- public Executor hpTaskExecutor() {
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(10);
- executor.setMaxPoolSize(20);
- executor.setQueueCapacity(200);
- executor.setKeepAliveSeconds(60);
- executor.setThreadNamePrefix("shareTaskExecutor-");
- executor.setWaitForTasksToCompleteOnShutdown(true);
- executor.setAwaitTerminationSeconds(60);
- // 增加 TaskDecorator 属性的配置
- executor.setTaskDecorator(new CustomTaskDecorator());
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
- executor.initialize();
- return executor;
- }
- }
给@Anysc注解指定进行共享拦截的任务执行器即可
- @PostMapping("/testAsync")
- @ResponseBody
- public Object testAsync(@RequestBody Map
params) throws Exception{ - Result result = Result.okResult();
- asyncUtil.executeAsync();
- return result;
- }
-
- @Component
- public class AsyncUtil {
- @Async("shareTaskExecutor")
- public void executeAsync () throws InterruptedException {
- System.out.println("开始执行executeAsync");
- Thread.sleep(3000);
- System.out.println("结束执行executeAsync");
- }
- }