1. 哪个项目能离开网络,数据库,操作系统来运行?所以生态圈的应用技术主要在这些知识点处。
2. Java组件,组件其实就是一个应用程序块 但是它们不是完整的应用程序,不能单独运行。就有如一辆汽车,车门是一个组件,车灯也是一个组件。但是光有车灯车门没有用,它们不能跑上公路在java中这些组件就叫做javabean,有点像微软以前的com组件,要特别说明的是,由于任何一个java文件编译以后都是以类的形式存在所以javabean肯定也是一个类,这是毫无疑问的。那么容器里装载的是什么呢?就是这些组件。而容器之外的程序需要和这些组件交互必须通过容器。举个例子,IE发送了一个请求给容器,容器通过调用其中的一个组件进行相关处理之后将结果反馈给IE,这种与客户端软件交互的组件就叫做servlet。但是组件有很多种,那么如何区分这些组件呢?有多种管理办法,比如同是同样是servlet,有些是通过jsp生成的而有些是开发人员自己写的,那么通过jsp生成的servlet集中放在一个地方而开发人员自己写的则需要在xml里面配置一些基本的参数同时,不同组件有可能还需要继承一些特定的父类或者接口,这也是容器管理的需要还有其他的一些组件。那么容器有很多种,按照他们装载的组件类型划分:比如有装EJB的EJB容器,有装servlet与jsp还有静态页面的web容器等等,这种只含有web容器的应用服务器也被叫做web服务器 。(当表示层的应用软件通过网络向appserver发送一个请求的时候 appserver自动找到相应容器中的组件,执行组件中的程序块,把得到结果返还给客户 而我们要做的事就是写组件也就是javabean,然后放到appserver里面去就可以了 至于怎样与IE通讯,怎样截获网络上的请求,怎样控制对象的数量等等 这些繁琐而无味的工作我们都不管,都由appserver去做吧,把注意力集中在业务逻辑上 )
3. 框架就是一组相互协作的类,对于特定的一类软件,框架构成了一种可重用的设计。
4. 对于Servlet,我们常常这样称呼:Servlet容器。Servlet工作原理:首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet,doPost等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息。所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。
Servlet生命周期分为三个阶段: 1,初始化阶段 调用init()方法 2,响应客户请求阶段 调用service()方法 3,终止阶段 调用destroy()方法
Servlet初始化阶段: 在下列时刻Servlet容器装载Servlet: 1,Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码: <loadon-startup> 1 </loadon-startup>
2,在Servlet容器启动后,客户首次向Servlet发送请求 3,Servlet类文件被更新后,重新装载Servlet。Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。
Servlet响应请求阶段: 对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。service方法从ServletRequest对象获得客户请求信息,处理该请求,并通过ServletResponse对象向客户返回响
应信息。
对于Tomcat来说,它会将传递过来的参数放在一个Hashtable中,该Hashtable的定义是:private
Hashtable<String String[]> paramHashStringArray =
new
Hashtable<String String[]>();
这是一个String-->String[]的键值映射。HashMap线程不安全的,Hashtable
线程安全的。
Servlet终止阶段: 当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法,在destroy()方法中可以释放掉Servlet所占用的资源。
Servlet何时被创建: 1,默认情况下,当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例。 2,当web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。 注意:在web.xml文件中,某些Servlet只有<serlvet>元素,没有<servlet-mapping>元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在<servlet>元素中配置一个<load-on-startup>子元素,让容器在启动的时候自动加载这些Servlet并调
用init()方法,完成一些全局性的初始化工作。
Web应用何时被启动: 1,当Servlet容器启动的时候,所有的Web应用都会被启动 2,控制器启动web应用Servlet与JSP的比较: 有许多相似之处,都可以生成动态网页。 JSP的优点是擅长于网页制作,生成动态页面比较直观,缺点是不容易跟踪与排错。 Servlet是纯Java语言,擅长于处理流程和业务逻辑,缺点是生成动态网页不直观。
对于文中说到的,Servlet生成动态网页不直观。servlet可以用于生成动态的Web页内容。但是,它的一个缺点是必须将HTML标记和文本嵌入到Java源代码中。这样,如果要改变静态的HTML文本,必须修改Java源代码并重新进行编译。同时,在servlet中有许多静态HTML代码和一些动态HTML代码混在一起,由于正常的HTML代码是Java源代码的一部分,所以很难阅读和维护这些代码。JSP就是为了克服上述缺点而引入的。
编辑文件:CurrentTime.jsp如下所示:
<html><head> <title>CurrentTime</title></head><body> CurrentTime is <%= new java.util.Date()%></body></html>
将程序放到tomcat容器下运行。
5. 继续探究Servlet,Servlet本身是单实例的,这样当多个用户同时访问某个Servlet时,会访问该唯一的Servlet实例中的成员变量,如果对成员变量进行写入工作,那就会导致Servlet的多线程问题,即数据不一致。
解决Servlet多线程同步问题的方案: 1,Servlet实现了javax.servlet.singleThreadModel(Servlet2.4中已经废弃该接口),此时的Servlet容器将保证Servlet实例是以单线程的方式运行,也就是说同一时刻,只会有一个线程运行Servlet的service()方法。 不推荐使用,大大降低了效率。 2,去除实例变量,使用局部变量 推荐 3,使用同步代码块 synchronized{...} 不推荐使用
6. Cookie的英文原意是“点心”,当用户访问WEB服务器时,服务器在用户硬盘上存放的信息,好像是服务器送给用户的点心。服务器可以根据Cookie来跟踪用户,这对于需要区别用户场合特别有用。先来看看我们在HTML5项目中使用过的cookie具体案例:
这个是在H5/js/common.js中的两个函数。
//保存到cookiefunction setCookie(name,value,days) { var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString(); } //读取cookies function getCookie(name) { var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)"); if(arr=document.cookie.match(reg)) return unescape(arr[2]); else return null; }
两个函数,分别用来设置cookie和取得cookie。
setTimeout(function() {
var cookieChid=getCookie('chid');
if(cookieChid !='w5')
{
$("#underonlaodFlag").attr("style","display:display");
}
},300);
在其他页面中,通过这段JS,延迟300ms执行,保证先加载了common.js, 再执行这段JS。做出判断。
var uid=getCookie('uid')==null?'':getCookie('uid'); //这个同样是其他页面需要使用cookie的案例。
继续来读代码
public class CookieServlet extends HttpServlet{ private int count1; private int count2; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("cookiename"+ count1++,"cookievalue"+ count2++); cookie.setMaxAge(10);//设置存活时间 单位秒 resp.addCookie(cookie); Cookie[] cookies = req.getCookies(); if(null == cookies) { return; } for(Cookie cookie2:cookies) { System.out.println(cookie2.getName()); System.out.println(cookie2.getValue()); } }}
//代码中展现了:Servlet 中创建、存储和接收客户端存储Cookie的过程。
7. 客户端的cookie都有生命周期的,一般为两周。又或者用户主动清空了自己的cookie,那么服务器怎么来跟踪用户记录呢?Session回话,Session用于跟踪客户的状态,Session是指在一段时间内,单个客户与WEB服务器一连串相关的交互过程。在一个Session中,客户可能多次请求访问同一个网页,也有可能请求访问各种不同的服务器资源。
Web服务器跟踪客户状态通常有四种方法: 1,建立含有跟踪数据的隐藏字段 type=hidden 2,重写包含额外参数的URL 3,使用持续的Cookie 4,使用Servlet API中的Session(会话)机制
Session的生命周期: 当客户第一次访问WEB应用中支持Session的某个页面时,就会开始一个新的session 接下来客户访问这个WEB应用中不同的网页时,都处于同一个session中 默认情况下,JSP页面是支持Session的,如果想不支持Session,可使用标签<%@ page session="false"%> 在下列情况下,Session将结束生命周期,Servlet容器将释放HttpSession占用的资源: 1,客户浏览器关闭? 2,Session过期 3,服务器端调用了HttpSession的Invalidate()方法 如何做到在浏览器关闭时删除Session? 严格的讲,做不到这一点。可以做的努力的办法是在所有的客户端页面里使用javascript的方法window.onclose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除Session; 但是对于浏览器崩溃或强行杀死进程这种非常规手段仍然无能为力。 实际上我们在项目中也不会这么做,而是让服务器在Session过期时将其删除。
Session运行机制: 当一个Session开始时,Servlet容器将创建一个HttpSession对象,在HttpSession对象中可以存放客户的状态信息(例如购物车)。 Servlet容器为HttpSession分配一个唯一标志符,称为SessionID。Servlet容器将SessionID作为Cookie保存在客户的浏览器中。 每次客户发送Http请求时,Servlet容器可以从HttpServletRequest对象中读取SessionID,然后根据SessionID找到对应的HttpSession对象,从而获取客户的状态信息。Session的接口HttpSession: getId() 返回session的ID Invalidate() 让当前session失效,Servlet容器会释放HttpSession对象占用的资源 getAttribut() setAttribute() isNew() 判断是否是新创建的session,如果是返回true 否则返回false setMaxInactiveInterval() 设置session的最大有效时间 单位为秒 如果设置为负数,表示不限制session处于不活动状态的最大有效时间,默认的设置时间为30分钟
8. 说完了Servlet,来到了我们常用的框架中是怎么拦截过滤Servlet的。那就说到了Servlet的过滤器Filter。
Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。Servlet过滤器本身不生成请求和响应对象,它只提供过滤作用。Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容。在Servlet被调用后检查Response Header和Response内容,Servlet过滤器负责过滤WEB的组件可以是Servlet,JSP和HTML。
Filter接口: 每一个Servlet过滤器都会实现javax.serlvet.Filter接口,这个接口中含有三个过滤方法必须实现: init(FilterConfig):这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器后将调用这个方法,在这个方法中可以读取web.xml中Servlet过滤器的初始化参数 doFilter(ServletRequest,ServletResponse,FilterChain):这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。 destroy():Servlet容器在销毁过滤器实例前调用这个方法,在这个方法中可以释放Servlet过滤器占用的资源。
我们可以看一段使用struts框架中的过滤器的实例是怎么操作的。
//这个是在web.xml中使用struts2的过滤器的配置文件,
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
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 容器或者其他开发框架都已经实现掉了。
12.
- 2楼美洲象
- 楼主讲得非常循序渐进,深入浅出,强!
- 1楼我爱博客园AAA
- mark~,,可以和你一起交流吗 群:452982916 小伙伴们都在等你