servlet回顾

  • servlet

    • genericServlet抽象类
    • HttpServlet抽象类
    • ServletRequest接口
    • HttpServletRequest接口
    • ServletResponse接口
    • HttpServletResponse接口
    • ServletConfig接口
    • ServletContext接口
  • javaweb应用的生命周期
  • Servlet的生命周期
  • servletcontext共享数据
  • servletcontextlistener 监听器
  • 防止页面被缓存
  • 文件下载
  • 上传文件
  • 生成动态图像
  • 读写Cookie
  • 请求转发
  • 包含
  • 请求范围
  • 重定向
  • 避免并发问题

servlet

首先明确,下面各种方法和接口由容器提供商实现。我们自己只需要重写部分方法。

?

?

5个方法,三个方法由容器调用。

  • init(ServletConfig config)初始化对象。
  • service(ServletRequest req,ServletResponsr res)响应客户请求
  • destroy() 结束Servlet对象

代码可调用下两个方法。

  • getServletConfig() 返回一个包含Servlet初始化参数信息的对象
  • getServletInfo 返回包含servlet创建者 版权的字符串

genericServlet抽象类

为Servlet接口提供了通用实现,与网络层协议无关,还实现了servletconfig接口和 serializable接口

service()是其中唯一的抽象方法。

该类使用了装饰设计模式

HttpServlet抽象类

针对不同的请求方式,实现了相应的方法。但是默认的实现,都会返回一个错误。

为什么是抽象类?

先要明确,有抽象方法一定是抽象类,但是抽象类不一定有抽象方法。二,只是强调该类在开发者没有自定义实现的情况下无法被初始化而已,这叫适配器 。可参考 里氏替换原则

ServletRequest接口

  • 获得客户机信息

    getRequestURL方法返回客户端发出请求时的完整URL。

    getRequestURI方法返回请求行中的资源名部分。

    getQueryString 方法返回请求行中的参数部分。

    getRemoteAddr方法返回发出请求的客户机的IP地址

    getRemoteHost方法返回发出请求的客户机的完整主机名

    getRemotePort方法返回客户机所使用的网络端口号

    getLocalAddr方法返回WEB服务器的IP地址。

    getLocalName方法返回WEB服务器的主机名

    getMethod得到客户机请求方式

  • 获得客户机请求头

    getHeader(string name)方法

    getHeaders(String name)方法

    getHeaderNames方法

  • 获得客户机请求参数(客户端提交的数据)

    getParameter(name)方法 一个数据时使用,多个数据时使用下一个GPV方法

    getParameterValues(String name)方法

    getParameterNames方法

    getParameterMap方法

HttpServletRequest接口

getScheme()方法返回请求的计划,比如http,https或者ftp.

getServerName()方法返回被发送请求的服务器的主机名

getServerPort()方法返回被发送请求的端口号。

getContextPath()返回请求地址的根目录,以"/"开关,但不是以"/"结尾。

一个常用的获得服务器地址的连接字符串是:

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

getCookies() 取得cookie

getMethod() 取得请求方法,如get,post或put

getRequestURL() 取得请求URL(统一资源定位符)

getRequestURI() 取得请求URI(统一资源标识符)

getSession() 取得对应session

getQueryString() 取得请求中的查询字符串,即URL中?后面的内容

ServletResponse接口

setCharacterEncoding()设置响应正文的字符编码

setContenLength() 设置响应正文长度

setContentType() 设置响应正文MIME类型

setBufferSize() 设置响应正文的缓冲区的大小

reset()清空缓冲区内正文数据,并且清空响应状态代码和响应头

resetBuffer() 仅仅清空缓冲区正文数据,不清空状态代码和响应头

flushBuffer() 强制把缓冲区的响应正文发送到客户端

isCommitted() 判断数据是否已经发送到了客户端

getOutputStream() 返回一个对象,用来输出二进制的正文数据

getWriter() 返回一个对象,用它来输出字符串形式的正文数据

注:

  • ServletResponse默认MIME类型是纯文本

    HttpServletResponse默认MIME类型是html

    编码方式:以下三种方式是等价的:

    ?

