大数据WEB阶段(九)Servlet+Request

55 篇文章 0 订阅
3 篇文章 0 订阅

Servlet与Request

一、概述

  1. Servlet
    1. 是sun公司提供的一门用于开发动态web资源的技术
    2. 按照这套规范写出来的servlet可以放置在web应用中在servlet容器中运行 。
  2. 开发servlet步骤

    1. 写一个类实现servlet接口 , 并实现其中的方法
    2. 在web.xml中为servlet配置对外访问路径
    3. 案例:

      手写一个servlet:
          1.在指定位置(如D盘)创建一个FirstServlet.java文件, 创建FirstServlet类, 继承GenericServlet类
              public class FirstServlet extends GenericServlet{}
      
          2.添加未实现的service方法, 实现内部代码
              public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException{
                  String dateStr = new Date().toLocaleString();
                  res.getWriter().write(dateStr);
              }
      
          3.添加包结构, 并导入依赖包
              package cn.servlet;
              import java.util.*;
              import java.io.*;
              import javax.servlet.*;
      
          4.编译Servlet类
              在编译之前, 找到 [tomcat7.0]\lib\servlet-api.jar 包, 在cmd窗口中将其所在路径设置给classpath
                  如: set classpath=E:\software\tomcat7.0\lib\servlet-api.jar
      
              带包编译:
                  进入到FirstServlet.java所在路径
                  命令: javac -d . FirstServlet.java 
                  其中: -d是带包编译
                       点(.)表示编译后的class存放在当前目录下
      
          5.将编译的class所在的整个目录放在WEB应用下的/WEB-INF/classes目录下
      
          6.在web.xml中配置Servlet对外访问的虚拟路径
              <servlet>
                  <servlet-name>FirstServlet</servlet-name>
                  <servlet-class>cn.servlet.FirstServlet</servlet-class>
              </servlet>
              <servlet-mapping>
                  <servlet-name>FirstServlet</servlet-name>
                  <url-pattern>/FirstServlet</url-pattern>
              </servlet-mapping>
      
          7.将WEB应用配置到tomcat服务器中, 并启动服务器访问如下路径来访问FirstServlet
              http://localhost/news/servlet/FirstServlet
      

二、使用myeclipse开发servlet

  1. 使用myeclipse开发servlet程序时 , 可以新建一个servlet , 默认继承HttpServlet , 在Servlet内部会覆盖doGet()和 doPost()方法 , 分别来处理GET请求和POST请求 。
  2. 新建项目
    1. 新建一个web project, 给设置一个项目名称 ,一般其他保持默认即可 , 然后finish , 弹出的对话框选择yes即可。
  3. 新建一个Servlet
    1. 新建一个servlet , 如果new中找不到servlet , 注意视图是否换到MyEclipse中 , 给一个包名和类名 , 下面对勾只留doGet()和doPost(),其他去掉 , 下一步
    2. 这里将最后两行删掉,是一些xml中的提示,其他地方一般保持默认即可,也可以修改对外访问路径,其中name和URL会自动配置到xml中。最后finash。
  4. 一些疑问
    1. 为什么要继承HttpServlet?
      1. 因为这是一个继承了GenericServlet的类,已经提供doGet()和doPost()方法,可以方便我们开发web项目。
      2. 而GenericServlet是一个基础的实现,如果要用此类,需要自己写doGet()和doPost()方法,并且需要在service方法中对请求进行判断,会比较麻烦。
    2. HttpServlet底层又是如何实现的?
      1. 可以打开HttpServlet源码,发现HttpServlet也是继承自GenericServlet,同时,HttpServlet会写各种方法,比如doGet()和doPost(),然后在service方法中进行判断,不同的请求调用不同的方法。
  5. 注意:
    1. 复制一个servlet之后 , web.xml文件中不会自动生成配置文件 ,, 所以一般不要复制 , 直接新建 。
  6. 在myeclipse配置tomcat ,并将项目发布到tomcat中
    1. 查看http://blog.csdn.net/chou_out_man/article/details/78700153

三、Servlet继承结构


