Servlet浅析

HTTP网络协议包内部结构

HTTP请求协议包

是浏览器在发送请求时负责创建的,浏览器将请求信息,写入到请求协议包中。HTTP请求协议包内部自上而下有四层结构。

image-20210331200133005

HTTP响应协议包

在服务端计算机的【资源调度软件】准备推送文件时,负责创建。【响应协议包内容】可以由【资源调度软件】写入,可以由Java命令(response)写入。HTTP响应协议包自上而下有四层结构。

image-20210331200547295

客户端计算机上浏览器管理

命令浏览器向指定网站发送请求

  1. 通过FORM表单命令

    <form action="http://www.baidu.com">
    </form>
    
  2. 通过超链接命令

    <a href="http://www.baidu.com">163.com</a>
    
  3. 浏览器的地址栏对象

    window.location="http://www.sina.com";
    

请求方式[POST/GET]

image-20210331202527145

如何控制浏览器采用的请求方式

  1. GET方式
    • 超链接标签
    • location对象
    • FORM表单中method=GET
  2. POST方式
    • FORM表单中method=POST

使浏览器在发送请求时,携带请求参数

固定的请求参数内容

  1. 超链接标签

    <a href="http://www.baidu.com?uname=mike&age=23">百度</a>
    
  2. location对象

    window.location="http://www.baidu.com?uname=mike&age=23"
    

动态请求参数内容【FORM表单】

  1. 【表单域标签分类】:input,select, textarea
  2. 【表单域标签作为请求参数条件】
    • 表单域标签必须声明在FORM内部
    • 表单域标签必须声明【name属性】,作为【请求参数名】
    • 针对checkboxradio,只有被选中的情况下,才能作为请求参数

HTTP服务器

Tomcat服务器

Tomcat端口号

存储位置:tomcat安装目录下/conf/server.xml

<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000" redirectPort="8443" />

Servlet规范

基础

如何开发一个Servlet接口实现类

  1. 创建一个实现类,继承【HttpServlet】
  2. 【HttpServlet】存在Tomcat中/lib/servlet-api.jarjavax.servlet.http.HttpServlet
  3. 根据来访的浏览器采用的请求方式,重写对应doGet或者doPost方法
  4. /WEB-INF中的web.xml注册Servlet接口实现类,通知Tomcat当前网站存在一个动态资源文件

Tomcat调用Servlet接口实现类流程

image-20210331205155069

