day05_HTTP_Servlet

HTTP

1. HTTP简介

  • HTTP全称:Hyper Text Transfer Protocol【超文本传输协议】
  • HTTP作用:约束报文格式
  • 报文:浏览器与服务器通信时传输的数据,称之为报文
  • 浏览器与服务器通信方式
    • 浏览器向服务器发出:请求
    • 服务器向浏览器做出:响应

2. 报文种类

2.1 请求报文

  • 浏览器向服务器发送请求时,携带数据,称之为请求报文
  • 请求报文格式
    • 请求行
      • 请求方式【get|post】 请求URI 协议版本【HTTP1.1】
    • 请求头
      • User-Agent:包含浏览器端信息,如:操作系统、浏览器版本等信息
      • Referer:存储请求上一个【前一个】URL
      • Cookie:存储Cookie信息
    • 请求体【GET请求,没有请求体】
      • 请求数据【参数】

2.2 响应报文

  • 服务器向浏览器做出响应时,携带数据,称之为响应报文
  • 响应报文格式
    • 响应行
      • 协议版本 状态码【 响应码】 提示文本
    • 响应头
      • Content-Type:设置响应类型,如:text/html;charset=UTF-8
    • 响应体
      • 响应数据

2.3 GET请求和POST请求区别

  • 参数区别
    • GET请求参数,在URL后使用?拼接参数
    • POST请求参数,存储请求体中
  • 安全性
    • GET相对不安全
    • POST相对安全
  • 数据大小
    • GET请求,参数在URL后使用?拼接参数,参数有大小限制
    • POST请求,参数在请求体中,参数无大小限制

2.4 响应码

  • 200:请求响应成功
  • 404:请求失败,请求资源未找到【url地址不正确】
  • 500:请求失败,请求资源找到了,但服务器内部有错误【代码写错了】
  • 302:请求重定向
  • 等等…

Servlet

1. Servlet简介

1.1 为什么使用Servlet

  • 原因:以实现注册功能为例,需要将html中数据最终插入数据库中,所以此时需要将html中数据先提交java代码,再使用JDBC技术插入数据库。但html无法直接请求xxx.java文件,所以此时需要servlet技术。

1.2 什么是Servlet

  • 理解层面:Servlet就是具有URL属性【特性】的java程序
  • 定义层面:Servlet 是运行在服务端(tomcat)的Java小程序,是sun公司提供一套定义动态资源规范
  • 代码层面:Servlet就是一个接口,或javax.servlet.Servlet接口的实现类

2. Servlet之Helloworld

  1. 创建动态工程
    • javax.servlet.Servlet这个包在servlet-api.jar包下
    • 需要为web.xml【注解】中为Servlet实现注册
  2. 准备html发送请求
  3. 创建HelloworldServlet类
    • HelloworldServlet实现javax.servlet.Servlet
    • 重写接口中相应方法【接口中方法,默认抽象方法】
  4. 在web.xml中注册HelloworldServlet
    • 设置全类名【类的全限定名】,通知Servlet容器【web容器、服务器】创建当前Servlet
    • 为当前Servlet设置URL特性

3. Servlet工作原理【执行流程】

  • 浏览器向服务器端组件Servlet发送请求【HelloworldServlet】
  • 通过指定URL去web.xml中检索注册URL【/HelloWorldServlet】
  • 通过servlet-mapping中的servlet-name与servlet中的servlet-name进行匹配
  • 匹配成功,会找到指定servlet-class
  • 执行Servlet中的相应方法【service()】

4. Servlet生命周期【面试题】

  • 构造器:Servlet创建时,调用构造器方法【单例】
    • 执行时机:第一次请求Servlet时,触发构造器,创建Servlet对象
    • 执行次数:在整个生命周期中,执行一次
  • init():初始化Servlet时,调用init()方法
    • 执行时机:第一次请求Servlet时,构造器之后,执行init()
    • 执行次数:在整个生命周期中,执行一次
  • service():处理请求,做出响应时, 调用service()方法
    • 执行时机:每次请求Servlet时,均调用service(),处理请求做出响应
    • 执行次数:在整个生命周期中,执行多次
  • destroy():销毁Servlet对象时,调用destroy()方法
    • 执行时机:在关闭服务器时,调用destroy()方法,销毁Servlet对象
    • 执行次数:在整个生命周期中,执行一次

