现在的位置: 首页 > 综合 > 正文

Servlet总结

2018年05月19日 ⁄ 综合 ⁄ 共 5266字 ⁄ 字号 评论关闭

一、servlet是什么?
是由sun公司制订的一种用来扩展web服务器功能的组件规范。
(1)扩展web服务器功能
  当请求到达web服务器(apache提供的web server,微软的iis)时,这些web服务器只能够处理静态资源(即需要事先将html文件写好,并且保存到服务器特定的文件夹下面)的请求,如果是一个动态资源(需要计算,然后动态生成相应的html)的请求,web服务器不能够处理,需要扩展其功能。
(2)组件
  1)什么是组件?
   符合特定的规范,并且实现了部分功能的,可以单独部署的软件模块。
  2)什么是容器?
   符合特定的规范,并且提供组件的运行环境的程序。
  3)serlvet容器是什么?
   servlet就是一个组件,需要部署到servlet容器才能运行。  
二、如何开发一个servlet?
step1,先写一个java类,实现Servlet接口或者继承HttpServlet抽象类。
step2,编译
step3,打包
  即需要建立一个具有如下结构的文件夹
  appname(应用名称)
   WEB-INF
    classes(放.class文件)
      lib(可选,放.jar文件)
      web.xml(描述文件)
step4,部署
  将step3生成的整个文件夹拷贝到容器特定的文件夹底下,比如,tomcat容器对应的是webapps。
  另外,也可以使用jar命令将step3生成的整个文件夹压缩(.war)。
step5, 访问
  http://ip:port/appname/url-pattern
注:使用myeclipse来开发servlet(略)

三、servlet是如何运行的?
比如,在浏览器地址栏输入http://ip:port/web01/greeting
  step1, 浏览器依据ip,port建立与服务器之间的连接。
  step2,浏览器将请求数据打包(按照http协议)。
  step3,浏览器发送请求。
  step4,服务器解析请求数据包,将解析的结果写到request对象上(为了方便servlet读取请求数据)。同时,服务器还会创建一个response对象(为了方便servlet输出处理的结果)。
  step5, 服务器依据请求资源路径(/web01/greeting) 找到应用所在的文件夹,并且依据"/greeting"找到对应的servlet类名。接下来要创建servlet对象。
  step6, 服务器要调用servlet的service方法,会将事先创建好的request,response对象作为参数传递进来。所以,可以通过request对象获得请求数据,也可以通过response对象输出处理的结果。
  step7,服务器通过response对象获得处理结果,然后将处理结果打包,发送给浏览器。
  step8,浏览器解析服务器返回的处理结果,然后生成相应的界面。
  
