![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Java
文章平均质量分 93
卓立~
现在一家电商做广告平台,Java后端后端开发
展开
-
Spring MVC源码解读『Spring MVC示例』
前面几篇文章,我们介绍了Servlet和Tomcat的工作原理。我们之前也说到Spring MVC底层其实也是Servlet,也需要TomcatWeb容器配合才能工作,本篇文章开始,我们就来介绍探索一下Spring MVC的相关细节。本篇文章个先来回顾一下Spring MVC的用法。1. 什么是MVC相信所有的开发人员都避免不了接触一个概念——MVC,这个概念是个比较抽象的概念,也没有没有官方权威定义,全凭我们开发人员自己理解。我一度感觉自己对MVC已经了解地很清楚了,但是在写本篇文章,打算来介绍M原创 2020-12-21 07:36:04 · 559 阅读 · 1 评论 -
Tomcat源码解读『Tomcat类加载机制』
本篇文章我们来探索一下Tomcat的类加载机制,如果我们搜Tomcat的类加载机制,绝大多数结果都会给出答案——打破双亲委托机制。但是感觉很多文章介绍的都不是很清楚,所以本篇文章就从我的理解上来分析一下Tomcat的类加载机制,希望能讲的明白。关于JVM类加载机制,我们在之前的文章Java编程拾遗『Java ClassLoader工作机制』已经介绍过,有兴趣的可以去了解一下。1. Tomcat类加载机制要考虑的问题Tomcat作为Servlet容器,它负责加载我们的Servlet类,此外它还负.原创 2020-12-21 07:35:45 · 1360 阅读 · 2 评论 -
Tomcat源码解读『Tomcat是如何处理web请求的』
之前的四篇文章,我们介绍了Tomcat启动过程的实现:Tomcat源码解读『Tomcat是怎么启动的』 Tomcat源码解读『server.xml解析』 Tomcat源码解读『Context如何构建的』 Tomcat源码解读『web.xml解析』我们知道,Tomcat启动之后,就可以响应来自客户端的web请求了,本篇文章我们来看一下Tomcat容器是如何响应web请求的。1. Servlet是如何生效的做过Java Web的我们都知道,我们的具体业务处理逻辑是卸载Servlet中的,不难原创 2020-12-19 11:19:35 · 722 阅读 · 1 评论 -
Tomcat源码解读『web.xml解析』
上篇文章我们介绍了Tomcat Context是如何构建的,了解了Context构建的两种方式:Host启动,触发HostConfig的Lifecycle.START_EVENT事件监听,构建Context 后台线程,定期去执行Host的backgroundProcess方法,触发HostConfig的Lifecycle.PERIODIC_EVENT事件监听,构建Context这里的构建Context,指的是构建一个Context对象,并将构建好的Context对象与Host组件关联起来(调用hos原创 2020-12-19 11:17:36 · 1317 阅读 · 1 评论 -
Tomcat源码解读『Context如何构建的』
上一篇文章我们介绍了server.xml是如何解析的,其中在介绍Context解析时,提到,多数情况下,并不需要在server.xml中配置Context,而是由HostConfig自动扫描部署目录,以context.xml文件为基础进行解析创建(如果通过IDE启动Tomcat并部署应用,其Context配置将会被动态更新到server.xml中)。所以大多数情况下,Context并不会在server.xml解析时构建出来。那么Context是如何构建出来的?本篇文章就来探索一下Tomcat Conte原创 2020-12-19 11:15:04 · 409 阅读 · 1 评论 -
Tomcat源码解读『server.xml解析』
上篇文章我们介绍到,在Catalina的load方法中,完成了server.xml的解析,将server.xml配置的Server、Service、Connector、Engine、Host各组件实例化,并维护父子级关系。本篇文章我们来看一下server.xml是如何解析的。不难看到,parseServerXml方法执行后,各Tomcat组件就已经生成了。1. parseServerXml核心的解析逻辑就在上图38~49行:Digester digester = start ? c原创 2020-12-19 11:13:22 · 756 阅读 · 1 评论 -
Tomcat源码解读『Tomcat是怎么启动的』
上篇文章我们介绍了Tomcat的核心组件的的基本功能以及在Tomcat中的实现,但是这些组件类是如何被启动起来的?比如我们知道Context组件的功能是管理子容器Wraper的生命周期,那么在Context组件启动时,肯定要创建Wrapper实例并启动Wrapper。同理,我们知道Tomcat这么多组件,肯定有一个先后的启动过程(因为Tomcat的组件本来就是分层级的)。本篇文章我们就来介绍一下,Tomcat是怎么启动的。使用过Tomcat的我们都知道,可以通过Tomcat的/bin目录下的脚本star原创 2020-12-19 11:12:11 · 448 阅读 · 1 评论 -
Tomcat源码解读『基础类介绍』
通过之前两篇关于Tomcat的介绍,我们已经清楚知道Tomcat的作用及基本的工作原理。本篇文章开始,我们来从解读Tomcat源码。本篇先来介绍一下Tomcat的基础类,以便我们后续介绍Tomcat启动流程,工作流程。我们知道,Tomcat的能作为web容器正常工作,依赖于Server.xml配置文件,如下:<?xml version="1.0" encoding="UTF-8"?><Server port="8005" shutdown="SHUTDOWN"> &l原创 2020-12-19 11:10:59 · 534 阅读 · 1 评论 -
Tomcat系统架构
上篇文章,我们自定义实现了一个简单的不能再简单的Tomcat容器,大致了解了Tomcat的工作主要功能。本篇文章我们就来看一下正主——Tomcat,每一个从事Java Web开发的都需要了解的基础工具。Server:Tomcat顶层容器,可以包含一个或多个Service组件 Service:Server内部的中间组件,包含Connector和Container两个核心组件,负责将一个或多个Connector组件绑定在一个Container上 Connector:用于处理连接相关的事情,并提供So原创 2020-12-19 11:09:47 · 434 阅读 · 1 评论 -
自定义实现一个mini版Tomcat
通过之前的介绍,我们大致了解了Tomcat的基础功能,即为Servlet生效提供环境支持。那么Tomcat肯定需要提供以下基础功能:提供Socket服务:实现对某些端口的监听,从而实现请求到来时,Tomcat可以感知到。同时该Socket服务也需要支持HTTP协议。 封装请求和响应:通过之前的介绍,我们知道在我们开发Servlet时,Web容器已经将Context、Request、Response替我们封装好了,可以直接使用。Tomcat作为一款Servlet容器,肯定要支持这项功能。 请求分发:一原创 2020-12-19 11:08:32 · 744 阅读 · 1 评论 -
Java Web三大组件
上篇文章我们介绍了Servlet和Jsp以及一些Java Web开发的基础概念,本篇文章我们来介绍另一Java Web开发中的重要概念——Java Web三大组件,即Servlet、Filter和Listener。1. Servlet由于我们上篇文章已经介绍过Servlet了,这里就不再详细介绍了,透过现象看本质——什么是servlet。2. FilterFilter(过滤器)用于拦截用户请求,在服务器作出响应前,可以在拦截后修改request和response。可以实现一次编码,多处应用。原创 2020-12-19 11:05:56 · 871 阅读 · 1 评论 -
透过现象看本质——什么是servlet
我们通过几篇文章介绍了Spring的IOC和AOP两大属性,本来打算开始介绍Spring MVC的。但是想了一下,在介绍MVC框架之前,还是应该来缕清MVC底层的本质——Servlet,这个看着“非常久远”的概念,以便我们能更好地了解学习框架。提到Servlet,有很多人可能是有些陌生的,因为在工作中一般很少直接用到Servlet,都是直接上手框架,以至于很容易出现如下两种看法:框架和Servlet割离,认为是两个概念,比如“Servlet还在使用吗” 知道框架和Servlet有关联,但把Serv原创 2020-12-19 11:03:30 · 663 阅读 · 2 评论 -
Java编程拾遗『JVM垃圾回收』
垃圾收集(Garbage Collection)通常被称为GC,大部分人都把这项技术当作Java语言的伴生产物。事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp语言是第一门真正使用内存动态分配和垃圾收集技术的语言。经过半个世纪的发展,内存动态分配与内存回收技术已经相当成熟,一切看起来都进入“自动化”时代,那么为什么我们还要去了解GC和内存分配呢?原因很简单:当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”技术实施必要的监控和调原创 2020-06-30 08:26:36 · 283 阅读 · 0 评论 -
Java编程拾遗『JVM内存区域』
作为一名Java开发人员,JVM是我们每天都会打交道的对象。但是由于JVM处于知识体系的底层,同时工作中有可能接触的机会不是很多,导致很多人都对JVM相关的知识一知半解。一般只会在面试的时候,才来准备这部分内容。但JVM是为了让我们更好的理解Java,更深入了解我们每天开发程序的执行机制。所以从本篇文章开始,我们来介绍以下JVM相关的知识。大致规划一下应该会包括 以下内容:JVM内存区域、垃圾...原创 2020-01-07 07:43:15 · 206 阅读 · 0 评论 -
Java编程拾遗『Java ClassLoaser工作机制』
ClassLoader顾名思义就是类加载器,负责将类的.class文件中的二进制数据加载到JVM中,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构(类的方法代码,变量名,方法名,访问权限,返回值等)。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。类加...原创 2020-01-07 07:41:48 · 321 阅读 · 0 评论 -
Java编程拾遗『ThreadLocal』
本篇文章,我们来介绍一下,Java多线程编程中一个比较常用的工具,线程本地变量——ThreadLocal。ThreadLocal简单的来讲,就是每个线程都有同一个成员变量的独有拷贝。由于每个线程都有成员变量独立的拷贝,所以不存在多线程访问同一成员变量的问题,也就解决了线程安全问题。之前我们介绍的锁,是解决线程安全问题的一个途径,那么本篇文章介绍的线程本地变量是另一种解决线程安全问题的思想,就是通过...原创 2020-01-07 07:39:31 · 215 阅读 · 0 评论 -
Java编程拾遗『线程协作工具』
在之前的文章Java编程拾遗『线程协作』中,介绍了一些线程协作的场景,并做了简单的代码实现,比如上文中的MyLatch、AssemblePoint、MySemaphore等。其实上篇文章介绍的线程协作场景,在Java API中都有响应实现。本篇文章就来介绍一下,Java API中提供的一些线程协作工具及使用场景。本篇文章会介绍以下几种协作工具:CountDownLatch CyclicBar...原创 2020-01-07 07:38:05 · 223 阅读 · 0 评论 -
Java编程拾遗『线程池』
在之前的文章中,我们已经讲了很多Java线程的使用以及Java并发编程的原理,本篇文章,我们来重点看一下Java并发编程中一个比较常用的工具——线程池的使用以及源码实现,这也是Java面试的基本问题。在使用线程池之前,我们可以尝试考虑这样一个问题,如果没有线程池,我们是怎样实现多线程编程的以及实现方式有哪些问题?首先,如果没有线程池,我们一般会直接通过new Thread()构造出多个线程,然...原创 2020-01-07 07:36:59 · 223 阅读 · 0 评论 -
Java编程拾遗『并发容器——并发队列』
本篇文章,来探讨一下Java并发包中的各种队列。Java并发包提供了丰富的队列类,可以简单分为:无锁非阻塞并发队列:ConcurrentLinkedQueue和ConcurrentLinkedDeque 普通阻塞队列:基于数组的ArrayBlockingQueue,基于链表的LinkedBlockingQueue和LinkedBlockingDeque 优先级阻塞队列:PriorityBl...原创 2020-01-07 07:34:15 · 161 阅读 · 0 评论 -
Java编程拾遗『并发容器——ConcurrentSkipListSet和ConcurrentSkipListMap』
由于水平有限,ConcurrentSkipListSet和ConcurrentSkipListMap的实现又比较复杂,所以并没有去通读源码。下文的内容来自《Java编程的逻辑》,简单讲了ConcurrentSkipListMap基于跳跃表实现的思想,有兴趣的小伙伴也可以去读一下源码。之前的文章介绍了ConcurrentHashMap,也讲到ConcurrentHashMap不能排序,容器类中可...原创 2020-01-07 07:32:34 · 333 阅读 · 0 评论 -
Java编程拾遗『并发容器——ConcurrentHashMap』
在之前的文章中已经介绍过的哈希表数据结构有HashMap、TreeMap、LinkedHashMap、HashTable以及Collections类生成的各种同步Hash容器。但是我们也了解到,HashMap是非线程安全的,在多线程环境下会出现数据安全性问题,比如多线程同时rehash过程中产生的死循环(Java7)及元素丢失问题。HashTable和Collections类生成的同步容器倒是可以...原创 2020-01-05 10:42:43 · 242 阅读 · 0 评论 -
Java编程拾遗『并发容器——CopyOnWrite』
从本片文章开始我们来介绍并发容器类,之前的文章介绍过普通容器类,比如ArrayList、LinkedList等。但是这些容器都有个问题,就是非线程安全,多线程并发写,会存在线程安全问题,所以Java提供了并发容器类来解决普通容器类的线程安全问题。本篇文章我们先来看一种解决容器类线程安全的思想——CopyOnWrite(写时复制)。1. 同步容器在讲CopyOnWrite并发容器之前,先来介...原创 2020-01-05 10:36:47 · 227 阅读 · 0 评论 -
List拆分
工作中遇到将一个List划分为等长的多个List,自己写了两个方法,测试可以用,作为这个平台的第一篇博文,记录一下 给定子List的长度,将一个List划分为多个List private <T> List<List<T>> averageAssign(List<T> source,int bccSize){ List<List&l...原创 2018-11-01 06:48:15 · 1373 阅读 · 0 评论 -
Jackson 序列化对象问题
今天再工作中遇到一个问题,将一个对象序列化为json,传给前端做展示。对象成员变量定义按照驼峰形势定义,但是序列化出来的json各个字段却变成了下划线形势(scenesType -> scenes_type),查了好久终于定位到问题所在。public class InterventionController { @Autowired private ObjectMapper ...原创 2018-11-01 07:04:33 · 2758 阅读 · 0 评论 -
Arrays.asList和Lists.newList使用时的陷阱
昨天在开发中遇到一个场景,调用RPC,拿到返回结果(int[]数组),使用jackSon序列化为Json对象时,发现一个诡异的现象,在使用Lists.newArrayList和Arrays.asList将数组转为List时,转出来的对象并不是与原数组对应的一个List,二十一个很诡异的对象。后来研究一下JDK,发现了陷阱所在。首先看一下Arrays.asList这个方法,这个方法可以将数组转成...原创 2018-11-01 07:06:18 · 12881 阅读 · 0 评论 -
java十六进制字符串和String互转
通过redis-cli使用redis做存储时,发现当存入的值为汉字时,实际存入的是汉字对应编码的十六进制串。当时的第一反应是从redis中拿到的是一个十六进制串,我应该对这个十六进制串进行解码,解成汉字。随后试着去写了一个十六进制字符串与String互转的demo。但当我使用jedis取数据时,发现取出来的其实就是解码过后的汉字串,猜测应该是jedis做了解码这一过程,之后的文章我会对此进行讲解,...原创 2018-11-01 07:08:48 · 10073 阅读 · 0 评论 -
Java8函数式编程
java中存在一个概念,一切皆是对象。在 Java 中定义的函数或方法不可能完全独立,也不能将方法作为参数或返回一个方法给实例。如果要给一个方法传递函数功能,只能通过匿名类的方法。如下所示:button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { ...原创 2018-11-01 07:10:05 · 158 阅读 · 0 评论 -
Java8日期与时间
昨天在工作中,写了一个关于时间的工具类,其中一个函数的功能是判断当前时间是否为0点。本来想一天是86400秒,如果通过当前的unix时间与86400取余,且余数为0的话,那么肯定是0点了。所以我写了如下的代码:public class DateUtil { public Boolean is0Clock(Long unixTimeStamp) { return un...原创 2018-11-01 07:14:19 · 361 阅读 · 0 评论 -
Java中LocalDate和Date互转
上篇文章介绍了Java8和Java8之前的时间处理的相关类,但是在日常开发中难免会遇到Java8和之前的旧对象互转的需求。我整理了一下之前的内容,做了一个工具类,如下:public class DateUtils { /** * @Author: zhuoli * @Description: 判断unix当前unix时间是否为0点 * @param u...原创 2018-11-01 07:16:10 · 4604 阅读 · 0 评论 -
Guava学习笔记
Guava是一种基于开源的Java库,其中包含谷歌很多项目正在使用的核心库,简化编码,并减少编码错误。这个库提供了用于集合,缓存,支持原语,并发性,常见注解,字符串处理,I/O、验证等的实用方法。在Java8之前,Guava就已经提供了如Optional处理、函数式编程等的解决方案。Java8中也新增了Guava中的一些特性,足以说明Guava的牛逼之处。虽然Java8中合并了一些Guava的特性...原创 2018-11-01 07:17:27 · 204 阅读 · 0 评论 -
Guava Ordering
Ordering是Guava基于比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。从实现上说,Ordering实例就是一个特殊的Comparator实例。Ordering把很多基于Comparator的静态方法(如Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。Ordering比较器构...原创 2018-11-02 07:04:17 · 261 阅读 · 0 评论 -
Spring Boot配置
Spring Boot号称可以去除XML,但未做到零配置,它体现出了一种”习惯优于配置”的思想,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。 一般情况下默认的配置足够满足日常开发所需,但在特殊的情况下,我们往往需要用到自定义属性配置、自定义文件配置、多环境配置、外部命令引导等一系列功能。对于这些功能,Spring Boot都给予了很好的...原创 2018-11-03 14:30:50 · 122 阅读 · 0 评论 -
Spring Boot日志管理
日志作为一个项目必备的一个模块,对于排查问题是必不可少的。在开始写本篇文章之前,先讲一下几个概念Sl4j、LogBack、Log4j、Apache commons Log等概念的联系和区别,这对于了解本文是非常重要的。slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现。...原创 2018-11-03 14:32:06 · 2412 阅读 · 0 评论 -
Java开发利器Lombok
Lombok简介 Lombok是一种Java的实用工具,可用来帮助开发人员消除Java的冗长代码,尤其是对于简单的Java对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现Lombok,开发人员可以节省构建getter/setter以及诸如hashCode()和equals()这样的方法。Lombok会在编译时修改插入代码,因此不会影响任何运行时的性能。 安装Lombok...原创 2018-11-03 14:33:41 · 585 阅读 · 0 评论 -
Spring Boot中log4j的配置
上篇文章Spring Boot日志管理,我简单讲述了Spring Boot中使用默认日志Logback进行日志管理的配置。在上篇文章中有讲到,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。但是log4j作为一款常用的日志库,在实际开发中还是很常用的,本片文章,我将简单介绍一下Spring Boot中如何使用Log4J进行日志管理。创建Spring B...原创 2018-11-03 14:34:30 · 2490 阅读 · 0 评论 -
Java8 Stream reduce操作
Reduce,顾名思义为减少的意思,就是根据指定的计算模型将Stream中的值计算得到一个最终结果。在之前的一篇文章Java8函数式编程中简单介绍,Stream的count、min 和max方法底层都是依赖reduce实现的,本篇文章将简单介绍一下Java8 Stream reduce的几种基本用法。首先来看一下Reduce三种形式:S.N. 方法说明 1 Optional...原创 2018-11-03 14:35:20 · 8060 阅读 · 2 评论 -
Java8 Stream groupingBy对List进行分组
提到Group By,首先想到的往往是sql中的group by操作,对搜索结果进行分组。其实Java8 Streams API中的Collector也支持流中的数据进行分组和分区操作,本片文章讲简单介绍一下,如何使用groupingBy 和 partitioningBy来对流中的元素进行分组和分区。 groupingBy 首先看一下Java8之前如果想对一个List做分组操作,我们需要...原创 2018-11-03 14:37:04 · 89792 阅读 · 4 评论 -
Java 8 Stream partitioningBy对List分区
partitioningBy分区是一种特殊的分组,可以将List划分为两个子List,使用起来比较简单,如下:@Testpublic void partitionByTest(){ List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map<Boolean, List&l...原创 2018-11-03 14:38:07 · 3238 阅读 · 0 评论 -
Java8实现Map/List/Set排序
Java8之前如果想对一个集合排序,那么集合元素要么实现了Comparable接口,要么另外定义一个继承于Comparator的比较器并实现compare方法,使用起来是非常麻烦的。在我之前的文章中也介绍了一种Guava的排序实现方案,也是非常简单的,有兴趣的同学可以去了解一下Guava Ordering 。Java8之后可以使用java.util包的Comparator比较器,实现对集合的排序,...原创 2018-11-03 14:39:15 · 7347 阅读 · 0 评论 -
SpringBoot + JdbcTemplate实现mysql数据库访问
在开发服务端程序时,数据库交互是非常常见的,如果没了数据库,站点相应也就变成了静态的。从本片文章开始,我会介绍一下SpringBoot连接mysql的几种常见方式(包括使用mybatis ORM框架)。本篇文章首先介绍一下使用JdbcTemplate实现mysql数据库连接,Spring Framework在Jdbc上面做了深层次的封装,通过依赖注入功能,可以将 DataSource 注入到Jdb...原创 2018-11-03 14:39:59 · 639 阅读 · 0 评论