深入分析Java Web技术内幕

一.深入Web请求过程

1.B/S架构:

1) 都基于统一的HTTP协议交互数据,与C/S长连接的交互模式不同,HTTP采用无状态的短连接的通信方式。

2)当用户在浏览器里输入url时,首先会请求DNS将这个域名解析成对应的IP地址,然后根据这个ip地址在互联网上找到对应的服务器,向这个服务器发送一个get请求,服务器返回数据给浏览器。在服务器端可能还有很复杂的业务逻辑:服务器会有很多台,负载均衡去决定到底哪一台服务器;请求的数据是存储在分布式缓存里/静态文件/数据库中;当数据返回给浏览器时,浏览器解析数据时发现还有一些静态资源(如CSS,JS或者图片)时又会发起另外的HTTP请求,而这些请求很可能会在CDN上

3)互联网上所有的资源都要用一个URL表示,如果要发布一个服务或者一个资源到互联网上,url必须保证全世界唯一

4)数据解析,展示在浏览器中进行

2.DNS域名解析过程: 先检查浏览器缓存有没有对应的记录;如果浏览器缓存没有,看操作系统缓存(hosts文件)是否有;如果还没有,那么会离开本地,请求域名服务器(网络配置中的DNS地址),本区域的域名服务器;如果本区域的域名服务器没有命中,那么去Root Server; 根域名服务器返回给本地域名服务器一个所查询域的主域名服务器地址(全球13台);本地域名服务器向返回的主域名服务器地址发送请求;主域名服务器查找并返回此域名对应的Name Server域名服务器地址; Name Server会查询出结果并将结果返回给本地域名服务器;本地域名服务器缓存此域名并返回给用户;用户缓存此域名 nslookup

3.CDN内容分布网络: 缓存静态文件,将网站的内容发布到最接近用户网络的边缘。提高网络速度,一个公司都会有一个DNS解析服务器,CNAME指向CDN全局中的DNS服务器,再由它返回给离这个放回用户最近的CDN节点。

4.负载均衡: 

1) 链路负载均衡: 负载均衡由DNS控制,优点是没有代理,速度快。缺点是客户有缓存,如果一个节点挂掉,则无法访问(少用)

2) 集群负载均衡: 软件的,需要经过多个代理服务器

3) 操作系统负载均衡

二. IO:

1.序列化:  Java序列化就是将一个对象转化成一串二进制表示的字节数组,通过保存或转移这些字节数组来达到持久化的目的。

1) 父类继承Serializable接口,所有子类都可以被序列化

2) 如果序列化的属性是对象,该对象也必须序列化,否则报错

3) 反序列化时,如果serialVersionUID被修改,那么反序列化失败

4) 反序列化时,如果对象属性有修改,修改部分会丢失,不会报错

2.网络传输:

1)建立通信链路: 当客户端与服务器端通信时,客户端首先要创建一个Socket实例,操作系统将为这个Socket实例分配一个没有被使用的本地端口号,并创建一个包含本地和远程地址和端口号的套接字数据结构,这个数据结构将一直保存在系统中直到这个连接关闭。早创建Socket实例的构造函数完成之前,将要进行TCP的3次握手协议,完成后对象创建成功。

   服务端会创建一个ServerSocket实例,调用accept()方法进入阻塞状态,等待客户端请求。里面有未完成/完成两个Socket队列,等与客户端三次握手完成后,返回Socket实例,并将这个Socket实例对用的数据结构从未完成列表中移到已完成列表。

2.NIO的工作方式: 非阻塞的

1) Channel和Selector,Buffer

2) Selector可以同时监听一组通信信道(Channel)上的I/O状态,前提是这个Selector已经注册到这些通信信道中。如果有多个通道有数据,那么会把这些数据分配到对应的数据Buffer中。所以关键的地方是,有一个线程来处理所有连接的数据交互,每个连接的数据交互都不是阻塞式,同时可以处理大量连接请求。

3) FileChannel.transferXXX: 减少了数据从内黑到用户空间的复制,直接在内核空间移动

4) FileChannel.map: 将文件按一定大小块映射为内存区域,当程序访问到这个内存区域时将直接操作这个文件数据,省去了数据从内核空间向用户空间的复制。合适大文件的只读操作。

3.数据传输: 连接已经建立,客户端服务器端各有一个Socket实例。在网络中数据通过字节流传输。 

1)一个线程专门负责监听客户端的连接请求,而且是以阻塞方式执行;另一个线程专门负责处理请求,这个线程采取NIO方式.

4. 网络传输优化:

1) 减少网络交互次数: 