小知识点:
  第三步浏览器发送请求有get方式和post方式两种:
  1)哪一些情况下,浏览器使用get方式发请求:
   a,直接在浏览器地址栏输入某个地址
   b,点击链接
   c,表单默认的提交方式
  2)get请求的特点
   a,如果有请求参数,会将这些参数添加在请求资源路径的后面(所以,get方式能够提交的参数大小有限制)。
   b,get方式还会将请求参数显示在浏览器地址栏,不安全。
  3)哪一些情况下,浏览器会使用post方式发请求:
   只有一种方式:设置了表单的method="post"。
  4)post请求的特点
   a,请求参数会添加到实体内容里面,参数大小没有限制。
   b,请求参数不会显示在浏览器地址栏,相对安全(并不会对请求参数加密)。
   
  第五步的时候,servlet容器(web服务器,比如tomcat)如何处理请求资源路径?
  比如,我们在浏览器地址栏输入:http://ip:port/web01/abc.html,则"/web01/abc.html"为请求资源路径。
  step1, 容器依据应用名("/web01")找到应用所在的文件夹。
  step2, 容器会假设这是一个servlet,会匹配web.xml配置文件里面的url-pattern:
  精确匹配: 要求url-pattern必须是"/abc.html"。
  通配符匹配: 使用"*"来代替任意的零个、一个或者多个字符。
    比如 <url-pattern>/*</url-pattern>
  后缀匹配:使用"*."开头,接一个任意的字符串。
   比如 <url-pattern>*.do</url-pattern>
   以上会匹配所有以".do"结尾的请求。
  (优先级:精确匹配>通配符匹配>后缀匹配)
  step3,如果以上匹配均不成功,容器会认为这是一个资源文件(比如是一个html文件),然后查找相应的资源文件,如果找到则返回,找不到返回404。
  
四、servlet的生命周期
(1)生命周期的含义:
  servlet容器如何创建servlet对象、如何初始化、如何调用servlet对象的方法完成请求处理以及如何销毁servlet对象的整个过程。
(2)生命周期可以分成四个阶段:
  1)实例化:
   a,含义:容器调用servlet构造器,创建其对象。
   b,什么时候实例化:
    第一种情况: 容器在收到请求之后。
    第二种情况: 容器在启动之后,会预先创建好一些servlet对象。要求这些servlet配置load-on-startup参数。
  2)初始化
   a,含义:容器调用servlet对象的init方法(init(ServletConfig)),
   初始化是在实例化之后立即进行的,并且只进行一次。
   b, init(ServletConfig config)方法:
    容器会事先创建好一个符合ServletConfig接口的对象,该对象提供了一个getInitParameter方法来获得servlet的初始化参数(在web.xml文件当中,使用init-param配置的参数)。
   c, 如何实现自已的初始化逻辑
    一般只需要override init()方法。因为init(ServletConfig config)方法里面调用了init()方法
  3)就绪/调用
   a,含义:容器收到请求之后,会调用servlet对象的service方法来处理请求。
  4)销毁
   a,含义:容器依据自身的算法,将不再需要的servlet对象删除掉,在删除之前,会调用servlet对象的destroy方法。该方法也只会执行一次。
   b,destroy方法一般不需要去override。
(3)跟生命周期相关的几个接口与类
   a, Servlet接口
    init(ServletConfig config)
    service(ServletRequest req,ServletResponse res)
    destroy()
   b, GenericServlet抽象类
    实现了Servlet接口,主要实现了init,destroy方法。
   c, HttpServlet抽象类 
    继承了GenericServlet,主要实现了service方法。
   会依据请求方式分别调用doGet,doPost方法(HttpServlet抽象类的doGet,doPost方法只是抛出了一个异常,需要子类去override)。
   d, ServletConfig接口
    //获得servlet的初始化参数。
    String getInitParameter(String paraName);


五、表单的处理
1)如何获得请求参数值
  a, String request.getParameter(String paraName);
  注意:当paraName与实际的参数名称不一致,会返回null。
  b, String[] request.getParameterValues(String paraName);
   当有多个参数名称相同的情况下,用这个方法 比如:  ?city=bj&city=wh&city=cs
2)如何处理中文参数值
  当表单提交的时候,浏览器会按照打开该页面时的编码格式对表单中的中文参数值进行编码。
  而服务器默认情况下,会使用iso-8859-1这种编码格式进行解码。所以会出现乱码问题。
  解决办法:
   方式一:
   step1,要保证使用指定的编码格式打开页面。
   比如,对于html文件,可以使用<meta http-equiv="content-type" content="text/html;charset=utf-8">
   jsp文件:使用 <[email=%@page]%@page[/email] pageEncoding="utf-8" contentType="text/html;charset=utf-8"%>
   step2,在服务器,使用request.setCharacterEncoding("utf-8");
   注意:
   a,该方法必须要放在所有的request.getParameter方法的前面。
   b,只对post请求有效。
   方式二:适用于get,post请求。
   step1,要保证使用指定的编码格式打开页面。
   step2, new String(str.getBytes("iso-8859-1"),"utf-8"); 
   
六、重定向与转发
(1)什么是重定向?
  服务器向浏览器发送一个302状态码及一个Location消息头(该消息头的值是一个地址,称之为重定向地址),浏览器会立即向重定向地址发请求。
(2)什么是转发?
  一个web组件(servlet/jsp)将未完成的处理通过容器转交给另外一个web组件继续完成。
   最常见的情况是:一个servlet获得数据,然后转发给一个jsp,由这个jsp来生成相应的页面。
(3)如何重定向?
  response.sendRedirect(String url); 
(4)如何转发?
  step1, 先绑订数据到request对象上。
   //绑订数据到request对象上,name:绑订名称 obj:绑订值。
    request.setAttribute(String name,Object obj);
    //依据绑订名称找到绑订值,如果找不到,返回null。
    Object request.getAttribute(String name);
  step2,获得一个转发器
   //url:转交给哪一个web组件,一般是一个jsp。//RequestDispatcher:是一个接口。
   RequestDispatcher rd =  request.getRequestDispatcher(String url);
  step3,转发
   //转发所涉及的每个web组件都会共享同一个request,response。
   rd.forward(request,response); 
(5)编程需要注意的问题
  a,重定向和转发之前,不能够调用out.close方法。
  b,重定向和转发之前,会清空response对象中缓存的数据。
(6)特点
  a,重定向的地址任意。转发的目的地只能够是同一个应用内部的某个组件的地址。
  b,重定向之后,浏览器地址栏的地址会变成重定向地址。转发之后,浏览器地址栏的地址没有变化。

小知识:常见的错误处理
  1)404
   404是一个状态码(服务器发送给浏览器的一个三位数字,表示服务器处理的状态),404表示依据请求资源路径找不到对应的资源。
   解决办法: 依据http://ip:port/appname/url-pattern检查请求资源路径。
  2)500
   500也是一个状态码,表示系统错误。
   解决办法:检查源代码以及配置文件。
  3)405
   表示找不到对应的方法来处理请求。
   解决办法:检查service方法的签名。

七、servlet线程安全问题
(1)为什么说servlet会有线程安全问题?
  a,servlet只有一个实例,即不管有多少个请求,容器只会创建一个servlet实例。
  b,当容器收到一个请求之后,会启动一个线程来处理请求,该线程会调用servlet实例的方法。
  如果有多个线程都在访问同一个servlet实例的方法,该方法有线程不安全的代码(比如,该方法在修改servlet实例的属性)就有可能发生线程安全问题。
(2)如何解决?
  a,加锁
   可以使用synchronized对整个service方法加锁,也可以对具有线程安全问题的代码块加锁。
  b,可以让servlet实现SingleThreadModel接口。容器会为每一个线程分配一个servlet实例,但是,会产生过多的servlet实例,不建议使用。

抱歉!评论已关闭.