java-web(三) Servlet

三、Servlet

Servlet概述

  • servlet= server+applet :运行在服务器端的java程序
  • Servlet是一个接口,一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet 接口
  • 作用:接收请求,处理逻辑,响应结果

Servlet快速入门

  • 案例需求:编写一个普通的java类,通过浏览器可以访问
  • 步骤分析
    • ① 创建web项目
    • ② 编写普通java类,实现servlet接口
    • ③ 在web.xml配置url-pattern(servlet 访问路径)
    • ④ 部署web项目
    • ⑤ 启动测试

代码编写

  • ① 使用IDEA创建web项目

    在这里插入图片描述

  • ② 编写普通java类,实现servlet接口

    • 编写抽象方法(service方法)
    package com.lagou.servlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class QuickServlet implements Servlet {
    
        /*
         *   init: servlet对象创建时,调用此方法完成初始化操作
         */
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
    
        }
    
        /*
            getServletConfig:获取servletConfig配置对象
         */
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        /*
            对外提供服务的方法,tomcat会调用servlet里面的service方法执行具体的业务逻辑
            servletRequest:请求对象:借助该对象来获取请求参数
            servletResponse:响应对象:借助该对象来向浏览器响应一些数据
         */
        /*
         *   service:用户访问servlet时,调用此方法完成业务逻辑的处理
         */
        @Override
        public void service(ServletRequest servletRequest,
                            ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("servlet入门成功了....");
    
        }
    
        /*
         *   获取servlet的描述信息
         */
        @Override
        public String getServletInfo() {
            return null;
        }
    
        /*
         *   destroy:当servlet对象销毁,会调用此方法完成销毁操作
         */
        @Override
        public void destroy() {
    
        }
    }
    
  • ③ 配置web.xml

    • 配置servlet网络访问路径
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--配置QuickSerlvet
               servlet-name : 当前配置的servlet起一个别名(名称)
               servlet-class: 编写的就是配置的servlet的全限定类名
        1  -->
    
        <servlet>
            <servlet-name>QuickServlet</servlet-name>
            <servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
        </servlet>
    
        <!--
            servlet-mapping:给servlet设置一个映射地址
                servlet-name:给指定名称的servlet来配置映射地址
                url-pattern:具体该serlvet的映射地址(访问路径)*必须以/开头
        -->
        <servlet-mapping>
            <servlet-name>QuickServlet</servlet-name>
            <url-pattern>/quickServlet</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • ④ 部署web项目

    使用IDEA + Tomcat部署项目

servlet执行原理

  • 原理图

    在这里插入图片描述

Servlet生命周期

生命周期相关

思想介绍
  • 生命周期:指的是 一个对象从生(创建)到死(销毁)的一个过程

    // 1. servlet对象创建时,调用此方法 
    public void init(ServletConfig servletConfig);
    // 2. 用户访问servlet时,调用此方法 
    public void service(ServletRequest servletRequest, ServletResponse servletResponse);
    // 3. servlet对象销毁时,调用此方法 
    public void destroy()
    
代码演示
  • ① LifeServlet

    package com.lagou.life;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class LifeServlet implements Servlet {
    	/*
         *   init: servlet对象创建时,调用此方法完成初始化操作
         */
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
            System.out.println("LifeServlet的init方法执行了,该对象被创建完成了...");
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    	/*
         *   service:用户访问servlet时,调用此方法完成业务逻辑的处理
         */
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("LifeServlet的service方法执行了,执行了具体的业务逻辑...");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    	/*
         *   destroy:当servlet对象销毁,会调用此方法完成销毁操作
         */
        @Override
        public void destroy() {
            System.out.println("LifeServlet的destroy方法执行了,该对象被销毁了...");
        }
    }
    
    
  • ② 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
            version="4.0">
    
       <!--LifeSerlvet-->
       <servlet>
           <servlet-name>LifeSerlvet</servlet-name>
           <servlet-class>com.lagou.life.LifeServlet</servlet-class>
    
           <!--配置上该标签,serlvet就会在启动服务器的时候去完成实例化,并进行初始化操作
               标签内部需要写数值  正整数 1-3在tomcat的web.xml被使用了,所以建议从4开始使用
           -->
           <load-on-startup>4</load-on-startup>
       </servlet>
    
       <servlet-mapping>
           <servlet-name>LifeSerlvet</servlet-name>
           <url-pattern>/LifeSerlvet</url-pattern>
       </servlet-mapping>
    </web-app>
    