四、修改servlet模板

  1. 方式一:
    1. 下载http://dl.download.csdn.net/down11/20171203/44e21f5d54727c09ffa2214f7427287b.jar?response-content-disposition=attachment%3Bfilename%3D%22com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar%22&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1512269518&Signature=J1sMRCVX4mp3WUiO%2FO2%2BloDU52U%3D&user=chou_out_man&sourceid=10142677
    2. 拷贝到【MyEclipse安装目录】\Common\pligins目录下 , 会提示是否替换文件 , 确定提换即可 , 如果没有提示 , 则有可能进错目录了
  2. 方式二:
    1. 在【MyEclipse安装目录】\Common\pligins目录下找到文件:com.(1)genuitec.eclipse.wizards.xxx.jar,在此文件中的Templates目录下可以看到Servlet.java源代码。
    2. 打开源代码 , 将doGet()和doPost()两个方法的注释和方法中的内容删掉即可
    3. 修改之后保存
    4. 重启MyEclipse后新建servlet即可看到效果 。

五、Servlet调用过程

  1. 调用过程
  2. Servlet生命周期
    1. Servlet实例在第一次被访问时创建, 创建之后服务器会立即调用init方法进行初始化的操作, 从此以后该实例会一直驻留在服务器的内存中, 为后续的请求服务, 只要有请求访问servlet, 服务器就会调用service方法来处理这个请求, 直到服务器关闭或者是web应用被移出容器时为止, 随着web应用的销毁, servlet实例也会跟着销毁, 在销毁之前, 服务器就调用destroy方法进行善后的处理.

六、servlet虚拟路径

在web.xml文件中可以配置对外访问的虚拟路径 , 可以直接写一个路径或者通过通配符*号写一个路径
1. 方式一:直接写一个路径

    /servlet/dotestservlet

