专栏首页阿杜的世界Servlet请求和响应

Servlet请求和响应

在Java Web中Servlet、请求和响应是最基本的三个对象,在Web容器的管理下,这三者能够完成基本的HTTP请求处理。

Servlet的作用是为客户提供服务。servlet的角色是接受一个客户的请求,再返回一个响应。请求可能非常简单,例如:给我提供一个欢迎页面;也可能非常复杂,例如:为当前的购物车结账,这个请求会带一些客户端传来的参数,servlet需要知道自己如何使用请求中的参数,还需要知道该返回什么样的响应。

一、Servlet

1. Servlet受容器管理

Java Web服务器处理用户请求的基本过程:用户在客户端点击一个链接,浏览器会向Web应用服务器发送一个URL请求,该URL会指向一个servlet;Web容器看出这个请求指向某个servlet A,就会创建两个对象(HttpServletRequest和HttpServletResponse),并分配或创建一个线程,调用servlet A对应的service方法(上述请求和响应对象作为参数);service根据HTTP请求区分出客户端发来的是GET还是POST请求,并调用对应的doGet()或doPost()方法;在doGet()或doPost()方法中进行业务逻辑的处理,处理完成后的结果通过响应对象返回写回给客户端。

2. Servlet的生命周期

在容器启动时,XXXServlet在JVM的管理下被实例化为一个对象,这时候它还不是servlet,需要在容器的管理下调用init()方法进行初始化,获得ServletConfig和ServletContext对象的引用后,才称为一个真正的Servlet。

Servlet的一生.png

  1. init()
  • 何时调用?servlet实例创建后,并在servlet能为客户请求提供服务之前,容器需要通过init方法初始化servlet。
  • 作用?初始化servlet实例,使之获得web容器的相关信息
  • 是否会被覆盖?有可能
  1. service()
  • 何时调用?当一个客户请求到来时,容器会创建(或从线程池分配一个线程),并调用servlet的service方法
  • 作用?这个方法会确定HTTP方法(GET or POST),并调用对应的servlet方法——doGet或doPost;
  • 是否会被覆盖?可以,但是不会
  1. doGet()或doPost()
  • 何时调用?
  • 作用?具体的业务逻辑
  • 是否会被覆盖?至少要覆盖其中之一

关键点:每个请求都在一个单独的线程中运行!

3. Servlet的继承体系

  • servlet接口:javax.servlet.Servlet,表示所有的Servlet都有这5个方法,其中init、service和destroy三个方法和servlet的生命周期有关
  • GenericServlet:javax.servlet.GenericServlet,这是一个抽象类,它实现了开发者需要的大部分基本servlet方法,大多数servlet的“servlet行为”都来自这个类;
  • HttpServlet:javax.servlet.http.HttpServlet,这也是一个抽象类,它实现了自己的service()方法,处理servlet的HTTP特性(service方法不仅仅只处理HTTP请求)。
  • MyTestServlet:这是开发者自己编写的处理类,一般只需要实现doGet()和doPost()方法。

servlet的继承体系.png

二、请求和响应

1. ServletRequest的继承体系

HttpServletRequest的API与HTTP有关,例如:Cookie、首部(Header)和会话(Session)等;

HttpServletRequest的继承体系.png

2. ServletResponse的继承体系

ServletResponse(响应)也是类似,用于帮助servlet给客户端返回处理结果,而HttpServletResponse增加了HTTP相关的内容(例如:错误、cookie和首部)等API。

HttpServletResponse的继承体系.png

HttpServletRequest和HttpServletResponse这些都是servlet规范里指定的接口,而web容器开发商(例如tomcat)会负责实现这些接口,例如:HttpServletResponseWrapper和ApplicationHttpResponse等,作为开发者,我们只需要知道,在处理doGet()和doPost方法时,容器会给这个方法传HttpServletRequest和HttpServletResponse两个参数。

