JAVA 拾遗 --eqauls 和 hashCode 方法

缘起—lombok 引发的惨案

Lombok 是一种 Java™ 实用工具,可用于帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注解实现这一目的。

最近一个新项目中开始使用了 lombok,由于其真的是太简单易懂了,以至于我连文档都没看,直接就上手使用了,引发了一桩惨案。


JAVA 拾遗--JPA 二三事

记得前几个月,spring4all 社区刚搞过一次技术话题讨论:如何对 JPA 或者 MyBatis 进行技术选型?传送门:http://www.spring4all.com/article/391 由于平时工作接触较多的是 JPA,所以对其更熟悉一些,这一篇文章记录下个人在使用 JPA 时的一些小技巧。补充说明:JPA 是一个规范,本文所提到的 JPA,特指 spring-data-jpa。

tips:阅读本文之前,建议了解值对象和实体这两个概念的区别。

使用 @Embedded 关联一对一的值对象

现实世界有很多一对一的关联关系,如人和身份证,订单和购买者…而在 JPA 中表达一对一的关联,通常有三种方式。下面就以订单(Order)和购买者(CustomerVo)为例来介绍这三种方式,这里 CustomerVo 的 Vo 指的是 Value Object。


JAVA 拾遗 --Instrument 机制

最近在研究 skywalking,发现其作为一个 APM 框架,比起作为 trace 框架的 zipkin 多了一个监控维度:对 JVM 的监控。而 skywalking 集成进系统的方式也和传统的框架不太一样,由于其需要对 JVM 进行无侵入式的监控,所以借助了 JAVA5 提供的 Instrument 机制。关于“Instrument”这个单词,没找到准确的翻译,个人理解为“增强,装配”。


研究优雅停机时的一点思考

开头先废话几句,有段时间没有更新博客了,除了公司项目比较忙之外,还有个原因就是开始思考如何更好地写作。远的来说,我从大一便开始在 CSDN 上写博客,回头看那时的文笔还很稚嫩,一心想着反正只有自己看,所以更多的是随性发挥,随意吐槽,内容也很简陋:刷完一道算法题记录下解题思路,用 JAVA 写完一个 demo 之后,记录下配置步骤。近的来看,工作之后开始维护自己的博客站点: www.cnkirito.moe 也会同步更新自己公众号。相比圈子里其他前辈来说,读者会少很多,但毕竟有人看,每次动笔之前便会开始思考一些事。除了给自己的学习经历做一个归档,还多了一些顾虑:会不会把知识点写错?会不会误人子弟?自己的理解会不会比较片面,不够深刻?等等等等。但自己的心路历程真的发生了一些改变。在我还是个小白的时候,学习技术:第一个想法是百度,搜别人的博客,一步步跟着别人后面配置,把 demo run 起来。而现在,遇到问题的第一思路变成了:源码 debug,官方文档。我便开始思考官方文档和博客的区别,官方文档的优势除了更加全面之外,还有就是:“它只教你怎么做”,对于一个有经验有阅历的程序员来说,这反而是好事,这可以让你有自己的思考。而博客则不一样,如果这个博主特别爱 BB,便会产生很多废话(就像本文的第一段),它会有很多作者自己思考的产物,一方面它比官方文档更容易出错,更容易片面,一方面它比官方文档更容易启发人,特别是读到触动到我的好文时,会抑制不住内心的喜悦想要加到作者的好友,这便是共情。我之后的文章也会朝着这些点去努力:不避重就轻,多思考不想当然,求精。

最近瞥了一眼项目的重启脚本,发现运维一直在使用 kill -9 <pid> 的方式重启 springboot embedded tomcat,其实大家几乎一致认为:kill -9 <pid> 的方式比较暴力,但究竟会带来什么问题却很少有人能分析出个头绪。这篇文章主要记录下自己的思考过程。

kill -9 和 kill -15 有什么区别?

在以前,我们发布 WEB 应用通常的步骤是将代码打成 war 包,然后丢到一个配置好了应用容器(如 Tomcat,Weblogic)的 Linux 机器上,这时候我们想要启动 / 关闭应用,方式很简单,运行其中的启动 / 关闭脚本即可。而 springboot 提供了另一种方式,将整个应用连同内置的 tomcat 服务器一起打包,这无疑给发布应用带来了很大的便捷性,与之而来也产生了一个问题:如何关闭 springboot 应用呢?一个显而易见的做法便是,根据应用名找到进程 id,杀死进程 id 即可达到关闭应用的效果。

上述的场景描述引出了我的疑问:怎么优雅地杀死一个 springboot 应用进程呢?这里仅仅以最常用的 Linux 操作系统为例,在 Linux 中 kill 指令负责杀死进程,其后可以紧跟一个数字,代表 ** 信号编号 **(Signal),执行 kill -l 指令,可以一览所有的信号编号。


给初中级 JAVA 准备的面试题

笔者作为一个今年刚毕业的初级 JAVA,根据群里水友的讨论,也结合自己刚毕业时的一些面经,加上近期一点点在公司面试别人的经验,总结了如下的常见面试问题,适用于初级和中级 JAVA。

