IntelliJ IDEA 执行maven命令(或者自动导入maven项目)时,报如下错误:

[ERROR] Malformed \uxxxx encoding.

这个问题经常出现在本地存在多个Maven版本来回切换的时候,或者本地有多个maven项目的时候。 \uxxxx 可能是\u0000。

看起来像是某次执行maven的时候,由于maven仓库找不到或者网络异常,由于某些版本的maven bug,把maven本地仓库里某些依赖的配置文件弄乱了。(参见:https://issues.apache.org/jira/browse/MRESOLVER-216

解决办法是把有问题的artifact删除,重新执行maven命令就可以了。当然你可以直接把本地仓库目录(比如默认的~/.m2/repository/)都删掉,但是后面仍需要重新下载所有的maven依赖。最好是只把有问题的依赖删除。

如何找到有问题的artifact依赖呢?在IntelliJ IDEA里,打开Find In Files搜索框(Windows系统,快捷键ctrl+shift+f),输入\u0000 或者 \uxxxx, 选择在特定目录下搜索,选择本地maven仓库的文件夹。根据搜索结果,删除对应的artifact对应的文件夹就可以了。

2024-01-11-maven-encoding-error.png

如果习惯使用Windows命令行,也可以执行如下命令来查找有问题的依赖包。

findstr /S /M '\u0000' *.*

有个朋友从阿里云买了一台低配的轻量应用服务器,内存只有1GB,在上面部署安装了ubuntu,apache http server 2,php和mysql,使用wordpress搭了一个个人博客,系统稳定运行了一段时间。

这个朋友是写Java的,用Spring Boot开发了一个Java应用,也部署到了这台轻量服务器。为了复用域名和证书,使用了apache2的proxypass转发特定路径的请求到这个Java应用。apache2的配置大概如下:

ProxyPass "/webapp1/" "http://localhost:8080/webapp1/"
ProxyPassReverse "/webapp1/" "http://localhost:8080/webapp1/"
ProxyPreserveHost On
ProxyPassReverseCookieDomain "localhost" "xxxx.com"
ProxyPassReverseCookiePath "/webapp1/" "/webapp1/"

配置完后,重启apache2后,应用可以正常访问了。但是没过一会儿,发现Java应用无法访问了,原来的个人博客也打不开了,都提示响应超时。自己排查了很久,无从下手,于是找我来帮忙。

我首先登录了阿里云轻量应用服务器的控制台,查看实例的监控数据,发现IO突然增高,磁盘每秒读次数从个位数窜到了2000多,cpu使用率也从接近0涨到了30%左右,其他指标,比如网络流量,网络带宽都是正常的水位没有变化。

由于阿里云轻量服务器的控制台监控数据比较少,因此,我远程登录到了服务器上,发现ssh登录响应也很慢,好不容易登录进去,执行top命令,发现内存使用90%,load大概5-7左右。

仔细看了每个进程的cpu和内存占比,发现有一个进程【kswapd0】很奇怪,使用cpu特别高。网上搜索了下,这个进程是Ubuntu系统里负责换页(RAM内存和交换分区)管理的。也就意味着RAM内存不够用了。使用top命令查看进程内存的使用,发现mysqld这个进程占了40%多的内存(400多MB),再加上部署的Java Spring Boot应用(也是吃内存的大户),肯定是把1GB的内存吃光了。

当时觉得mysql服务使用400多MB内存有点奇怪,因为没多少数据量,博客的并发连接也很低,竟然占了这么多内存。于是继续网上搜索,发现mysql内存占用高,可能有很多原因,排除数据量和并发度,有一个原因是开启了mysql的performance schema(https://dev.mysql.com/doc/refman/8.0/en/performance-schema-quick-start.html) 导致吃内存的,performance schema主要是用于性能监测。个人使用其实没必要,可以关闭此特性。于是修改了my.conf配置文件:

[mysqld]
performance_schema=OFF

使用

sudo service mysql stop/start

重启mysql服务,通过top再次查看内存占比,只有17%左右了(大概170多MB),问题解决了。当然还可以继续调整mysql的配置来降低内存使用,不过已经没有必要了,性价比不高。

当然排查过程不是一帆风顺的。比如:
1)由于系统load高,曾经多次ssh登录不上去,想要通过安装iotop来查看导致io高的进程也因为系统load高而无法安装。关键时刻还是手动重启了几次服务器。
2)由于在配置apache2的proxypass来转发请求时,使用a2enmod开启了apache的几个模块,因此最开始怀疑是开启的模块有问题导致的。