HttpServletResponse接口

addHeader(String name,String value)向HTTP响应头加入一项内容

sendError(int) 向客户端发一个代表错误的Http响应状态码

sendError(int src,String msg) 向客户端发一个错误代码和一个具体错误消息

addCookie(Cookie cookie) 向HTTP响应中加入一个cookie

ServletConfig接口

作为servlet接口init(ServletConfig config)的参数,与servlet产生关联。servletconfig对象与servletcontext对象关联。

  • getInitParameter(String name) 根据给定的初始化参数名,返回匹配的初始化参数值(静态方法,可以直接调用,
    String color = getInitParmeter("color"))
  • getInitParameterNames()返回一个枚举对象,包含所有的参数名
  • getServletContext() (静态方法)返回当前servletContext对象

在web.xml中,

<init-param>
<param-name>color</param-name>
<param-value>red</param-value>
</init-param>

ServletContext接口

本接口是Servlet与Servlet容器之间直接通信的接口。容器在启动web应用的时候,会创建一个ServletContext对象,每个web应用都有唯一的对象。

  1. 在web应用范围内存取共享数据的方法。
  • setAttribute(String name, java.lang.Object object)把一个对象和参数名绑定,存入到ServletContext中。
  • getAttribute(String name) 返回相应的属性值
  • etc
  1. 访问当前Web应用的资源
  2. getContentPath() 返回当前web应用的URL入口
  3. getInitParameter(String name) 根据给定参数名,返回初始化参数值(web.xml)中配置的
  4. 访问容器中的其他web应用
  5. 访问容器的相关信息
  6. 访问服务器端端文件系统资源
  7. 输出日志
  8. log(String msg) 向Servlet的日志文件中写日志
  9. log(String message,java.lang.Throwable throwable)向日志文件中写错误日志以及异常的堆栈信息
<context-param>
    <param-name>email</param-name>
    <param-value>[email protected]</param-value>
</context-param>

javaweb应用的生命周期

  • 启动
    把web.xml加载到内存
    创建servletcontext对象
    对所有的Filter初始化
    对需要在启动时就被初始化的Servlet进行初始化(创建servletconfig对象,把web.xml中的初始化值包含进来,调用init(servletconfig对象)
  • 运行
    如果servlet已经初始化了,就调用service()
    如果还没被初始化,就先初始化,再调用service()方法
  • 终止
    销毁所有servlet
    销毁Filter
    销毁相关对象 如ServletContext

Servlet的生命周期

初始化阶段

1.容器加载Servlet类,将.class文件的数据读入到内存中

2.容器创建ServletConfig对象,容器使其与当前web应用的ServletContext对象关联

3.创建Servlet对象

4.调用servlet对象init(ServletConfig config)

下面两种情况,servlet会进入初始化

1.第一次被访问

2.web.xml配置了

运行阶段

销毁阶段

一个web应用一个context,一个servlet一个config,config可调用静态的getContext得到该对象

servletcontext共享数据

统计访问次数,就用serveletcontext设置一个属性(计数器)

servletcontextlistener 监听器

上述的统计方式会导致web应用重启后数据消失,由监听器监控web生命周期,当周期结束时,把计数写入数据库。

防止页面被缓存

设置响应头

?

第一种用于HTTP1.0的浏览器 第二种用于HTTP1.1 第三种都可以 表示过期时间

文件下载

public class DownloadServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,HttpServletResponse response)
         throws ServletException, IOException {
    OutputStream out; //输出响应正文的输出流
    InputStream in;  //读取本地文件的输入流
    //获得filename请求参数
    String filename=request.getParameter("filename");

    if(filename==null){
      out=response.getOutputStream();
      out.write("Please input filename.".getBytes());
      out.close();
      return;
    }

    //创建读取本地文件的输入流
    in= getServletContext().getResourceAsStream("/store/"+filename);
    int length=in.available();
    //设置响应正文的MIME类型
    response.setContentType("application/force-download");
    response.setHeader("Content-Length",String.valueOf(length));
    response.setHeader("Content-Disposition", "attachment;filename=\""+filename +"\" "); 

    /** 把本地文件中的数据发送给客户 */
    out=response.getOutputStream();
    int bytesRead = 0;
    byte[] buffer = new byte[512];
    while ((bytesRead = in.read(buffer)) != -1){
      out.write(buffer, 0, bytesRead);
    } 

    in.close();
    out.close();
  }
}