相关解析
  • 创建
    • 1)默认情况下
      • 用户第一次访问时,创建servlet,执行init方法
    • 2)修改创建时机
      • <load-on-startup></load-onstartup>
      • ​ 正数:4-N 【服务器启动时,创建】
      • ​ 补充:Tomcat的web.xml里有1,3 所以推荐4-n
      • ​ 负数(默认值):-1 【用户第一次访问时,创建】
    • 如果是默认情况下的创建,则用户发送请求后才创建servlet实例化,当有多个servlet并且多用户访问不同servlet时,每个servlet都需要实例化,需要耗费长时间,体验不好,所以需要修改创建时机
  • 运行(提供服务)
    • 用户每次访问时,都执行service方法
  • 销毁
    • 服务器正常关闭时,销毁servlet,执行destroy方法
  • 在这里插入图片描述
笔试题
  • 问题:请描述下servlet的生命周期
  • 答案:servlet是一个单实例多线程的,默认情况下,第一次请求来的时候,才会对该servlet进行实 例化,并执行初始化init方法,随后再执行service方法完成业务处理,当每一次请求发送过来,都会重新开启一个线程,来执行servlet中的service方法,当服务器关闭或者servlet被移除的时候,会执行 destory方法

Servlet体系结构

  • 主要讲解其他方式创建Servlet服务

  • 体系结构图

    在这里插入图片描述

GenericServlet

  • GenericServlet是Servlet的实现类,其为抽象类,重写了大部分Servlet接口的方法,编写普通java类继承GenericServlet时,只需要重写service方法,使得代码更简洁

  • ① 编写普通java类,继承GenericServlet抽象类

    package com.lagou.servlet;
    
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import java.io.IOException;
    
    public class ServletDemo1 extends GenericServlet {
    
        @Override
        public void init() throws ServletException {
            super.init();
            System.out.println("ServletDemo1的初始化方法执行了..");
        }
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("ServletDemo1 extends GenericServlet...");
        }
    
    
        @Override
        public void destroy() {
            super.destroy();
            System.out.println("ServletDemo1的销毁方法执行了");
        }
    }
    
  • ② 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--ServletDemo1-->
        <servlet>
            <servlet-name>ServletDemo1</servlet-name>
            <servlet-class>com.lagou.servlet.ServletDemo1</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>ServletDemo1</servlet-name>
            <url-pattern>/servletDemo1</url-pattern>
        </servlet-mapping>
    </web-app>
    

HttpServlet

  • HttpServlet继承了GenericServlet,其是抽象类,用来处理HTTP协议中的交互,其可以根据不同的请求方法做出不同的处理;其内部又定义了不同请求的处理方法,普通java类继承HttpServlet只需要重写请求处理方法既可

  • HttpServlet为最常用的创建Servlet服务的方式

    在这里插入图片描述

  • ① 编写前端html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    	<h3>用户登录</h3>
        <form action="http://localhost:8080/servlet_demo/servletDemo2" method="post">
            <input type="submit" value="提交表单">
        </form>
    
      <a href="/servlet_demo/mimeServlet?fileName=a.jpg">获取文件的mime类型</a>
    
    </body>
    </html>
    
  • ② 编写普通java类,继承HttpServlet抽象类

    package com.lagou.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class ServletDemo2 extends HttpServlet {
    
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("ServletDemo2中的doGet方法执行了...");
    
        }
    
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("ServletDemo2中的doPost方法执行了...");
        }
    }
    
    
  • ③ 配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--ServletDemo1-->
        <servlet>
            <servlet-name>ServletDemo2</servlet-name>
            <servlet-class>com.lagou.servlet.ServletDemo2</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>ServletDemo2</servlet-name>
            <url-pattern>/servletDemo2</url-pattern>
        </servlet-mapping>
    </web-app>
    