当然,以上只是排查过程的记录,还有一些知识点值得后续深入了解,比如内存吃紧导致换页进程工作造成磁盘读升高,系统为啥没有杀死吃内存的进程,Java进程为啥没OOM,MySQL的performance schema的机制等等。

以上,容我喝完朋友的咖啡,再去细细研究。

原文地址:http://mybatis.org/generator/philosophy.html

由于MyBatis Generator这个工具更加聚焦在数据库表而非领域模型,因此会导致一些设计理念上的质疑。我们将会花费一些段落来讨论下这种方式。

首先,这个工具做了它该做的东西。关于这个工具,我们没有对它应该/不应该实现什么做任何声明。总的来说,我们是富领域模型(rich domain models)的坚定倡导者,但是,创建一个富领域模型和回答模型应该如何持久化并不是同一件事情。

如果你的特定设计理念是领域模型驱动其他所有决策,并且数据库设计屈从于领域模型,那么这个工具(包括MyBatis本身)可能不太适合于你的应用。在这种情况下,我们建议你认真研究下Hibernate,它可能更符合你的应用设计与理念。

但是并非所有项目都符合这一范式。甚至于几乎没有企业级的应用完全符合这个范式。MyBatis对于数据库设计和领域模型设计同等重要的项目提供了很大的帮助。MyBatis不是一个对象关系映射器,并且不会尝试把对象持久过程透明化。因此,需要应用开发者来写SQL以便于与数据库交互。

在大型或企业级项目中,很多下面的这些因素会经常出现:

  • 数据库设计与面向对象的领域设计是分开的(单独管理)。
  • 数据库设计者没有面向对象的工具(比如继承),所以,他们不会用面向对象的术语来思考。
  • 应用设计者无法完全控制数据库表的最终形态。比如对于应用来说适合放到一个对象的数据可能会被拆成数据库里的多张表中。
  • 数据库的设计往往与面向对象的设计大相径庭,导致出现表和对象显著不匹配。

以上这些因素往往预示着MyBatis能够很好的适用于你的应用,这也是MyBatis Generator能够起到很好帮助作用的项目类型。那么在这种情况下应该如何使用MyBatis呢?

数据访问对象(DAO)模式仍然是主要的模式。MyBatis Generator可以为每张表生成一组对应的基本的对象。生成的代码是事务中性的,这意味着如果要在一个事务中操作多个表,那么很容易通过在生成的代码添加事务特性来扩展实现。或者你可以创建其他的更好的匹配领域模型持久化需求的DAO(或者服务方法),配合在同一个事务中使用一个或多个生成的对象。

作为一个例子,考虑一个典型的Order对象,典型的header/detail问题。在一些环境下,这种对象至少需要持久化到4个表里,两个key表,一个header表,一个detail表(再次声明,我们这里不是说这就是正确的设计,只是在描述事实)。你的应用应该仍然是与Order对象交互,可能在某些地方(比如OrderDAO或者service对象里)有个saveOrder(Order order)方法。这个方法会与为其中每个表生成的代码来交互。

在这个案例中代码生成给我们带来了什么?几个事情:

  • 重用。很可能一些表会从多个不同的DAOs或者service方法来访问。在应用中为每个表创建一个DAO提高了重用性和一致性。
  • 数据库抽象-定义应用持久化的服务层。这些方法可以很快的稳定下来。随着数据库设计的演化:
    1、随着表结构的变更,代码可以随时重新生成
    2、service方法可以按需修改
    3、应用的上层逻辑可以保持不变。
  • 开发者效率。根据表生成DAO既快速,又可重复,并且无错误。开发者可以集中于对象的持久化,并在需要时把精力用在复杂的表连接查询上。
  • 更少的缺陷。因为应用中最繁琐最容易出错的部分(让SQL与对象匹配)已经自动化了。

项目结构类似:

petstore-parent
|--petstore-api
|--petstore-server
|--petstore-common
|--petstore-bootstrap

其他项目只依赖petstore-api这个模块,所以,只需要deploy这个模块到远程仓库就可以了。
但是petstore-api依赖petstore-parent(在父模块的pom文件中统一管理依赖和相关配置,petstore-parent的package方式为pom)
所以,需要把petstore-api和petstore-parent deploy到远程仓库。

如果在petstore-parent目录下执行mvn deploy, 会把所有的四个子模块都会deploy到远程仓库,这很明显不是我们想要的。

