首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,472 阅读
2
Nacos持久化MySQL问题-解决方案
933 阅读
3
Docker搭建Typecho博客
753 阅读
4
滑动时间窗口算法
729 阅读
5
Nginx反向代理微服务配置
701 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
3
篇与
的结果
2022-04-23
线程封闭
线程封闭当访问共享数据时,通常是要使用同步。如果要避免使用同步,就是不提供共享数据。如果仅在单线程中访问数据,就不需要同步,这种技术就叫做线程封闭,它是实现线程安全最简单的方式之一。当某个对象封闭在一个线程当中时将自动实现线程安全性,即使被封闭的对象本身它并不是安全的,实现线程主要有三种方式。实现线程封闭的三种方式:1、Ad-hoc线程封闭:程序控制实现,最糟糕,忽略2、堆栈封闭:局部变量,无并发问题:栈封闭简单理解就是通过局部变量来实现线程封闭,多个线程访问对象的同一个方法,方法内部的局部变量会拷贝到每个线程的线程栈当中,只有当前线程才能访问到,互不干扰。所以局部变量是不被多个线程所共享的。尽量少用全局变量(不是全局常量)。3、ThreadLocal线程封闭:特别好的封闭方法。维护线程封闭一种更规范的方法就是使用ThreadLocal。ThreadLocal底层是一个map,可以就是线程名字,value就是我们封装的对象。ThreadLocal提供get、set方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回的是当前线程在调用set时设置的值。ThreadLocal一般用于防止对可变的单实例变量或者全局变量进行共享。ThreadLocal使用:代码示例1、自定义ThreadLoca工具package com.yanxizhu.demo.concurrency.DemoThrodLocal.ThreadLock; /** * @description: 使用ThrodLock的线程封闭,实现在一个线程种数据共享 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 22:56 * @version: 1.0 */ public class MyThroldLock { private final static ThreadLocal<Long> requestholder = new ThreadLocal<>(); //用ThreadLock提供的set方法,向ThreadLock中放入共享数据id //一般在实际接口处理前调用 public static void add(Long id) { requestholder.set(id); } //用ThreadLock提供的get方法获取ThreadLock中共享的数据 public static Long get() { return requestholder.get(); } //用ThreadLock提供的remove方法移除共享数据,不然容易导致内存溢出 //一般在接口真正处理完后调用 public static void remove() { requestholder.remove(); } }2、自定义过滤器Filterpackage com.yanxizhu.demo.concurrency.DemoThrodLocal.filter; import com.yanxizhu.demo.concurrency.DemoThrodLocal.ThreadLock.MyThroldLock; import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @description: 自定一自己的filter,实现filter接口,注意是servlet中的 * 说明: * Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序, * 主要的用途是设置字符集、控制权限、控制转向、做一些业务逻辑判断等。其工作原理是, * 只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求, * 此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作; * 同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。 * 它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 23:02 * @version: 1.0 */ @Slf4j public class HttpFilter implements Filter { //初始化的 public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //一般需要强转成HttpServletRequest、HttpServletResponse,这样才能直接获取用户浏览器访问时携带信息 //比如获取用户session中的用户信息 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //一般登录会将用户信息写入session,这里只是演示一下 // String userName = (String) request.getSession().getAttribute("userName"); log.info("do filter,线程id {},请求地址{}", Thread.currentThread().getId(), request.getServletPath()); //通过向ThreadLock添加共享值 MyThroldLock.add(Thread.currentThread().getId()); // 所有处理完后,记得执行下面,不然不会往下执行 filterChain.doFilter(servletRequest, servletResponse); } //销毁时的 public void destroy() { } }注册自定义过滤器HttpFilterpackage com.yanxizhu.demo.concurrency.DemoThrodLocal.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @description: 将自定义的filter添加到spring拦截器中 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 23:37 * @version: 1.0 */ @Configuration public class MyFilterConfig { @Bean public FilterRegistrationBean httpFilter() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new HttpFilter()); filterRegistrationBean.addUrlPatterns("/demo/*"); return filterRegistrationBean; } }3、自定义拦截器HandlerInterceptorpackage com.yanxizhu.demo.concurrency.DemoThrodLocal.interceptor; import com.yanxizhu.demo.concurrency.DemoThrodLocal.ThreadLock.MyThroldLock; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @description: 自定义HandlerInerceptor * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 22:28 * @version: 1.0 */ @Slf4j @Component public class MyHandlerInterceptor implements HandlerInterceptor { //接口处理之前 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("进入controller之前的preHanler方法。。。。"); return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("这个是干嘛的呢。。。"); } //接口处理之后 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("之后的方法。。。。afterCompletion,MyThroldLock.remove()"); MyThroldLock.remove(); return; } }注册自定义拦截器MyHandlerInterceptorpackage com.yanxizhu.demo.concurrency.DemoThrodLocal.interceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @description: 自定义WebMVCConfig * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 22:31 * @version: 1.0 */ @Configuration public class MyWebMvcConfigurerAdapter implements WebMvcConfigurer { @Autowired MyHandlerInterceptor myHandlerInterceptor; public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/**"); } }4、编写Controller测试ThreadLock的使用package com.yanxizhu.demo.concurrency.DemoThrodLocal.controller; import com.yanxizhu.demo.concurrency.DemoThrodLocal.ThreadLock.MyThroldLock; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @description: HandlerInterceptor 拦截器测试 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/22 22:25 * @version: 1.0 */ @RestController @RequestMapping("/demo") @Slf4j public class ThreadLockController { @GetMapping("/myHandlerInterceptor") public String myHandlerInterceptorTest() { log.info("进入Controoler方法种。。。。。。"); return "My HandlerInterceptor....,共享ThreadLock的变量为:"+MyThroldLock.get(); } }测试请求地址http://127.0.0.1:8080/demo/myHandlerInterceptor页面输出结果:My HandlerInterceptor....,共享ThreadLock的变量为:46IDEA控制台输出结果:do filter,线程id 50,请求地址/demo/myHandlerInterceptor 进入controller之前的preHanler方法。。。。 进入Controoler方法种。。。。。。 这个是干嘛的呢。。。 之后的方法。。。。afterCompletion注意点注意过滤器Filter和拦截器HandlerInterceptor的区别及使用方式。可参考地址:https://blog.csdn.net/yb546822612/article/details/102950040https://blog.csdn.net/yb546822612/article/details/102950981
2022年04月23日
221 阅读
0 评论
3 点赞
2022-03-10
Feign远程调用丢失请求头问题
openFeign远程调用丢失请求头feign在远程调用之前要构造请求,调用会经过很多拦截器。丢失请求头原因,是远程调用重新构建了request请求,新的request没有请求头headr。解决方案:定义一个feign的拦截器先来看一下feign远程调用类SynchronousMethodHandler// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package feign; import feign.InvocationHandlerFactory.MethodHandler; import feign.Logger.Level; import feign.Request.Options; import feign.codec.Decoder; import feign.codec.ErrorDecoder; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; final class SynchronousMethodHandler implements MethodHandler { private static final long MAX_RESPONSE_BUFFER_SIZE = 8192L; private final MethodMetadata metadata; private final Target<?> target; private final Client client; private final Retryer retryer; private final List<RequestInterceptor> requestInterceptors; private final Logger logger; private final Level logLevel; private final feign.RequestTemplate.Factory buildTemplateFromArgs; private final Options options; private final ExceptionPropagationPolicy propagationPolicy; private final Decoder decoder; private final AsyncResponseHandler asyncResponseHandler; private SynchronousMethodHandler(Target<?> target, Client client, Retryer retryer, List<RequestInterceptor> requestInterceptors, Logger logger, Level logLevel, MethodMetadata metadata, feign.RequestTemplate.Factory buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder, boolean decode404, boolean closeAfterDecode, ExceptionPropagationPolicy propagationPolicy, boolean forceDecoding) { this.target = (Target)Util.checkNotNull(target, "target", new Object[0]); this.client = (Client)Util.checkNotNull(client, "client for %s", new Object[]{target}); this.retryer = (Retryer)Util.checkNotNull(retryer, "retryer for %s", new Object[]{target}); this.requestInterceptors = (List)Util.checkNotNull(requestInterceptors, "requestInterceptors for %s", new Object[]{target}); this.logger = (Logger)Util.checkNotNull(logger, "logger for %s", new Object[]{target}); this.logLevel = (Level)Util.checkNotNull(logLevel, "logLevel for %s", new Object[]{target}); this.metadata = (MethodMetadata)Util.checkNotNull(metadata, "metadata for %s", new Object[]{target}); this.buildTemplateFromArgs = (feign.RequestTemplate.Factory)Util.checkNotNull(buildTemplateFromArgs, "metadata for %s", new Object[]{target}); this.options = (Options)Util.checkNotNull(options, "options for %s", new Object[]{target}); this.propagationPolicy = propagationPolicy; if (forceDecoding) { this.decoder = decoder; this.asyncResponseHandler = null; } else { this.decoder = null; this.asyncResponseHandler = new AsyncResponseHandler(logLevel, logger, decoder, errorDecoder, decode404, closeAfterDecode); } } public Object invoke(Object[] argv) throws Throwable { RequestTemplate template = this.buildTemplateFromArgs.create(argv); Options options = this.findOptions(argv); Retryer retryer = this.retryer.clone(); while(true) { try { return this.executeAndDecode(template, options); } catch (RetryableException var9) { RetryableException e = var9; try { retryer.continueOrPropagate(e); } catch (RetryableException var8) { Throwable cause = var8.getCause(); if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) { throw cause; } throw var8; } if (this.logLevel != Level.NONE) { this.logger.logRetry(this.metadata.configKey(), this.logLevel); } } } } Object executeAndDecode(RequestTemplate template, Options options) throws Throwable { Request request = this.targetRequest(template); if (this.logLevel != Level.NONE) { this.logger.logRequest(this.metadata.configKey(), this.logLevel, request); } long start = System.nanoTime(); Response response; try { response = this.client.execute(request, options); response = response.toBuilder().request(request).requestTemplate(template).build(); } catch (IOException var12) { if (this.logLevel != Level.NONE) { this.logger.logIOException(this.metadata.configKey(), this.logLevel, var12, this.elapsedTime(start)); } throw FeignException.errorExecuting(request, var12); } long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); if (this.decoder != null) { return this.decoder.decode(response, this.metadata.returnType()); } else { CompletableFuture<Object> resultFuture = new CompletableFuture(); this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime); try { if (!resultFuture.isDone()) { throw new IllegalStateException("Response handling not done"); } else { return resultFuture.join(); } } catch (CompletionException var13) { Throwable cause = var13.getCause(); if (cause != null) { throw cause; } else { throw var13; } } } } long elapsedTime(long start) { return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); } Request targetRequest(RequestTemplate template) { Iterator var2 = this.requestInterceptors.iterator(); while(var2.hasNext()) { RequestInterceptor interceptor = (RequestInterceptor)var2.next(); interceptor.apply(template); } return this.target.apply(template); } Options findOptions(Object[] argv) { if (argv != null && argv.length != 0) { Stream var10000 = Stream.of(argv); Options.class.getClass(); var10000 = var10000.filter(Options.class::isInstance); Options.class.getClass(); return (Options)var10000.map(Options.class::cast).findFirst().orElse(this.options); } else { return this.options; } } static class Factory { private final Client client; private final Retryer retryer; private final List<RequestInterceptor> requestInterceptors; private final Logger logger; private final Level logLevel; private final boolean decode404; private final boolean closeAfterDecode; private final ExceptionPropagationPolicy propagationPolicy; private final boolean forceDecoding; Factory(Client client, Retryer retryer, List<RequestInterceptor> requestInterceptors, Logger logger, Level logLevel, boolean decode404, boolean closeAfterDecode, ExceptionPropagationPolicy propagationPolicy, boolean forceDecoding) { this.client = (Client)Util.checkNotNull(client, "client", new Object[0]); this.retryer = (Retryer)Util.checkNotNull(retryer, "retryer", new Object[0]); this.requestInterceptors = (List)Util.checkNotNull(requestInterceptors, "requestInterceptors", new Object[0]); this.logger = (Logger)Util.checkNotNull(logger, "logger", new Object[0]); this.logLevel = (Level)Util.checkNotNull(logLevel, "logLevel", new Object[0]); this.decode404 = decode404; this.closeAfterDecode = closeAfterDecode; this.propagationPolicy = propagationPolicy; this.forceDecoding = forceDecoding; } public MethodHandler create(Target<?> target, MethodMetadata md, feign.RequestTemplate.Factory buildTemplateFromArgs, Options options, Decoder decoder, ErrorDecoder errorDecoder) { return new SynchronousMethodHandler(target, this.client, this.retryer, this.requestInterceptors, this.logger, this.logLevel, md, buildTemplateFromArgs, options, decoder, errorDecoder, this.decode404, this.closeAfterDecode, this.propagationPolicy, this.forceDecoding); } } } 远程调用时,构建了RequestInterceptor。自定义feign拦截器import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /** * @description: TODO * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/3/10 23:03 * @version: 1.0 */ @Configuration public class FamilyFegin { @Bean(name ="requestInterceptor") public RequestInterceptor requestInterceptor(){ return new RequestInterceptor() { @Override public void apply(RequestTemplate requestTemplate) { //RequestContextHolder拿到刚请求来的数据 ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); System.out.println("调用feign之前"); //同步请求头数据 String cookie = request.getHeader("Cookie");//老数据 //给新请求同步老请求的cookie requestTemplate.header("Cookie", cookie); } }; } }拦截器说明RequestContextHolder.getRequestAttributes()获取到RequestAttributes类,RequestAttributes源码:// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package org.springframework.web.context.request; import org.springframework.lang.Nullable; public interface RequestAttributes { int SCOPE_REQUEST = 0; int SCOPE_SESSION = 1; String REFERENCE_REQUEST = "request"; String REFERENCE_SESSION = "session"; @Nullable Object getAttribute(String var1, int var2); void setAttribute(String var1, Object var2, int var3); void removeAttribute(String var1, int var2); String[] getAttributeNames(int var1); void registerDestructionCallback(String var1, Runnable var2, int var3); @Nullable Object resolveReference(String var1); String getSessionId(); Object getSessionMutex(); } ServletRequestAttributes继承了AbstractRequestAttributes,AbstractRequestAttributes实现了RequestAttributes,因此可以强转。 public abstract class AbstractRequestAttributes implements RequestAttributes { protected final Map<String, Runnable> requestDestructionCallbacks = new LinkedHashMap(8); private volatile boolean requestActive = true; public AbstractRequestAttributes() { } public void requestCompleted() {注意:该处理是在同步一个线程种处理的,才能获取之前的heard中的cookie信息。异步多线程该处理方式不同。
2022年03月10日
276 阅读
0 评论
6 点赞
2022-03-10
Springboot拦截器配置
Springboot拦截器配置1、拦截器配置,主要实现HandlerInterceptor接口import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @description: 拦截器,配合FamilyWebConfig 配置使用 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/3/10 22:36 * @version: 1.0 */ @Component public class LoginUserInterceptor implements HandlerInterceptor { public static ThreadLocal<Object> objUser = new ThreadLocal<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object loginusr = request.getSession().getAttribute("LOGIN_USR"); if(loginusr != null){ objUser.set(loginusr); //登录了才能访问 return true; }else{ //没登录,跳转去登录 return false; } } } 由于拦截器需要配合web配置使用,因此创建web配置。2、web配置主要实现WebMvcConfigurer接口import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @description: WEB配置 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/3/10 22:40 * @version: 1.0 */ public class FamilyWebConfig implements WebMvcConfigurer { @Autowired LoginUserInterceptor loginUserInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginUserInterceptor).addPathPatterns("/**"); } }
2022年03月10日
201 阅读
0 评论
2 点赞