url-pattern的配置方式

  • 单映射

    在这里插入图片描述

Servlet映射多个url
  • 多映射

    在这里插入图片描述

url映射模式
  • 配置 url地址取值可以是

    • 精确匹配(掌握)
      • /servletDemo3 localhost:8080/项目路径/servletDemo3
    • 目录匹配
      • /aa/*
    • 后缀匹配
      • .xxx 例如:*.do
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--
            只要浏览器符合目录匹配规则,都可以访问到这个servlet:             
        			/aa/abc            
    				/aa/asadfasdf 
        --> 
        <servlet>    
            <servlet-name>ServletDemo4</servlet-name>    
            <servlet-class>com.lagou.servlet.QuickServlet</servlet-class> 
        </servlet> 
        <servlet-mapping>    
            <servlet-name>ServletDemo4</servlet-name>    
            <url-pattern>/aa/*</url-pattern> 
        </servlet-mapping>
    	<!--     只要浏览器符合后缀匹配规则,都可以访问到这个servlet                						aa.do                
                    bb.do                
                    xx.do 
    	--> 
        <servlet>    
            <servlet-name>ServletDemo5</servlet-name>    
            <servlet-class>com.lagou.servlet.QuickServlet</servlet-class> 
        </servlet> 
        <servlet-mapping>    
            <servlet-name>ServletDemo5</servlet-name>    
            <url-pattern>*.do</url-pattern> 
        </servlet-mapping>
    </web-app>
    

Request对象

request对象概述

  • 用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中

  • 作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息

    在这里插入图片描述

获取请求行信息

  • 例如: GET /servlet_demo/requestDemo1 HTTP/1.1

  • 相关API:

    • 1.获取请求方式 GET【掌握】
      • String getMethod()
    • 2.获取项目虚拟路径(项目名)/servlet_demo【掌握】
      • String getContextPath()
    • 3.获取URL http://localhost:8080/servlet_demo/requestDemo1
      • 统一资源定位符(确定某一个地址) 中华人民共和国
      • StringBuffer getRequestURL()
    • 4.获取协议和版本号 HTTP/1.1
      • String getProtocol()
    • 5.获取客户端ip
      • String getRemoteAddr()
  • 代码演示

    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class RequestDemo1 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 演示request对象获取请求行信息
            System.out.println("请求方式:" + request.getMethod());
            System.out.println("虚拟路径:" + request.getContextPath());
            System.out.println("URL:" + request.getRequestURL());
            System.out.println("协议和版本:" + request.getProtocol());
            System.out.println("客户端IP地址:"+ request.getRemoteAddr());
        }
    
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req,resp);
        }
    }
    

获取请求头信息

  • 例如: Host: 127.0.0.1:8080

  • 相关API:

    • 1.获取知道请求头名称对应的值,注:名称不区分大小写
      • String getHeader(String name)
    • 2.获取所有请求头的名称
      • Enumeration<String> getHeaderNames()
      • 注:是Iterator前身
  • 代码演示

    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Enumeration;
    
    public class RequestDemo2 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
              // 获取请求头信息
            // 获取指定的头信息 Host
            String host = request.getHeader("Host");
            System.out.println(host);
    
            // 先获取到所有的请求头名称
            Enumeration<String> headerNames = request.getHeaderNames();
            //遍历
            while (headerNames.hasMoreElements()){
                // 请求头名称
                String name = headerNames.nextElement();
                // 根据名称获取值
                String value = request.getHeader(name);
                System.out.println(name + ":" + value);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

获取请求体信息(请求参数)

  • 不论get还是post请求方式,都可以使用下列方法来获取请求参数

  • 参数

    • username=jack&password=123&hobby=drink&hobby=perm
  • 相关API

    • 获取指定参数名的值 username=jack
      • String getParameter(String name)
    • 获取指定参数名的值数组 hobby=drink&hobby=perm
      • String[] getParameterValues(String name)
    • 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
    • Map<String,String[]> getParameterMap()
    • 中文乱码【重点】
      • get:在tomcat8及以上版本,内部URL编码(UTF-8)
      • post:编码解码不一致,造成乱码现象
      • 客户端(浏览器)编码:UTF-8
      • 服务器默认 解码:ISO-8859-1 拉丁文
      • 指定解码:void setCharacterEncoding(String env)
        • 注:其必须在方法内,且是行首
  • 代码演示

    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Map;
    
    public class RequestDemo3 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
            // 设置解码为UTF-8 ,解决post中文乱码问题
            request.setCharacterEncoding("UTF-8");
            // 获取表单提交的请求参数
            String username = request.getParameter("username");
            System.out.println("用户名:" + username);
    
            // 获取爱好这样的多个value的数组类型
            String[] hobbies = request.getParameterValues("hobby");
            System.out.println( Arrays.toString(hobbies));
    
            // 获取所有的请求参数的key和value 
            // String:表单中的name属性值 String[]:请求参数的value值
            Map<String, String[]> parameterMap = request.getParameterMap();
            parameterMap.forEach((k,v)->{
                System.out.println(k + "=" + Arrays.toString(v));
            });
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
            // 设置解码为UTF-8 ,解决post中文乱码问题
    
            doGet(request, resp); //让doGet方法中业务逻辑执行
        }
    }
    

请求转发

  • 一种在服务器内部的资源跳转方式

    在这里插入图片描述

  • 相关API

方法描述
RequestDispatcher getRequestDispatcher(String path)通过reqeust对象,获得转发器对象 (path为要跳转到的路径)
void forward(ServletRequest request, ServletResponse response)通过转发器对象,实现转发功能
  • 请求转发特点

    • 浏览器:发了一次请求
    • 地址栏:没有发生改变
    • 只能转发到服务器内部资源…
  • 链式编程

    • request.getRequestDispatcher("/bServlet").forward(reqeust,response)
  • 代码演示

    • AServlet
    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class AServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("AServlet中功能上执行了");
    
            // 请求转发到Bservelt String path: 写的就是要跳转的资源路径
       		// 1.获取到转发器对象
            // RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/");
    
            // 2.借助转发器对象进行真正的请求转发
            // requestDispatcher.forward(request,resp);
    
            // 链式编程
            request.getRequestDispatcher("/bServlet").forward(request,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    
    • BServlet
    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class BServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("BServlet中功能下执行了");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    

域对象(共享数据)

  • 域对象:一个有作用范围的对象,可以在范围内共享数据

  • request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据

    在这里插入图片描述

  • 相关 API

    方法描述
    void setAttribute(String name, Object o)设置数据
    Object getAttribute(String name)获取数据
    void removeAttribute(String name)删除数据
  • 生命周期

    • 何时创建
      • 用户发送请求时,创建request
    • 何时销毁
    • 服务器返回响应是,销毁request
    • 作用范围
      • 一次请求,包含多次转发
  • 代码演示

    • AServlet
    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class AServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("AServlet中功能上执行了");
    		request.setAttribute("haobao", "香辣鸡腿堡");
            // 链式编程
            request.getRequestDispatcher("/bServlet").forward(request,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    
    • BServlet
    package com.lagou.request;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class BServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		// 从request域中取出数据
            String hanbao = (String) req.getAttribute("hanbao");
            System.out.println(hanbao);
            System.out.println("BServlet中功能下执行了");
            // 删除request域中数据
            req.removeAttribute("hanbao");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    

Response对象

概述

  • response对象表示web服务器给浏览器返回的响应信息

  • 作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息

  • 在这里插入图片描述

  • Response体系结构

    ServletResponse 接口            
        |       
    HttpServletResponse 接口            
        |       
    org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)
    

设置Http响应消息

  • 响应行

    * 格式        
            协议/版本号 状态码     
    * 例如        
            HTTP/1.1 200        
    * API    
       1. 设置状态码            
            void setStatus(int sc)           200 302 304 404 500
    
  • 响应头

    * 格式        
            响应头名称:响应头的值         
    * 例如        
            Location:http://www.lagou.com        
    * API    
       1. 设置指定头名称和对应的值            
            void setHeader(String name, String value) 
    
  • 响应体

    * API(输出流对象)    
       1. 字符输出流            
            PrintWriter getWriter()        
       2. 字节输出流            
            ServletOutputStream getOutputStream()                
       
       注意:在同一个servlet中,二种类型的输出流不能同时存在,互斥
    

响应重定向

  • 重定向理解图

    在这里插入图片描述

  • 需求:用户访问AServlet后,服务器告诉浏览器重定向到BServlet

  • 步骤分析

    * 方式一       
        // 1.设置状态码        
            response.setStatus(302);    
        // 2.设置响应头 Location        
            response.setHeader("Location","重定向网络地址");                
    * 方式二    
        // 1.response这哥们封装专门处理重定向的方法        
            response.sendRedirect("重定向网络地址");
    
  • 重定向特点

    • 地址栏会发生改变
    1. 重定向是二次请求
    2. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源…
    3. 不能使用request域共享数
  • 请求转发与重定向的区别

    1. 哪个对象    
        转发(request对象的方法)                
            request.getRequestDispatcher("/bServlet").forward(request,response);   
        重定向(response对象的方法)                
            response.sendRedirect("/day10_response/bServlet");  
            
    2. 几次请求    
        转发        
            地址栏: 没有改变        
            浏览器: 发了一次请求        
            服务器: 只有一对请求和响应对象        
            发生的位置: 服务器    
        重定向        
            地址栏: 发生了改变        
            浏览器: 发了两次请求        
            服务器: 有两对请求和响应对象        
            发生的位置: 浏览器 
            
    3. 小结    
        写法         
            转发("/servlet资源路径") 服务器内部行为        
            重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为    
        使用场景(重点掌握)         
            如果需要传递数据(request域),使用转发        
            如果不需要传递数据(request域),使用重定向
    
  • 代码演示

    • CServlet
    package com.lagou.response;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class CServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("访问到了CSerlvet,接下来重定向到DServlet");
            // 设置重定向
          /*  resp.setStatus(302);
            resp.setHeader("Location","dServlet");*/
    
            // 设置重定向 方式二:常用
            resp.sendRedirect("https://www.lagou.com/");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    
    • DServlet
    package com.lagou.response;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class DServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("DServlet执行了.....");
        }
        
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