执行mvn deploy命令时,实际执行了maven-deploy-plugin插件,而这个插件有个配置可以设置跳过部署该模块。参考(https://maven.apache.org/plugins/maven-deploy-plugin/faq.html#skip)

<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>
    </plugins>
</build>

而针对我们上面的那个例子,为了避免在各个子模块中都增加这段配置,可以统一在父模块的POM文件中增加如下配置。

<project> 
  ...
  <properties>
    <maven.deploy.skip>false</maven.deploy.skip>
  </properties>
  ...
  <build>
      <pluginManagement>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-deploy-plugin</artifactId>
                  <configuration>
                      <skip>${maven.deploy.skip}</skip>
                  </configuration>
              </plugin>
          </plugins>
      </pluginManagement>
  </build>
  ...
</project>

然后在不需要deploy的子模块(此例子中为petstore-server, petstore-common, petstore-bootstrap)的POM文件中增加如下配置:

<properties>
    ...
    <maven.deploy.skip>true</maven.deploy.skip>
</properties>

这样在父模块的目录下执行mvn deploy时就只会deploy petstore-api和petstore-parent了。

更多参考资料(https://maven.apache.org/plugins/maven-deploy-plugin/deploy-mojo.html#skip)。值得注意的是,这个配置是Maven 2.4版本添加的,也就是2.4+的版本才支持此配置。

如果一个父项目下的子项目大部分都不需要deploy,就像我们开头提的那种场景,可以通过maven的-N(-N,--non-recursive Do not recurse into sub-projects)选项来先deploy parent pom,然后切到子项目下deploy子项目。
比如:

//in petstore-parent directory
mvn -N deploy
cd petstore-api
mvn deploy

发现去年也是今天(0131)写的年度读书报告。整好一年,记录下2020年的读书情况。

读书量

19年读了43本书,应该是有记录以来最多的一年了。20年截止到今天读了30本书。所以19年还是最多的一年。

去年读的多,当时分析主要原因是出差的来回火车上和出差地每天的地铁通勤时间比较多,再有微信读书加持。所以看了很多书。

今年呢,虽然仍然在出差,但是由于疫情,有段时间开车去出差和开车上下班,所以,读书的时间少了。另外,今年工作比去年更忙了,更累了,所以有段时间根本没心情/精力看书。综合下来读书时间确实少了。

当然,对于数量,个人心里倒是不怎么介意。读书已经成为生活的不可或缺的一部分,反而有时会因沉迷其中而自责。不管干啥,沉迷其中无法自拔总会被其所伤,有张有弛,方能从容不迫。

阅读终端

用Excel做了下数据分析,去年的时候,微信读书:纸质书:Kindle的比例是19:12:12,到了今年,就只剩下微信读书和纸质书了,比例是24:6。

原因的话,电子阅读确实方便了许多,现在机不离手,随时随地都可以看,微信阅读的免费无限卡也是香得很。

去年的flag要把家里的纸质书读完,很明显也是没有完成。反而又买了很多纸质书堆在家里。

不过有些想看的书,微信读书也没有,所以,21年,纸质书应该会多看一些,包括家里买的和去图书馆借书。

作者国籍

去年最多的是美中日(14:12:7),今年还是美中日,不过顺序稍微变了下,美日中(10:7:5),剩下的是欧洲各国加起来8。基本代表了当前世界的格局了。

题材分类

去年的时候,立了个flag,”减少虚构类的,增加非虚构类的“,这个倒是执行的不错。今年基本上读的大部分都是非虚构类的,心理学,管理学,社会科学,这些书籍看多了,总觉得道理很对,但是没经历,不思考,不实践的话,看完就忘了。

看看自己看的这些书,感觉完全不像工科毕业的,专业的书籍基本没看。21年要看一些自己专业的书籍,吃饭的家伙不能丢。

年度书籍

《自卑与超越》和《被讨厌的勇气》让我了解了阿德勒和他的个体心理学,你经历了什么不重要,怎么看待你的经历,对你更重要。《结构思考力》是今年为了做PPT特意看的,号称国内版的《金字塔原理》,个人觉得对于梳理思路和清晰表达帮助很大,比后者更容易理解。而今年的年度书籍,我把它送给《最好的告别》,人终有一死,如何向死而生,面对衰老与死亡,涉及到的方方面面都讲到了。

去年立的flag完成情况

-把家里买了没读的纸质书读完:没完成,今年又买了好多。

-专题阅读-历史方向:历史的貌似一本没读,-_-||

-不追求数量,精读,读经典,有输出:未完成,貌似就看完了毛姆的三部曲之后写了一篇公众号。

-减少虚构类的,增加非虚构类的:完成还可以,虚构类只占1/6。

2021继续立flag

反正flag就是用来被打破的,继续立flag。

-继续消灭家里的存书,减少电子阅读量。

-增加专业书阅读量。

-减少漫无目的很散的阅读,增加专题阅读。

-控制数量,慢慢读。