zoukankan      html  css  js  c++  java
  • 02 http,servlet,servletconfig,HttpServletRequest ,HttpServletResponse

    Http协议

    协议:双方在交互、通讯的时候, 遵守的一种规范、规则。
    http协议:针对网络上的客户端 与 服务器端在执行http请求的时候,遵守的一种规范。 其实就是规定了客户端在访问服务器端的时候,要带上哪些东西, 服务器端返回数据的时候,也要带上什么东西。
    版本:
        1.0请求数据,服务器返回后, 将会断开连接
        1.1请求数据,服务器返回后, 连接还会保持着。 除非服务器 | 客户端 关掉。 有一定的时间限制,如果都空着这个连接,那么后面会自己断掉。
       
    Http请求数据解释

    请求的数据里面包含三个部分内容 :请求行 、 请求头 、请求体

    *请求行
            POST /examples/servlets/servlet/RequestParamExample HTTP/1.1


            POST : 请求方式 ,以post去提交数据
            /examples/servlets/servlet/RequestParamExample
            请求的地址路径 , 就是要访问哪个地方。
            HTTP/1.1 协议版本
    * 请求头
            Accept: application/x-ms-application, image/jpeg, application/xaml+xml,
    image/gif, image/pjpeg, application/x-ms-xbap, */*
            Referer: http://localhost:8080/examples/servlets/servlet/RequestParamExample
            Accept-Language: zh-CN
            User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
            Content-Type: application/x-www-form-urlencoded
            Accept-Encoding: gzip, deflate
            Host: localhost:8080
            Content-Length: 31
            Connection: Keep-Alive
            Cache-Control: no-cache

            Accept: 客户端向服务器端表示,我能支持什么类型的数据。
            Referer : 真正请求的地址路径,全路径
            Accept-Language: 支持语言格式
            User-Agent: 用户代理 向服务器表明,当前来访的客户端信息。
            Content-Type: 提交的数据类型。经过urlencoding编码的form表单的数据
            Accept-Encoding: gzip, deflate : 压缩算法 。
            Host : 主机地址
            Content-Length: 数据长度
            Connection : Keep-Alive 保持连接
            Cache-Control : 对缓存的操作

    * 请求体
    浏览器真正发送给服务器的数据
            发送的数据呈现的是key=value ,如果存在多个数据,那么使用&
            firstname=zhang&lastname=sansan

    Http响应数据解析
    请求的数据里面包含三个部分内容 : 响应行 、 响应头 、响应体

        HTTP/1.1 200 OK
        Server: Apache-Coyote/1.1
        Content-Type: text/html;charset=ISO-8859-1
        Content-Length: 673
        Date: Fri, 17 Feb 2010 02:53:02 GMT

        ...

    * 响应行
        
            HTTP/1.1 200 OK
            协议版本  
            状态码
                200 : 成功,正常处理,得到数据。
                403  : for bidden  拒绝
                404 : Not Found
                500 : 服务器异常
            OK
                对应前面的状态码  

    * 响应头
            Server:  服务器是哪一种类型。  Tomcat
            Content-Type : 服务器返回给客户端你的内容类型
            Content-Length : 返回的数据长度
            Date : 通讯的日期,响应的时间    

    Get 和  Post请求区别
    * post
    1. 数据是以流的方式写过去,不会在地址栏上面显示。  现在一般提交数据到服务器使用的都是POST
    2. 以流的方式写数据,所以数据没有大小限制。一定需要一个Content-Lenght的头说明数据的长度有多少
    * get
    1. 会在地址栏后面拼接数据,所以有安全隐患。 一般从服务器获取数据,并且客户端也不用提交上面数据的时候,可以使用GET
    2. 能够带的数据有限, 1kb大小    

    Web资源
    在http协议当中,规定了请求和响应双方, 客户端和服务器端。与web相关的资源。 有两种分类

    * 静态资源
        html 、 js、 css
    * 动态资源
        servlet/jsp

    servlet:
    其实就是一个java程序,运行在我们的web服务器上,用于接收和响应 客户端的http请求。
    更多的是配合动态资源来做。 当然静态资源也需要使用到servlet,只不过是Tomcat里面已经定义好了一个 DefaultServlet


    Hello Servlet

    得写一个Web工程 , 要有一个服务器。
    测试运行Web工程
    
    1. 新建一个类, 实现Servlet接口
    2. 配置Servlet , 用意: 告诉服务器,我们的应用有这么些个servlet。
        在webContent/WEB-INF/web.xml里面写上以下内容。
    
      <!-- 向tomcat报告, 我这个应用里面有这个servlet, 名字叫做HelloServlet , 具体的路径是
    
    com.itheima.servlet.HelloServlet -->
      <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.itheima.servlet.HelloServlet</servlet-class>
      </servlet>
    
      <!-- 注册servlet的映射。  servletName : 找到上面注册的具体servlet,  url-pattern: 在地址
    
    栏上的path 一定要以/打头 -->
      <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/a</url-pattern>
      </servlet-mapping>
    
    3. 在地址栏上输入 http://localhost:8080/项目名称/a


    Servlet的通用写法
      

     Servlet (接口)
            |
            |
        GenericServlet
            |
            |
        HttpServlet (用于处理http的请求)
    定义一个类,继承HttpServlet 复写doGet 和 doPost
    public class HelloHttpServer extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
    
    ServletException, IOException {
            // TODO Auto-generated method stub
            super.doGet(req, resp);
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
    
    ServletException, IOException {
            // TODO Auto-generated method stub
            super.doPost(req, resp);
        }
    
    }


    Servlet的生命周期:
    生命周期:从创建到销毁的一段时间
    生命周期方法:
    从创建到销毁,所调用的那些方法。
    init方法
    在创建该servlet的实例时,就执行该方法。
    一个servlet只会初始化一次, init方法只会执行一次
    默认情况下是 : 初次访问该servlet,才会创建实例。
    service方法
    只要客户端来了一个请求,那么就执行这个方法了。
     该方法可以被执行很多次。 一次请求,对应一次service方法的调用
    destroy方法
      servlet销毁的时候,就会执行该方法
        1. 该项目从tomcat的里面移除。
        2. 正常关闭tomcat就会执行 shutdown.bat

    让Servlet创建实例提前:
    默认情况下,只有在初次访问servlet的时候,才会执行init方法。 有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至是做一些比较耗时的逻辑。
    在配置的时候, 使用load-on-startup元素来指定, 给定的数字越小,启动的时机就越早。 一般不写负数, 从2开始即可。

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.fly.servlet.HelloServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
      </servlet>


    ServletConfig:
    Servlet的配置,通过这个对象,可以获取servlet在配置的时候一些信息

    <servlet>
          <servlet-name>ServletConfigName</servlet-name>
          <servlet-class>com.fly.servlet.HelloServletConfig</servlet-class>
          <init-param>
               <param-name>name</param-name>
              <param-value>fly</param-value>
          </init-param>
      </servlet>
    public class HelloServletConfig extends HttpServlet{
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
    
    ServletException, IOException {
            ServletConfig config = getServletConfig(); //得到servlet配置对象 专门用于在配置servlet的信息
            String servletName = config.getServletName(); ////获取到的是配置servlet里面servlet-name 的文本内容
            System.out.println("servletName:"+servletName);
            
            String name = config.getInitParameter("name"); // 可以获取具体的某一个参数
            System.out.println("name:"+name);
            
            Enumeration<String> names = config.getInitParameterNames(); // 可以获取具体的某一个参数
            while (names.hasMoreElements()) {  //遍历取出所有的参数名称
                String key = (String) names.nextElement();
                String value = config.getInitParameter(key);
                System.out.println("key:"+key+"value:"+value);
            }
        /*    servletName:ServletConfigName
            name:fly
            key:namevalue:fly*/
    
        }
        
    }


    为什么需要有这个ServletConfig
    servlet 里面需要一个数字或者叫做变量值。 但是这个值不能是固定了。 所以要求使用到这个servlet的公司,在注册servlet的时候,必须要在web.xml里面,声明init-params


    ===========================================================================
    HttpServletRequest 和 HttpServletResponse
    Servlet配置方式
    1.全路径匹配:
    以 / 开始 /a /aa/bb
    localhost:8080/项目名称/aa/bb
    2.路径匹配 , 前半段匹配:
    以 / 开始 , 但是以 * 结束 /a/* /*
    其实是一个通配符,匹配任意文字
    localhost:8080/项目名称/aa/bb
    3.以扩展名匹配:
    写法: 没有/ 以 * 开始 *.扩展名 *.aa *.bb

    ServletContext:
    Servlet 上下文每个web工程都只有一个ServletContext对象。

    如何得到对象
        ServletContext context = getServletContext();
    作用:
    1获取全局配置参数
    2获取web工程中的资源
    3存取数据,servlet间共享数据 域对象

    全局配置参数:
      <!-- 用于配置全局的参数 -->
      <context-param>
      <param-name>name</param-name>
      <param-value>fly</param-value>
      </context-param>
    获取全局参数:
    ServletContext servletContext = getServletContext();
    String name = servletContext.getInitParameter("name");
    System.out.println("context-name:"+name);

    获取Web应用中的资源:
    1. 获取资源在tomcat里面的绝对路径
       

        //获取ServletContent对象
            ServletContext context = getServletContext();
            //获取给定文件在服务器上的绝对路径(文件放在项目结构的WebContent)
            String realPath = context.getRealPath("file/config.properties");
            
            Properties properties = new Properties();
            FileInputStream inputStream = new FileInputStream(realPath);
            properties.load(inputStream);
            String name = properties.getProperty("name");
            System.out.println("name:"+name);
            inputStream.close();


    2. getResourceAsStream 获取资源 流对象
     

    直接给相对的路径,然后获取流对象。
            ServletContext context = getServletContext();
            
            Properties properties = new Properties();
            //获取web工程下的资源,转化为流对象
            InputStream is = context.getResourceAsStream("file/config.properties");
            properties.load(is);
            String name = properties.getProperty("name");
            System.out.println("name:"+name);
            is.close();


    通过classloader去获取web工程下的资源:

    //ClassLoader   wtpwebappsxxWEB-INFclassses
    //要回到         wtpwebappsxx
    InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");


    使用ServletContext存取数据:

    //获取表单数据
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            //向客户端输出内容
            PrintWriter writer = response.getWriter();
            if ("abc".equals(username)&&"123".equals(password)) {
                System.out.println("登录成功");
                
                Object object = getServletContext().getAttribute("count");
                int count = 0;
                if (object!=null) {
                    count = (int) object;
                }
                getServletContext().setAttribute("count", count+1);
                
    //            writer.println("login success");
    //            writer.write("login success");
                response.setStatus(HttpServletResponse.SC_FOUND); //302重定向
                response.setHeader("Location", "home.html");
            }else {
                writer.println("login failed");
            }
    
    =====================
    
        // 取值
            int count = (int) getServletContext().getAttribute("count");
            // 输出到界面
            response.getWriter().write("当前访问次数:第"+count+"次访问");
    
    细节;
     <form action="login" method="get">   相对路径


    ServletContext 何时创建, 何时销毁?
    服务器启动的时候,会为托管的每一个web应用程序,创建一个ServletContext对象
    从服务器移除托管,或者是关闭服务器。
    ServletContext 的作用范围:同一个项目。

    HttpServletRequest:
    这个对象封装了客户端提交过来的一切数据。

    1. 可以获取客户端请求头信息

            //得到一个枚举集合  
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String name = (String) headerNames.nextElement();
                String value = request.getHeader(name);
                System.out.println(name+"="+value);
                
            }


    2. 获取客户端提交过来的数据

            String name = request.getParameter("name");
            String address = request.getParameter("address");
            System.out.println("name="+name);
            System.out.println("address="+address);
    
    
            //name=zhangsan&name=lisi&name=wangwu 一个key可以对应多个值。
    
            Map<String, String[]> map = request.getParameterMap();
            
            Set<String> keySet = map.keySet();
            Iterator<String> iterator = keySet.iterator();
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                System.out.println("key="+key + "--的值总数有:"+map.get
    
    (key).length);
                String value = map.get(key)[0];
                String value1 = map.get(key)[1];
                String value2 = map.get(key)[2];
                
                System.out.println(key+" ======= "+ value + "=" + value1 + "="+
    
    value2);
            }


    3. 获取中文数据

     客户端提交数据给服务器端,如果数据中带有中文的话,有可能会出现乱码情况,那么可以参照以下方法解决。

    * 如果是GET方式
        
        1. 代码转码
                String username = request.getParameter("username");
                String password = request.getParameter("password");
                
                System.out.println("userName="+username+"==password="+password);
                
                //get请求过来的数据,在url地址栏上就已经经过编码了,所以我们取到的就是乱码,
                //tomcat收到了这批数据,getParameter 默认使用ISO-8859-1去解码
                
                //先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串
                username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
                System.out.println("userName="+username+"==password="+password);
       直接在tomcat里面做配置,以后get请求过来的数据永远都是用UTF-8编码。
        
    
        2. 可以在tomcat里面做设置处理 conf/server.xml 加上URIEncoding="utf-8"
     
              <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"
    
    redirectPort="8443" URIEncoding="UTF-8"/>
    
    * 如果是POST方式
    
            //设置请求体里面的文字编码。  get方式,用这行,没用
            request.setCharacterEncoding("UTF-8");
        
            //这行设置一定要写在getParameter之前。


    HttpServletResponse:

     负责返回数据给客户端。

    输出数据到页面上

        //以字符流的方式写数据    
            //response.getWriter().write("<h1>hello response...</h1>");
            //以字节流的方式写数据
            response.getOutputStream().write("hello response".getBytes());


    响应的数据编码问题:

    String string = Charset.defaultCharset().name(); string类的getByte()方法使用的码表
    // 以字符流输出
    
     //response.getWriter()
            //1. 指定输出到客户端的时候,这些文字使用UTF-8编码
            response.setCharacterEncoding("UTF-8");
     
            //2. 直接规定浏览器看这份数据的时候,使用什么编码来看。
            response.setHeader("Content-Type", "text/html; charset=UTF-8");
            
            response.getWriter().write("你好...");
    
    //以字节流输出
    
    //response.getOutputStream()
    
            
            //1. 指定浏览器看这份数据使用的码表
            response.setHeader("Content-Type", "text/html;charset=UTF-8");
            
            //2. 指定输出的中文用的码表
            response.getOutputStream().write("你好..".getBytes("UTF-8"));
    
    //不分情况,一行搞定
    response.setContentType("text/html;charset=UTF-8");


    下载资源:
    1.直接以超链接的方式下载,不写任何代码。 也能够下载东西下来。

        让tomcat的默认servlet去提供下载:
        <a href="download/a.rar">cc.rar</a><br>

     原因是tomcat里面有一个默认的Servlet -- DefaultServlet 。这个DefaultServlet 专门用于处理放在tomcat服务器上的静态资源。

    2.

    // <a href="DownLoad?download=cc.rar">c.rar</a>
            //获取要现在的文件的名字
            String fileName = request.getParameter("download");
            //获取文件在tomcat的绝对路径
            String path = getServletContext().getRealPath("download/"+fileName);
            //以下载的方式提醒用户,而不是直接展示
            response.setHeader("Content-Disposition", "attachment;filename="+fileName);
            //转化成输出流
            InputStream is = new FileInputStream(path);
            OutputStream os = response.getOutputStream();
            
            int len = 0;
            byte[] b = new byte[1024];
            while((len=is.read(b))!=-1) {
                os.write(b, 0, len);
            }
            os.close();
            is.close();

     中文文件下载
      针对浏览器类型,对文件名字做编码处理 Firefox (Base64) , IE、Chrome ... 使用的是URLEncoder
         

      public static String base64EncodeFileName(String fileName) {
                BASE64Encoder base64Encoder = new BASE64Encoder();
                try {
                    return "=?UTF-8?B?"
                            + new String(base64Encoder.encode(fileName
                                    .getBytes("UTF-8"))) + "?=";
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
           /*
             * 如果文件的名字带有中文,那么需要对这个文件名进行编码处理
             * 如果是IE ,或者  Chrome (谷歌浏览器) ,使用URLEncoding 编码
             * 如果是Firefox , 使用Base64编码
             */
            //获取来访的客户端类型
            String clientType = request.getHeader("User-Agent");
            
            if(clientType.contains("Firefox")){  //包含Firefox
                fileName = DownLoadUtil.base64EncodeFileName(fileName);
            }else{
                //IE ,或者  Chrome (谷歌浏览器) ,
                //对中文的名字进行编码处理
                fileName = URLEncoder.encode(fileName,"UTF-8");
            }

    完整:
           

    // <a href="DownLoad?download=cc.rar">c.rar</a>
            //获取要现在的文件的名字
            String fileName = request.getParameter("download");
            //防止有中文
            fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8");
            
            //获取文件在tomcat的绝对路径
            String path = getServletContext().getRealPath("download/"+fileName);
            /*
             * 如果文件的名字带有中文,那么需要对这个文件名进行编码处理
             * 如果是IE ,或者  Chrome (谷歌浏览器) ,使用URLEncoding 编码
             * 如果是Firefox , 使用Base64编码
             */
            //获取来访的客户端类型
            String clientType = request.getHeader("User-Agent");//包含Firefox
            if (clientType.contains("Firefox")) {
                fileName = DownLoadUtil.base64EncodeFileName(fileName);
            }else {
                //对中文的名字进行编码处理
                fileName = URLEncoder.encode(fileName,"UTF-8");
            }
            //以下载的方式提醒用户,而不是直接展示
            response.setHeader("Content-Disposition", "attachment;filename="+fileName);
            //转化成输出流
            InputStream is = new FileInputStream(path);
            OutputStream os = response.getOutputStream();
            
            int len = 0;
            byte[] b = new byte[1024];
            while((len=is.read(b))!=-1) {
                os.write(b, 0, len);
            }
            os.close();
            is.close();
    View Code
  • 相关阅读:
    Django REST framework+Vue 打造生鲜电商项目(笔记三)
    「数据结构与算法之链表(Python)」(四)
    微服务的注册中心
    git学习(十一) idea git pull 解决冲突
    git学习(十) idea git reset 操作
    git学习(九) idea git stash操作
    git学习(八) git stash操作
    git 学习笔记
    git学习(五) git diff操作
    git:Your branch and 'origin/master' have diverged
  • 原文地址:https://www.cnblogs.com/fly-book/p/9911293.html
Copyright © 2011-2022 走看看