响应中文

  • 需求:向页面输出中文数据没有乱码

  • 步骤分析

    1. 通过response获取字符输出流        
            PrintWriter pw = response.getWriter();        
    2. 通过字符输出输出文本        
            pw.write("中文....");
    
  • 解决中文乱码

    1. 指定服务器响应编码方式        
    		response.setCharacterEncoding("GBK");        
    2. 统一浏览器和服务器编码(常用)        
    		response.setContentType("text/html;charset=utf-8"); 
    
  • 代码演示

    package com.lagou.response;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class EncodeServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            // 设置编码时,一定要写在首行
            //resp.setCharacterEncoding("GBK");
            // 统一浏览器和服务器编码
            resp.setContentType("text/html;charset=utf-8");
    
            // 向页面输出中文
            PrintWriter writer = resp.getWriter();
            writer.write("中文..");
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

ServletContext对象

概述

  • web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象

  • ServletContext对象 代表:当前web项目

    在这里插入图片描述

主要作用
  • 其是域对象(用于共享数据)
  • 获取资源在服务器的真实地址
  • 获取全局的配置参数
  • 获取文件MIME类型
获取ServletContext对象
  • 1. 通过request对象获得        
    		ServletContext sc = request.getServletContext();        
    2. 继承HttpServlet后,可以直接调用        
    		ServletContext sc = this.getServletContext();
    

