JsonParser解析json字符串双引号问题

** 今天在项目 中使用到了JsonParser解析json字符串为JsonArray或者JsonObject,解析之后使用 如下代码获取到的字符串多了一层 “”(双引号) **

JSON字符串格式如下

** 如果将这样的字符串直接设值在 yaml 文件中,那么设置完成后的 yaml文件如下: **

** 调试查看之后发现 Jarray.get(k) 获取得到的是 JsonPrimitive对象(会在字符串外面再加一对引号) **

** 弄清楚原因之后我们只要在 Jarray.get(k) 之后再对对象取值就可以了 **

参考链接


JsonParser解析json字符串双引号问题

Jakarta EE - Java EE的终结者

什么是 Jakarta EE

Jakarta EE并不是新技术,他的前身就是大家熟悉的Java EE,老一辈的程序员可能还记得J2EE,是的,他们都是同一个东西,至于为什么会改来改去,这里面就有很多故事了。

1998年12月,SUN公司发布了JDK1.2,开始使用Java 2 这一名称,第二年Sun公司联合IBM、Oracle、BEA等大型企业应用系统开发商共同制订了一个基于Java组件技术的企业应用系统开发规范,名字很自然就取为Java 2 Platform Enterprise Edition简称J2EE,后面的事情大家也知道,JDK版本升的很快,J2EE名称如果跟着Java版本走必然会给开发人员造成困惑不利于该技术的推广,终于在2006年,SUN公司在发布Java 5后正式将J2EE改名为Java EE(Java Platform, Enterprise Edition),很多早期j2ee开发者虽然现在用的是最新的java ee标准但他们还是认为自己在用j2ee,当然,只是名称的改变并没有给开发者带来什么麻烦,相比之下下面这个就是要命。

2009年,Oracle宣布收购SUN,Java相关技术自然归Oracle所有,在2017年,Oracle 宣布开源 Java EE 并将项目移交给 Eclipse 基金会,但Oracle移交的很不痛快,提了很多要求,其中就包括不能再使用Java EE这个名称,虽然有点无理但Eclipse基金会还是接受了这个要求并且改名为Jakarta EE,经历了从j2ee到java ee的改名再经历一次似乎也无所谓,但要命的是Oracle要求Jakarta EE不能修改javax命名空间,这个就意味着java ee移交后代码就此封版,如果想修改代码,不好意思,请另起炉灶,所以,Oracle你移交的意义在哪?

那么从Java EE到Jakarta EE会给企业带来什么影响?下面我们一起分析。

名称的转变

这个对企业影响不大,对开发者影响也不大,你可以愉快用着Jakarta EE最新标准的同时跟同事说java ee发布新版本了。

命名空间的转变

如果你是用Maven进行开发,那么Java EE的依赖是这么定义的

我们可以看到groupId是javax,并且源码的结构如下:

所有的源码都定义在javax.*这个路径下,根据Oracle的要求Jakarta EE不能修改javax命名空间,那么Jakarta EE只能将代码中javax修改为jakarta,因此最新版本Jakarta Maven描述是长这样的:

源码目录:

可以看到除了顶层包名称不一样下面的定义都一样,那么包路径更改会有什么影响?影响非常大。

  • 所有java ee应用服务器比如Weblogic,GlassFish等如果要支持最新版本的jakarta ee就必须修改源码重新编译,并且如果支持了jakarta ee就无法支持java ee,也就是无法向前兼容,Tomcat虽然只是Servlet容器但是Servlet本身就是Java EE的一部分,因此也逃不过修改的命运。据说Tomcat可以对应用进行自动代码转换以支持jakarta,因此在不远的将来我们可以看到各种奇技淫巧去兼容jakarta,是不是想起了被IE支配的恐惧。
  • 企业如果需要用到jakarta ee最新特性必须修改现有代码,修改并不复杂,就是把代码中import javax.*替换为import jakarta.*,修改完重新编译打包部署,似乎很简单,事实上没那么简单。
  • 对企业来说,保持应用服务器处于最新版本是必须的,因为新版本可能修复了老版本的漏洞,并且性能上也可能有一定的提升,但如果升级应用服务器的同时也要修改源码代码就很大,修改的成本,带来的风险并不是所有企业都能接受的。
  • 假设修改了一个应用,那么就需要部署到新版本应用服务器上,由于新服务器不兼容老应用因此需要运维两套应用服务器,运维成本提高,两套应用服务器也可能涉及license问题,不知道各厂商要怎么解决这个问题。

总之企业面临两难的境地,要么升级改系统源码,要么保持不变不升级,要么部分升级运维两套应用服务器,刀刀都要命。

未来

在如今各种诸如spring boot框架的包装下,在应用层面已经找不到Java EE的影子了,这些框架完全有能力抛弃jakarta自己实现,对于这些框架来说,跟随jakarta的意义似乎不大。对于企业来说,拥抱spring boot已经大势所趋,Java EE又搞出这么一件事,只会更加坚定企业转型的决心。对于开发者来说,Java EE已经是古董级的技术,Spring Boot不香吗,有什么理由去用jakarta EE。Oracle似乎也是看到了Java EE行将就木就索性移交出去,还能换取Eclipse基金会的董事会席位,但我还是看不懂Oracle对Java EE致命的这一刀目的何在,weblogic和中间件也是Oracle重要的两块业务,这两块业务都依赖Java EE,这么做只会两败俱伤。

