暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

javaweb基础(一)

Hello 帅帅 2021-02-05
498

Servlet

server applet:运行在服务器端的小程序

servlet是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。

使用方法

xml配置方法

  1. 定义一个类实现servlet接口

     public class ServletDemo1 implements Servlet {
     
         @Override
         public void init(ServletConfig servletConfig) throws ServletException {
             System.out.println("开始此servlet,只执行一次");
        }
         
         @Override
         public ServletConfig getServletConfig() {
             return null;
        }
         //提供服务的方法
         @Override
         public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
             System.out.println("每次访问都会执行一次此方法");
        }
     
         @Override
         public String getServletInfo() {
             return null;
        }
     
         @Override
         public void destroy() {
             System.out.println("在Tomcat正常关闭时结束此方法");
        }
     }
  2. 在web.xml文件中

     <servlet>
         <servlet-name>demo1</servlet-name>
         <servlet-class>com.company.web.servlet.ServletDemo1</servlet-class>
         <!-- <0则在被访问时创建(默认) -->
         <!-- >=0在服务器被创建时创建   -->
         <load-on-startup>-1</load-on-startup>
     </servlet>
     <servlet-mapping>
         <servlet-name>demo1</servlet-name>
         <url-pattern>/demo1</url-pattern>
     </servlet-mapping>