上传文件

在html中,在

标签中,使用anctype="MULTIPART/FORM-DATA"

容器将表单包装成httpservletrequest对象,解析出复杂表单的个部分很复杂。所以利用Apache的两个软件包简化过程。

  • commons-fileupload-1.2.1.jar 文件上传包
  • commons-io-1.4.jar 输入输出包

主要是用fileupload上传文件,该包依赖于io包

?

对于每一个“multipart/form-data”的请求,该包把复合表单的每一部分看作一个FileItem对象。该对象分为两种:

1.formField 普通表单类型

2.非formFiled:上传文件类型,文件域就是这种类型。

DiskFileItemFactory类,对象的工厂

DiskFileItem类,把上传的文件数据保存到硬盘上

public class UploadServlet extends HttpServlet {
  private String filePath; //存放上传文件的目录
  private String tempFilePath; //存放临时文件的目录

  public void init(ServletConfig config)throws ServletException {
    super.init(config);
    filePath=config.getInitParameter("filePath");
    tempFilePath=config.getInitParameter("tempFilePath");
    filePath=getServletContext().getRealPath(filePath);
    tempFilePath=getServletContext().getRealPath(tempFilePath);
  }
  public void doPost(HttpServletRequest request,HttpServletResponse response)
         throws ServletException, IOException {
    response.setContentType("text/plain");
    //向客户端发送响应正文
    PrintWriter outNet=response.getWriter();
    try{
      //创建一个基于硬盘的FileItem工厂
      DiskFileItemFactory factory = new DiskFileItemFactory();
      //设置向硬盘写数据时所用的缓冲区的大小,此处为4K
      factory.setSizeThreshold(4*1024);
      //设置临时目录
      factory.setRepository(new File(tempFilePath));

      //创建一个文件上传处理器
      ServletFileUpload upload = new ServletFileUpload(factory);
      //设置允许上传的文件的最大尺寸,此处为4M
      upload.setSizeMax(4*1024*1024); 

      List /* FileItem */ items = upload.parseRequest(request);    

      Iterator iter = items.iterator();
      while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();
        if(item.isFormField()) {
          processFormField(item,outNet); //处理普通的表单域
        }else{
          processUploadedFile(item,outNet); //处理上传文件
        }
      }
      outNet.close();
    }catch(Exception e){
       throw new ServletException(e);
    }
  }

  private void processFormField(FileItem item,PrintWriter outNet){
    String name = item.getFieldName();
    String value = item.getString();
    outNet.println(name+":"+value+"\r\n");
  }

  private void processUploadedFile(FileItem item,PrintWriter outNet)throws Exception{
    String filename=item.getName();
    int index=filename.lastIndexOf("\\");
    filename=filename.substring(index+1,filename.length());
    long fileSize=item.getSize();

    if(filename.equals("") && fileSize==0)return;

    File uploadedFile = new File(filePath+"/"+filename);
    item.write(uploadedFile);
    outNet.println(filename+" is saved.");
    outNet.println("The size of " +filename+" is "+fileSize+"\r\n");
  }
}

在web.xml中配置filepath和tempFilePath的值

生成动态图像

读写Cookie

cookie基本运行机制

?

有Cookie类,每个对象都包含一个名字和一个值

Cookie the Cookie = new Cookie("username", "tom")

response.addCookie(the Cookie)

Cookie cookies[] = request.getCookies()

cookie.setMaxge(int)

大于零,表示在客户端硬盘保存的时间

等于零,删除当前cookie

小于零,就不保存到硬盘,仅仅保存在当前浏览器进程中,关闭浏览器,cookie消失

默认为-1

请求转发