域对象(共享数据)

  • 当前项目范围内,共享数据(多个servlet都可以获取)

    在这里插入图片描述

  • 相关方法

    1. 存储数据        
    		void setAttribute(String name,Object value) 
    2. 获取数据        
    		Object getAttribute(String name) 
    3. 删除数据        
    		void removeAttribute(String name)
    
  • 生命周期

    1. 何时创建?        
    		项目加载时,创建        
    2. 何时销毁?        
    		项目卸载时,销毁
    3. 作用范围?        
    		与项目共存亡(多个servlet都可以操作它)
    
  • 代码演示

    • OneServlet
    package com.lagou.servletContext;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class OneServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            // 向servletContext域对象中存入数据
            //  ServletContext servletContext1 = this.getServletContext();
            ServletContext servletContext = req.getServletContext();
    
            servletContext.setAttribute("user","jack");
            System.out.println("OneServlet中存入了数据....");
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    • TwoServlet
    package com.lagou.servletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class TwoServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            // 从servletContext域中取出数据
            String user = (String) req.getServletContext().getAttribute("user");
            System.out.println("TwoServlet中取出的数据为" + user);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

获取资源在服务器的真实地址

  • 可以实现web项目的移植性…动态获取文件真实路径

  • 文件的真实路径并不是文件在项目中所放的位置,而是项目启动后,被放在一个加载目录中

  • 相关API

  • String getRealPath(String path)

  • 代码演示

    package com.lagou.servletContext;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class RealpathServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            // 获取lagou.jpg文件的真实路径
            ServletContext servletContext = req.getServletContext();
            String realPath = servletContext.getRealPath("/img/lagou.jpg");
            System.out.println(realPath);
    
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

