0%

JavaWeb之Servlet

记录在JavaWeb开发中学习的Servlet相关知识!💯💤

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

🕶Servlet是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

Servlet在Web中结构

配置Servlet

1. 在web.xml中配置

<!--配置Servlet -->
<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>cn.sucre.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet</url-pattern> 虚拟路径,用于浏览器中访问
</servlet-mapping>

⭐️2. Servlet3.0支持注解配置。

在类上使用@WebServlet注解,进行配置:@WebServlet({"资源路径"})

3. 执行原理

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

  2. 查找web.xml文件,查找对应的<url-pattern> 内容,与资源路径匹配。

  3. 如果匹配成功,则获取对应的<servlet-class>的类名。

  4. 服务器端tomcat通过类名反射class.forName()将字节码文件加载进内存,并使用class.newInstance()创建Servlet对象。

  5. 执行该Servlet子类中的方法实现业务功能,如service()。

Servlet的生命周期:

  1. 默认情况下,第一次被访问时,执行init()方法,Servlet被创建,该方法只执行一次。
    • Servlet的init()方法只执行一次,说明Servlet在内存中只存在一个对象,即Servlet是单例的,当多个用户同时访问时,可能存在线程安全问题。
      • 解决:尽量不要在Servlet类中定义成员变量。即使定义了成员变量,也不要对修改值,可以在函数中定义局部变量。
  2. Servlet通过调用destroy()方法终止,一般用于释放资源,只执行一次。Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

Servlet-GenericServlet-HttpServlet

  • 体系结构
    Servlet – 接口
    |
    GenericServlet – 抽象类
    |
    HttpServlet – 抽象类

  • GenericServlet:实现了 Servlet 接口,并且对其中的 init() 和 destroy() 和 service() 提供了默认实现。如果继承这个类的话,必须重写 service() 方法来对处理请求。

  • HttpServlet:进一步继承并封装了 GenericServlet,使得使用更加简单方便,使用 HttpServletRequest 和 HttpServletResponse扩展了 Http 的内容,这两个类分别是 ServletRequest 和 ServletResponse 的子类。HttpServlet 中对原始的 Servlet 中的方法都进行了默认的操作,不需要显式的销毁初始化以及 service(),在 HttpServlet 中,自定义了一个新的 service() 方法,其中通过 getMethod() 方法判断请求的类型,从而调用 doGet() 或者 doPost() 处理 get,post 请求。使用该类时只要继承 HttpServlet,然后重写 doPost() 或者 doGet() 方法处理请求即可。

浏览器的请求消息格式-Request对象

1. 请求消息格式

  • 浏览器请求网页时将向服务器发送请求消息,消息格式包括:

    1. 请求行: 请求方式 请求url 请求协议/版本 如: GET /login.html HTTP/1.1

    2. 请求头:包含浏览器告诉服务器的相关信息,常用的有User-Agent和Referer

    3. 请求空行:用于POST方法中隔离请求头和请求体,GET方法中不存在请求体

    4. 请求体:用于POST请求中封装请求消息的请求参数

    5. 示例:

      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	//请求体
      

2. HttpServletRequest对象:用来获取请求消息

  1. 获取请求行数据:

    浏览器输入:http://localhost:8080/MyProject/sucre/main/MyRequest

  2. 获取请求体数据

    • getHeader(String name):通过请求头的名称获取对应的值
  3. 获取请求体数据
    只有POST方式有请求体,在POST的方式中将请求体封装成流对象。首先要获取流对象,其次从流对象中获取数据

    • getReader():获取字符输入流,只能操作字符数据
    • getInputStream():获取字节输入流,可以操作所有类型数据
  4. 通用获取参数,不论GET和POST都可用

    • String getParameter(String name):根据参数名称获取参数值
    • String[] getParameterValues(String name):根据参数名称获取参数值的数组
    • Enumeration<String> getParameterNames():获取所有请求的参数名称
    • Map<String,String[]> getParameterMap():获取所有参数的map集合

服务器的响应消息格式-Response对象

1. 响应消息格式

  • 服务器向客户端浏览器发送响应消息,消息格式主要包括:

    1. 响应行: 协议/版本 响应状态码 状态码描述

      • ⭐️状态码:
        1. 1xx:服务器接受了客户端消息,但没有接受完成,等待一段时间后,发送该类状态码。
        2. 2xx:成功。代表:200。
        3. 3xx:重定向。代表:302(重定向),304(访问缓存)。
        4. 4xx:客户端错误。404(请求路径没有对应的资源), 405:请求方式没有对应的doXxx方法。
        5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
    2. 响应头:

      • 格式:头名称: 值

      • 常见的响应头:Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式

    3. 响应空行

    4. 响应体:传输的数据

2. HttpServletResponse对象:用来设置响应消息

  1. 设置响应行的状态码: setStatus(int sc)

  2. 设置响应头数据:setHeader(String name, String value)

  3. 设置响应体:

    • 步骤:
      1. 获取输出流
      + 设置编码防止中文乱码:response.setContentType("text/html;charset=utf-8");
      + 字符输出流:PrintWriter getWriter()
      + 字节输出流:ServletOutputStream getOutputStream()
      2. 使用输出流将数据输出到浏览器

