221125-Android Studio 报错(Installed Build Tools revision 3x.0.0 is corrupted)解决方法

由于谷歌应用市场要求编译sdk最低为31,最近升级却发现一直有问题,重复卸载、下载好几次,提示都一样

编译报错:Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager

下面的解决方案适用于win系统

220824-基于引入包选择具体实现类的使用姿势小结

最近遇到一个需求场景,开源的工具包,新增了一个高级特性,会依赖json序列化工具,来做一些特殊操作;但是,这个辅助功能并不是必须的,也就是说对于使用这个工具包的业务方而言,正常使用完全不需要json相关的功能;如果我强引用某个json工具,一是对于不适用高级特性的用户而言没有必要;二则是我引入的json工具极有可能与使用者的不一致,会增加使用者的成本

因此我希望这个工具包对外提供时,并不会引入具体的json工具依赖;也就是说maven依赖中的<scope>设置为provided;具体的json序列化的实现,则取决于调用方自身引入了什么json工具包

那么可以怎么实现上面这个方式呢?

220809-实战小技巧20:巧用函数方法实现二维数组遍历

对于数组遍历,基本上每个开发者都写过,遍历本身没什么好说的,但是当我们在遍历的过程中,有一些复杂的业务逻辑时,将会发现代码的层级会逐渐加深

211231-Java调用本地程序的几种姿势

作为一个后端同学,经常被安全的小伙伴盯上,找一找安全漏洞;除了常说的注入之外,还有比较吓人的执行远程命令,唤醒本地应用程序等;然后有意思的问题就来了,写了这么多年的代码,好像还真没有尝试过用java来唤醒本地应用程序的

比如说一个最简单的,打开本地的计算器,应该怎么搞?

接下来本文将介绍一下如何使用java打开本地应用,以及打开mac系统中特殊一点的处理方式(直白来说就是不同操作系统,使用姿势不一样)

211228-Jar文件提取与查看

最近遇到一个奇怪的问题,一个jar包无法解压,直接使用jar xvf xxx.jar没有任何响应

因为实际想看的只是jar包中的某个class文件,基于此可以通过 jar tf 查看文件列表,在通过 jar xf xxx.jar xxxfile的方式来解压指定文件来实现目的

接下来记录一下jar包的几个操作case

211220-JDNI注入:RMI之绕过trustURLCodebase配置的注入实例演示

上一篇博文介绍了RMI绑定一个Reference,导致加载远程class文件时导致的注入问题,当时有提到对于高级的版本,对于默认的配置为java.rmi.server.useCodebaseOnly=false,对于远程的class文件做了安全校验的,但是即便如此,也并没能完全限制住注入

接下来我们来实例演示一下

211216-JDNI注入:RMI Reference注入问题

前面一篇介绍了基础的RMI的使用case JDNI注入:RMI基本知识点介绍 - 一灰灰Blog,其中有说到客户端通过rmi访问server时,表现和我们常见的rpc也一致,客户端拿到代理执行的方法,也是在远程服务端执行的,怎么就存在注入问题呢?

接下来我们再来看一个知识点,RMI + Reference,利用反序列化来实现注入

211213-JDNI注入:RMI基本知识点介绍

远程方法调用,现在更多的使用RPC来处理,至于RMI好像没有那么多了,最近闹的火热的log4j2漏洞,又让几个关键词jndi,rmi,ldap频繁出现;对于我这种面向Spring编程的javer而言,这些是啥? 干嘛用的?为啥漏洞这么多?

接下来简单学习下RMI的基本知识点

211209-Java使用URI.create()注意事项

记录一个在实际使用过程中遇到的问题,在解析一个url格式的字符串中的域名时,直接使用下面这种姿势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static ImmutablePair</**host*/String, /**uri*/String> foramtUri(String uri) {
// uri中空格去除,避免转换异常
URI u = URI.create(uri);
String host = u.getHost();
if (u.getPort() > 0 && u.getPort() != 80) {
host = host + ":80";
}

String baseUri = u.getPath();
if (u.getFragment() != null) {
baseUri = baseUri + "#" + u.getFragment();
}

if (StringUtils.isNotBlank(baseUri)) {
baseUri = host + baseUri;
} else {
baseUri = host;
}

return ImmutablePair.of(host, baseUri);
}

正常使用上面这种进行解析,没啥问题,结果某天突然抛了个异常

211126-Java实现位图转矢量图

通过前面几篇图片转字符、灰度图的文章介绍之后,接下来我们再来看一个有意思的东西,基于前文的基础,实现位图转矢量图的功能