第一次请求Servlet时,服务器创建Servlet对象【执行构造器】,之后执行init()方法进行初始化操作,最后执行service()方法,处理请求做出响应。以后再次请求Servlet,只执行service()方法,当关闭服务器时,调用destroy()方法,销毁Servlet对象
Servlet生命周期进阶版
要求:注册Servlet时,设置Servlet优先级


HelloWorldServlet

com.atguigu.servlet.HelloWorldServlet

1

启动服务器时,服务器创能Servlet对象【执行构造器】,调用init()方法进行初始化操作;每次请求Servlet时调用service()方法,处理请求做出响应。当关闭服务器时,调用destroy()方法,销毁Servlet对象

5. ServletConfig与ServletContext

5.1 ServletConfig

  • 概念:ServletConfig对象封装Servlet配置信息,每个Servlet都有唯一对应ServletConfig对象,该对象由服务器创建,最终以参数的形式传入到init()方法中
  • 作用:
    • 获取servlet名称:servletConfig.getServletName()
    • 获取servlet初始化参数值:servletConfig.getInitParameter()
    • 获取ServletContext对象:servletConfig.getServletContext()

5.2 ServletContext【重要】

  • 概念:ServletContext对象是Servlet上下文对象,每个web应用对应唯一ServletContext,该对象由服务器创建,获取方式如下:
    • servletConfig.getServletContext()
    • request.getServletContext()
  • 作用:
    • 获取指定资源的真实路径【d:/】:servletContext.getRealPath()
    • 获取上下文路径:servletContext.getContextPath()
      • 上下文路径:通过上下文路径,访问当前项目
    • 获取上下文初始化参数:servletContext.getInitParameter()
      • 配置上下文初始化参数

      • jdbcurl
        jdbc:mysql://localhost:3306/dbname


    • ServletContext是域对象
      • 一共四个域【聚齐再讲】
      • servletContext.setAttibute()
      • servletContext.getAttibute()
      • servletContext.removeAttibute()

6. 最终创建Servlet方式

目前创建Servlet方式不足

  1. 最好只留下service()方法,处理请求做出响应
  2. 最好提示注册Servlet

6.1 继承HttpServlet

  • EndServlet : HttpServlet : GenericServlet : javax.servlet.Servlet

6.2 GenericServlet与HttpServlet作用

  • GenericServlet作用
    • 提供获取对象方法【getServletConfig()和getServletContext】
    • @Override
      public ServletConfig getServletConfig() {
      return config;
      }
      @Override
      public ServletContext getServletContext() {
      return getServletConfig().getServletContext();
      }
    • 将service()方法,抽象化
    • @Override
      public abstract void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException;
  • HttpServlet作用
    • 重写service():类型转换
    • @Override
      public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {
      HttpServletRequest request;
      HttpServletResponse response;
      try {
      request = (HttpServletRequest) req;
      response = (HttpServletResponse) res;
      } catch (ClassCastException e) {
      throw new ServletException(lStrings.getString(“http.non_http”));
      }
      service(request, response);
      }
    • 重载service():通过请求方式不同,调用不同处理方法
    • protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
      //获取请求方式
      String method = req.getMethod();
      if(“GET”.eq(method)){
      doGet(req,resp);
      }else if(“POST”.eq(method)){
      doPost(req,resp);
      }else if()…

      }
    • Servlet中提供7种请求方式
    • GET POST PUT DELETE

7. request对象和response对象【最重要】

