servlet&&HTTP协议&&Request对象学习

servlet&&HTTP协议&&Request对象学习


1.servlet 的体系结构和介绍

Servlet
||
GenericServlet:将除service方法外的其余方法默认空实现,只将service方法作为抽象(在正式开发的时候,我们不会使用这种方法),在使用的时候,直接直接定义一个类继承genericservlet类即可
||
HttpServlet:对http协议的一种封装,简化操作
处理了一个判断请求的功能,在以前使用的servlet中当一个访问来后,创建完service方法,无论是get方法请求还是 post方式请求,都需要进行判断才能使用,因为这两种方式是不同的,所以我们需要判断,而HttpServlet就在内部对这个进行
编写,直接有doget,dopost方法,来响应不同方式的请求。而我们一般只写一个
在doget中调dopost,或者在dopost中调doget;


2.servlet的相关配置

  • 1.使用注释,资源路径可以有多个,也就是说使用不同的资源路径,创建同一个servlet,访问同一个servlet
  • 2.在WebServlet注释的定义中,可以看出,urlPattern是使用数组进行定义的所以,使用大括号对资源路径进行赋值
    @WebServlet({"/demo4","/de4","/d4"})//* 使用这三个资源路径都可以访问到servlet资源路径.
  • 3.路径定义规则:的优先级很低,使用之后,会优先匹配别的资源路径
    1./xxx : /
    :所有的资源路径都可以访问到当前的servlet
    2./xxx/xxx (目录结构) :/xxx/* :也可以使用通配符
    :/user/demo :多级目录
    3.*.do(自定义后缀名) :demo.do

2.Http协议(Hyper Text Transfer Protocol)

  • 概念:超文本传输协议
    传输协议:定义了客户端与服务器端通信的时候,请求消息和响应消息的格式

  • http协议的特点
    1,基于tcp/ip协议的高级协议,也就是说面向连接的,安全的,协议,进行通信的时候需要进行三次握手。
    2,默认端口号是:80。
    3,基于请求/响应模型:一次请求对应一次响应,不会出现一次请求多次响应的情况,也不可能是对个请求一个响应。
    4,无状态的:每次请求之间相互独立,不能交互数据


    抓包,百度网页的每一个资源都是一次请求
  • 历史版本
    1.0:每一次请求响应都是建立新的连接
    1.1:复用链接,将所有资源获都传输成功后再断开连接,但是每一个资源都是
    基于请求/响应的模式


  • http请求/响应消息数据格式(在使用浏览器,开发者工具抓包的时候,浏览器太高级会导致我们去学习的时候很不便利,所以我们使用垃圾一点的浏览器,查看原始头)
    1.请求行:(请求方式 请求url 请求协议和版本,在浏览器中会用其他的方式显示,但是内容还是这个内容)
    如:GET /login.html?name=xzw http/1.1
    请求方式
    http协议有7种请求方式,而我们常见的方式有两种,get,post方式
    GET方式:
    1,请求参数在请求行中,在url后 ,如:name=xzw
    2,请求的url长度有限制
    3,不太安全(在url中可以之间看见参数)
    POST方式:
    1,请求参数在请求体中
    2,请求的url长度没有限制
    3,相对安全(在url中看不见参数)

2,请求头(键值对的形式存在,请求头名称,请求头值)(就是客户端浏览器发送给服务器的一些信息)
如:
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;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
Connection: keep-alive
Cookie: Idea-9bab5137=3dd752db-249a-4508-851c-04dd5f28bc9e
Upgrade-Insecure-Requests: 1
If-Modified-Since: Sun, 26 Jan 2020 08:12:31 GMT
If-None-Match: W/"620-1580026351282"
Cache-Control: max-age=0
其中几个常用的请求头:
1.User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息,这个信息可以在服务器中获取,然后根据这个信息解决服务器的兼容问题
2.accept:可以接受什么样的文本
3.referer:告诉服务器,我当前的请求从哪里来?
referer:http://localhost:8080/java_idea_request/input.html
作用:1.防盗链2.统计功能(判断叠加)
说明:就是可以通过这个请求头,去判断当前请求是从哪个连接过来的,可以防止盗链,和统计工作


3.请求空行:就是用来分隔请求头和请求体的
4.请求体:封装Post请求消息的请求参数



Tomcat服务器在请求和响应是真正的过程

1.Tomcat服务器会根据请求的url资源路径,创建对应的servlet对象。
2.Tomcat服务器会创建request和response对象,request对象中会封装请求消息数据。
3.Tomcat服务器将request对象和response对象传递给service方法,并且调用service方法。
4.我们可以通过request对象获取请求消息数据,再通过response对象设置响应信息数据
5.服务器在给浏览器做出响应之前,从response对象中那程序员设置的响应数据信息(也就是说,在浏览器还没有接受到响应的时候,是服务器先获取到response中的数据,在将数据响应给浏览器)
(!就是说我以前认为的request对象就是请求,response对象就是响应是不对的,他们只是对请求和响应的封装)


  • request&&response对象的原理:
    1.request和response对象是服务器创建的,我们只是使用它
    2.request对象是用来获取请求信息的,而response对象是用来设置响应消息的

1.request对象

1.request继承体系结构


继承关系

ServletRequest(接口)
|| 继承
HttpServletRequest(接口)
|| 实现
RequestFacade(tomcat对象):我们实际使用的对象就是RequestFacade对象

  • RequestFacade对象在文档中没有,可以在tomcat的源码中找到,也就是说这是tomcat对HttpServlet接口进行的实现

2.request对象的功能

  • 1.获取请求行信息
    1,请求行信息包括:请求方式 请求url 请求协议和版本
    2,方法:
@WebServlet("/request_demo2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求头方法
        String method = req.getMethod();
        System.out.println("方法:"+method);
        //2.获取虚拟目录V
        String contextPath = req.getContextPath();
        System.out.println("虚拟路径:"+contextPath);
        //3.获取资源路径
        String servletPath = req.getServletPath();
        System.out.println("资源路径:"+servletPath);
        //4.获取get请求的请求参数
        String queryString = req.getQueryString();
        System.out.println("请求参数"+queryString);
        //5.获取请求参数url
        String requestURI = req.getRequestURI();
        StringBuffer requestURL = req.getRequestURL();
        System.out.println("url:"+requestURL);
        System.out.println("uri:"+requestURI);
        //6.获取协议和版本
        String protocol = req.getProtocol();
        System.out.println("协议和版本:"+protocol);
        //7.获取客户机的ip地址
        String remoteAddr = req.getRemoteAddr();
        System.out.println("客户机的ip地址"+remoteAddr);
    }

(!):URL和URI的区别:URI的范围更大
URL:统一资源定位符--http://localhost:8080/java_idea_request/request_demo2
中华人民共和国
URI :统一资源标识符--/java_idea_request/request_demo2
共和国

  • 2.获取请求头信息
  • 3.获取请求体信息

  • 2.获取请求头信息
    1,请求头信息 键值对的存在
    2,方法:两个方法比较重要
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取所有的请求头信息  Enumeration看做迭代器使用
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            //2.通过请求头名称获取请求头的值
            String header = request.getHeader(name);
            System.out.println(name+":"+header);
        }
    }
  • 案例:浏览器兼容和盗链问题还有统计数据的功能
    1,浏览器兼容的问题
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //案例一:浏览器兼容问题,就是要获取User-agent的值,判断他的包含那一种浏览器的名字
        String user_agent = request.getHeader("User-agent");
        if (user_agent!=null){
            if (user_agent.contains("Chrome")){
                System.out.println("谷歌浏览器");
            }
            else if (user_agent.contains("Firefox")){
                System.out.println("火狐浏览器");
            }
        }else {
            System.out.println("user_agent为空");
        }
    }

2,统计数据功能

public class RequestDemo5 extends HttpServlet {
    private  static   int a=0;
    private  static   int b=0;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //实现对百度和网易两个网站的进入的访问量统计
        //1.获取Referer信息,然后判断获取的Referer中的信息,判断是否在其中包含所需要的数据,进行叠加
        String referer = request.getHeader("Referer");
        if (referer!=null){
        if (referer.contains("baidu")){
           this.a++;
        }else if(referer.contains("wangyi")){
            this.b++;
        }
        System.out.println("百度访问:"+this.a+"次");
        System.out.println("网易访问:"+this.b+"次");
        }
    }

3,防盗链

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取Referer的值
        String referer = request.getHeader("referer");
        System.out.println(referer);
        //2.判断链接是否来自首页
        if (referer!=null){
            if (referer.contains("java_idea_request")){
                //正常播放
                System.out.println("正常播放");
            }else {
                //请在优酷首页播放
                System.out.println("请在优酷首页进入");
            }
        }
    }
  • 3.获取请求体信息
    请求体只有在Post请求方式,才会有请求体,在请求体中封装了post请求的请求参数
    获取步骤:
    1,获取流对象,字符流或者是字节流
    2,从流对象中获取数据
    方法:
public class RequsetDemo7 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取字符流对象:getReader();
        BufferedReader reader = request.getReader();//获取字符流,获取字符
        //2.获取字节流对象getInputStream();
        // ServletInputStream inputStream = request.getInputStream();//获取字节流,操作所有类型的文件
        String str = null;
        //2.获取流对象中的数据
       while((str=reader.readLine())!=null){
           System.out.println(str);
       }
    }
  • 3.request 对象的其余功能
    1,获取请求参数,通用方法(以前的方法获取的是一个字符串的形式,每一个键值对之间用&连接,而且在使用的时候还要分成get方式和post方式)
    方法
   //1. 通用方式获取请求参数
        String username = request.getParameter("name");
        String password = request.getParameter("password");
        System.out.println("username:"+username);
        System.out.println("password:"+password);
   //2.根据参数名获取参数数组
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("兴趣是");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
   //3.获取所有参数名
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String name = parameterNames.nextElement();
            String parameter_value = request.getParameter(name);
            System.out.println(name+":"+parameter_value);
        }
   //4.获取所有参数的集合
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<String> strings = parameterMap.keySet();
        for (String string : strings) {
            String[] values = parameterMap.get(string);
            System.out.println(string);
            for (String value : values) {
                System.out.println("    "+value);
            }
        }

在使用的过程中,会出现中文乱码的问题:


中文乱码问题
  • get方式:tomcat8已经将get方式的乱码问题解决了
  • post方式:会乱码,主要原因是底层使用流的方式获取数据
    解决方法:设置流的编码,在获取参数之前设置request的编码
    request.setCharacterEncoding("utf-8");
    我么在使用的时候,无论是使用get方式还是post的方式都需要设置编码
    效果:
    中文编码正常


  • 4.请求转发
    概念:一种在服务器内部资源跳转方式
    Aservlet
    ||两个内部资源之间的跳转方式
    Bservlet

1.步骤:

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Demo9的doGet方法调用成功");
        //1.获取转发器对象,并使用它进行转发,请求路径是在虚拟路径下的
        request.getRequestDispatcher("/requestDemo10").forward(request,response);
    }
控制台

浏览器地址栏没有发生变化

2,特点(面试题经常与重定向之间进行比较)
1.浏览器的地址栏没有发生变化
2.只能请求转发到当前服务器的内部资源中
3.转发是一次请求(调用了请求路径的service方法)


  • 5.共享数据:request域,只能在请求转发中实现,也就是说只能在服务器内部资源中使用
    域对象:一个有作用范围的对象,可以在范围内共享数据
    request域:代表一次请求的范围,一般用于请求转发的多个资源中,共享数据
    方法(因为在请求转发中,使用的都是当前请求的request对象,进行的请求转发,所以一般用于请求转发的多个资源中,共享数据)
//demo9
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Demo9的doGet方法调用成功");
        //1.存储数据
        request.setAttribute("name","xzw");
        //3.通过键值移除域中的数据
        request.removeAttribute("name");
        //1.获取转发器对象,并使用它进行转发,请求路径是在虚拟路径下的
        request.getRequestDispatcher("/requestDemo10").forward(request,response);
    }
//demo10
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("进入demo10......");
        //2.获取request域中的内容
        Object name = request.getAttribute("name");
        if (name!=null){
            System.out.println(name.toString());
        }else {
            System.out.println("对象为空,可能已经移除");
        }
    }
获取成功

移除键值对后

  • 6.获取servletcontext:
   //获取servletContext对象
        ServletContext servletContext = request.getServletContext();
        System.out.println("servletContext:"+servletContext);
//结果:
servletContext:org.apache.catalina.core.ApplicationContextFacade@5a1fec1b


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容