JAVA

  1. HashMap 相关

HashMap 一直是经典的面试题,所有面试官都喜欢问他,因为它可以牵扯出非常多的知识点,而面试者到底能了解到何种程度,则一定程度反映其综合能力。

细节聊扩容因子 LoadFactor=0.75,初始大小 InitailCapacity=16


打开 orika 的正确方式

缘起

架构分层

开发分布式的项目时,DO 持久化对象和 DTO 传输对象的转换是不可避免的。集中式项目中,DO-DAO-SERVICE-WEB 的分层再寻常不过,但分布式架构(或微服务架构)需要拆分模块时,不得不思考一个问题:WEB 层能不能出现 DAO 或者 DO 对象?我给出的答案是否定的。

新的项目分层结构

这张图曾出现在我过去的文章中,其强调了一个分层的要素:服务层 (应用层) 和表现层应当解耦,后者不应当触碰到任何持久化对象,其所有的数据来源,均应当由前者提供。


JAVA 拾遗 -- 关于 SPI 机制

JDK 提供的 SPI(Service Provider Interface)机制,可能很多人不太熟悉,因为这个机制是针对厂商或者插件的,也可以在一些框架的扩展中看到。其核心类 java.util.ServiceLoader 可以在 jdk1.8 的文档中看到详细的介绍。虽然不太常见,但并不代表它不常用,恰恰相反,你无时无刻不在用它。玄乎了,莫急,思考一下你的项目中是否有用到第三方日志包,是否有用到数据库驱动?其实这些都和 SPI 有关。再来思考一下,现代的框架是如何加载日志依赖,加载数据库驱动的,你可能会对 class.forName(“com.mysql.jdbc.Driver”)这段代码不陌生,这是每个 java 初学者必定遇到过的,但如今的数据库驱动仍然是这样加载的吗?你还能找到这段代码吗?这一切的疑问,将在本篇文章结束后得到解答。

首先介绍 SPI 机制是个什么东西


java 小技巧 (一)-- 远程 debug

该系列介绍一些 java 开发中常用的一些小技巧,多小呢,从不会到会只需要一篇文章这么小。这一篇介绍如何使用 jdk 自带的扩展包配合 Intellij IDEA 实现远程 debug。

项目中经常会有出现这样的问题,会令程序员抓狂:关键代码段没有打印日志,本地环境正常生产环境却又问题… 这时候,远程 debug 可能会启动作用。

1 准备用于 debug 的代码

准备一个 RestController 用于接收请求,最后可以通过本地断点验证是否成功开启了远程 debug


XML 与 javabean 的转换

XML 可以说是一种被时代淘汰的数据传输格式,毕竟相比较 JSON,其语法,表现形式,以及第三方类库的支持,都要略逊一筹,但最近在对接一些老接口时,主要还是以 XML 为主,而翻阅相关的文档以及博客,没看到很好的文章介绍如何使用 xml 进行数据传输,所以简单写下此文,做一下记录。内心多多少少还是会抵制对接如此老旧的接口,不过生活还是要继续。

Code First

先上一段代码,展示一下如何封装,讲解放到后面

一个典型的对接方提供的 XML 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ORDER>
<ORDER_NO>10086</ORDER_NO>
<TOTAL_PRICE>3.14</TOTAL_PRICE>
<CREATE_TIME>2017-08-26 03:39:30</CREATE_TIME>
<ORDER_ITEMS>
<ORDER_ITEM>
<GOODS_NAME> 德芙 </GOODS_NAME>
<NUM>3</NUM>
</ORDER_ITEM>
<ORDER_ITEM>
<GOODS_NAME> 旺仔 </GOODS_NAME>
<NUM>10</NUM>
</ORDER_ITEM>
</ORDER_ITEMS>
</ORDER>

而我们要对应的实体类,则应当如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@XmlRootElement(name = "ORDER")// <1>
@XmlAccessorType(XmlAccessType.FIELD)// <1>
public class Order {

@XmlElement(name = "ORDER_NO")// <1>
private String orderNo;

@XmlElement(name = "TOTAL_PRICE")
private BigDecimal totalPrice;

@XmlElement(name = "CREATE_TIME")
@XmlJavaTypeAdapter(DateAdapter.class) // <2>
private Date createTime;

@XmlElementWrapper(name = "ORDER_ITEMS") // <3>
@XmlElement(name = "ORDER_ITEM")
private List<OrderItem> orderItems;

}
1
2
3
4
5
6
7
8
9
10
@XmlAccessorType(XmlAccessType.FIELD)
public class OrderItem {

@XmlElement(name = "GOODS_NAME")
private String goodsName;

@XmlElement(name = "NUM")
private Integer num;

}

我举的这个示例基本包含一般情况下所有可能出现的需求

<1> 常用注解 XmlRootElement,XmlAccessorType,XmlElement

<2> 日期转换的适配器注解

<3> 如何在 XML 中设置集合

在介绍这三点之前,先给出转换的工具类


Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×