2. 方式二:通过通配符*号写一个路径
1. 以 / 开头, 以 /* 结尾

        如: /servlet/*   /a/*  /*
2. 以 *.后缀 的形式, 

        如: *.html   *.servlet  *.do *.action
3. 使用*号匹配符写路径, 路径的配置变得更加灵活, 但是也可能会造成, 一个url会被多个servlet Mapping所匹配 , 如:

        Url:http://localhost/day09/servlet/SecondServlet.do

        Servlet1:Test1: /servlet/*
        Servlet2:Test2: *.do
4. 匹配规则:
    1. *.后缀的优先级永远最低
    2. 哪一个最接近哪一个起作用
    3. 示例:

            Servlet1 映射到 /abc/* 
            Servlet2 映射到 /* 
            Servlet3 映射到 /abc 
            Servlet4 映射到 *.do 

            当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应
            Servlet引擎将调用Servlet1。
            当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应
            Servlet引擎将调用Servlet3。
            当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应
            Servlet引擎将调用Servlet1。
            当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
            Servlet引擎将调用Servlet2。

七、Request

  1. 代表HTTP请求的对象
  2. 继承结构
  3. request功能

    1. 获取客户端相关信息

      1. getRequestURL方法 – 返回客户端发出请求完整URL

        如: http://localhost/day09/servlet/SecondServlet
        
      2. getRequestURI方法 – 返回请求行中的资源名部分

        如: /day09/servlet/SecondServlet
        
      3. getQueryString方法 – 返回请求行中的参数部分

        如: username=zhangfei&password=123
        
      4. getRemoteAddr方法 – 返回发出请求的客户机的IP地址

        如: 127.0.0.1  //可能会出现0:0:0:0:0:0:0:1形式,是ipv6的表现形式。
        
      5. getMethod – 得到客户机请求方式

        如: GET或POST
        
      6. getContextPath – 获得当前web应用虚拟目录名称

        如: /day09
        
      7. 注意:在写路径时不要将web应用的虚拟路径的名称写死, 应该在需要写web应用的名称的地方通过getContextPath方法动态获取
    2. 获取请求头信息

      1. getHeader(name)方法 –String
      2. getHeaders(String name)方法 — Enumeration
        可以通过遍历枚举遍历每一个信息

        例如:while (values.hasMoreElements()) {
            String value = (String) values.nextElement();
            System.out.println(value);
        }
        
      3. getHeaderNames方法 — Enumeration
      4. getIntHeader(name)方法 — int
      5. getDateHeader(name)方法 — long(日期对应毫秒)
    3. 获取请求参数

      1. getParameter(String name) — String 通过name获得值
      2. getParameterValues(String name) — String[ ] 通过name获得多值 checkbox
      3. getParameterMap() — Map key :name value: 多值
      4. getParameterNames() — Enumeration 获得所有name
      5. 请求参数时的乱码问题

        1. 乱码分析: 编码和解码时使用的 码表不一致造成的 。
        2. 编码是在浏览器中进行的 , 浏览器打开页面时使用的是什么码表 ,在发送数据时使用的也是相同的码表 。
        3. 解码在服务器端进行 , 如果不指定解码时使用的码表 , 则默认使用ISO-8859-1
        4. 解决方案: 在服务器解码前 , 通知服务器解码时应该使用的码表。使浏览器编码和服务器解码时的码表一致 。
        5. Post方式提交参数的解决方案:

          request.setCharacterEnCoding("utf-8");//用来通知服务器使用什么编码来接受请求实体内容中的数据, 如果使用的是POST提交, POST提交的请求参数就是在请求实体内容中!, 所有这个方法可以解决POST提交的乱码问题!!!
          
        6. Get方式提交参数的解决方案

          GET提交的请求参数由于不在请求实体内容中,而是在请求行中的请求资源路径后面拼接着, 所以这行代码对GET提交的参数乱码不起作用!!!                 
                  GET提交的乱码问题可以通过手动编解码来解决!!
                  //>>username为乱码, 通过乱码反向编码得回二进制数组
                  byte[] bytes = username.getBytes("iso8859-1");
                  //>>通过二进制数组查询正确的码表, 得出正确的数据
                  username = new String(bytes, "utf-8");
          
    4. 实现请求转发

      1. 请求重定向: 302状态码+Location响应头
      2. 请求转发: 与请求重定向都可以实现资源的跳转 , 但是区别是 :请求转发是服务器内部的并且是同一web应用内部的跳转 , 而重定向的资源跳转没有限制 。
      3. 请求转发的特点:

        1. 一次请求一次响应 。
        2. 地址栏不会发生变化
        3. 转发被限制在同一个web应用中
        4. 实现代码

          创建servlet:RequestDemo3和RequestDemo4,RequestDemo3转发到RequestDemo4
            在RequestDemo3中:
          /*
                   * 在web阶段写路径时,除了请求转发和请求包含在写
                   * 路径是不用包含web应用的虚拟路径,其他地方都需要
                   * 加上web应用的虚拟路径。
                   * 完整路径:http://localhost/day09/servlet/RequestDemo4
                   */
                  request.getRequestDispatcher("/servlet/RequestDemo4").forward(request, response);
          
            在RequestDemo4中响应:
                 response.getWriter().write("1$");
          
        5. request开发细节:

          在转发之前, 如果response缓冲区被写入了数据但是还没有打给浏览器, 在转发时response缓冲区(数据)将会被清空!
          例如:在RequestDemo3中添加代码:
          response.getWriter().write("no money!");
          发现浏览器中并未得到"no money!"这段字符串的响应。
          
              在转发之前, 如果response缓冲区被写入了数据并且已经打给了浏览器, 转发将会失败!!
          例如:在RequestDemo3中添加代码:
          response.getWriter().write("no money!");
                  response.flushBuffer();
          发现浏览器可以显示"no money!",因为强制刷新了,但是转发就会报错,因为已经响应过了,一次请求对应一次响应。
          
              在同一个Servlet中转发不能进行多次!!(A既转发B, 又转发给C)
              但是可以进行多重转发(比如A转发给B, B再转发给C)
          
    5. 作为域对象来使用
      1. 域对象: 一个对象具有一个可被看见的范围 , 并且利用该对象上的map可以在整个范围内实现资源的共享
      2. 域对象提供的方法(可以操作map中的数据)
        1. setAttribute(String name,Object value) :用来存储一个对象,也可以称之为存储一个域属性
        2. getAttribute(String name); 用来获取request中的数据
        3. removeAttribute(String name); 用来移除request中的域属性
        4. getAttributeNames(); 获取所有域属性的名称
      3. 域对象生命周期
        1. 请求开始时创建 , 请求结束时死亡
      4. 作用范围: 一次请求链
      5. 主要功能:
        1. 在作用范围内共享数据
    6. 实现请求包含

      1. 请求包含是服务器中内部资源合并的现象
      2. 如果浏览器请求ServletA , 但是A不能独立完成处理这个请求 , 需要另外一个ServletB帮忙 , 于是在A中可以将B包含进来 ,包含进来之后将由A和B共同处理这次请求 , 处理的结果也将合并在一起 , 一同发送给浏览器 。 如:

        request.getRequestDispatcher(“B的路径”).include(request, response);
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值