注解配置

     @WebServlet("/demo2")//访问demo2目录会创建此servlet
    @WebServlet({"/demo2","/demo3"})//访问demo2或demo3会创建此servlet
    @WebServlet("/demo4/demo3")//访问demo4/demo3会创建此servlet
    @WebServlet("/demo4/*")//访问demo4下的所有会创建此servlet
    @WebServlet("/demo4/*.do")//访问demo4下的所有有.do后缀会创建此servlet
    public class ServletDemo2 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    }
    @Override
    public ServletConfig getServletConfig() {
    return null;
    }
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("------------------");
    }
    @Override
    public String getServletInfo() {
    return null;
    }
    @Override
    public void destroy() {
    }
    }

    WebServlet
    源码:

       @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface WebServlet {
      String name() default "";//相当于<Servlet-name>
      String[] value() default {};//代表urlPatterns()属性配置
      String[] urlPatterns() default {};//相当于<url-pattern>
      int loadOnStartup() default -1;//相当于<load-on-startup>
      WebInitParam[] initParams() default {};
      boolean asyncSupported() default false;
      String smallIcon() default "";
      String largeIcon() default "";
      String description() default "";
      String displayName() default "";
      }

      执行原理

      1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径

      2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。

      3. 如果有,则在找到对应的<servlet-class>全类名

      4. tomcat会将字节码文件加载进内存,并且创建其对象

      5. 调用其方法

      继承体系

      Servlet -- 接口 -->  GenericServlet -- 抽象类   --> HttpServlet  -- 抽象类

      • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象方法。将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可

      • HttpServlet:对http协议的一种封装,简化操作

        • 定义类继承HttpServlet

        • 复写doGet/doPost方法

         @WebServlet("/demo3")
        public class ServletDemo3 extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        }
        }

        Http

        Hyper Text Transfer Protocol 超文本传输协议

        请求消息数据格式:请求行+请求头+请求空行+请求体

        请求行

        请求方式 请求url 请求协议/版本

        GET demo.html HTTP/1.1

        请求方式:

        序号方法描述
        1GET向特定的资源发出请求。
        2HEAD向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
        3POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中
        4PUT向指定资源位置上传其最新内容
        5DELETE请求服务器删除Request-URL所标识的资源
        6CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
        7OPTIONS返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
        8TRACE回显服务器收到的请求,主要用于测试或诊断

        请求头

        协议头说明示例状态
        Accept可接受的响应内容类型(Content-Types
        )。
        Accept: text/plain
        固定
        Accept-Charset可接受的字符集Accept-Charset: utf-8
        固定
        Accept-Encoding可接受的响应内容的编码方式。Accept-Encoding: gzip, deflate
        固定
        Accept-Language可接受的响应内容语言列表。Accept-Language: en-US
        固定
        Accept-Datetime可接受的按照时间来表示的响应内容版本Accept-Datetime: Sat, 26 Dec 2015 17:30:00 GMT临时
        Authorization用于表示HTTP协议中需要认证资源的认证信息Authorization: Basic OSdjJGRpbjpvcGVuIANlc2SdDE==固定
        Cache-Control用来指定当前的请求/回复中的,是否使用缓存机制。Cache-Control: no-cache
        固定
        Connection客户端(浏览器)想要优先使用的连接类型Connection: keep-alive``Connection: Upgrade
        固定
        Cookie由之前服务器通过Set-Cookie
        (见下文)设置的一个HTTP协议Cookie
        Cookie: $Version=1; Skin=new;
        固定:标准
        Content-Length以8进制表示的请求体的长度Content-Length: 348
        固定
        Content-MD5请求体的内容的二进制 MD5 散列值(数字签名),以 Base64 编码的结果Content-MD5: oD8dH2sgSW50ZWdyaIEd9D==废弃
        Content-Type请求体的MIME类型 (用于POST和PUT请求中)Content-Type: application/x-www-form-urlencoded固定
        Date发送该消息的日期和时间(以RFC 7231中定义的"HTTP日期"格式来发送)Date: Dec, 26 Dec 2015 17:30:00 GMT固定
        Expect表示客户端要求服务器做出特定的行为Expect: 100-continue
        固定
        From发起此请求的用户的邮件地址From: user@itbilu.com
        固定
        Host表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略。Host: www.itbilu.com:80``Host: www.itbilu.com
        固定
        If-Match仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要用于像 PUT 这样的方法中,仅当从用户上次更新某个资源后,该资源未被修改的情况下,才更新该资源。If-Match: "9jd00cdj34pss9ejqiw39d82f20d0ikd"固定
        If-Modified-Since允许在对应的资源未被修改的情况下返回304未修改If-Modified-Since: Dec, 26 Dec 2015 17:30:00 GMT固定
        If-None-Match允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),参考 超文本传输协议 的实体标记If-None-Match: "9jd00cdj34pss9ejqiw39d82f20d0ikd"固定
        If-Range如果该实体未被修改过,则向返回所缺少的那一个或多个部分。否则,返回整个新的实体If-Range: "9jd00cdj34pss9ejqiw39d82f20d0ikd"固定
        If-Unmodified-Since仅当该实体自某个特定时间以来未被修改的情况下,才发送回应。If-Unmodified-Since: Dec, 26 Dec 2015 17:30:00 GMT固定
        Max-Forwards限制该消息可被代理及网关转发的次数。Max-Forwards: 10
        固定
        Origin发起一个针对跨域资源共享的请求(该请求要求服务器在响应中加入一个Access-Control-Allow-Origin
        的消息头,表示访问控制所允许的来源)。
        Origin: http://www.itbilu.com
        固定: 标准
        Pragma与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生。Pragma: no-cache
        固定
        Proxy-Authorization用于向代理进行认证的认证信息。Proxy-Authorization: Basic IOoDZRgDOi0vcGVuIHNlNidJi2==固定
        Range表示请求某个实体的一部分,字节偏移以0开始。Range: bytes=500-999
        固定
        Referer表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer
        其实是Referrer
        这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer
        了。
        Referer: http://itbilu.com/nodejs固定
        TE浏览器预期接受的传输时的编码方式:可使用回应协议头Transfer-Encoding
        中的值(还可以使用"trailers"表示数据传输时的分块方式)用来表示浏览器希望在最后一个大小为0的块之后还接收到一些额外的字段。
        TE: trailers,deflate
        固定
        User-Agent浏览器的身份标识字符串User-Agent: Mozilla/……
        固定
        Upgrade要求服务器升级到一个高版本协议。Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11固定
        Via告诉服务器,这个请求是由哪些代理发出的。Via: 1.0 fred, 1.1 itbilu.com.com (Apache/1.1)固定
        Warning一个一般性的警告,表示在实体内容体中可能存在错误。Warning: 199 Miscellaneous warning固定

        请求空行

        空行,就是用于分割POST请求的请求头,和请求体的。

        请求体(正文)

        封装POST请求消息的请求参数的

           POST /login.html    HTTP/1.1
          Host: localhost
          User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
          Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
          Accept-Encoding: gzip, deflate
          Referer: http://localhost/login.html
          Connection: keep-alive
          Upgrade-Insecure-Requests: 1

          username=zhangsan

          Request

          Request对象是来获取请求消息

          Request对象继承体系结构

          ServletRequest -- 接口 | 继承 HttpServletRequest -- 接口 | 实现 org.apache.catalina.connector.RequestFacade类(tomcat)

          Request功能

          获取请求行数据

          请求行:GET day14/demo1?name=zhangsan HTTP/1.1

          方法:

          1. 获取请求方式 :GET

            • String getMethod()

          2. (*)获取虚拟目录:/day14

            • String getContextPath()

          3. 获取Servlet路径: demo1

            • String getServletPath()

          4. 获取get方式请求参数:name=zhangsan

            • String getQueryString()

          5. (*)获取请求URI:/day14/demo1

            • String getRequestURI(): /day14/demo1

            • StringBuffer getRequestURL()  :http://localhost/day14/demo1

          6. 获取协议及版本:HTTP/1.1

            • String getProtocol()

          7. 获取客户机的IP地址:

            • String getRemoteAddr()

           
            @WebServlet("/demo3")
            public class ServletDemo3 extends HttpServlet {
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("doPost");
            }

            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String method = req.getMethod();
            String contextPath = req.getContextPath();
            String servletPath = req.getServletPath();
            String queryString = req.getQueryString();
            String requestURI = req.getRequestURI();
            StringBuffer requestURL = req.getRequestURL();
            String protocol = req.getProtocol();
            String remoteAddr = req.getRemoteAddr();
            System.out.println("请求方式:"+method);
            System.out.println("虚拟目录:"+contextPath);
            System.out.println("Servlet路径:"+servletPath);
            System.out.println("get方式请求参数:"+queryString);
            System.out.println("URI:"+requestURI);
            System.out.println("URL:"+requestURL);
            System.out.println("协议及版本:"+protocol);
            System.out.println("客户机的IP地址:"+remoteAddr);
            }
            }

            输出:

               GET
              WebTomcat_war
              demo3
              null
              WebTomcat_war/demo3
              http://localhost:8080/WebTomcat_war/demo3
              HTTP/1.1
              0:0:0:0:0:0:0:1

              获取请求头数据

              方法:

              • String getHeader(String name):通过请求头的名称获取请求头的值

              • Enumeration<String> getHeaderNames():获取所有的请求头名称

                     @Override
                protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                Enumeration<String> headerNames = req.getHeaderNames();
                while (headerNames.hasMoreElements()) {
                String s = headerNames.nextElement();
                String header = req.getHeader(s);
                System.out.println(s + " : " + header);
                }

                String agent = req.getHeader("user-agent");
                if (agent.contains("Chrome")) {
                System.out.println("你使用的是谷歌浏览器");
                } else if (agent.contains("edge")) {
                System.out.println("你使用的是edge浏览器");
                }
                }

                输出:

                   host  :  localhost:8080
                  connection : keep-alive
                  upgrade-insecure-requests : 1
                  user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75
                  accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
                  sec-fetch-site : none
                  sec-fetch-mode : navigate
                  sec-fetch-user : ?1
                  sec-fetch-dest : document
                  accept-encoding : gzip, deflate, br
                  accept-language : zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
                  cookie : JSESSIONID=C981EFE2E9E19533C612212F2457FD5B; Phpstorm-20f921f5=e75a0f7d-9766-4502-8af8-465f6ed9632f; _ga=GA1.1.72471488.1606467110; user_device_id_timestamp=1606487566478; Hm_lvt_fdafb975c7b15a614fe2dd7716c44e87=1606467111,1606487567

                  获取请求体数据

                  只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

                  步骤:

                  1. 获取流对象

                    • BufferedReader getReader():获取字符输入流,只能操作字符数据

                    • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据

                  2. 再从流对象中拿数据

                         @Override
                    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                    BufferedReader reader = req.getReader();
                    String line;
                    while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                    }
                    }

                    输出:

                     username=admin&password=1234567890

                    界面:

                    获取请求参数通用方式

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

                    1. String getParameter(String name):根据参数名称获取参数值username=zs&password=123

                    2. String[] getParameterValues(String name):根据参数名称获取参数值的数组  hobby=xx&hobby=game

                    3. Enumeration<String> getParameterNames():获取所有请求的参数名称

                    4. Map<String,String[]> getParameterMap():获取所有参数的map集合

                        @Override
                      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      req.setCharacterEncoding("utf-8");
                      String username = req.getParameter("username");

                      Enumeration<String> parameterNames = req.getParameterNames();

                      // while(parameterNames.hasMoreElements()){
                      // String name=parameterNames.nextElement();
                      // System.out.print(name);
                      // String value = req.getParameter(name);
                      // System.out.print(" ---- ");
                      // System.out.println(value);
                      // }

                      Map<String, String[]> parameterMap = req.getParameterMap();
                      for(String name: parameterMap.keySet()){
                      String[] values=parameterMap.get(name);
                      System.out.println(name);
                      Arrays.stream(values).forEach(System.out::print);
                      System.out.println("---");
                      }
                      }

                      输出:

                         username
                        20185655---
                        password
                        12343212---
                        hobby
                        singdancerap---

                        请求转发

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

                        1. 步骤:

                          1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)

                          2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request,

                        ServletResponse response)

                        1. 特点:

                          1. 浏览器地址栏路径不发生变化

                          2. 只能转发到当前服务器内部资源中。

                          3. 转发是一次请求

                           @WebServlet("/demo7")
                          public class ServletDemo7 extends HttpServlet {
                          @Override
                          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                          System.out.println("demo7");
                          req.getRequestDispatcher("/demo8").forward(req, resp);
                          }

                          @Override
                          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                          this.doPost(req, resp);
                          }
                          }

                          @WebServlet("/demo8")
                          public class ServletDemo8 extends HttpServlet {
                          @Override
                          protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
                          System.out.println("demo8");

                          }

                          @Override
                          protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
                          this.doPost(req,resp);
                          }
                          }

                          输出:

                             demo7
                            demo8

                            共享数据

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

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

                            • 方法:

                              • void setAttribute(String name,Object obj):存储数据

                              • Object getAttitude(String name):通过键获取值

                              • void removeAttribute(String name):通过键移除键值对

                               @WebServlet("/demo7")
                              public class ServletDemo7 extends HttpServlet {
                              @Override
                              protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                              req.setAttribute("name", "wenwen");
                              System.out.println("demo7");
                              req.getRequestDispatcher("/demo8").forward(req, resp);
                              }

                              @Override
                              protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                              this.doPost(req, resp);
                              }
                              }
                              @WebServlet("/demo8")
                              public class ServletDemo8 extends HttpServlet {
                              @Override
                              protected void doPost(HttpServletRequest req, HttpServletResponse resp) {

                              Object name = req.getAttribute("name");
                              System.out.println(name);
                              System.out.println("demo8");

                              }

                              @Override
                              protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
                              this.doPost(req, resp);
                              }
                              }

                              输出:

                                 demo7
                                wenwen
                                demo8

                                获取ServletContext

                                • ServletContext getServletContext()

                                   ServletContext servletContext = req.getServletContext();
                                  System.out.println(servletContext);

                                  输出:

                                     org.apache.catalina.core.ApplicationContextFacade@64e82ff


                                    文章转载自Hello 帅帅,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                    评论