7.1 request请求对象

  • 类型:HttpServletRequest
  • 概念:request对象封装浏览器向服务器发送请求时请求报文【请求行,请求头,请求体】,该对象由服务器创建,以参数形式传入到service()中,最终传入doGet()或doPost()方法中
  • 作用:
    1. 获取请求行
      • 获取请求方式:request.getMethod()
      • 获取URI:request.getRequestURI()
      • 获取URL:request.getRequestURL()
        • 获取协议:request.getScheme()
        • 获取服务器名称:request.getServerName()
        • 获取服务器端口号:request.getServerPort()
        • 获取上下路径:request.getContextPath()
    2. 获取请求头:request.getHeader()
    3. 获取请求参数
    • 常见请求参数
    • 1.测试请求参数
    • 2.
      • request.getParameter():获取请求参数,单个参数,单个值
      • request.getParameterValues():获取请求参数,单个参数,多个值【多选框】
      • request.getParameterMap():获取请求参数,多个参数,多个值【获取所有请求参数】
    1. 请求转发【路径跳转】
    • //1. 获取转发器
      RequestDispatcher requestDispatcher = request.getRequestDispatcher(“target.html”);
      //2. 执行转发
      requestDispatcher.forward(request,response);
    1. request是域对象
      • request.setAttibute()
      • request.getAttibute()
      • request.removeAttribute()

7.2 response响应对象

  • 类型:HttpServletResponse
  • 概念:response对象封装服务器向浏览器做出响应时的响应报文【响应行、响应头、响应体】,该对象由服务器创建,以参数形式传入到service()中,最终传入doGet()或doPost()方法中
  • 作用:
    • 设置响应行
      • 设置状态码: response.setStatus(404);
    • 设置响应头
      • 设置文本类型及字符集:response.setHeader(“Content-Type”,”text/html;charset=UTF-8”);
    • 响应数据
      • 获取响应流,响应数据
      • PrintWriter writer = response.getWriter();
        writer.write(“xxx成功啦!”);
      • 重定向【路径跳转】
      • response.sendRedirect(“target.html”);

7.3 转发与重定向区别【面试题】

  • 转发地址栏不变,重定向地址栏改变
  • 转发携带request对象,重定向未携带request对象
  • 转发浏览器只发送一次请求,重定向浏览器发送两次请求
  • 转发可以访问WEB-INF下资源,重定向不能直接访问WEB-INF下资源
    • WEB-INF目录属于web应用私有目录,服务器内部可以访问,浏览器不能直接访问

8. 练习

8.1 需求

  • 使用request&response对象,实现伪登录&伪注册功能【不使用JDBC】
  • 假设数据库只有一条数据,username=guoqiang &pwd=123456
  • 登录业务
    • 登录成功:使用转发跳转login_success.html
    • 登录失败:使用重定向跳转回login.html
  • 注册业务
    • 注册成功:使用转发跳转regist_success.html
    • 注册失败:使用重定向跳转回regist.html

8.2 示例代码

登录页面



用户名:

密码:



protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}

  1. /**<br /> * 处理登录请求<br /> *<br /> * 登录业务<br /> * //假设数据库只有一条数据,username=guoqiang &pwd=123456<br /> * - 登录成功:使用转发跳转login_success.html<br /> * - 登录失败:使用重定向跳转回login.html<br /> * @param request<br /> * @param response<br /> * @throws ServletException<br /> * @throws IOException<br /> */<br /> protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br /> //获取请求参数【uname&pwd】<br /> String uname = request.getParameter("uname");<br /> String pwd = request.getParameter("pwd");<br /> if("guoqiang".equals(uname) && "123456".equals(pwd)){<br /> //登录成功:使用转发跳转login_success.html<br /> request.getRequestDispatcher("page/login_success.html").forward(request,response);<br /> }else{<br /> //登录失败:使用重定向跳转回login.html<br /> response.sendRedirect("page/login.html");<br /> }
  2. }<br />

9. web应用中乱码问题