关于位图与矢量图的简单理解如下:

  • 位图:如Jpg/png,放大之后会失真,看到像素块
  • 矢量图:如svg,放大图片也不会失真

211122-Java实现GIF图转字符动图实例demo

上一篇文章介绍了静态图转字符的实现demo;接下来也该是动态图转字符的demo了

从前面几篇文章的学习过程中,要想实现这个功能就属于信手拈来了

211121-Java实现图片转字符输出示例demo

前面几篇博文介绍了使用jdk来对图片做一些有意思的转换,接下来我们再介绍一个有意思的玩法,直接根据图片,输出一个二维字符数组,实现用字符来实现绘画的场景

211120-Java实现Gif图转字符动图

前面介绍了两篇基于jdk实现图片灰度处理、转字符图片的操作,接下来我们在将之前的能力扩展一下,支持将一个gif图灰度化或者转gif字符图

211116-Java实现图片转字符图片示例demo

前面介绍了一篇java实现图片灰度化处理的小demo,接下来再介绍一个有意思的东西,将一个图片转换成字符图片

211112-Java实现图片灰度化

本文通过一个简单的实例,演示如何使用java来实现图片灰度化处理,主要借助下面两种策略来处理颜色

灰度化公式

1
avgColor = red * 0.299f + green * 0.587f + blue * 0.114f

均值方式

1
avgColor = (red + green + blue) / 3.0f

211108-封装一个根据路径获取文件资源的工具类

通常我们最多的场景是从本地资源中读取文件,这个时候我们经常需要注意的是相对路径、绝对路径问题;

除了从本地获取文件之外,从网络中获取文件资源(如图片)也属于相对常见的场景,接下来我们封装一个工具类,可以支持以上各种类型的数据读取

211102-实战小技巧18:Map转换的几种方式

在日常开发过程中,从一个Map转换为另外一个Map属于基本操作了,那么我们一般怎么去实现这种场景呢?有什么更简洁省事的方法么?

211028-Email发送失败问题记录

最近升级了一下SpringBoot的版本,结果发现之前工作的好好的邮件突然罢工了,罢工的原因还不止一个,接下来记录一下解决方案

211011-构建一个创建Map的工具类来辅助理解可变传参

虽说java作为编译语言,但是它本身也提供了很多运行时能力,今天介绍一个非常基础的知识点,可变参数传递

210903-实战小技巧17:随机数生成怎么选

每天一个实战小技巧,随机数生成怎么选

随机数生成,java中有一个专门的Random类来实现,除此之外,使用Math.random的也比较多,接下来我们简单学习下,随机数的使用姿势

210901-实战小技巧15:如何判断类为基础类型or基础类型的包装类

每天一个实战小技巧,判断类为基础类型or基础类型的包装类

判断一个类是否为基础类型属于常规操作了,一般我们遇到这种case,要怎么处理呢?

一个一个的if/else判断? 还是其他的操作姿势?

210830-实战小技巧14:配置文件Properties

每天一个实战小技巧,Properties配置文件

properties配置文件,相信各位小伙伴都不会太陌生,常用Spring的可能会经常看到它,虽说现在更推荐的是使用Yaml配置文件,但是properties配置文件的使用频率也不低

在jdk中有一个直接关连的类Properties,接下来我们来看一下它的用法

210826-实战小技巧13:进制转换很简单

每天一个实战小技巧,进制转换很简单

进制转换,属于基本技能了,在java中要实现进制转换很简单,可以非常简单的实现,接下来我们来看下它的使用姿势

210825-实战小技巧12:数字格式化

每天一个实战小技巧,数字格式化

数字的格式化场景,更多的是在日志输出、金额计算相关的领域中会用到,平常我们可能更多使用String.format来格式化,但是请注意,数字格式化是有一个DecimalFormat,专门来针对数字进行格式化

今天我们的知识点就是DecimalFormat来实现数字格式化

210821-实战小技巧11:数组拷贝

每天一个实战小技巧,数组拷贝

说实话,在实际的业务开发中,基本上很少很少很少…会遇到数组拷贝的场景,甚至是我们一般都不怎么用数组,List它不香嘛,为啥要用数组

现在问题来了,要实现数组拷贝,怎么整?

210820-实战小技巧10:不可变容器

每天一个小技巧:不可变容器

不可变容器,看着好像在实际的业务中不怎么会用到,但实则不然,相信每个小伙伴都用过,或者看到过下面的代码

1
2
Collections.emptyList();
Collections.emptyMap();