参考


PBKDF2加密的实现

PBKDF2(Password-Based Key Derivation Function)

通过哈希算法进行加密。由于哈希算法是单向的,能够将不论什么大小的数据转化为定长的“指纹”,并且无法被反向计算。

另外,即使数据源仅仅修改了一丁点。哈希的结果也会全然不同。

这种特性使得它很适合用于保存password。由于我们须要加密后的password无法被解密,同一时候也能保证正确校验每一个用户的password。可是哈希加密能够通过字典攻击和暴力攻击破解。

password加盐。盐是一个加入到用户的password哈希过程中的一段随机序列。

这个机制可以防止通过预先计算结果的彩虹表破解。每一个用户都有自己的盐,这种结果就是即使用户的password同样。通过加盐后哈希值也将不同。

为了校验password是否正确,我们须要储存盐值。通常和password哈希值一起存放在账户数据库中。或者直接存为哈希字符串的一部分。

首先要生成一个盐值salt,再把原始passwordsalt加密得到密文。验证的时候,把用户输入的password和同样的盐值salt使用同样的加密算法得到一个密文,将这个密文和原密文相比較,同样则验证通过,反之则不通过。


測试结果为:

参考链接


Robolectric 3.x编写屏幕分辨率/多语言/资源文件相关测试用例

在编写 Android 测试用例的时候,有时候我们需要涉及到屏幕分辨率相关测试用例。

比如不同分辨率得到不同的像素数值,可以参考如下:

比如不同语言得到不同的字符串,可以参考如下:

其他相关的测试参数,参考 Device Configuration

注意需要在 build.gradle 中增加资源包含信息,否则在测试的时候会找不到指定的资源文件,默认只测试代码,被测试的资源文件不打包进入应用。

参考如下:

参考链接


动态Java代码注入(JDK/Android)

JDK下使用javax.tools.JavaCompiler进行动态代码的生成,编译,执行。

在本文中,我们将研究如何将Java代码动态加载到正在运行的jvm中。 该代码可能是全新的,或者我们可能想更改程序中某些现有代码的功能。