3. GET和POST的区别

  • POST方法有请求体
  • GET方法的查询参数直接跟在URL后面,不够安全;
  • GET请求可以建立书签,POST请求则不能
  • GET请求是幂等的,POST请求不是(GET请求仅仅用于查询一些数据,POST请求则用于在服务器上更新数据),在业务上会遇到既需要POST请求,又需要保证请求幂等的情况(例如库存扣减),这种情况需要我们出具对应的实现方案。参见:

4. HTTP请求的API

  • getHeader(),可以获取首部信息,例如request.getHeader("User-Agent")可以获取客户端的平台和浏览器信息。
  • getIntHeader(),如果首部信息中的“key/value”对中的value是int类型的,可以使用这个方法直接获取值而不需要显式类型转换
  • getCookies(),可以获取与请求相关的cookie
  • getSession(),可以获取与请求相关的会话
  • getMethod(),可以获取http方法
  • getInputStream(),可以获取请求的输入流
  • getParameter(String name),可以获取HTTP请求的请求参数,对于GET请求,可以获取查询字符串中的数据、对于POST请求,可以获取请求体中的数据
  • getRemotePort(),获取客户端的端口号
  • getServerPort(),获取服务端接受请求的端口号(请求一开始发送服务端的哪个端口?)
  • getLocalPort(),获取服务端处理请求的端口号(请求最后是发送到服务端的哪个端口?)

5. HTTP响应的API

大多数情况下,使用响应只是为了向客户发回数据。会对响应调用两个方法:setContentType()和getWriter()。在此之后,可以将HTML或其他内容写入到流。不过,你也可以使用响应设置首部、发送错误或增加Cookie。

  • setContentType(),设置响应返回的MIME类型
  • getOutputStream(),获取HTTP输出字节流
  • getWriter(),获取HTTP输出字符流
  • addCookie(Cookie cookie),给响应首部中增加cookie对象,注意这里不是增加“key/value”对
  • addHeader(),在响应首部中添加一个“key/value”对
  • setHeader(),在响应首部中设置一个“key/value”对;和addHeader()的区别是,如果响应首部中已经有对应的key存在,setHeader()会覆盖现有的值,而addHeder()会新增一个“key/value”对,使用时需要注意
  • encodeRedirectURL(),对包含session ID的URL进行编码。使用场景:在浏览器不支持使用cookie跟踪会话时,可以使用URL重写(即将URL重定向到另一个URL,而这个URL的后面会带上session id传给客户端,这个URL在返回给客户端之前需要经过编码)
    /**
     * Encodes the specified URL for use in the <code>sendRedirect</code> method
     * or, if encoding is not needed, returns the URL unchanged. The
     * implementation of this method includes the logic to determine whether the
     * session ID needs to be encoded in the URL. Because the rules for making
     * this determination can differ from those used to decide whether to encode
     * a normal link, this method is separated from the <code>encodeURL</code>
     * method.
     * <p>
     * All URLs sent to the <code>HttpServletResponse.sendRedirect</code> method
     * should be run through this method. Otherwise, URL rewriting cannot be
     * used with browsers which do not support cookies.
     *
     * @param url
     *            the url to be encoded.
     * @return the encoded URL if encoding is needed; the unchanged URL
     *         otherwise.
     * @see #sendRedirect
     * @see #encodeUrl
     */
    public String encodeRedirectURL(String url);
  • sendError(),给客户端返回错误的响应(错误码、错误信息),在该方法被调用之后,就意味着响应已经被返回给客户端,也就不能再调用response的任何方法,否则会报IllegalStateException。
    /**
     * Sends an error response to the client using the specified status code and
     * clears the output buffer. The server defaults to creating the response to
     * look like an HTML-formatted server error page containing the specified
     * message, setting the content type to "text/html", leaving cookies and
     * other headers unmodified. If an error-page declaration has been made for
     * the web application corresponding to the status code passed in, it will
     * be served back in preference to the suggested msg parameter.
     * <p>
     * If the response has already been committed, this method throws an
     * IllegalStateException. After using this method, the response should be
     * considered to be committed and should not be written to.
     *
     * @param sc
     *            the error status code
     * @param msg
     *            the descriptive message
     * @exception IOException
     *                If an input or output exception occurs
     * @exception IllegalStateException
     *                If the response was committed
     */
    public void sendError(int sc, String msg) throws IOException;
  • setStatus(),设置响应的状态码
  • sendRedirect(),用于URL重定向,告诉客户端去访问另一个URL来完成需求,如果location没有以“/”开头,则它是相对路径,容器会负责将这个相对路径转化成该web应用的绝对路径;否则容器会把它当做绝对路径处理。
    /**
     * Sends a temporary redirect response to the client using the specified
     * redirect location URL. This method can accept relative URLs; the servlet
     * container must convert the relative URL to an absolute URL before sending
     * the response to the client. If the location is relative without a leading
     * '/' the container interprets it as relative to the current request URI.
     * If the location is relative with a leading '/' the container interprets
     * it as relative to the servlet container root.
     * <p>
     * If the response has already been committed, this method throws an
     * IllegalStateException. After using this method, the response should be
     * considered to be committed and should not be written to.
     *
     * @param location
     *            the redirect location URL
     * @exception IOException
     *                If an input or output exception occurs
     * @exception IllegalStateException
     *                If the response was committed or if a partial URL is given
     *                and cannot be converted into a valid URL
     */
    public void sendRedirect(String location) throws IOException;