今天我们来介绍一下如何使用不可变容器,以及使用时的注意事项

210819-实战小技巧9:List.subList使用不当StackOverflowError

实战小技巧:List.subList使用不当StackOverflowError

相信每个小伙伴都使用过List.subList来获取子列表,日常使用可能没啥问题,但是,请注意,它的使用,很可能一不小心就可能导致oom

210818-实战小技巧8:容器的初始化大小指定

每天一个实战小技巧:容器的初始化大小指定

容器可以说是我们日常开发中,除了基本对象之外,使用最多的类了,那么平时在使用的时候,是否有主意到良好编程习惯的大佬,在创建容器的时候,一般会设置size;那么他们为什么要这么干呢?是出于什么进行考量的呢?

今天我们将针对最常见的List/Map/Set三种容器类型的初始化值选择,进行说明

210817-实战小技巧7:排序比较要慎重

每天一个实战小技巧:排序比较要慎重

今天介绍的又是一个非常非常基本的基本知识点,为啥要单独拎出来?还是因为这个东西虽然非常简单,但是很容易掉坑,我已经遇到几次不严谨的写法了

210816-实战小技巧6:枚举的特殊用法

每天一个实战小技巧:枚举的特殊用法

难道我们日常使用的枚举还有什么特殊的玩法不成?没错,还真有,本文主要介绍枚举的两种不那么常见的使用姿势

  • 利用枚举来实现单例模式
  • 利用枚举来实现策略模式

210814-实战小技巧5:驼峰与下划线互转

每天一个实战小技巧:驼峰与下划线划转

这个考题非常实用,特别是对于我们这些号称只需要CURD的后端开发来说,驼峰与下划线互转,这不是属于日常任务么;一般来讲db中的列名,要求是下划线格式(why? 阿里的数据库规范是这么定义的,就我感觉驼峰也没毛病),而java实体命名则是驼峰格式,所以它们之间的互转,就必然存在一个驼峰与下划线的互转

今天我们就来看一下,这两个的互转支持方式

210812-实战小技巧4:优雅的实现字符串拼接

每天一个实战小技巧,字符串拼接

相信没有小伙伴没有写过这样的代码,比如说现在让我们来实现一个字符串拼接的场景,怎样的实现才算是优雅的呢?

210811-实战小技巧3:字符串与容器互转

每天一个实战小技巧:字符串与Collection的互转

将字符串转换为List,这种业务场景可以说非常非常常见了,实现方式也比较简单

1
2
3
4
public List<String> str2list(String str, String split) {
String[] cells = str.split(split);
return Arrays.asList(cells);
}

那么除了上面这种实现方式之外,还有其他的么?

210810-实战小技巧2:数组与list互转

每天一个实战小技巧:数组与list互转

这个考题比较常见,也比较简单,难道就这也有什么可以说到的门路不成?

接下来本文好好的说一说它的几种实现姿势,总有一款你喜欢的

210809-实战小技巧:字符串占位替换-JDK版

字符串占位替换,相信没有小伙伴是陌生的,这东西可以说是伴随着我们所有的项目工程,编码过程;别不相信,如

  • String.format
  • sql参数拼接的占位
  • log日志输出

接下来我们看一下在我们的日常工作生涯中,经常涉及到的几种占位替换方式

210518-String#format数量不匹配抛异常

偶然发现一个问题,在使用String.format进行格式化输出时,发现参数个数不匹配时,会抛出异常,如

1
String msg = String.format("hello %s, %s", "a");

上面这个执行之后,会抛MissingFormatArgumentException异常,提示信息如

1
java.util.MissingFormatArgumentException: Format specifier '%s'

210514-IDEA代码修改不生效,需要mvn install问题记录

最近用idea开发一个项目,遇到一个鬼畜的问题,代码修改之后,启动测试发现不生效,只有重新mvn clean install之后才能加载到改动的代码

这就有点过分了,怀疑是idea的配置问题导致的,没有什么特别好的办法,只能删配置重新导入

  • 删除 .idea文件夹
  • 删除 *.iml文件
  • 重新导入项目

210512-IDEA 项目module无法导入问题记录

idea一个项目有多个module,忽然发现一个module显示不太正常,如

一般有两种方法,基本的如:

  • 选中pom.xml,右键
  • maven
  • unignore Projects

210412-JDK 常见并发控制手段

单实例的并发控制,主要是针对JVM内,我们常规的手段即可满足需求,常见的手段大概有下面这些

  • 同步代码块
  • CAS自旋
  • 阻塞队列,令牌桶等