Servlet请求路径的写法

  1. 具体请求路径

    【要求】:请求的【资源文件地址】与当前servlet中url-pattern完全一致;必须以/开头。

    【例子】:

    OneServlet 
    <url-pattern>/one.do</url-pattern>
    localhost/myWeb/one.do 会被调用
    localhost/myWeb/abc/one.do 不会被调用
    
  2. 前置条件请求路径

    【要求】:请求的【资源文件地址】以当前Servlet中的内容为开头;必须以/开头,以*结尾

    【例子】:

    OneServlet
    <url-pattern>/abc/*<url-pattern>
    localhost/myWeb/abc/two.do	会被调用
    localhost/myWeb/abc/one.html 会被调用
    
  3. 后置条件请求路径

    【要求】:请求的【资源文件地址】以当前Servlet中的内容为结尾;不能以/为开头,必须以*为结尾。

    【例子】:

    OneServlet
    <url-pattern>*.do</url-pattern>
    localhost/myWeb/abc/one.do 会被调用
    localhost/myWeb/five.do 会被调用
    localhost/myWeb/five.do?uname=mike 会被调用
    
  4. 通配符请求路径:

    【要求】:当前Servlet可以接受对当前网站的所有请求;

    【例子】:

    OneServlet <url-pattern>/*</url-pattern>
    localhost/myWeb/* 会被调用
    

优先级:【具体请求路径】>【前置条件】>【通配符】>【后置条件】

Servlet实例对象【生命周期】

  1. 所有Servlet实例对象都是由Tomcat负责创建,开发人员不能创建

  2. 创建时机:

    1. 【默认情况】:当第一个用户访问这个Servlet时,Tomcat负责创建

    2. 【人工干预】:要求Tomcat在启动时,创建Servlet实例对象

      <servlet>
      <load-on-startup>0</load-on-startup>
      </servlet>
      
  3. Tomcat运行期间,一个Servlet实现类只能被创建一个实例对象。

  4. Tomcat关闭时,由Tomcat销毁所有的Servlet实例对象

五种工具对象

介绍

  1. HttpServletResponse:负责将运行结果写入到响应包中
  2. HttpServletRequest:负责读取请求协议包信息
  3. ServletContext:为当前网站中所有的Servlet提供【共享数据】
  4. Cookie:在一次会话中,存储浏览器在服务端产生的私人数据
  5. HttpSession:在一次会话中,存储浏览器在服务端产生的私人数据

HttpServletResponse接口

通过【响应对象】将【英文】字符串写入【响应体】中

String str="hello HttpServletResponse";
//从【响应对象】获得一个输出流
PrintWriter out=response.getWriter();
//利用【输出流】将【字符串】写入【响应体】
out.write(str);
//隐藏步:Tomcat在OneServlet调用完毕后,将响应包推送到浏览器中

out.write()与out.print()

int num=50;
PrintWriter out=response.getWriter();
out.write(num);//只能将字符串或者unicode码写入响应体中,一个值为50 的unicode码对应字符串为2
out.println(num);//将任意东西写入,并且保持原始状态

乱码与字符集

String str="下课休息";
//浏览器根据【响应头】中设置的【字符集】对接受的内容进行解码
//默认【响应头】中字符集是【ISO-8859-1】无法解析中文内容
response.setCharacterEncoding("GBK");
PrintWriter out = response.getWriter();
out.println(str);
String str="China中国<br/>America美国<br/>Franch法国";
//浏览器根据【响应头】中的【内容类型】处理接受的结果
//默认情况下【内容类型】为"text" ,即存放的是字符串内容
response.setCharacterEncoding("UTF-8");
//若返回内容包含html标签,则需要重新设置【内容类型】response.setContentType("text/html");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(str);

远程查询服务

步骤:

  1. 导入依赖的工具类(Dbutil,SqlSession)
  2. 导入mysql驱动包(WEB-INF下创建【lib】文件夹、将mysql驱动包复制到lib下)
  3. 创建实体类model.Dept
  4. 创建数据操控类 dao.DeptDao
  5. 创建Servlet controller.DeptFindServlet

DeptFindServlet

response.setContentType("text/html;charset=UTF-8");
DeptDao dao = new DeptDao();
List<Dept> deptList=null;
PrintWriter out=null;
//1.JDBC查询所有部门信息
deptList = dao.findAll();
//2.响应对象将查询结果写入响应体中
out = response.getWriter();
for(Dept dept:deptList){
    out.write(dept.getDeptNo()+" "+dept.getDname()+" "+dept.getLoc());
}

DeptDao

public class DeptDao {
    public List findAll(){
        String sql = "select * from dept";
        List deptList = SqlSession.selectList(sql,Dept.class);
        return deptList;
    }
}

Dept

public class Dept {
    private Integer deptNo;
    private String dname;
    private String loc;
    //setter&getter...
    public Dept(Integer deptNo, String dname, String loc) {
        this.deptNo = deptNo;
        this.dname = dname;
        this.loc = loc;
    }
    //确保有无参构造-反射
    public Dept() {
    }
}

HttpServletRequest接口

作用:

  1. 读取【请求行】信息(请求地址、请求方式)

    String url=request.getRequestURL();
    String method=request.getMethod();
    
  2. 读取【请求头】或【请求体】中所有的【请求参数名】

    request.getParameterNames();//保存到枚举对象中
    
  3. 读取请求体或请求头中的【参数内容】(?uname=1&uname=2)

    String value=request=request.getParameter("请求参数名");//单个参数
    String array[]=request.getParameterValues("请求参数名");//多个参数
    

读取当前请求协议包所有的请求参数名称

Enumeration<String> parameterNames = request.getParameterNames();
        while(parameterNames.hasMoreElements()){
            String parametername = parameterNames.nextElement().toString();
            response.getWriter().println(parametername);
        }

TODO:request远程添加服务

请求对象与响应对象的生命周期【概念】

  1. 都是由Tomcat负责创建,当Tomcat收到一个【请求协议包】时,会为这个【请求协议包】创建一对request和response,一次请求对应一对erquest和ersponse。
  2. Tomcat调用被请求的Servlet中服务方法(doGet/doPost),负责将本次【请求对象和响应对象】作为参数传入到服务方法中。
  3. 在服务的Servlet工作完毕后,Tomcat负责销毁本次请求的request和response

中文请求参数乱码问题【概念】

  1. 在【GET】方式中,请求头中默认为【UTF-8】,Tomcat9.0默认采用【UTF-8】

  2. 在【POST】方式中,请求体中默认为【ISO-8859-1],需要重设request字符集

    request.setCharacterEncoding("utf-8");
    

ServletContext接口

介绍

  1. 提供全局作用作用域对象,一个网站中一个,为当前工程中所有Servlet提供【共享数据】

  2. 使用

    ServletContext application = request.getServletContext(); //向Tomcat所要全局作用域对象
    

共享数据来源

  1. 添加到web.xml

    <context-param>
    	<param-name>共享数据名</param-name>
        <param-value>共享数据内容</param-value>
    </context-param>
    

    使用【只读】

    ServletContext application = request.getServletContext();
    value=application.getInitParameter("name");
    
  2. 通过Servlet添加【可修改】

    application.setAttribute("name",value);
    value=application.getAttribute("name");
    

会话【概念】

  1. 定义:一个浏览器与一个服务器的一次完整交流
  2. 特点:
    • 在一次会话中,经历多次响应和请求
    • 在一次会话中,同一个浏览器往往访问多个Servlet
  3. 需求:在一次会话过程中,在浏览器要访问的Servlet之间进行数据共享
  4. 解决方案:Cookie和HttpSession

介绍

  1. Servlet规范提供的一个工具类,在一个会话过程中Servlet之间进行数据共享
  2. 存储在浏览器上,保存本次会话的共享数据
  3. 存在于【请求头】和【响应头】中,以{key:value}形式存在

使用

Cookie c1=new Cookie("key",value);//一个Cookie中只能有一个键值对,只能存储String类型
Cookie c2=new Cookie("key2",URLEncoder.encode(饺子,"utf-8"));//中文编码问题
(Tomcat9以下)
URLDecoder.decode(name);//反编码
response.addCookie(c1);//写入响应头中
Cookie array[]=request.getCookies();//从请求头中读取cookie

生命周期

  1. 默认保存在浏览器内存中,关闭时Cookie消失

  2. 【人工干预】:要求保存到硬盘,并指定时间

    cookie.setMaxAge(time);//以秒为单位的时间
    

Cookie应用

OneServlet 设置cookie
{
    //1.读取当前用户的基本信息
    String username = request.getParameter("username");
    String jiaozi = request.getParameter("jiaozi");
    //2.将当前用户的私人数据保存到Cookie中
    //中文Cookie编码问题
    Cookie c1 = new Cookie("key1",username);
    Cookie c2 = new Cookie("key2", jiaozi);
    //设置c1对象需要在用户硬盘上存活1分钟
    c1.setMaxAge(60);//60s

    //3.将Cookie对象写入到【响应包】中的【响应头】
    response.addCookie(c1);
    response.addCookie(c2);
}
TwoServlet读取cookie
{
     //1.读取当期那来访浏览器推送的Cookie
        Cookie[] cookies = request.getCookies();
        //根据得到的Cookie
        for(Cookie cookie:cookies){
            String keyname = cookie.getName();//读取Cookie中关键字名称
            String value = cookie.getValue();
            if("key1".equals(keyname)){
                System.out.println("欢迎"+value);
            }else if ("key2".equals(keyname)){
                System.out.println("已准备"+ value);
            }
        }
}

HttpSession接口

与Cookie的区别

  1. 相同点:都是为同一个会话的Servlet之间提供共享数据

  2. 不同点:

    Cookie HttpSession
    存储位置 浏览器内存或硬盘上 内存
    存储内容 只能存储String类型 可以存储任意类型
    存储数量 只能存储一个键值对 一个HttpSessio对象可以存储任意个键值对

使用

  1. 在浏览器来访时,Tomcat不会主动创建HttpSession对象

    只有浏览器访问的Servlet提出要求时,才会创建Session对象

  2. 申请Session对象:

    HttpSession session = request.getSession(); //已有session返回session,否则创建(用于存储数据)
    HttpSession session = request.getSession(true);//与无参一样
    HttpSession session = request.getSession(false); //已有session返回session,否则返回null (用于验证)
    
  3. Tomcat如何将Session和浏览器关联:在Tomcat创建一个Session对象,并生成唯一编号,将编号保存到cookie中,推送到当前浏览器内存中。Tomcat根据浏览器返回的cookie判断是否有session对象

  4. 使用

    session.setAttribute("key",共享数据)
    session.getAttribute("key")
    

HttpSession简单购物车

OneServlet

//1.读取浏览器推送过来的商品名称
String goodsName =  request.getParameter("name");
//2.向Tomcat索要当前浏览器在服务端的HttpSesion
HttpSession session = request.getSession();
//3.将用户选择的商品保存到当前用户Session中
Integer goodsNum = (Integer)session.getAttribute(goodsName);
if(goodsNum==null){
    session.setAttribute(goodsName, 1);
}else{
    session.setAttribute(goodsName, goodsNum+1);
}
<center>
        <h1>商品展示页面</h1>
        <table border="2">
            <tr>
                <td>面包</td>
                <td>15.00</td>
                <td><a href="/myweb/one.do?name=面包">放入购物车</a></td>
            </tr>
            <tr>
                <td>啤酒</td>
                <td>10.00</td>
                <td><a href="/myweb/one.do?name=啤酒">放入购物车</a></td>
            </tr>
            <tr>
                <td>烤肠</td>
                <td>30.00</td>
                <td><a href="/myweb/one.do?name=烤肠">放入购物车</a></td>
            </tr>
        </table>
    </center>

多个Servlet来处理同一次请求方案

前提:

  1. 一个Servlet只负责实现一个功能
  2. 浏览器在一次请求时,只能请求一个资源文件,如果客户需要多个Servlet协同完成,需要用户多次【手动提交请求】完成任务,降低服务质量

重定向

原理

  1. 【浏览器二次发送请求】,第一次得到302状态码,【地址栏会改变】,请求方式一定是【GET】
  2. 在第一个Servlet工作完成后,将第二个Servlet的地址推送给客户浏览器,浏览器根据这个地址自动向第二个Servlet发出请求

image-20210402122231453

用法

response.sendRedirect("第二个Servlet地址");//将地址写入响应头中的location

适用场景:添加/删除/更新功能Servlet之后-->调用查询功能Servlet

请求转发

原理

  1. 【服务器自动请求第二个Servlet】,请求方式一律跟随浏览器发出的请求方式(否则会405异常),【地址栏不变】
  2. 在第一个Servlet工作完成后,代替浏览器向Tomcat申请调用第二个Servlet

image-20210402122020062

image-20210402122033316

用法

RequestDispatcher report = request.getRequestDispatcher("第二个Servlet地址");//创建资源申请报告对象,不能从网站根目录开始写,写url-pattern
report.forward(request,response);//推送申请报告
//数据共享域 application HttpSession request

适用场景:查询Servlet调用JSP时

不适用场景:添加/删除/更新功能Servlet 之后 -> 查询功能Servlet

posted @ 2021-04-02 14:09  两块钱的争论  阅读(121)  评论(0)    收藏  举报