JavaWeb之Servlet

Servlet:
Sun公司制订的一种用来扩展Web服务器功能的组件规范。当浏览器将请求发送给Web服务器(比如:apcahe的web server),Web服务器会向Servlet容器发送请求,Servlet容器负责解析请求数据包。
—> 组件:是符合一定规范,并且实现部分功能的可以单独部署的软件模块。组建必须要部署到容器里面才能运行。
—> 容器:也是符合一定规范,并且提供组件的运行环境的程序。

Tomcat:Tomcat本身是一个Servlet容器,即可以提供Servlet运行环境的一个程序,但是Tomcat还提供了Web服务器所具有的所有功能,所以我们也称Tomcat是一个Web服务器。Tomcat的默认端口是8080。
—> 目录结构:
①bin目录:存放启动和关闭服务器的一些脚本(命令)。
②common目录:共享(部署在该服务器上的所有程序都可以使用)的一些jar包。
③conf目录:存放服务器的一些配置文件。
④webapps目录:部署目录。
⑤work目录:服务器运行时,生成的一些临时文件。

Http:(Hypertext transport protocol)是超文本传输协议。是一种应用层协议,由W3C制定,它定义了浏览器(或者其他客户端)与Web服务器之间通讯的过程及数据格式。
—> 通信步骤:
①:浏览器建立与Web服务器之间的连接(Socket)。
②:浏览器要将请求数据打包(请求数据包),然后发送给Web服务器。
③:Web服务器将处理结果打包(响应数据包),然后发送给浏览器。
④:Web服务器关闭连接。
◆ 特点:一次请求,一次连接。优点:Web服务器可以利用有限的连接个数为尽可能多的客户服务(效率高)。如果浏览器要再发请求,就必须重新建立一个新的连接。

Https:(Hyper Text Transfer Protocol over Secure Socket Layer)是为安全为目标的HTTP通道,即HTTP下加入SSL层。
—> 与HTTP区别
①:https地协议需要到ca申请证书(https://www.[shuzizhengshu.com/);
②:http的信息是明文传输,https则具有安全性的ssl加密传输协议;
③:两者使用的是完全不同的连接方式,端口也不一样,http是80,https是443;
④:http是无状态的;https是由ssl+http协议构建的可加密传输、身份认证的网络协议。

信任主机:采用https的服务器必须从CA (Certificate Authority)申请一个用于证明服务器用途类型的证书。该证书只有用于对应的服务器的时候,客户端才信任此主机。
—>两种信任主机方式:
1)一般意义上的https,就是服务器有一个证书;
服务器端和客户端之间所有通讯都是加密的;
a. 客户端产生一个对称的密钥,通过服务器的证书来交换密钥,即一般意义上的握手过程;
b.接下来所有信息都是加密的。第三方即使截获,也没有任何意义,因为他没有密钥,当然篡改也就没有什么意义了。
2)少许对客户端有要求的情况下,会要求客户端也必须有一个证书。
这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码,还有一个CA 认证过的身份。(大多数个人银行的专业版是这种做法,具体证书可能是拿U盘(即U盾)作为一个备份的载体。)

ssl协议工作流程:
①:客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;

②:服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;

③:客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;
④:服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。

ssl握手过程:
①客户端的浏览器向服务器传送客户端SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。

②服务器向客户端传送SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。

③客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行第四步。

④用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
⑤如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。

⑥如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。

⑦服务器和客户端用相同的主密码即“通话密码”,一个对称密钥用于SSL 协议的安全数据通讯的加解密通讯。同时在SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。

⑧客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。

⑨服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。

⑩SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。

—> 数据格式:
1)请求数据包:
①请求行:请求方式+请求资源路径+协议描述。
②若干消息头:消息头是一些键值对,一般由W3C定义,有特定的含义。
③实体内容:只有当请求方式为post时,浏览器才会将请求参数添加到实体内容里面,如果请求方式为get,浏览器会将请求参数添加到请求资源路径的后面。
2)响应数据包
①状态行:协议描述+状态码+状态描述。
②若干消息头:服务器也可以发送一些消息头给浏览器
③实体内容:程序处理之后,返回的结果。
3)get/post:
①get请求会将请求参数添加到请求资源路径的后面,因为请求行存放的数据大小有限(也就是地址栏的最长字节数),所以get请求只能提交少量的数据。
②get请求会将请求参数显示在浏览器地址栏,不安全(比如,路由器会记录整个地址)
③ post请求会将请求参数添加到实体内容里面,所以,可以提交大量的数据。
④ post请求不会将请求参数显示在浏览器地址栏,相对安全一些。但是,post请求并不会对请求参数进行加密处理。用HTTPS协议进行加密处理