乱码情况
请求乱码:
POST方式发送请求时,出现乱码
GET方式发送请求时,未出现乱码
响应乱码
响应过程中,默认出现乱码

9.1 基本概念

  • 字符集:所有字符集合,包括【中文、英文字符、各个国家字符、及标点符号等】
    • 常用字符集:UTF-8【支持较大量中文字符】、GBK【GB2312:支持少量中文字符】、ISO-8859-1【不支持中文字符】等
  • 编码与解码
    • 编码:将字符转换为二进制过程,称之为编码
    • 解码:将二进制转换为字符过程,称之为解码
    • 乱码:编码与解码使用字符集不一致时,出现乱码现象

9.2 浏览器与服务器默认编码与解码情况

  • 服务器默认编码与解码一致为:ISO-8859-1【不支持中文】
  • 浏览器
    • 默认编码:
    • 默认解码:GBK

9.3 默认请求与响应乱码情况

  • 乱码种类
    • 浏览器向服务器发送请求时,出现乱码:请求乱码
      • 浏览器编码与服务器解码不一致
    • 服务器向浏览器做出响应时,出现乱码:响应乱码
      • 服务器编码与浏览器解码不一致
  • Tomcat8.5及以后版本,解决GET请求乱码问题

9.4 解决乱码

  • 解决请求乱码
    • 解决GET请求乱码
      • Tomcat8.5及以后版本,不用解决【服务器默认解决GET请求乱码问题】
      • Tomcat7解决方案
        • 思路:找到修改8080位置,设置字符集问题
        • 代码:tomcat->conf->server.xml
        • connectionTimeout=”20000”
          redirectPort=”8443” />
    • 解决POST请求乱码
      • 思路:浏览器编码【UTF-8】与服务器解码【ISO-8859-1】不一致
        • 将服务器解码设置为:UTF-8
      • 代码:request.setCharacterEncoding(“UTF-8”);
  • 解决响应乱码
    • 思路及代码:服务器编码【ISO-8859-1】与浏览器解码【GBK】不一致
      1. 将服务器编码设置为:GBK
        • response.setCharacterEncoding(“GBK”);
      2. 将服务器编码与浏览器解码均设置为:UTF-8【推荐使用】
        • response.setContentType(“text/html;charset=UTF-8”);
  • 总结:三行代码解决请求与响应乱码问题

10. web应用中绝对路径

web应用中路径问题:由于使用转发跳转路径时,转发地址栏不变,此时使用相对路径不可靠【../】,可能出现404。所以建议使用绝对路径

10.1 什么是绝对路径

  • 以【/】开头路径,称之为绝对路径

10.2 【/】代表意义

  • 服务器解析【/】,代表当前上下文路径,即为:http://localhost:8080/day06_Servlet
    • 以下两种情况由服务器解析【/】
      • 注册中的【/】,web.xml中【/】或注解
      • 转发中【/】
  • 浏览器解析【/】,代表当前服务器路径,即为:http://localhost:8080
    • 以下两种情况由浏览器解析【/】
      • html代码中使用【/】,如:等
      • 重定向中【/】

10.3 Servlet注册路径问题

  • Servlet默认路径注册在当前上下文路径下
  • /RegistServlet
  • 运行期间的【上下文】路径,相当于编写代码期间的【web】路径

10.4 示例代码

  • html代码






  • 登录成功!




    回首页
  • Servlet代码
  • //登录成功:使用转发跳转login_success.html
    request.getRequestDispatcher(“/page/login_success.html”).forward(request,response);
    //登录失败:使用重定向跳转回login.html
    response.sendRedirect(request.getContextPath()+”/page/login.html”);

11. 基于注解【JavaEE6(web3.0)】注册Servlet

//@WebServlet(name = “Servlet30”,value={“/Servlet30”,”/Servlet3”})
@WebServlet(name = “Servlet30”,value=”/Servlet30”)
public class Servlet30 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br />        System.out.println("Servlet30");<br />    }<br />}