一个Servlet对象无法获得另一个servlet对象的引用。

特点:

* 源组件和目标组件处理的都是同一个客户请求,共享一个request和response对象 源组件的响应结果不会发送到客户端(会给目标组件再发送到客户端)

* 如果在请求转发前提交了响应结果(如flushBuffer,close),会抛出异常(会显示源组件内容,日志中会有异常)。如果不提交,不会显示。

* disspatcher.forward(request,response)后的代码也会执行

* 目标组件可以是servlet、jsp、html

* 都依赖于javax.servlet.RequestDispatcher()

这个接口表示请求分发器:

forward() 把自己的东西转发到别的组件

include() 将别人的东西包含到自己中

通过两种方式得到RequestDispathcer对象

* 调用servletcontext的getrequestDispatcher(String path)

* 调用servletRequset的getrequestdispatcher(String path)

path为目标组件的路径。两种区别在于,前者要求绝对路径,后者可以为绝对路径也可以是相对路径

包含

特点:

源组件和被包含的目标组件的输出数据都会添加到响应结果

目标组件中对响应状态代码或者响应头的操作都会被忽略。

请求范围

web的应用范围是指web应用的生命周期,与servletcontext对象的生命周期对应。

请求范围是指服务器端响应一次客户请求的过程,从一个servlet接受到请求开始,到返回响应结果结束。与servletrequest对象和servletresponse对象的生命周期对应。

重定向

Response.sendRedirect(String location)

1.用户输入特定的URL,请求访问服务器端的某个组件

2.服务器端组件返回一个302的响应结果,含义为让浏览器再请求访问另外一个web组件,在响应结果中包含另外一个web组件的URL,这个组件不一定在同一个服务器上

3.浏览器接受到这种响应结果后,立即自动请求访问另一个组件

4.浏览器收到另一个组件的响应结果

源组件

request.setAttribute("msg",message)

response.sendRedirect("/helloapp/output1?msg="+message)

output1组件:

String message = (String)request.getAttribute("msg")

注意:

  • 源组件的响应结果不会发送到浏览器中,如果在sernRedirect之前已经提交了响应结果,会抛出异常。
  • 源组件调用重定向方法后到代码也会执行
  • 不共享数据(request或者response)

避免并发问题

多个客户访问同一个servlet,容器会创建多个线程来访问同一个对象,而不是为每个访问创建一个对象。这样就会导致一些并发问题。

解决方案:

1. 合理决定在Servlet中定义的变量的作用域

2. 对于多线程同时访问数据导致的并发问题的情况,使用同步机制进行同步

3. 不要使用被废弃的 javax.servlet.singthreadmodel

对于方案1:

一个请求对应一个工作线程,一个线程对应一个username变量。

局部变量在一个方法中定义。当一个线程执行这个方法时就会创建这个局部变量。如果有多个线程执行该方法,每个线程都会有自己的局部变量。

实例变量在类中定义,每个实例都有自己的实例变量。如果多个线程执行一个实例方法,都会访问同一个实例变量。

容器对于每一个servlet只会创建一个servlet对象。

不要使用实例变量,要把变量定义在service方法中

对于方案2:

使用synchronise()同步代码块,避免同时操作同一个数据。

对于方案3:

如果servlet实现了这个接口,会有两种方式来运行servlet

1.任意时刻,只允许一个工作线程执行servlet的service方法。

2.创建一个servlet对象池,不同的客户操作不同的servlet对象。

Tomcat是第二种方式。

时间: 2024-10-12 10:42:06

servlet回顾的相关文章

Java Servlet 回顾