210225-分页遍历的两种使用姿势

在日常开发中,分页遍历迭代的场景可以说非常普遍了,比如扫表,每次捞100条数据,然后遍历这100条数据,依次执行某个业务逻辑;这100条执行完毕之后,再加载下一百条数据,直到扫描完毕

那么要实现上面这种分页迭代遍历的场景,我们可以怎么做呢

本文将介绍两种使用姿势

  • 常规的使用方法
  • 借助Iterator的使用姿势

210129-Java对象内存地址输出

当一个对象没有重写hascode方法时,它返回的内存地址,当覆盖之后,我们有什么办法获取对象的内存地址么?

  • 使用 System.identityHashCode() 输出内存地址

210121-StringUtils字符串分割使用姿势异常记录

字符串分割,属于比较常见的case了,在实际开发中,相信很多小伙伴会借助common-lang工具包中的StringUtils来实现,使用姿势也很简单

1
String[] ans = StringUtils.split("a,b,c", ",");

一般来讲上面这种使用方式没有问题,但是当分隔符前后为空时,需要特别注意,可能会和你预期的返回不一致

210107-Spring工具类之基本元素判断

实际业务开发中偶尔会遇到判断一个对象是否为基本数据类型,除了我们自老老实实的自己写之外,也可以借助Spring的 BeanUtils 工具类来实现

1
2
3
4
5
// Java基本数据类型及包装类型判断
org.springframework.util.ClassUtils#isPrimitiveOrWrapper

// 扩展的基本类型判断
org.springframework.beans.BeanUtils#isSimpleProperty

201121-Mac android studio 4.1 missing essential plugin问题解决

android studio 4.1 禁用一个插件之后重启,结果发现应用都起不来了,直接报了一个错误

这就有点尴尬了,禁用一个插件直接导致不可用,那么能想到的解决办法就是将这个插件启用,问题是应用都跪了,怎么启用插件呢?

201021-LRU算法急速实现版

借助LinkedHashMap飞速实现一个LRU算法的缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.LinkedHashMap;
import java.util.Map;

/**
* 基于LinkedHashMap实现的LRU算法
* Created by @author yihui in 17:36 20/10/19.
*/
public class LruCache<K, V> extends LinkedHashMap<K, V> {
private int size;

public LruCache(int size) {
super(size, 0.75f, true);
this.size = size;
}

@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// 当元素个数,超过指定的大小时,淘汰最老的数据
return size() > size;

}

public static void main(String[] args) {
LruCache<String, Integer> cache = new LruCache<>(4);
for (int i = 0; i < 6; i++) {
cache.put("key_" + i, i);
System.out.println(cache);
}

System.out.println(cache.size);
}
}

201010-Android A WebView method was called on thread JavaBridge

Android开发过程中,偶遇一个webview与android通信的问题,提示A WebView method was called on thread 'JavaBridge'. All webview methods must be called...

这个问题发现Android 9以上会出现,解决方法是@JavascriptInterface注解的方法必须指定在UI线程执行,将原来方法里的代码放入run里面执行即可

如下

1
2
3
4
5
6
// 注意这个activity就是webview所在的activity
H5DetailActivity.this.runOnUiThread(new Runnable() {
public void run() {
webView.loadUrl("javascript:initBookList('" + ans + "')");
}
});

200821-Android webview内嵌h5基础使用说明

Android可以通过webview来内嵌html页面,从而实现灵活的信息展示;最近客串android开发中,正好遇到了这样的一个小场景,所以简单的记录一下Android与html之间的交互,包含以下内容

  • webview的基本设置
  • Andriod调用js方法
  • js调用android方法
  • 图片长按下载

200817-谷歌内购服务教程与避雷指南

最近客串了一把android开发,对接谷歌的内购商品,这个过程真的是特别不顺,各种意想不到的坑,一踩一个;

接下来记录一下谷歌内购服务的完整配置流程,以及在最后测试阶段可能遇到的各种问题;在正式开始之前,请确定以下基本条件

  1. 科学上网
  2. 准备gmail邮箱
  3. 准备google play账号(地区不要选择中国大陆,因为不支持购买)
  4. 授权开启商家账号
  5. 准备测试机(谷歌服务四件套得有)

200430-Java实现AES ECP PKCS5Padding加解密工具类

Java 实现一个AES/ECB/PKCS5Padding 加解密算法工具类

  • 加密算法: AES
  • 模式: ECB
  • 补码方式: PKCS5Padding
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×