获取全局的配置参数

  • 读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取)

  • 相关API

    • String getInitParameter(String name)
  • 代码演示

    • web.xml配置全局参数
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
    	<!--全局配置参数:所有的servlet都可以读取...-->
        <context-param>
            <param-name>encode</param-name>
            <param-value>UTF-8</param-value>
        </context-param>
    </web-app>
    
    • OneServlet
    package com.lagou.servletContext;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class OneServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            ServletContext servletContext = req.getServletContext();
            // servletContext获取到全局配置参数
            String encode = servletContext.getInitParameter("encode");
            System.out.println("获取到的全局配置参数-"+ encode);
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

获取文件MIME类型

  • 在互联网通信过程中定义的一种文件数据类型格式

  • 格式: 大类型/小类型 例如: text/html image/jpeg

  • 相关API

    • Sting getMimeType(String filename)
  • 代码演示

    package com.lagou.servletContext;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MimeServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            // 获取指定文件的mime类型
            // servlet_demo/mimeServlet?fileName=a.jpg
            // 获取请求参数
            String fileName = req.getParameter("fileName");
    
            // 获取文件的mime类型
            String mimeType = req.getServletContext().getMimeType(fileName);
            resp.getWriter().write(fileName + "----" + mimeType);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

案例:统计网站的访问次数

  • 需求:一般个人博客的首页,都会显示你是第几位访问此网站…

  • 思路图

    在这里插入图片描述

  • 代码演示

    • web.xml配置
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
    	<!--CountServlet-->
        <servlet>
            <servlet-name>CountServlet</servlet-name>
            <servlet-class>com.lagou.servletContext.CountServlet</servlet-class>
            <load-on-startup>4</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>CountServlet</servlet-name>
            <url-pattern>/countServlet</url-pattern>
        </servlet-mapping>
    </web-app>
    
    • CountServlet
    package com.lagou.servletContext;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class CountServlet extends HttpServlet {
    
        @Override
        public void init() throws ServletException {
            // 向servletContext域中存入变量count,并且初始值为0
            this.getServletContext().setAttribute("count",0);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
           //1. 设置响应编码
            resp.setContentType("text/html;charset=utf-8");
    
           //2. 向页面响应信息
            resp.getWriter().write("<h1>拉勾博客</h1>");
    
            //3.进行servletContext域中的取值   取  加  存    0
            // 取
            Integer count = (Integer) this.getServletContext().getAttribute("count");
    
            // 加
            count++;
    
            resp.getWriter().write("<dev>你是,第"+ count + "位访问此网站的人</dev>");
            // 存
            this.getServletContext().setAttribute("count",count);
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    

    注:本内容为个人拉勾教育大数据训练营课程笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值