说说Java生态圈的那些事儿

发表于:2015-8-04 09:17

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:RunforLove    来源:51Testing软件测试网采编

分享:
  9. 数字九嘛,立即想到的就是JSP的九大内置对象。
  JSP有以下九种内置对象:
  request,请求对象
  response,响应对象
  pageContext,页面上下文对象
  session,会话对象
  application,应用程序对象
  out,输出对象
  config,配置对象
  page,页面对象
  exception,异常对象
  重点学习:request,session,application
  1. request的setAttribute()与getAttribute()方法一般都是成对出现的,首先通过setAttribute()设置属性和属性值,然后通过getAttribute()方法获得与属性对应的对象值(获取到之后,一般都要向下类型转换,将属性值转换为真正的对象)。setAttribute()与ge   tAttribute()都是在服务器端内部执行的,客户端不知道服务器端是否执行该方法。
  2. request.getParameter()是服务器端获取到客户端通过表单或url请求参数所发送过来的参数值,是客户端与服务器端之间的交互。服务器端要想获取客户端发送过来的数据,就需要通过getParameter()来获取,没有setParameter()方法。
  3. request内数据的存活范围就是在request对象的存活范围内,当客户端向服务器端发送一个请求,服务器向客户端返回一个响应后,该请求对象就被销毁了;之后再向服务器端发送新的请求时,服务器会创建新的request对象,该request对象与之前的request对象没有任   何关系,因此也无法获得在之前的request对象中所存放的任何数据。
  4. session内数据的存活范围就是session对象的存活范围。
  application(应用对象):存活范围最大的对象,只要服务器没有关闭,application对象就会一直存在。在整个服务器的运行当中,application对象只有一个。
  application.getRealPath("")返回资源在服务器上的具体位置。
  10. 做Java Web项目当然离不开网络,你要学会HTTP协议以及衍生的一些知识。(另详述)
  11. 理论实在太枯燥,我们说几个实际开发中的场景吧:
  //场景一:(异步消息机制)
  在J2EE系统中最常见的一个场景,前端浏览器 jsp/servlet向服务器端发出一个请求,jsp/servlet将请求传递给后端的应用程序处理业务逻辑,业务模块将响应的结果直接返回给客户端,而不是真正的计算结果,例如一个网站的用户注册功能,一个用户点击注册以后,将会发
  送一份邮件给他当时的注册邮箱,如果需要等到邮件发送成功再返回给用户结果的话,用户体验将会很差,所以将结果直接返回给用户,将用户注册的信息通过消息发送给后端程序慢慢处理。
  上面的异步消息机制。JMS(Java消息服务)大体上有 3个部分消息发送端、中间件服务器、消息接收端。三个组件缺一不可。 JMS消息分为两种消息模式,点对点和发布者/订阅者。许多提供商支持这种。程序员可以在他们的分布式软件中实现面向消息的操作,这些操作将具有不同面向消息中间件产品的可移植性。Java消息服务器是指,将数据通过消息作为载体在网络中从一个系统异步传送给另一个系统。这样的异步消息传送意味着:发送者不需要等待接收者接收或处理该消息;它可以自由地发送消息并持续进行处理。这样一个异步式的架构主要依赖于一台消息服务器(message server)。消息服务器,也称为消息路由器(message router)或代理(broker),它负责从一个消息传送客户端向其他消息传送客户端传送消息。
  JMS对与一个大型系统是必不可少的一个应用组件,可以利用JMS来实现3个目的:
  1.提高可伸缩性(Increase Scalability),
  2.可以利用JMS来缓解系统瓶颈(Reduce  Bottlenecks)
  3.提高系统对用户的响应能力
  Topic消息和Queen消息:
  Topic  是一对多的消息传送,你可以看做是QQ应用程序 QQ群 聊天中的一对多发送消息,一个人发出消息,可以有多个订阅的人阅读的到,需要有一个消息主题作为支柱,Tocip消息发送完毕以后 无论有      没有客户端接收,JMS服务器中的Topic消息都不会存在JMS服务器中。
  Queue是一对一的消息传送,你可以看做是QQ应用程序中的一对一发送消息,一个人发出消息,只能有另外一个人阅读的到,中间需要通过一个队列支持Queue消息发送完毕后会保存在 JMS服务器的队列        中,如果接收端接收以后将从队列中摘除。
  Topic发送完毕以后不会保留在JMS服务器;Queue消息发送完毕后会保存在 JMS服务器的队列中。
  //场景一:(Java应用多线程的场景)
  我们的项目部署在Tomcat上,上百个客户端访问同一个web应用,tomcat接入后都是把后续的处理扔给一个新的线程来处理,这个新的线程最后调用到我们的servlet程序,比如doGet或者doPost方法。你想,如果不采用多线程机制,上百个人同时访问一个web应用的时候,
  tomcat就得排队串行处理了,那样客户端根本是无法忍受那种访问速度的。所以说,Tomcat内部采用的就是多线程。
  比如任务 a和任务 b要并行处理,单个线程只能串行处理,先做完任务 a然后再做任务b。如果想要多个任务同时执行的话,就必须为每个任务分配一个线程,然后通过java虚拟机的线程调度,来同时执行多个任务。比如你的CPU是多核心的话,就可以让一个CPU执行一个线程。如果只有一个CPU的话,底层是按照分时复用的原则,各个线程按照时间片来获得CPU资源。那么这种场景,显然也是需要使用多线程的。
  在Java web 开发方面,几乎用不到多线程!因为有多线程的地方 servlet 容器或者其他开发框架都已经实现掉了。
  //场景一:(Java集合类的应用场景)
  说到集合类,无非就是三个:List、Set和Map。
  集合类,就是容器。容器就是箱子,Java中的箱子就是用来盛放Java对象。他们这三个箱子还是不一样的。
  第一个箱子,箱子List。在J2EE web项目中,我们的admin管理端,常常需要呈现一些数据。比如你做了一个淘宝,对于商家来说,商家登录管理端。需要看到自己所有的订单,以列表的形式展现出来。那么这是我们常常会使用ArrayList。
  ArrayList<OrderList> list = new ArrayList<OrderList>();
  list.add(new OrderList());
  list.add(new OrderList());
  list.save();
  List这个箱子,按照对象进入的数学保存元素,不做排序和编辑操作。元素可以重复。
  强调一下,List是接口不是类。List接口继承自 Collection接口。实现List接口的类主要有三个:LinkedList, ArrayList, Vector(面试中常有三种的区别)
  List接口有三个实现类:LinkedList,ArrayList,Vector
  LinkedList:底层基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢
  ArrayList和Vector的区别:ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低
  List的功能方法
  实际上有两种List: 一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,它并不是为快速随机访问设计的,而是具有一套更通用的方法。
  List : 次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推荐LinkedList使用。)一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。
  ArrayList : 由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和移除元素。因为那比LinkedList开销要大很多。(ArrayList有默认的初始化容量以及扩容机制,面试中常被提及)
  LinkedList : 对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替。)还具有下列方法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 这些方法 (没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
  第二个箱子,箱子Set。假如我们现在想要在一大堆数据中查找 X 数据。LinkedList的数据结构就不说了,查找效率低的可怕。ArrayList哪,如果我们不知道X的位置序号,还是一样要全部遍历一次直到查到结果,效率一样可怕。HashSet天生就是为了提高查找效率的。
  当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致; 如果不一致,直接加进去; 如果一致,再进行equals方法的比较。equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则添加进去。
  http://www.java3z.com/cwbwebhome/article/article8/83553.html?id=4632  关于HashSet与hasCode() 的关系,可以看这篇帖子。
  Set无放入顺序,元素不可重复。同样的Set是接口,它继承自Collection接口,它的实现类有:HashSet(底层由HashMap实现),TreeSet,LinkedHashSet
  Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)
  Set : 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
  HashSet : 为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
  TreeSet : 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
  LinkedHashSet : 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
  第三个箱子,箱子Map。List,Set,Map是否继承自Collection接口?List,Set是,Map不是。 Collection是最基本的集合接口。 Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当做一组key集合和一组value集合,或者一组key-value映射。
  Map的功能方法:
  方法put(Object key, Object value)添加一个“值”(想要得东西)和与“值”相关联的“键”(key)(使用它来查找)。方法get(Object key)返回与给定“键”相关联的“值”。可以用containsKey()和containsValue()测试Map中是否包含某个“键”或“值”。标准的Java类库中包含了几种不同的Map:HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap。它们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定“键”等价的策略等各不相同。
  执行效率是Map的一个大问题。看看get()要做哪些事,就会明白为什么在ArrayList中搜索“键”是相当慢的。而这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为“散列码”(hash code),来取代对键的缓慢搜索。“散列码”是“相对唯一”用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有Java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。
  HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显著提高性能。
  Map : 维护“键值对”的关联性,使你可以通过“键”查找“值”
  HashMap : Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
  LinkedHashMap : 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
  TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
  WeakHashMao : 弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。
  IdentifyHashMap : 使用==代替equals()对“键”作比较的hash map。专为解决特殊问题而设计。
  12. 讲到Java这门语言,就不得不说其运行时候很关键的一部分,Java虚拟机。它承上启下,基于操作系统,服务于我们的程序。我们的程序的具体执行是在Java虚拟机中来执行的。我们在Java基础知识中,知道有基本数据类型和引用数据类型。所以,很多人只知道有堆内存和栈内存。但是,很显然程序真正运行的时候,内存的划分远比这个发杂的多,接下来我们就详细了解一下Java运行时,内存是怎么划分疆域的。
  方法区                               堆
  本地方法栈                            程序计数器
  虚拟机栈
  为了容易记忆,总共划分为五个部分。方法区、本地方法栈、虚拟机栈、堆、程序计数器。
  // 方法区
  方法区与java堆栈一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等。虽然java规范里面把方法区描述为堆的一个逻辑部分,但是其实它是一个非堆【Non-Heap】,其目的就是为了和java堆区分开。
  在HotSpot虚拟机中,很多人都把方法区成为永久代,其实只在hotspot才存在方法区,在其他的虚拟机没有方法区这一个说法的。本文是采用Hotspot,所以把方法区介绍了。在这里在啰嗦一下,如果方法区无法满足内存分配需求时候就会抛出OutOfMemoryError异常。
  // 本地方法栈
  本地方法栈和虚拟机栈差不多,只不过java虚拟机执行java的方法,本地方法区执行的是native方法而已,有的虚拟机把本地方法和虚拟机栈合二为一。
  // Java虚拟机栈
  java虚拟机栈和程序计数器一样的,线程都是私有的,它的生命周期与线程一样【虚拟机栈描述的是java方法执行的内存模型,每个方法执行的时候都会创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程。就对应着一个栈在虚拟机中从入栈道出栈的过程。
  // 程序计数器
  程序计数器是一个很小的内存空间,它的作用其实很简单,就是当前线程所执行的字节码行号的指示器。在Hotspot虚拟机中字节码解释器工作的时候就是通过改变这个计数器的值来选取下一条需要执行的字节码指令、分支、循环、跳转、异常处理等等。
  // 堆
  在java程序员中堆,肯定不陌生,堆是使用的最多的,也是程序猿最关心的一快内存区域。堆中所有的线程都共享一个内存区域,在虚拟机启动的时候就被创建,此内存区域唯一的目的就是存放对象实例,几乎所有的对象实例都在这里分配,但是随着JIT的成熟,有些时候可能不一样。
  同时java堆中也是GC管理的主要区域,有时候也叫GC堆,java堆中可以分为新生代和老年代,Eden空间,from Survivor空间,To Survivor空间。新生代和Eden空间采用的GC算法【主要是分代收集算法】不一样。
  13. Java集合类框架。
33/3<123
重磅发布,2022软件测试行业现状调查报告~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号