(在开始之前,您可能想知道为什么到底有人会这样做。显而易见的示例是规则引擎之类的东西。规则引擎希望为用户提供添加或更改规则的能力,而不必重新启动规则。您可以通过将DSL脚本作为规则注入,由规则引擎调用此方法,这种方法的真正问题是必须对DSL脚本进行解释,使其运行起来非常缓慢。然后可以像程序中的任何其他代码一样编译和运行该程序,效率将提高几个数量级。

我们将要使用的库是Chronicle开源库Java-Runtime-Compiler 。

从下面的代码中您将看到,该库的使用极其简单-实际上,它实际上只需要几行。 创建一个CachedCompiler,然后调用loadFromJava。 (有关实际最简单的用例,请参见此处的文档。)

下面列出的程序执行以下操作:

  1. 创建一个线程,该线程每秒调用一次Strategy。
  2. 加载将两个数字相加的策略
  3. 等待3秒
  4. 加载从另一个数中减去一个数的策略

这是完整的代码清单:

这是输出:

请注意,在每次加载策略时,在代码中我们都创建了一个新的ClassLoader和一个CachedCompiler。 这样做的原因是,ClassLoader一次只能加载一个特定类的一个实例。

如果仅使用该库来加载新代码,则可以这样做,而无需创建ClassLoader(即使用默认的ClassLoader)和CachedCompiler。

Android下使用由于无法使用javax.tools.JavaCompiler,因此使用 linkedin/dexmaker 进行动态代码的生成,编译,执行。

参考链接


Java Socket 实现HTTP与HTTPS协议发送POST/GET请求

JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求

        哇,一看标题怎么这么长啊,其实意思很简单,哥讨厌用HTTP Client做POST与GET提交觉得那个毕竟是别人写得API库,所以我就自己实现了一个简单的HTTP客户端,支持POST方式提交数据,GET方式查询数据,是测试Restful API比较方便点,然后支持form与JSON两种方式提交数据,当然也支持返回数据为JSON格式.当然这些东西都是基于JAVA Socket直接完成的,不借助任何第三方的库,主要是JDK的API其实已经够用啦. 当然我也没有用URLConnect这个东西,毕竟它在Socket基础上又包装了一下,有违我写这篇文章的目的.

        好啦,讲完理由,下面就说说要怎么样才能实现啊,光说不练假把式啊!大致分了几个步骤

        一:当然是要知道HTTP协议,知道常用的HTTP请求头,比如Host, Accept, Content-Type 知道HTTP协议支持的方法,常用有GET/POST/PUT/DELETE等如果不知道,也不用担心,我保证你读完这篇文章,你就知道一些啦,当然有个最好的参考文档就是HTTP相关的RFC文档,认真读一下肯定解决你自己心中的HTTP那些疑惑

       二: 知道发送HTTP GET与POST格式很重要, 固定的格式如下:

       [REQUEST]<SP><URL><SP>[HTTP VERSION]<CLRF>
       [REQUEST HEADER: ]<SP>[VALUE]<CLRF>
       可以有多个请求头
       最后<CLRF>
       发送完HTTP请求头部以后, 针对不同请求如POST要发送内容部分,发送完成以后同样,以<CLRF>结尾.
       解释: <SP>表示空格, <CLRF>表示回车换行JAVA中表示为”\r\n”REQUEST表示HTTP请求命令,可以为POST, GET, PUT, DELETE等之一,HTTP VERSION的常见可能值为HTTP/1.1或者HTTP/1.0

     三: 如果1与2的知识你都具备了,下面就来介绍一下JAVA Socket的相关知识,如何创建一个JAVA客户端套接字Socket s = new Socket()如此即可,简单吧!如何连接到远程的主机与端口, 当提供URL字符串时候,可以这么做

   即可连接到远程主机,下面就可以请求文章内容了, 也很容易的

最后也是最重要的一点,字符编码,尽量都用同一种字符编码来发 送请求数据,推荐使用utf-8测试程序, 我写两个简单的PHP文件放 在wamp server上,完成对全部代码的测试。

四:关于HTTP与HTTPS

        HTTP协议是位于第四层协议TCP之上完成的应用层协议, 端到端都是明文传送,别人一旦网络抓包以后都可以看到你的提交与请求数据,这个好像不太安全. HTTP协议的默认端口是80这个是RFC文档声明的,属于官方标准,没什么道理可以讲.HTTPS是基于SSL加密传输的,这样别人截获你的数据包破解的概率要小一点,比HTTP安全一点,其默认端口是443, 好像QQ邮箱与谷歌的WEB Mail邮箱都是基于HTTPS. 但是HTTPS通信方式只是传输数据加密,都客户端来说是透明的,它还是一样要遵守HTTP协议规范来发送POST与GET请求等.完整的测试程序如下:

http协议实现:

想要成为支持HTTPS客户端, 只要在创建Socket的时候如下:

https协议实现:

所以有时候离开apache的HTTP Client等第三方Jar,程序员也是一样活!

参考链接


Java Socket 实现HTTP与HTTPS协议发送POST/GET请求

HttpClient利用MultipartEntityBuilder取代MultipartEntity上传图片文件到服务器

注意:在HttpClient4.3之后,原来的上传文件方法MultipartEntity已经不建议使用,现替换成新的httpmime下面的MultipartEntityBuilder。

需要添加httpclient-4.5.jar、httpmime-4.5.jar两个包

maven添加:


下面我们对比一下MultipartEntity和MultipartEntityBuilder的使用区别:

MultipartEntityBuilder:

MultipartEntity:

直接上替换后的测试代码:


继续阅读HttpClient利用MultipartEntityBuilder取代MultipartEntity上传图片文件到服务器

正则表达式 - 字符匹配不以某字段开头或者结尾

正则表达式 - 字符匹配不以某字段开头或者结尾

最近有一个需求,要求是判断某个字符串不以什么开头。然后就开始探索这个不以什么开头和不易什么结尾的正则怎么写,why?

不以某字符串开头

这里需要提一个概念叫 否定式前项匹配 这个东东。

向前匹配

根据匹配的字符序列后面存在一个特定的字符序列或者不存在一个特定的序列来决定是否匹配。对于向前匹配,出现在指定项后面的字符序列不会被正则表达式返回。

这里说后面存在一个特定字符序列, 也称之为肯定式向前查找
不存在一个特定的序列,也称之为否定式向前查找
这两个概念后续再深入

开始解决这个问题不以某字符串开头:

这里使用了下面几个元符号:

  1. ^ 判断是否是开头
  2. ?! 这里是否定向前查询

示例:

  1. 不以test 开头字符串

继续阅读正则表达式 - 字符匹配不以某字段开头或者结尾

Spring Boot实现异步任务

Spring Boot中的另外一个任务:异步任务。所谓异步任务,其实就是异步执行程序,有些时候遇到一些耗时的的任务,如果一直卡等待,肯定会影响其他程序的执行,所以就让这些程序需要以异步的方式去执行。那么下面就来介绍Spring Boot 如何实现异步任务。

一、使用注解@EnableAsync 开启异步调用方法

在application启动类中,加上@EnableAsync注解,Spring Boot 会自动扫描异步任务。

二、创建异步执行类,定义@Component及@Async组件

创建com.weiz.tasks包,在tasks包里增加AsyncTask 异步任务类,加上@Component 注解,然后在需要异步执行的方法前面加上@Async注解,这样Spring Boot容器扫描到相关异步方法之后,调用时就会将这些方法异步执行。

说明:@Async 加上这个注解,就表示该方法是异步执行方法。

三、调用

创建一个DoTask调用类,我们看看这几个方法,是怎么执行的:

继续阅读Spring Boot实现异步任务