2) 减少网络传输数据量的大小: zip

3) 减少编码:尽量直接以字节发送,如果字符的话还要先转成字节

5.适配器模式:

1) 把一个类的接口变换成客户端所能接受的另一种接口,即适配器继承原接口,实现目标接口。改变接口

2) 各种流之间的转化

6.装饰器模式: 

1) 在不影响原有使用该类的对象的情况下,将原有的类增加功能,保持原有接口

2)流,增加功能

7.影响相应时间因素:

1)带宽: 一秒钟一个物理链路最大能传送的比特数。

2)传输距离

3)TCP拥塞控制


三.Java web的中文编码问题:

1.需要编码原因: 计算机存储最小的字符是字节,8bit. 最多表示255个不同文字,人文字太多,无法用一个字节表示,所以引入字符。从字符到字节需要编码

2.所谓的编码即字符到字节的翻译方式,转化规则

3.压缩时,不同的算法让字符数减少,但字节数没减少。只是将多个单字节通过编码转化成一个多字字节。减少的是String.length(),而并没有减少最终的字节数。

4. Java Web中存在编码转换的地方:

1) 客户端发送HTTP请求时: URL/COOKIE/

2)服务器解析时:URI/COOKIE/POST表单参数

3)读取数据库或文件等信息

4)发回给客户端

5.URL: 浏览器编码URL将非ASCII字符按照某种编码格式编码成16进制数字后将每个16进制数字前面加%. URI与query String解码方式不同

1) query String 是通过getParameter()获取参数值,query字符串参数解码参数在HTTP hearder定义。要么是在Header中的ContentType定义的CharSet,要么是默认的ISO

2) URI: 是在connector定义的,默认是ISO 

6. 客户端解码时,先根据Content-Type的charset来解码,没有则根据<meta charset> 解码,还没有则用浏览器默认解码方式解码

7.Java WEB:数据在网络中传输都是以字节为单位的,所以所有数据必须可以序列化为字节,所以必须实现Serializable接口。

8.程序涉及到I/O时,只要注意指定统一的编解码,一般不会出现乱码,否则可能会出现使用操作系统默认编码的情况。 inputStream/Reader

9.UTF8适合网络传输,丢字节也不太影响。UTF16编码效率最高,适合本地磁盘与内存间。但不适合网络传输(16位)。GBK支持所有中文,但编码效率低。推荐UTF-8

10. JS中的编码问题: 

1)外部引入的JS文件,如果没有在<script charset>中设值,那么浏览器会以当前页面的默认字符集解析这个js文件。

2) JS的url编码: encodeURI进行UTF-8编码。在每个码值前面加上%

11.常见问题分析:都是char到byte以及byte到char时出现的问题


四.Java编译原理

1. JAVAC: 是一种编译器,将JAVA语言转化为JVM能够识别的语言。JVM在转化成机器能够识别的语言(平台无关性)

                 .java ---> .class


六.ClassLoader工作机制:

1.类加载器:负责将Class加载到JVM中。

2.如何加载class文件:

1) 找到.class文件并把这个文件包含的字节码加载到内存

2) 字节验证,Class类数据结构分析及相应内存分配,符号表的连接

3) 类静态属性和初始化赋值,静态块执行。

3.常见加载类错误分析:

1)ClassNotFoundException: 就是当JVM要加载指定文件的字节码到内存时,并没有找到相应的字节码,也就是这个文件并不存在。解决办法就是检查当前的classpath目录下有没有指定的文件存在。

2)NoClassDefFoundError:  引用某个类,JVM隐式加载这些类的时候发现这些类不存在。解决办法就是确保每个类引用的类都在当前的classpath下面。

3)ClassCastException: 强制类型转换时出这个错。

4.类的热部署:

JVM在加载类之前会检查请求的类是否已经被加载,也就是调用findLoadedClass()方法看是否能返回类的实例。判断是否为同一个类有两个条件,一个是看类完整性类名是否一致,另一个是看加载这个类的classLoader是否一致。所以实现热部署可以创建不同的ClassLoader的实例对象,然后通过这个不同的实例对象来加载同名的类。


七. JVM体系和工作方式:

1.JVM体系结构: 

1) 类加载器ClassLoader: class存在java堆中

2) 执行引擎:执行字节码文件:一个JVM实例中可以有多个执行引擎在工作(多线程),有些在执行用户程序,有些在执行垃圾回收等。每个执行引擎会创建自己的栈和pc寄存器

3) 内存区: 方法区和java堆被所有线程共享

4) 本地方法调用(c/c++)

