> 关于apache HttpClient的超时时间始终无法超过21秒的问题
如果你是要在windows系统上运行,暂时没有找到解决方案,而如果你是linux系统,你应该不会遇到默认21秒超
时,因为linux系统默认时间是127秒超时,而如果你想修改这个值,你可以这么做
vim /etc/sysctl.conf
net.ipv4.tcp syn retries =6
sysctl -p /etc/sysctl.conf
> 上面的这个6是代表等待127秒后超时,也是默认值。你可以随意修改这个值,1代表3秒,2代表7秒.7代表255
秒,8代表511秒。假设这个值为n.则超时时间为2的n+1次方减1.
超时时间 = 2^(n+1)-1.
在 Spring 中,Propagation 和 Isolation 是 @Transactional 注解中的两个重要属性:
1、Propagation(传播行为):用于指定在一个方法被另一个方法调用时,事务如何在它们之间进行传播。以下是一些常见的传播行为:
REQUIRED:默认行为,如果当前存在事务,则在该事务内执行,否则创建一个新事务。
REQUIRES_NEW:总是会创建一个新的事务,并在它自己的事务内执行。
SUPPORTS:如果有事务存在,则在事务内执行,否则以非事务方式执行。
NOT_SUPPORTED:以非事务方式执行,并且暂停当前事务(如果存在)。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
MANDATORY:要求当前方法在一个已存在的事务内执行,如果不存在事务,则抛出异常。
2、Isolation(隔离级别):指定事务应该如何隔离其他事务的影响。不同的隔离级别可以解决并发执行时的问题,如脏读、不可重复读和幻读。
DEFAULT:默认隔离级别,数据库默认的隔离级别。
READ_UNCOMMITTED:最低级别,允许脏读,不可重复读和幻读。
READ_COMMITTED:允许避免脏读,但是仍可能出现不可重复读和幻读。
REPEATABLE_READ:在同一事务中多次读取同一数据时,结果始终相同。可以避免脏读和不可重复读,但仍可能发生幻读。
SERIALIZABLE:最高级别,通过强制事务串行执行来解决所有问题。
> 脏读(Dirty Read):一个事务读取到了另一个事务未提交的数据。
> 不可重复读(Non-Repeatable Read):在同一个事务内,同一条记录的查询返回不同的结果。这可能是因为另一个事务修改了数据并提交了。
> 幻读(Phantom Read):在同一个事务内,同一次查询操作返回不同数量的记录。这可能是因为另一个事务插入了新的数据。
查询服务进程CPU情况:top –Hp pid
查询JVM GC相关参数:jstat -gc pid 2000 (对 pid [进程号] 每隔 2s 输出一次日志)
打印当前堆栈信息:jstack -l pid >> stack.log
防抖和节流是在前端开发中用于优化性能和提升用户体验的技术。
防抖(Debouncing):
防抖是一种限制事件处理频率的技术。在用户输入(比如输入框输入、窗口大小改变、滚动等)产生的事件中,防抖会延迟执行函数的调用,直到一定时间段内没有新的事件产生。如果在这个时间段内有新事件触发,旧的事件处理函数调用会被取消,然后重新设置一个新的计时器。这样可以确保在一连串的事件中,只有最后一个事件触发后才执行相应的操作。防抖常用于处理频繁触发的事件,例如输入框输入实时搜索功能,可以减少频繁的请求和操作,提升性能和用户体验。
节流(Throttling):
节流也是限制事件处理频率的一种方法,但不同于防抖的是,节流是在一定时间间隔内只执行一次函数。无论事件触发频率多高,节流都会按照设定的时间间隔执行一次。比如,页面滚动事件,可以使用节流来确保滚动事件不会过于频繁地触发,减少事件处理函数的执行次数,以此来降低浏览器的负荷。
在实际应用中,选择使用防抖还是节流取决于具体的场景需求。如果需要在事件频繁触发时只执行一次操作,使用防抖更合适;如果需要控制事件触发的频率,确保在一段时间内只执行一次函数,就可以选择节流。
redis序列化key value乱码(转义字符或二进制)
@Component
public class RedisConfig {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* String serializer redis template redis template.
*
* @return the redis template
*/
@Bean
public RedisTemplate<String, Object> stringSerializerRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
return redisTemplate;
}
}
过滤器抛异常导致前端请求跨域:
@Component
@WebFilter(filterName = "authFilter", urlPatterns = "/*")
public class AuthFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
private RedisService redisService;
private HandlerExceptionResolver handlerExceptionResolver;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ServletContext context = filterConfig.getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
assert ctx != null;
redisService = ctx.getBean(RedisService.class);
this.handlerExceptionResolver = (HandlerExceptionResolver) ctx.getBean("handlerExceptionResolver");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
if ("OPTIONS".equals(httpServletRequest.getMethod())) {
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
return;
}
Object val = redisService.getCacheObject(UPDATE_REDIS_KEY);
if (true) {
handlerExceptionResolver.resolveException(httpServletRequest, httpServletResponse, null,
new BaseException("错误信息"));
return;
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
反爬虫从以下几点考虑:
1.设置请求频率限制:通过限制请求频率可以防止爬虫过快地访问你的应用程序。你可以使用框架如Spring Boot的限流库(例如,Guava RateLimiter或Spring Cloud Gateway的限流功能)来实现请求频率限制。
2.使用验证码:在敏感操作或者需要用户登录的接口上,添加验证码验证可以防止机器人或爬虫自动化攻击。你可以使用图形验证码或短信验证码等方式来实现。
3.User-Agent验证:检查请求中的User-Agent字段,识别是否为常见的浏览器或合法爬虫。非法的User-Agent可以被认为是爬虫,并进行相应处理。
4.IP限制:限制同一IP地址的访问频率或并发连接数,以防止爬虫过度请求。
5.验证Referer字段:验证请求的Referer字段,判断请求是否来自合法的来源。非法的Referer可以被认为是爬虫或恶意请求。
6.页面解析防护:使用一些技术手段,如动态生成页面内容、添加无意义的噪音数据或使用反爬虫技术(如反爬虫算法、动态页面加载等)来 ersal)的方式进行页面展示,增加爬虫的难度。
7.使用Cookie或Token验证:在需要用户身份验证的接口上,使用Cookie或Token进行身份验证,并校验其合法性。
Java 响应式编程中的 Flux 和 Mono 是 Reactor 框架中最常用的两种响应式流类型,它们之间的区别主要在于:
返回值个数:Flux 可以返回 0 到 N 个元素,而 Mono 只能返回 0 或 1 个元素。
触发时机:Flux 可以在任意时刻多次触发事件,而 Mono 只能在一定条件下触发一次事件(例如,一个查询操作只有在成功时才会返回一个结果)。
操作符支持:Flux 支持的操作符更多,例如 zip, flatMap, groupBy, take, reduce 等,而 Mono 仅支持一些基本的操作符,例如 map, filter, switchIfEmpty 等。
Flux 和 Mono 在响应式编程中的应用场景也有所不同。一般来说,如果你需要处理一个可以包含多个元素的流,或者需要将多个流合并在一起处理,那么你可以使用 Flux;如果你只需要处理一个单一的结果,例如一个查询操作,那么你可以使用 Mono。
需要注意的是,Flux 和 Mono 可以组合使用,例如使用 flatMap 操作符从一个 Flux 中获取 Mono 对象,然后进行异步的单个元素处理。
transient和volatile是Java中的两个关键字,它们分别用于修饰变量,可以用来实现不同的功能。
transient关键字用于修饰对象的某个字段,表示该字段不参与序列化过程。在Java中,如果一个类实现了Serializable接口,那么该类的对象可以被序列化和反序列化,即可以将对象转化为字节流并存储到文件或者传输到网络中。但有时候,我们希望某个字段不被序列化,例如密码等敏感信息。这时候就可以使用transient关键字,将该字段标记为不参与序列化的字段。
volatile关键字用于修饰变量,表示该变量是易变的,多个线程对该变量的操作会直接影响到其他线程。在Java中,多线程并发访问共享变量时,可能会出现数据不一致的问题。例如,一个线程对变量进行修改时,另一个线程读取该变量的值可能会得到一个过期的值。这时候就可以使用volatile关键字,保证多个线程对变量的操作都是可见的。当一个变量被声明为volatile时,Java会保证每个线程都能够获取该变量的最新值。
需要注意的是,volatile关键字不能保证原子性。当多个线程同时对同一个volatile变量进行写操作时,可能会出现写覆盖的情况。如果需要保证原子性,可以使用synchronized关键字或者Atomic类来实现。