重定向:服务器发送一个302状态码及一个Location消息头(值是一个地址,称为重定向地址),通知浏览器立即向重定向地址发请求。[ response.sendRedirect(String url) ]
—> 特点:
1)重定向的地址是任意的(前提要存在否则报404)。
2)重定向之后,浏览器地址栏的地址会变成重定向地址。

请求转发:一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个Web组件继续完成。常见的情况是:一个Servlet将数据处理完毕之后,转交给一个JSP去展现。
—>步骤:
1)绑定数据到request:request里有个HashMap。request.setAttribute(String name,Object obj);
2)获得一个转发器:url:要转发给哪一个Web组件。RequestDispatcher rd=request.getRequsetDispatcher(String url);
3)转发: rd.forward(request,response);//JSP和Servlet会共享相同的请求和响应对象
4)在转发的目的地,可以使用request.getAttribute方法获得绑定的数据,然后进行处理。【注意:转发之前,先清空response对象中缓存的数据;不能调用out.close()或着out.flush只能同时处理一个响应】
—> 特点:
1)转发的目的地只能够是同一个应用内部的某个组件的地址。
2)转发之后,浏览器地址栏的地址不变。
3)转发所涉及的各个Web组件可以共享同一个request对象和response对象

转发和重定向的区别:
1)转发的目的地只能是同一个应用内部某个组件的地址,而重定向的目的地是任意的。
2)转发之后,浏览器地址栏的地址不变,而重定向会变。
3)转发所涉及的各个Web组件可以共享request对象,而重定向不可以。
4)转发是一件事情未做完,而重定向是一件事情已经做完。

Servlet容器资源路径处理
1)Servlet容器会先假设访问的是一个Servlet,会依据应用名(appname)找到应用所在的文件夹,然后找到web.xml文件。
2)匹配<url-pattern>
①精确匹配(完全匹配):“/”、大小写、名字完全一样。
②通配符匹配:使用 “” 来匹配任意长度的字符串,比如:<url-pattern>/</url-pattern>
③后缀匹配:使用“.”开头,后接任意的字符串,比如:<url-pattern>.do</url-pattern>
3)如果都不匹配,则容器认为访问的是一个静态资源文件(比如html文件),然后容器会查找该文件,如果找到则返回,否则会返回404

Servlet处理多种请求
1)使用后缀匹配模式,比如<url-pattern>*.do</url-pattern>
2)分析请求资源路径,然后依据分析的结果分别进行不同的处理,需使用String request.getRequestURI();

Servlet生命周期:四个阶段:
1)实例化:指的是容器调用Servlet的构造器,创建Servlet对象。
—> 时机:
情况1:容器收到请求之后才创建Servlet对象。在默认情况下,容器只会为Servlet创建唯一的一个实例(多线程,有安全问题。每次请求创建一个线程,由线程去调用方法)。
情况2:容器事先(容器启动时)将某些Servlet(需要配置load-on-startup参数)对象创建好。load-on-startup参数值必须是>=0的整数,越小,优先级越高(即先被实例化)。参数加在web.xml配置文件里的某个<servlet>标签里,如<load-on-startup>1</load-on-startup>
2)初始化:指的是容器在创建好Servlet对象之后,会立即调用Servlet对象的init方法。
3)就绪:指是Servlet对象可以接受调用了,容器收到请求之后,会调用Servlet对象的service方法来处理,且可以被执行多次。
4)销毁:销毁指的是Servlet容器在销毁Servlet对象之前,会调用destroy方法,且只会执行一次。

状态管理:将浏览器与Web服务器之间多次交互当作一个整体来看待,并且将多次交互所涉及的数据保存下来。
—> 类型:
1)客户端状态管理技术,即将状态(也就是多次交互所涉及的数据)保存在客户端(浏览器)。
2)服务器端状态管理技术,即将状态保存在Web服务器端。