5) Java源文件-->Javac编译器-->Class文件-->ClassLoader-->内存管理

     内存管理分为:Java堆,方法区,pc寄存器,本地方法区,Java栈(执行引擎)


八. JVM内存管理:

1.


九.Servlet工作原理解析:

1.Tomcat的Servlet容器: 

1) servlet容器启动过程:

2.MVC框架的基本原理是将所有的请求都映射到一个servlet,然后去实现service方法,这个方法也是MVC框架的入口。

3.Servlet的Listener: 

1)分成两类: 生命周期的不同状态触发以及由某个操作事件触发。

2)他们基本涵盖了整个Servlet声明周期中你感兴趣的事件

3) 基于观察者模式设计


十. 深入理解Session与cookie:

1. Session与cookie 的作用都是为了保持访问用户与后端服务器的交互状态。

2. Cookie传递信息时,随着Cookie个数的增多和访问量的增加,占的网络带宽很大。 所以大访问量时用Session, 但Session一个致命弱点是不能在多台服务器间共享。

3. Cookie: Key/value键值对

1) Cookie存储在客户端浏览器里,每次发送给服务器端。浏览器会对其大小进行限制。

4.Session:

1)每次只是通过cookie传一个id.

2)三种方式: url/Cookie(会覆盖掉URL的)/ssL

3) Servlet容器重启或者关闭时会将未过期的Session对象持久化到一个文件中。运行期间保存在StandardManager中的session集合中

4)因为session一直存在内存中数量太多会内存溢出。所以会检查session是否过期。检查Session是否有效是通过一个后台线程去检测或者每次request.getSession的时候去检测,所以过期了,创建一个新的,但原来的值没了。

5.在大型互联网系统中,单独使用Session和cookie都不行。

6. 分布式Session框架: 

1) 有一个订阅服务器: 在应用启动时,各个应用系统可以从这个订阅服务器订阅这个应用需要的可写Session项与cookie项。这样省去每个应用配置cookie。如果应用要使用一个新增cookie,可以通过一个统一的平台来申请,申请通过才将这个配置项增加到订阅服务器。

2) 因为应用是一个集群,所以不能将创建的session都保存在每台应用服务器的内存中,内存不够且session无法同步到所有的服务器中。所以要共享这些session必须将它们存储在一个分布式缓存中,memCache

3)如何存取cookie和session: 这个操作必须进入应用之前完成,所以可以配置一个filter拦截用户请求,把session对象set到request里。当用户这次请求完成之后,将这个session再更新到分布式缓存中。 也可以将一些非常重要的session再存储到cookie中,这样分布式缓存有问题不会影响关键业务进行。

4) cookie跨域名访问:一个域名下的Cookie不能被另外一个域名访问。如果在一个域名下已经登录成功,如何访问到另外一个域名的应用且保证登录状态有效。

   需要有一个跳转应用,这个应用可以被一个或者多个域名访问,主要功能是从一个域名下取得sessionID,然后将这个sessionID同步到另外一个域名下(即将同一个sessionID作为cookie写在两个域名下)。 请求第二个url时,没登录则302跳转到跳转应用,然后找,从客户端浏览器取出第一个sessionID,写入。在跳回第二个应用。

5)处理Cookie被盗: 盗取他人cookie加入自己浏览器,则也可以登录。所以在这个框架中设置一个Session签名,当用户登录成功后根据用户的私密信息生成一个签名,然后在浏览器与服务器间传递,每次客户端请求都先与分布式缓存里的session生成的签名进行比对,不一致,则清楚分布式缓存里的session,让用户重新登录。

7.Cookie压缩: Cookie是在Http的头部,如果量很大,可以考虑将cookie的多个k/v对看成普通的文本,做文本压缩。 即先将内容压缩成文本,然后放在cookie里。根据cookie规范,Cookie不能包括控制字符,所以要将压缩后的结果再转码(Base32/Base64)

8.防止表单重复提交: 因为网速慢或者恶意用户程序导致

    标识用户每一次访问请求,使每一次请求对于表单来说都是唯一的。表单中加一个隐藏域,这项每次的值都是唯一的token,存储到用户的session中,然后提交的时候与session中的值进行比对,如果是一样的,则继续提交表单并更新那个token值,否则不提交表单。


十一. Tomcat的系统架构与设计模式

1. 一个Container对应多个Connector.多个Connector和一个Container就形成了一个Service,有了Service就可以对外提供服务了。但是Service需要一个生存环境,归Server管

2.Connector主要用于对外交流,Container主要处理Connector接受的请求,主要是处理内部事务。Service将Connector与Container组装在一起,对外提供服务。

