- 博客(140)
- 收藏
- 关注
转载 java 8 Stream中操作类型和peek的使用
简介java 8 stream作为流式操作有两种操作类型,中间操作和终止操作。这两种有什么区别呢?我们看一个peek的例子:Stream<String> stream = Stream.of("one", "two", "three","four"); stream.peek(System.out::println);上面的例子中,我们的本意是打印出Stream的值,但实际上没有任何输出。为什么呢?中间操作和终止操作一个java 8的stream是由三部分组成的。
2022-04-30 17:57:24 2644
原创 怎么在java 8的map中使用stream
简介Map是java中非常常用的一个集合类型,我们通常也需要去遍历Map去获取某些值,java 8引入了Stream的概念,那么我们怎么在Map中使用Stream呢?基本概念Map有key,value还有表示key,value整体的Entry。创建一个Map:Map<String, String> someMap = new HashMap<>();获取Map的entrySet:Set<Map.Entry<String, String>> en
2022-04-30 17:55:47 1755
原创 在java 8 stream表达式中实现if/else逻辑
简介在Stream处理中,我们通常会遇到if/else的判断情况,对于这样的问题我们怎么处理呢?还记得我们在上一篇文章lambda最佳实践中提到,lambda表达式应该越简洁越好,不要在其中写臃肿的业务逻辑。接下来我们看一个具体的例子。传统写法假如我们有一个1 to 10的list,我们想要分别挑选出奇数和偶数出来,传统的写法,我们会这样使用:public void inForEach(){ List<Integer> ints = Arrays.asList(1, 2, 3
2022-04-30 17:53:47 6821
原创 Lambda表达式最佳实践
简介Lambda表达式java 8引入的函数式编程框架。之前的文章中我们也讲过Lambda表达式的基本用法。本文将会在之前的文章基础上更加详细的讲解Lambda表达式在实际应用中的最佳实践经验。优先使用标准Functional接口之前的文章我们讲到了,java在java.util.function包中定义了很多Function接口。基本上涵盖了我们能够想到的各种类型。假如我们自定义了下面的Functional interface:@FunctionalInterfacepublic inter
2022-04-30 17:48:09 258
原创 java并发Exchanger的使用
简介Exchanger是java 5引入的并发类,Exchanger顾名思义就是用来做交换的。这里主要是两个线程之间交换持有的对象。当Exchanger在一个线程中调用exchange方法之后,会等待另外的线程调用同样的exchange方法。两个线程都调用exchange方法之后,传入的参数就会交换。类定义public class Exchanger<V>其中V表示需要交换的对象类型。类继承java.lang.Object↳ java.util.concurrent.Excha
2022-04-30 17:44:35 2960
转载 java 8 Streams简介
简介java 8引入了lambda表达式,lambda表达式实际上表示的就是一个匿名的function。在java 8之前,如果需要使用到匿名function需要new一个类的实现,但是有了lambda表达式之后,一切都变的非常简介。我们看一个之前讲线程池的时候的一个例子://ExecutorService using class ExecutorService executorService = Executors.newSingleThreadExecutor();
2022-04-30 17:41:07 152
转载 java内存模型(JMM)和happens-before
java内存模型(JMM)和happens-before我们知道java程序是运行在JVM中的,而JVM就是构建在内存上的虚拟机,那么内存模型JMM是做什么用的呢?我们考虑一个简单的赋值问题:int a=100;JMM考虑的就是什么情况下读取变量a的线程可以看到值为100。看起来这是一个很简单的问题,赋值之后不就可以读到值了吗?但是上面的只是我们源码的编写顺序,当把源码编译之后,在编译器中生成的指令的顺序跟源码的顺序并不是完全一致的。处理器可能采用乱序或者并行的方式来执行指令(在JVM中只要程
2022-04-30 17:37:50 238
原创 java中的daemon thread
java中的daemon threadjava中有两种类型的thread,user threads 和 daemon threads。User threads是高优先级的thread,JVM将会等待所有的User Threads运行完毕之后才会结束运行。daemon threads是低优先级的thread,它的作用是为User Thread提供服务。 因为daemon threads的低优先级,并且仅为user thread提供服务,所以当所有的user thread都结束之后,JVM会自动退出,不管
2022-04-29 17:13:35 1340
转载 java中interrupt,interrupted和isInterrupted的区别
java中interrupt,interrupted和isInterrupted的区别前面的文章我们讲到了调用interrupt()来停止一个Thread,本文将会详细讲解java中三个非常相似的方法interrupt,interrupted和isInterrupted。isInterrupted首先看下最简单的isInterrupted方法。isInterrupted是Thread类中的一个实例方法: public boolean isInterrupted() { retu
2022-04-29 17:12:49 944
原创 java中的Atomic类
java中的Atomic类问题背景在多线程环境中,我们最常遇到的问题就是变量的值进行同步。因为变量需要在多线程中进行共享,所以我们必须需要采用一定的同步机制来进行控制。通过之前的文章,我们知道可以采用Lock的机制,当然也包括今天我们讲的Atomic类。下面我们从两种方式来分别介绍。Lock在之前的文章中,我们也讲了同步的问题,我们再回顾一下。 如果定义了一个计数器如下:public class Counter { int counter; public void incr
2022-04-29 17:11:30 279
原创 怎么在java中关闭一个thread
怎么在java中关闭一个thread我们经常需要在java中用到thread,我们知道thread有一个start()方法可以开启一个线程。那么怎么关闭这个线程呢?有人会说可以用Thread.stop()方法。但是这个方法已经被废弃了。根据Oracle的官方文档,Thread.stop是不安全的。因为调用stop方法的时候,将会释放它获取的所有监视器锁(通过传递ThreadDeath异常实现)。如果有资源该监视器锁所保护的话,就可能会出现数据不一致的异常。并且这种异常很难被发现。 所以现在已经不推荐是
2022-04-29 17:10:41 3148
原创 java中join的使用
java中join的使用join()应该是我们在java中经常会用到的一个方法,它主要是将当前线程置为WAITTING状态,然后等待调用的线程执行完毕或被interrupted。join()是Thread中定义的方法,我们看下他的定义:/*** Waits for this thread to die.** An invocation of this method behaves in exactly the same* way as the invocation* * {@lin
2022-04-29 17:01:22 4096
原创 java中线程的生命周期
java中线程的生命周期线程是java中绕不过去的一个话题, 今天本文将会详细讲解java中线程的生命周期,希望可以给大家一些启发。java中Thread的状态java中Thread有6种状态,分别是:NEW - 新创建的Thread,还没有开始执行RUNNABLE - 可运行状态的Thread,包括准备运行和正在运行的。BLOCKED - 正在等待资源锁的线程WAITING - 正在无限期等待其他线程来执行某个特定操作TIMED_WAITING - 在一定的时间内等待其他线程来执行某个特
2022-04-29 16:56:59 121
原创 java中ThreadLocal的使用
java中ThreadLocal的使用ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问。在定义ThreadLocal的时候,我们可以同时定义存储在ThreadLocal中的特定类型的对象。ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();上面我们定义了一个存储Integer的ThreadLocal对象。要存储和获取ThreadLocal中的对象也非常简单,使用get()和
2022-04-29 16:55:52 3110 1
原创 springboot~security中自定义forbidden和unauthorized返回值
对于spring-security来说,当你访问一个受保护资源时,需要检查你的token,当没有传递,或者传递的token有错误时,将出现401unauthorized异常;当你传递的token是有效的,但解析后并没有访问这个资源的权限时,将返回403forbidden的异常,而你通过拦截器@RestControllerAdvice是不能重写这两个异常消息的,我们下面介绍重写这两种消息的方法。两个接口AccessDeniedHandler 实现重写403的消息AuthenticationEntryPo
2022-04-27 11:21:30 914
原创 算法~如何将整数按着类型分段
如何将整数按着类型分段,即有个数字3,它可以表示类型1里的计数3;有个数字10005,它可以表求类型2里的5,这种设计主要用在类型和数字关系紧密的场景,向ThreadPoolExecutor用到了这种设计,ThreadPoolExecutor中的runState和workCount机制,实现在一个int变量中,存储这两种信息,如何实现的?`位运算基础位运算保证的运算的结果是2的n次幂// i = 10: 十进制 是10,二进制是 1010// i << 1: 左移1位,二进制变为 10
2022-04-27 11:20:33 212
原创 springboot~@ConditionalOnMissingBean一切为了可扩展性
@ConditionalOnMissingBean在很多spring框架里都得到很广泛的应用,如spring-boot-starter-security,spring-cloud-starter-oauth2中的应用。注意@ConditionalOnMissingBean这种注解需要添加在@Bean上面,而不是添加到@Service,@Component等上面。主要是根本的使用方法,而本篇主要阐述它在可扩展性上的应用,通过一个例子来说明问题,以讲故事的方式来阐述给大家听:从前,有一个接口,它提供.
2022-04-27 11:19:35 825 3
原创 springboot~为接口添加动态代理
为接口添加动态代理,不需要添加接口实现,通过定义FactoryBean的方式实现,将自定义业务在InvocationHandler接口实现即可ImportBeanDefinitionRegistrarImportBeanDefinitionRegistrar注入FactoryBean到SpringIOC中,而在FactoryBean中定义了类型T的动态代理,通过对InvocationHandler接口的实现来添加自定义行为,这里使用jdk默认的代理,只支持接口类型。使用场景当需要为某个接口动态添加
2022-04-27 11:17:19 1741
原创 springboot~容器化环境获取真实IP地址
首先,后端项目springboot,前端项目VUE,两个都是运行在docker容器里,通过k8s进行编排的。获取真实的客户端IP地址一 需要在前端VUE的宿主nginx中,添加请求头规则location /api { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_head
2022-04-27 11:16:40 2506
原创 keycloak~自定义directgrant直接认证
direct grant我们把它理解为通过rest接口直接认证,这是oauth2里的密码认证方式,即grant_type=password,它不需要走授权码这种复杂的流程,相当于传统的表单认证;keycloak事实上为我们准备了一个direct grant,只不过它只能使用username和password进行认证,如果你希望使用email,phoneNumber来进行密码认证,则需要另外去开发,下面就是开发的步骤:添加provider和providerFactory你的SelfDirectGrant
2022-04-27 11:15:47 718
原创 keycloak~jconsole监控wildfly和jboss
keycloak运行在wildfly(jboss)中,如果希望查询它在jboss中的运行情况,如堆内存,线程,GC等,可以通过jconsole进行远程监控。注意通过jconsole连接keycloak时,我们从keycloak中将jboss-cli-client.jar(放到jconsole.bat同级目录的bin/client下面)文件下载到windows客户端,从keycloak下载的jconsole.bat来启动它,如果使用JVM自带的jconsole是无法连接jboss服务器的,这一点我测试了很
2022-04-27 11:14:27 369
原创 跨域Cookie的读取
cookie的几个属性1 httpOnly:true 表示禁止客户端读cookie,即只能在服务端读取它2 SameSite:用来限制第三方 Cookie,从而减少安全风险。Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。Set-Cookie: CookieName=CookieValue; SameSite=Strict;Lax规则稍稍放宽,大多数情况也是不发送第三方 Co
2022-04-26 12:36:23 4227
原创 keycloak~管理平台的查询bug与自定rest中文检索
对于keycloak来说,它的管理平台在它的源码中的admin-client中,它会定义相关的rest接口规范;在我们使用keycloak管理平台时,其中有一个组的查询,在我们查询中文组时,它是不支持的,经过测试和mysql日志监控得到原因:keycloak rest使用javax.ws.rs包下面的注解,在使用@QueryParam注解来接收url参数时,当出现中文时,它实现是一个urlEncode的字符它本身不会对字段进行urlDecode的操作,所以我们自己要做;而spring框架帮我们作了这事,
2022-04-26 12:33:14 186
原创 maven~nexus开启游客下载
对于nexus这个私服务来说,匿名默认是不能下载包的,需要在nexus服务端进行配置配置添加nexus私服<!-- nexus下载包配置 --><repositories> <repository> <id>maven-public</id> <url>http://192.168.0.203:8081/repository/maven-public/</url>
2022-04-26 12:31:50 486
原创 springboot~thymeleaf为vue传递模型
非前后分离项目,后端页面想使用前端vue的mvvm思想,想使用iview强大的交互性,这时,可以使用thymeleaf+vue来实现,thymeleaf提供了后端页面引擎,vue支持在html页面上直接编译执行。后端依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>
2022-04-26 12:31:08 1769
原创 springboot~disruptor异步队列
DisruptorDisruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。Java内置队列的问题介绍Disruptor之前,我们先来看一看常用的线程安全的内置队列有什么问题。Java的内置队列如下表所示。队列的底层一般分成三种:数组、链表和堆。其中,堆一般情况下是为了实现带有优先级特性的队列,暂且不考虑。从数组和链表两种数据结构来看,基于数组线程安全的队列,比较典型的是ArrayBlockingQu
2022-04-26 12:30:16 1618
原创 Springboot~@Cacheable非侵入式缓存
如今,spring早已经集成了这个技术,并且得到了广大的应用。添加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.3.0.RELEASE</version></dependency>开启缓
2022-04-26 12:29:01 131
原创 FunctionalInterface~一个批量处理数据的类
主要使用了一个委托的方式 ,函数式接口,将需要处理的业务逻辑以参数的方式传到方法里,而批量处理的方法代码比较固定,所以进行了抽象。/** * 数据处理辅助类. */public class DataHelper { static Logger logger = LoggerFactory.getLogger(DataHelper.class); /** * 分页处理逻辑. * * @param total * @param mapper * @param q
2022-04-26 12:27:50 131
原创 Jboss~引用的中文乱码问题
对于运行在linux系统下的jboss容器来说,它会有默认的JAVA_OPTS配置,主要用来控制JVM的内存,而还有一点需要注意的,默认情况下,它的字符集不是utf-8,所以在jboss下面的中文是不会被正常显示的,这时,需要我们去修改jboss里的字符集。默认JAVA_OPTS JBoss Bootstrap Environment JBOSS_HOME: /opt/jboss/keycloak JAVA: java JAVA_OPTS: -server -Xms64m -Xmx
2022-04-26 12:26:31 716
原创 shade~实现打包多个关联包并过滤配置文件
使用maven-shade-plugin插件可以帮我们把多个依赖包打包一个jar包,并且在打包时可以帮我们过滤一些文件,比如每个依赖包里都有application.properties文件,在打包时这个文件会进行合并,这对于使用者来说是不希望的,它们更希望自己去写配置信息,所以在打包时,应该把配置文件过滤掉。下面代码帮我们实现了关联包合并及过滤配置文件<build> <plugins> <plugin>
2022-04-25 18:36:42 537
原创 keycloak~自定义redirect_uri的方法
在使用keycloak集成springboot的过程中,对于需要授权访问的接口,它会跳到keycloak里进行登录,之前有个redirect_uri,登录成功后会跳回本客户端,而这个地址默认没有修改的地方,需要我们手动开发,这块不是很方便。自定义redirect_uri一 重写BeanPostProcessor来实现@Componentpublic class KeycloackAuthenticationProcessingFilterPostProcessor implements BeanP
2022-04-25 18:36:01 978
原创 Activiti~相关概念
概念模型Model,主要是我们绘制的工作流程,它由一个个节点组成,一个流程必须要有开始节点和结束节点。ACT_RE_MODEL,节点Node,节点是组成流程的基本元素,节点又分为很多类型,我们经常用到的也就是启动事件,结束事件,用户活动,网关列表-互斥网关,并行网关等等。部署流程Deployment,将模型发布出去的过程叫做一个部署,同一个模型可以被部署多次,每一次部署都可以理解为一个版本,一般的,我们的模型发生变化后,都需要发布一个版本,让之后产生的流程保持最新版本。ACT_RE_DEPL
2022-04-25 18:35:22 1606 1
原创 maven~本地仓库的指定
默认情况下,你的maven仓库在当前用户目前下,有个.m2的文件夹,里面的settings.xml是配置maven的,而repository就是本地的仓库,而我们的仓库随着项目的增多,也会越来越大,这时你放在主硬盘上是不好的,我们应该把这个仓库放到外挂磁盘上。例如:外挂盘目录为/mnt,我们可以在上面建立目录maven_repository,然后去修改settings.xml即可。<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
2022-04-25 18:34:21 1986
原创 lombok~@SneakyThrows注解让代码更优雅
我们知道,java里的异常分为Exception和RuntimeException两大类,RuntimeException异常会由运行时帮我们进行捕获,统一进行处理;而Exception异常是受检异常(Checked Exception),需要我们自己在代码里显示的声明和处理。RuntimeException异常的代表llegalArgumentExceptionIllegalAnnotationExceptionEncodingExceptionException的代表IOExcepti
2022-04-25 18:33:19 3650
原创 java~lombok的@Data引发的问题
我们问题lombok是可以精简我们的代码的,让开发人员把精力放在业务上,而它封装的注解我们在使用时,需要多注意一下;@Data注解它是一个混合注释,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能,而我们问题@EqualsAndHashCode是重写equals和hash的注释,如果你是一个类,那可以不关心它;而如果你的类中有继承(父类子类),那么就要注意一下了。危险的@Data子类不能完全代表父类
2022-04-25 18:32:08 1197
原创 maven~生成spotbug文档
对于maven的一些插件来说,它们也都有着自己的依赖关系,建议把依赖的包和插件也写到pom里,如果你不写,在mvn时,它会自己去下载,如图:如果你希望生成spotbug文档,你可以添加下面的几个插件,注意它们的版本号,需要对应清楚 <plugins> <!-- 代码检查 --> <plugin> <groupId>org.apache.maven.plugins</gr
2022-04-25 18:31:16 1711 1
原创 springboot~拦截器的使用场景
在用户登陆之后,我们一般会把用户登陆的状态和相关信息进行存储,把对应的token返回到客户端进行存储,下次请求过来时,系统可以通过token拿到当前这个用户的相关信息,这是授权通常的作法,而有时一些业务里,你存储的用户信息不是全局的,可能只是某几个接口会用户某些信息,而你把它存储起来就不是很合理;并且一些隐私信息持久化到redis也不合理,这时就需要统一对这种接口的请求做一起处理了。拦截器HandlerInterceptor我们可以去实现这个HandlerInterceptor接口,它会把请求页面前,请
2022-04-24 17:46:30 1226
原创 springboot~redis正确的使用
redis实现了对数据的缓存,在项目里一些字典数据,会话数据,临时性数据都会向redis来存储,而在springboot里对redis也有支持,一般来说多个线程共同使用一个redis实现是有线程安全的风险的,而每个实现一个线程又太浪费资源,无法控制线程数量是非常危险的,所以就出现了一些redis线程池组件,下面说一下两个主要的组件。jedis 线程池主要是每个实例有自己的线程,线程可以从它建立的池子里获取lettuce lettuce是 apache推出的线程池工具,它的redis实例是可以被多个线程共
2022-04-24 17:45:39 1016
原创 springboot~CommandLineRunner接口实现自动任务加载
CommandLineRunner接口可以实现任务的自动加载,当项目启动完后,就会自动去执行CommandLineRunner接口里的run方法,你可以实现多个CommandLineRunner的实例,使用order来控制执行的顺序!/** * 项目启动后自动运行的代码CommandLineRunner */@Component@Order(1)public class MyStartupRunner1 implements CommandLineRunner { private Log
2022-04-24 17:44:37 1847 1
原创 k8s~fluentd的configmap设置es索引前缀
对于fluentd这个组件来说,你是负责抓取日志的,它可以从docker的控制台里抓取,也可以从指定文件夹里抓取,对于文件夹里存储的日志文件,我们需要先配置logback,然后再进行fluentd的configmap的配置,这样才能把持久化的日志抓取出来,并推送到elastic这种存储介质里。logback控制存储位置<?xml version="1.0" encoding="UTF-8"?><configuration> <property name="logP
2022-04-24 17:43:22 1462
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人