cookie:
①是一种客户端的状态管理技术。
②当浏览器访问服务器的时候,服务器可以将少量的数据以set-cookie消息头的方式发送给浏览器,浏览器会将这些数据保存下来。当浏览器再次访问服务器时,会将之前保存的这些数据以cookie消息头的方式发送给服务器。
【注意:有几个cookie,就有几个set-cookie消息头。】
1)创建:Cookie c=new Cookie(String name,String value);//name:cookie的名称。value:cookie的值
2)添加Cookie:response.addCookie(c);//调用响应对象的addCookie方法
3)查询Cookie:Cookie[] request.getCookies();//如果没有任何的cookie,则返回null; String cookie.getName();//返回cookie的名称; String cookie.getValue();//返回cookie的值;
4)编码:cookie的值或者名称只允许合法的ASCII码字符串,如果是中文,需要将中文转换成ASCII码字符串。
String URLEncoder.encode(String str,String code);
String URLDecoder.decode(String str,String code);
5)Cookie生存时间:默认情况下,浏览器会将cookie保存在内存里,只要浏览器不关闭,cookie会一直存在。
—> 启动FireFox后,操作系统会为浏览器开辟一块内存空间:
①浏览器(FireFox)访问服务器。
②服务器生成消息头setCookie发回给浏览器。
③浏览器将服务器生成的消息头保存到内存区域。
④当浏览器关闭,系统回收为浏览器分配的内存,cookie也相应消失。
—> 设置生存时间:使用cookie.setMaxAge(int seconds)方法。
①单位是秒。
②当seconds>0时,浏览器会将cookie保存在硬盘上,当cookie保存的时间超过了seconds,则cookie会被浏览器删除。
③当seconds<0时,缺省值(浏览器会将cookie保存在内存里)。
④当seconds=0时,删除cookie。所以Cookie中无删除方法,设置为0即可。而修改,则为覆盖,用相同的name。
6)Cookie路径问题:浏览器在向服务器上的某个地址发请求时,会比较请求地址与cookie的路径是否匹配,只有匹配的cookie才会发送。
①默认路径:值等于创建该cookie的组件的路径,比如:/web06_Cookie/
②匹配规则:只有当访问的地址是cookie的路径或着是其子路径时,浏览器才会将这个cookie进行发送。
7)Cookie限制:
①cookie可以被用户禁止。
②因为cookie保存在浏览器端,所以cookie不安全。对于一些敏感的数据,需要加密处理。
③cookie只能够保存少量的数据(大约是4K左右)。
④cookie的个数也有限制(浏览器只能够保存大约300个左右的cookie,另外对于某个服务器也有cookie个数的限制,大约是20个)。
⑤cookie只能够保存字符串,对象、集合、数组都不能保存。

session(会话):
①是服务器端的状态管理技术。
②当浏览器访问服务器时,服务器会创建一个session对象(该对象有一个唯一的id号,称之为sessionId)。接下来,服务器在默认情况下,会使用set-cookie消息头将这个sessionId发送浏览器,浏览器会将这个sessionId保存下来(内存中,因为指定生存时间)。当浏览器再次访问服务器时,会将sessionId使用cookie消息头发送给服务器,服务器依据这个sessionId就可以找到之前创建的session对象。
③用户与服务器之间的多次交互叫一次会话。

  1. 创建:
    —> 方式一:HttpSession s=request.getSession(boolean flag);//HttpSession是一个接口,返回一个符合要求的对象(工厂)
    【注意:当flag=true时:
    服务器会先检查请求当中是否有sessionId,如果没有则创建一个session对象。如果有sessionId,则服务器会依据sessionId查找对应的session对象,如果找到了,则返回session对象。根据sessionId找不到,则服务器会创建一个新的session对象。
    当flag=false时:服务器会先检查请求当中是否有sessionId,如果没有则返回null。如果有sessionId,则服务器会依据sessionId查找对应的session对象,如果找到了,则返回session对象。根据sessionId找不到,则服务器返回null。】
    —> 方式二:HttpSession s=request.getSession();//等价于HttpSession s=request.getSession(true);
  2. 常用方法:
    —> String getId():获得sessionId
    —> setAttribute(String name,Object obj):绑定一个对象到session对象上
    —> getAttribute(String name):获得绑定对象,如果不存在则返回null
    —> removeAttribute(String name):解除绑定(request也有)
  3. session超时:
    ① 服务器会将空闲时间过长的session对象删除。大部分服务器默认的session超时限制是30分钟。
    ② 修改超时限制:可以修改这个默认的超时限制。setMaxInactiveInterval(int seconds); 或者在web.xml中修改
<session-config>        <session-timeout>30</session-timeout>    </session-config>

③ 立即删除session:invalidate();//实际是清空session对象的内容,然后可以给其他人继续使用该session对象