3. Server负责提供一个接口让其他程序能够访问到这个Service集合,同时维护它所包含的所有Service的生命周期。

4. Tomcat中组件的生命周期是通过Lifecycle接口来控制的。组件只要实现这个接口就可以被拥有它的组件控制了。这样一层一层直到一个最高级的组件(Server从Tomcat启动开始到关闭结束). 除了控制生命周期的start和stop方法外,还有一个监听机制,在生命周期开始与结束的时候做一些额外的操作(Spring)

5.Connector组件: 主要任务是负责接收浏览器发过来的TCP连接请求,创建一个Request和Response对象分别用于和请求端交换数据。然后会产生一个线程来处理这个请求并把产生的Request和Response对象传给处理这个请求的线程,处理这个请求的线程就是Container组件要做的事了。

6.整体过程: 

HttpConnecter:

1) 接到请求后会初始化一个ServerSocket,之后初始化一个线程,等待新的连接请求

2) 创建一个线程池,构建Request和Response对象,并让所有的线程进入await()状态

3) 请求到来,将Socket分配给HttpProcesser

HttpProcesser

4)激活这个线程,开始run方法执行

5)解析HTTP header,创建SocketInputStream为input,output对象

6)将Request和Response对象传给Container组件执行

Container

7)一次Servlet处理

8) 返回Request,Response对象

10)Request,Response对象结束生命周期,关闭Socket

9) output.flush()将结果返回给客户端。

7. Container:

1)构成: Engine > Host >Context>Wrapper

2)Engine:初始化和它相关联的组件,以及一些事件的监听

3)Host: 一个Host在Engine中代表一个虚拟机,这个虚拟机的作用就是运行多个应用,保存主机应有信息..Host不是必须的,但是如果是war,解析web.xml,就需要Host

4)Context:具备了Servlet运行的基本环境,这个是必须的。找到正确的Servlet并执行。检查WEB-INF,容器开始监听

5) Wapper容器: Wapper代表一个Servlet,负责管理一个Servlet,包括Servlet的装载,初始化,执行以及资源回收。加载Servlet,执行init()方法,创建filter链,执行Servlet的Service方法(把请求交给Servlet了。)

8.Tomcat中的设计模式:

1) 门面模式: 多个子系统需要相互通信,但又不想让别人知道自己内部的情况,所以每个子系统设计一个门面,把别的系统感兴趣的数据封装起来,通过这个门面访问。ActiveRoleContainer.java .  这样保证数据隔离。Request/HttpRequest

2)观察者模式: 发布-订阅模式。也就是事件监听机制。 Lifecycle,每个阶段fireEvent. 通知时synchronized(listeners)遍历

3)命令模式: 功能分工,把发出命令的职责和执行命令的责任分开。 将命令对象交给命令接收者处理

4)责任链模式: 整个容器连在一起,最后到servlet。 每个对象都有下家对象的引用,执行完自己自动执行下家。直到最终链上每个对象都执行完,这样可以在不影响客户端的情况下能够在链上增加任意多的节点。责任链上的各个对象都实现统一接口。 Rule.


十二. Spring框架的设计理念与设计模式分析:

1. 核心组件:

1) Bean: Spring容器中运行的主体。Factory:解析配置文件的</bean>节点的信息,构造Bean

2) Context:为各个Bean之间建立并维持它们的关系,这种关系集合也叫Ioc容器.给Spring提供一个运行时环境,用于保存各个对象的状态。

3) Core: 维持Bean之间关系所需要的工具

2.Ioc容器如何工作:  实际上就是Context组件结合其它两个组件共同构建了一个Bean的关系网

1)步骤:

a. 构建BeanFactory

b. 注册可能感兴趣的事件

c. 创建Bean实例对象

d. 触发被监听的事件。

3.Spring的AOP特性:

1) 关键点: 代理的目的是调用目标方法时可以转而执行InvocationHandler类的invoke方法,所以如何在InvocationHandler上做文章是关键

4.设计模式:

1) 代理模式:给一个对象创建一个代理对象,由这个代理对象控制对原对象的引用,而创建这个代理对象后可以在调用原对象时增加一些额外操作。

2) 策略模式:  完成某个操作可能有多个方法,每种方法有不同的适用场合,各个方法都作为一个策略


十三.Spring MVC工作机制与设计模式

1. 设计模式:

1)模板模式:

a. 定义了完整的框架后,方法调用顺序已定,但还是会有定义一些抽象的方法让子类去实现。


十四. Ibatis


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值