一.转发请求RequestDispatcher 使用request域对象把数据带给转发资源,与重定向的区别:客户端只发出一次请求,服务器端调用多个资源,客户端浏览器地址栏没改变:转发是一次请求,使用的是同一个response和request: ? ServletContext.getRequestDispatcher(String); ServletContext.getNamedDispatcher(String); ServletRequest.getRequestDispatcher(St

Javaee----重新回顾servlet

最近面临找工作,不得不回顾一下java servelt . 发现lz的基本功还是很差 1. 每一个servlet都必须实现servlet接口,GenericServlet是个通用的.不特定于任何协议的Servlet,它实现了Servlet接口,而且HttpServlet继承与GenericServlet,因此HttpServlet也实现了Servlet接口,所以我们定义的Servlet只需要继承HttpServlet父类即可. 2. servlet 接口中定义了一个service方法,HttpS

9、Http回顾/Servlet

1 Http回顾 Http协议: 1)http协议: 对浏览器客户端和服务器端之间数据传输的格式规范. 2)http请求:浏览器->服务器端 格式: 请求行(请求方式(GET/POST) 请求资源(URI) http协议版本(http1.1)) 请求头(键值对形式存在. host.user-agent.referer) 一个空行 实体内容(POST提交的参数) HttpServletRequest对象: 请求对象.获取请求信息. 请求行:request.getMethod()   request

javaweb回顾第六篇谈一谈Servlet线程安全问题

前言:前面说了很多关于Servlet的一些基础知识,这一篇主要说一下关于Servlet的线程安全问题. 1:多线程的Servlet模型 要想弄清Servlet线程安全我们必须先要明白Servlet实例是如何创建,它的模式是什么样的. 在默认的情况下Servlet容器对声明的Servlet,只创建一个Servlet实例,那么如果要是多个客户同时请求访问这个Servlet,Servlet容器就采取多线程.下面我们来看一幅图 从图中可以看出当客户发送请求的时候,Servlet容器通过调度者线程从线程池

javaweb回顾第一篇servlet的学习和理解

前言:关于servlet相信学过java的都不会陌生,我最近又把这些基础知识整理一遍,便于自已能更好的理解ssm或者ssh,下面开始 1:Servlet接口 servlet有5个方法下面分别简单的介绍每个方法的作用 1.1:public void init(ServletConfig config) 在servlet被实例化以后,servlet容器会调用init方法来初始化该对象,这个方法主要是完成在请求前的一些初始化工作,比喻调用数据库连接,实例化对象等 1.2:public void ser

基础知识回顾第一章servlet的学习和理解

前言:关于servlet相信学过java的都不会陌生,我最近又把这些基础知识整理一遍,便于自已能更好的理解ssm或者ssh,下面开始 1:Servlet接口 servlet有5个方法下面分别简单的介绍每个方法的作用 1.1:public void init(ServletConfig config) 在servlet被实例化以后,servlet容器会调用init方法来初始化该对象,这个方法主要是完成在请求前的一些初始化工作,比喻调用数据库连接,实例化对象等 1.2:public void ser

【Web基础】JSP/Servlet 简单回顾

HTTP状态码: 2XX:请求成功 3XX:重定向 4XX:客户机中出现错误. 403-禁止--即使有授权也不需要访问.404 服务器找不到指定资源,文档不存在. 4XX:服务器出现错误.500 服务器内部错误--因为意外情况,服务器不能完成请求. JSP部分: JSP内置对象: 1 page Context --javax.servlet.jsp.PageContext 2.request--javax.servlet.http.HttpServletRequest 接口定义:public i

Servlet知识点回顾

一.Servlet生命周期 服务器调用一个Servlet的8个步骤: 1.在服务器启动时,当Servlet被配置好或者被客户首次请求时,由服务器加载servlet,这一步相当于下列代码: Class c=Class.forName("com.source.MyServlet"); 2.服务器创建一个Servlet类的实例来为所有的请求服务.利用多线程,可以由单个servlet类的实例来服务于并行的请求,此步相当于下列代码: Servlet s=(Servlet)c.newInstanc

javaWeb基础核心之一Servlet

既然是做JAVA开发的,先从一些基本的整理起来,算是知识回顾,加深记忆. 第一篇想到那理到哪,可能有点乱,不是太会排版,见谅,估计可能也就我自己看的懂. servlet在百度百科上的定义是这样的: Servlet(Server Applet),全称Java Servlet,未有中文译文.是用Java编写的服务器端程序.其主要功能在于交互式地浏览和修改数据,生成动态Web内容.狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况