Servlet的request与response对象追踪

在这里插入图片描述

Servlet的request与response对象追踪

HttpServletRequest和HttpServletResponse是Servlet规范中规定的两个接口,HttpServlet中并没有实现这两个接口的成员变量,它们只是HttpServlet的service和doXXX等方法的参数

要是问传入到HttpServlet中的service和doXXX方法中的,实现了HttpServletRequest和HttpServletResponse接口的类的对象是从哪来的,那自然是某段代码中实例化来的。

那么实例化这两个对象的代码在哪呢?答案是在Servlet标准的实现者 - Servlet容器中

以使用BIO模型的Tomcat 7.0.72为例:

  • ThreadPool将待处理的Socket连接丢给SocketProcessor处理
  • SocketProcessor调用AbstractConnectionHandler的process方法
  • AbstractConnectionHandler确认应使用Http11Processor来处理此请求,于是实例化一个(或者拿一个现成的)Http11Processor,调用其process方法来处理请求
  • 在Http11Processor被实例化时,org.apache.coyote.Request和org.apache.coyote.Response对象同时被实例化:
    public AbstractProcessor(AbstractEndpoint<S> endpoint) {
        this.endpoint = endpoint;
        asyncStateMachine = new AsyncStateMachine<S>(this);
        request = new Request();
        response = new Response();
        response.setHook(this);
        request.setResponse(response);
    }

这里的Request和Response并没有实现Servlet标准中javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse接口

  • 接下来,request和response对象被交给CoyoteAdapter的service方法处理,CoyoteAdapter将这两个对象解析并转化为org.apache.catalina.connector.Request和org.apache.catalina.connector.Response:
    public void service(org.apache.coyote.Request req,
                        org.apache.coyote.Response res)
        throws Exception {

        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);

        if (request == null) {

            // Create objects
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);

            // Link objects
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            req.getParameters().setQueryStringEncoding
                (connector.getURIEncoding());

        }
        //...
    }
  • org.apache.catalina.connector.Request和org.apache.catalina.connector.Response这两个类则实现了Servlet标准的接口:
package org.apache.catalina.connector;

/**
 * Wrapper object for the Coyote request.
 *
 * @author Remy Maucherat
 * @author Craig R. McClanahan
 */
public class Request implements HttpServletRequest {
//...
}
  • 此时的Request和Response对象,就已经符合题主所描述的“Servlet中的request和response”了。接下来,在Tomcat中还要进行7层的invoke调用和3层的filter,最终终于到达了Servlet(这还是没有自定义Filter的情况)

杂记-复习笔记

Servlet
  • 概念 :server applet 运行在服务器端的小程序

  • Tomcat部署的方式

    war:压缩打包后部署,修改文件都会重启Tomcat

    war-exploded:热部署,将web工作文件原样部署到Tomcat,修改不需要重启

    常见的是热部署在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写虚拟目录是xml文件名

    在这里插入图片描述

    Servlet就是一个接口,定义了Java类被浏览器访问到tomcat识别的规定

    将来我们定义一个类,实现了Servlet接口,复写方法

老版本配置

​ *创建javaEE项目

​ *定义一个类实现Servlet接口

​ *实现接口中的抽象方法

​ *配置Servlet

web.xml
<-- servlet3.0出现注解配置 -->
<servlet>
   <servlet-name>自定义名字<servlet-name>
   <servlet-class>java的全类名<servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>自定义名字</servlet-name>
    <url-pattern>自定义servlet访问地址</url-pattern>
</servlet-mapping>

1.当服务器接受到客户端浏览器的请求后,会解析请求URl的路径,获取访问的Servlet的资源路径
2.查找web.xml文件,是否有对应的<url-pattern>标签体内容
3.如果有,则会找到对应的<servlet-class>全类名
4.tomcat
       
 webservlet的注解配置      