6. 重定向和请求派发

  • 重定向是让浏览器访问新的URL完成工作,用户会在浏览器地址栏看到新的URL;
  • 请求派发是服务端的工作,是当前servlet委托另外的servlet完成请求,并给客户端发回响应,用户的浏览器地址栏的URL没有改变;

三、总结

  1. 理解servlet的生命周期
  2. 理解servlet处理客户请求的线程模型
  3. 理解servlet的继承体系
  4. 理解servlertRequest的继承体系
  5. 理解servlertResponse的继承体系
  6. 熟悉servlet可以从HTTP请求获取哪些内容,在实际应用中有什么作用
  7. 熟悉servlert可以使用HTTP响应给客户端返回什么内容,在实际应用中的场景
  8. 理解重定向和请求派发的区别

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java 8原生API也可以开发响应式代码?

    asphalt-automobile-automotive-1172105.jpg

    阿杜
  • Web前端学习(打卡机)

    在补齐了Java后端的短板之后,我准备补补前端的课。这篇文章可以作为我前端学习的过程记录(打开机)。

    阿杜
  • 会话管理

    Http协议是无状态协议,Web服务器没有短期记忆。在有些应用场景(例如:购物车)下,需要跨越多个请求识别同一个客户——客户跟踪,在Web应用中使用Cookie...

    阿杜
  • AI做不了“真”3D图像?试试Google的新生成模型

    近日,在 NeurIPS 2018 会议上接收的论文“ 视觉对象网络:图像生成与分离式的3D表示”中,麻省理工学院计算机科学与人工智能实验室(MIT CSAIL...

    AI科技大本营
  • 首个中国高校AI人才培养计划启动,Hinton、Hopcroft和李开复开班授课

    图灵奖得主John E. Hopcroft、深度学习的开创大神Jeffery Hinton,以及创新工场董事长李开复,将亲自担任首期培养计划第一次课程授课嘉宾。...

    量子位
  • 全球最大成人网站 PornHub 也用上了AI,目的是让用户更 Happy

    AI科技大本营的读者们,相信你们已经身经百战,什么刷脸打卡、识别罪犯等等,计算机视觉的各种用途对你们来说都不足为奇。 不过,这些往往都是非常正经的,请不要让它们...

    AI科技大本营
  • Tomcat初步

     启动Tomcat是通过双击bin/startup.bat,测试是否启动成功,主要是通过访问localhost:8080,如果后期有需要修改访问的端口,可以通过...

    mathor
  • JS笔记(一):基础知识

    free赖权华
  • torch.nn.init

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    于小勇
  • 快速去阴影--Fast Shadow Detection from a Single Image Using a Patched Convolutional Neural Network

    Fast Shadow Detection from a Single Image Using a Patched Convolutional Neural N...

    用户1148525

扫码关注云+社区

领取腾讯云代金券