ServletContext对象

  • 代表整个web应用,可以和程序的容器(服务器)来通信
  1. 使用request.getServletContext()或者this.getServletContext();获取该对象
  2. 功能:
    1. 获取MIME类型:String getMimeType(String file)
    2. 域对象:共享数据 setAttribute(String name,Object value),getAttribute(String name),removeAttribute(String name)
    3. 获取文件的真实(服务器)路径:String getRealPath(String path)

⭐️会话技术

☁️一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。会话跟踪技术是Web程序中用于跟踪用户整个会话的技术。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接,这就意味着服务器无法从连接上跟踪会话。因此引入CookieSession。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

📰Cookie

识别返回用户包括三个步骤:

  • 服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。
  • 浏览器将这些信息存储在本地计算机上,以备将来使用。
  • 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。
  1. 实现原理:基于响应头中的set-cookie字段以及请求头中的cookie字段实现。
    • set-cookie字段信息例如:
      Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; path=/; domain=sucre.com
      其中,expires 字段是一个指令,告诉浏览器在给定的时间和日期之后"忘记"该 Cookie;
    • 对应请求头中的cookie字段为:Cookie: name=xyz等
  2. cookie的使用
    • 在服务器端创建Cookie对象 new Cookie(String name, String value)
    • 在服务器端设置生存周期 cookie.setMaxAge(60*60*24);
    • 在服务器端通过response发送Cookie response.addCookie(Cookie cookie)
    • 在客户端获取Cookie Cookie[] request.getCookies()
  3. 在默认情况下,浏览器关闭后,Cookie将会销毁,使用setMaxAge(int second)可以设置Cookie保存时间。
    • second为正数,表示Cookie存储在本地硬盘中的时间;
    • second为负数为默认情况;
    • second为0表示删除Cookie信息。
  4. setPath(String path)用于设置Cookie的获取范围。
    • 默认情况下,设置为当前的虚拟目录;
    • 如果要共享,则可以将path设置为"/",表示根目录下所有项目共享该Cookie。
  5. setDomain(String path)如果设置一级域名相同,那么多个服务器之间Cookie可以共享。
    • 例如,setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中Cookie可以共享。
  6. Cookie的作用和特点
    • Cookie存储数据在客户端浏览器。
    • 浏览器对于单个Cookie的大小有限制(4kb)以及对同一个域名下的总cookie数量也有限制(20个)。
    • Cookie一般用于存储少量的不太敏感的数据。
    • 在不登录的情况下,Cookie用于完成服务器对客户端的身份识别。

📃Session

  1. Session在一次会话的多次请求间共享数据

  2. 实现依赖于Cookie

    • 在第一次访问服务器时,服务器内存中没有Session对象,创建该Session对象。
    • 向客户端发送相应数据时,set-cookie字段中包含JSESSIONID,即为服务器内存中该Session对象的id。
    • 客户端将Cookie信息存储到浏览器内部,下次访问服务器时,Cookie中将包含该JSESSIONID 值,保证了多次请求中共享相同的Session对象。
  3. 客户端浏览器关闭后,服务器不关闭,则会话已经结束,再次打开浏览器后两次获取的Session将不相同。

    • 可以创建Cookie,设置键JSESSIONID的存活时间(setMaxAge),使其持久化就可保证两次相同。
  4. Session的销毁

    • 服务器关闭
    • Session对象调用invalidate()
    • 默认失效时间为 30分钟,在tomcat设置中可以配置
  5. ⭐️如果客户端禁用了Cookie,通常有两种方法实现session而不依赖cookie。

    • URL重写。就是把sessionId直接附加在URL路径的后面。

    • 表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。

  6. ⭐️session与Cookie区别

  • session存储在服务器端,cookie存储在客户端。
    • session没有数据大小限制,cookie有限制,单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
    • session相对安全,cookie相对不安全,可以分析存放在本地的COOKIE并进行COOKIE欺骗。
    • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用cookie。
    • 生存周期不同。,session是IE启动到IE关闭,浏览器页面一关 ,Session就消失。Cookie是预先设置的生存周期,或永久的保存于本地的文件。

💊常见问题

  1. 重定向方式

    1. response.setStatus(302);
      response.setHeader("location", url);
    2. response.sendRedirect("url");
  2. ⭐️重定向redirect与转发forward的比较

  3. 重定向的特点:redirect

    • 地址栏发生变化
    • 重定向可以访问其他站点(服务器)的资源
    • 重定向是两次请求。不能使用request对象来共享数据
  4. 转发的特点:forward

    • 转发地址栏路径不变,问当前服务器下的资源
    • 转发是一次请求,可以使用request对象来共享数据
  5. 关于路径是否要加虚拟目录
    规则:

  • 给客户端浏览器使用:需要加虚拟目录 /
    • 给服务器使用:不需要加虚拟目录,如转发路径
  1. 建议使用request.getContextPath()动态获取虚拟目录
-------------------本文结束 感谢您的阅读-------------------

本文标题:JavaWeb之Servlet

文章作者:Sucre

发布时间:2020年07月31日 - 15:48:48

最后更新:2020年07月31日 - 16:08:11

原始链接:https://tangtangsama.github.io/article/959a4921.html/

非商业性使用-转载请保留原文链接及作者。

感谢您的支持和鼓励!