public @interface WebServlet {
    String name() default "";
    String[] value() default {};
    String[] urlPatterns() default {};//可以配置多个虚拟路径
    int loadOnStartup() default -1;
    WebInitParam[] initParams() default {};
    boolean asyncSupported() default false;
    String smallIcon() default "";
    String largeIcon() default "";
    String description() default "";
    String displayName() default "";
}
  • 生命周期方法

    实现Servlet接口:

    1.被创建:执行init方法,只会执行一次 🌵只会执行一次说明只有一个对象,容易出现线程安全的问题,尽量不要定义修改成员变量,🌵

    ​ servlet什么时候被创建:默认第一次被访问的时候被创建

    也可以配置执行Servlet的创建时机

    2.提供服务:执行service方法,每次访问执行

    3.被销毁执行destory方法

  • Servlet体系结构

    ||||||》对除了service之外的方法做了空实现

    GenericServlet----抽象类

    |||||》对http协议的一种封装,对请求方式等等一些判断简化

    HttpServlet --抽象类

    ps:当子类继承httpservlet时候没重写service时,调用会访问HttpServlet的service的方法,然后再根据请求方式分发调用对应的方法

    ​ 1.复写了doGet和doPost方法

    • ServletContext对象:

      概念:代表整个web应用,可以和程序的容器(服务器如tomcat)来通信,一个web应用只有一个

      获取:1.通过域对象(request,)获取

      作用:1.获取MIME类型

      ​ 🌰因为所有的规定的MiME都在tomcat里面存着的,所以与服务器通信可以知道指定文件该是哪种mime类型

      ​ 2.域对象,共享数据

      ​ 3.获取文件的真实(服务器)路径

      getRealPath()

      ​ 所有项目都是部署到服务器的,所以本地那个路径不是真实路径

HTTP协议
//常见的请求头:
user-Agent:浏览器告诉服务器,我访问你使用的浏览器的版本信息
Referer:地址  :当前请求来的地址
   1.可以防止别人链接到你网站的资源
   2.统计工作
//常见的响应头:
Content-Type:服务器告诉浏览器本次响应体的数据格式以及编码格式
Content-disposition:服务器告诉客户端以什么格式打开响应体数据
    *in-line:默认值,在当前页面
    *attachment;filename=xxx;以附加形式打开响应体,文件下载
   1.可以防止别人链接到你网站的资源
   2.统计工作   
request与response对象主要应用方法:
-----请求行
  获取请求方式
     //String getMethod()
  获取项目虚拟目录
    //String getContextPath()
  获取Servlet虚拟目录
    //String getServletPath()
  获取get方式请求体参数(get请求)
    //String getQueryString()
   获取请求URL和uri
   获取客户机的ip地址:
    //String getRemoteAddr()
-------请求头                --------响应头
    获取请求头                    设置响应头
    //String getHeader()        //setHeader()
--------请求体                --------------响应体
   1.获取流对象                    1.获取输出流           
   2.再从流对象中拿数据             2.使用输出流,将数据输出到客户端浏览器
`通用方法`
    //通过name获取请求参数值
    getParameter(name:参数名称) |多个值对一个参数键:getParameterValues
   //获取请求参数名称  
   getParameterNames()所有
    //获取请求参数Map集合
    getParameterMaps()
---------------------------------------------------------------
  request的请求转发
    getRequestDispatcher(string path)
    特点:1.浏览器地址不发生变化,只请求一次,只能转发到服务器内部资源
ps:post请求参数还是在流中获取,注意post乱码问题
   response重定向
    步骤1.设置状态码:response.setStatus(302);设置响应:response.setHeader("location","重定向路径")
    简化Api:response.sendRedirect("重定向路径")
    特点:1.重定向地址栏发生变化,是两次请求不能共享数据,可以访问其他站点的资源
    
---------------
    下载指定文件  ps:在maven里面会报错,原因是路径与正常部署是路径不同
    String filename = req.getParameter("filename");
        ServletContext servletContext = req.getServletContext();
        String mimeType = servletContext.getMimeType(filename);
        System.out.println(filename+""+mimeType);
        String realPath = servletContext.getRealPath("a.properties");
        resp.setHeader("content-type",mimeType);
        resp.setHeader("Content-disposition","attachment;filename=xxx");
        ServletOutputStream outputStream = resp.getOutputStream();
        FileInputStream fileInputStream = new FileInputStream(realPath);
        int a;
        while ((a = fileInputStream.read())!=-1){
            outputStream.write(a);
        }
        

String realPath = request.getServletContext().getRealPath("/");
        System.out.println(realPath);
        URL resource = Thread.currentThread().getContextClassLoader().getResource("");
        System.out.println(resource);
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("user.properties");
        System.out.println(resourceAsStream);

输出结果D:\a.java---!testJavaPlace\Maventest\src\main\webapp\
file:/D:/a.java---!testJavaPlace/Maventest/target/classes/
java.io.BufferedInputStream@55939162------模式maven的tomcat run
    
----------------------------------
输出结果D:\a.java---!testJavaPlace\Maventest\target\Maventest-1.0-SNAPSHOT\
file:/D:/a.java---!testJavaPlace/Maventest/target/Maventest-1.0-SNAPSHOT/WEB-INF/classes/
java.io.BufferedInputStream@2ca18815-----模式maven的tomcat run war

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值