用户禁止cookie后,如何继续使用session:

  1. 如果用户禁止cookie,服务器仍然会将sessionId以cookie的方式发送给浏览器,但是,浏览器不再保存这个cookie(即sessionId)
  2. 如果想要继续使用session,需要采取其他方式来实现sessionId的跟踪,如可以使用url重写来实现sessionId的跟踪。
    url重写:浏览器在访问服务器上的某个地址时,不能够直接写这个组件(Servlet/JSP)的地址,而应该使用服务器生成的包含有sessionId的地址。
    ① response.encodeURL(String utl);//encodeURL方法用在链接地址、表单提交地址。
    ② response.encodeRedirectURL(String url);//用于重定向
    ③ 转发不用考虑!是服务器内部,不是浏览器访问服务器。

session的优缺点:
—> 优点:
1)session比较安全(相对于cookie)因为将所有状态都写在服务器端。
2)session能够保存的数据类型更加丰富(cookie只能保存字符串)。
3)session能够保存的数据大小更大(cookie只能保存大约4K左右的数据),理论上session是没有限制的。
4)session没有被禁止的问题,也就不需要url重写(cookie可以被用户禁止)。
—> 缺点:
1)session会将数据放在服务器端,所以,对服务器的资源的占用比较大,而cookie会将数据保存在浏览器端,对服务器资源的占用没有。
2)session默认情况下,会将sessionId以cookie的方式发送给浏览器,浏览器会将session保存到内存中,如果浏览器关闭,浏览器发请求时就没有sessionId,服务器端的session对象就找不到了。
【注意:可使用 spring session来管理 】

过滤器: Servlet规范当中定义的一种特殊的组件,可以拦截Servlet容器的调用过程并进行相应的处理。某个过滤器只有一个实例,即单例模式。

监听器: Servlet规范当中定义的一种特殊的组件,用来监听容器产生的事件并进行处理。
—> 容器产生的两大类事件:
1)生命周期相关的事件:容器在创建或者销毁Requset对象、Session对象、ServletContext对象(Servlet上下文)时产生的事件。
2)绑定相关的事件:容器调用了 Request 对象、 Session 对象、 ServletContext 的 setAttribute 、 removeAttribute 时产生的事件。

**ServletContext **:容器在启动的时候,会为每一个应用创建唯一的一个符合ServletContext接口要求的对象(Servlet上下文),该对象一直存在,只有非容器关闭时对象被销毁。
—> GenericServlet. getServletContext() ;//通过GenericServlet抽象类获得上下文(其实也是调用了ServletConfig的getServletContext方法)
—> HttpSession. getServletContext();//通过Session获得上下文
—> ServletConfig .getServletContext() ;//通过ServletConfig接口获得上下文
—> FilterConfig .getServletContext() ;//通过过滤器获得上下文
** 作用:
1)绑定数据: setAttribute 、 removeAttribute 、 getAttribute 、 Request 、 Session 、 ServletContext 都提供了绑定数据的相关的三个方法,如果都满足使用的条件,应该优先使用生命周期短的 Request<Session<ServletContext )。

①Request对象上绑定的数据只有同一个请求所涉及的各个Web组件可以共享,例如:一个Servlet将数据绑定到Request,然后转发到一个jsp。请求先交给过滤器来处理,然后调用Servlet。
②Session对象上绑定的数据是用一个会话所涉及的各个Web组件可以共享。
③ServletContext对象绑定的数据是公开的,谁都可以访问,而且随时可访问

2)访问全局的初始化参数:即使用<context-param>配置的初始化参数,调用 String getInitParameter(String paramName) 方法,可以被同一个应用中的所有的Servlet、Filter共享。
3)依据逻辑路径(path)获得实际部署时的物理路径

**C/S架构: Client/Server **
1)两层的C/S架构:
—> 优点:开发效率高;
—> 缺点:
①对数据库而言可移植性差。
②不适合大型应用(服务器提供的连接个数是有限的)。
2)三层的C/S架构:有自定义协议;TCP/IP协议有两个问题:①拆包问题。②粘包问题。
—> 执行过程:用户点击GUI(图形界面),GUI调用通信,通信打包(自定义协议),发送请求给服务器通信,通信拆包(自定义协议),调用业务,业务处理,结果发给通信,通信打包,发送响应给客户端通信,通信拆包,然后更新GUI。

**B/S架构: Browser/Server **
和C/S三层架构相同,只是客户端不用写,服务器不用写,通信也不用写,浏览器里都有,采用http协议,是w3c标准,不需要自定义协议了。

博客地址:JavaWeb之Servlet

推荐阅读更多精彩内容