Servlet 基础知识1

47 阅读6分钟

1. 设置编码

1) doGet请求方式:
    get方式目前不需要设置编码(基于tomcat8)
    tomcat8 之前 , 设置编码:
    如果是get请求发送的中文数据 , 转码稍微有点麻烦
    
String name = req.getParameter("name");
byte[] bytes = name.getBytes(); // 将参数打散 
String s = new String(bytes, "UTF-8"); // 重新设置编码方式即可
//这样存入数据库的就不是乱码
2)doPost请求方式
    // 使用这种方式设置编码 , 防止中文乱码
    req.setCharacterEncoding("UTF-8");
    /* 但是注意一定要在获取参数之前的使用这个方法 , 因为服务器是第一次获取参数的时候解析所有参
    数,如果你没有在第一次获取参数之前就设置字符编码 , 那么这个方法是无效的.
    但是这种方法只是在post方法里面使用才有效 , doGet无效!!!
    */   
     

2. Servlet的继承关系

1) 继承关系

 javax.servlet.Servlet 接口
     javax.servlet.GenericServlet  抽象类
         javax.servlet.Http.HttpServlet   实现子类

2) 相关方法

javax.servlet.Servlet 接口

    void init(config)    - 初始化方法
    void service(request , response)    - 服务方法
    void destory     - 销毁方法
    service 方法  , 当客户端发送请求了 , 那么就会自动调用我们的service 方法 .

javax.servlet.GenericServlet 抽象类

    public abstract void service 还是一个抽象方法

javax.servlet.Http.HttpServlet 实现子类

     protected void service(request  , response )  实现方法
     

image.png

大概就是这样的 , 他就看的是你的请求方式 , 然后去调对应的方法 , 是post 那么就去调对应的dopsot方法。

我们进去看这个dopost方法

image.png

这个是javax.servlet.Http.HttpServlet类中的dopsot 方法 , 我们可以看到其实大概就是一个报错信息.其实这就是我们的405的报错的原因。因为我们发送请求的方式是get(method不写默认是get) ,但是你在Servlet里面又没有重写doget方法 , 重写的是dopost方法. 因为子类找不到 , 所以根据继承关系会去对应父类找 , 所以那么就调用javax.servlet.Http.HttpServlet 里面的doget 方法了 , 然后就抛出异常信息了405了。

小结:

  1. 继承关系:HttpServlet -> GenericServlet -> Serivce

  2. Servlet 中的核心方法: init() , service() , destroy() , 我们的service方法其实 是tomcat容器调用的。

  3. 服务方法: 当有请求过来时 , service 方法会自动响应(其实是tomcat容器调用的) 在HttpServlet 中我们会去分析请求的方式:到底是get 、post 、head 还是 delete等等 然后再决定调用的是哪个do开头的方法 那么在HttpServlet中这些do方法默认都是405的实现风格--要我们子类去实现对应 方法 , 否则就会报405.

  4. 因此 , 我们在新建Servlet时 , 我们才会去考虑请求方法 , 从而决定重写哪个do方法

Servlet 的生命周期

   1) 生命周期:从出生到死亡的过程 , 对应的Servlet中的三个方法.init() , service() , 
      destroy()

   2) 默认情况下:第一次接收请求时 , 这个Servlet会进行实例化(调用构造方法) 、初始(init())、
   然后服务(service())、关闭容器(执行destroy()).
   从第二次开始 , 每一次都是服务.
   当容器关闭时 , 其中的所有的Servlet方法实例会被销毁、调用销毁方法
   实例化 , 是tomcat 利用反射做的实例化.

   3) 通过调用相关的方法发现:
          单例 , 线程不安全....
          Servlet 实例tomcat只会创建一个 , 所有的请求都是一个实例去响应的.
          默认情况下 , 第一次请求时 , tomcat 才会去实例化 , 初始化 , 然后再去服务.
          好处: 提高系统启动速度
          缺点: 第一次响应的速度比较慢 , 响应时间比较长 .
          默认情况下 , 如果需要提高系统的启动速度 , 当前的默认情况就是这样.第一次请求再创建
          Servlet实例.
    4) Servlet 的初始化时机
            默认是第一次接收请求时, 实例化 , 初始化
            但是为了提高第一次接收请求响应的速度 , 我们可以设置它的响应时机.在启动的系统的时
            就去加载对应的类.
            我们可以通过设置 <load-on-startup> 设置先后顺序 , 最靠前的是 0</load-on-startup>
    5) Servlet 类 在容器中是单例的 , 线程不安全的. 正是因为是单例的 , 所以我们访问的变量,方
     法是同一个 , 就可能出现不同线程 , 做同一个条件判断的时候会出现不同的结果.导致程序异常,这
     种线程问题 . 在Java的多线程中讲的更加详细 , 比较经典的有售票问题……。
     最好不要去定义一些成员变量 , 导致成员变量值被修改后出现一些程序异常!不可避免一定要定义,
     请尽量不要拿去做条件判断 !            

  你访问那个页面 , 是向服务器发送请求 , 然后让服务器做出相应的反应. 比如把你需要的那个界面响
  应给你.

HTTP协议

  1、介绍
      HTTP: HyperText Transfer Protocol  超文本传输协议 , HTTP最大的作用就是确定了请求和
      响应数据的格式.浏览器发送给服务器的数据:请求报文; 服务器返回给浏览器的数据;响应报文
   2、请求报文
      1) Http 称为超文本传输协议
      2) Http 是无状态的
      3) Http 请求响应包含两个部分:请求和响应   
         请求:
           请求包含三个部分   
               1. 请求行
               2. 请求(消息)头
               3. 请求主体
           1) 请求行是三个信息:  1.请求的方式  2. 请求的URL  3. 请求的主体
           2)  请求的消息头中包含了很多客户端需要告诉服务器的的信息 ,  比如浏览器型号、版本、
               能接收请求的类型.
           3) 请求体 , 三种情况
                get方式 , 没有请求体 , 但是有一个queryString
                post方式 , 有请求体 , form data
                json 格式 , 有请求体 , request payload
   3、响应
       响应包含三个信息: 1. 响应行 2. 响应头 3.响应体
           1) 响应行包含三个信息: 1.协议 2. 响应状态码(200 , 404 , 405 , 500) 3. 响应状态
           2) 响应消息头:  响应的实际内容(比如请求页面时, 响应的是一个表单)

会话

1) Http 是无状态的
    - Http 无状态:服务器无法判断这两次请求是同一个客户端发过来的 , 还是不同的客户端发过来的
    - 无状态带来的现实问题: 第一次请求时添加商品到购物车 , 第二次请求是结账; 如果这两次请求服务
        器无法区分是同一个用户的 , 那么就会导致混乱.
    - 通过会话跟踪技术来解决无状态的问题.
 
 2)  会话跟踪技术
     - 客户端第一次发送请求给服务器 , 服务器获取session , 获取不到 ,则创建新的 , 然后响应给客户
       端
      - 下次客户端给服务器发请求时,会把session 带个服务器 , 那么服务器就获取到这个客户端的
      session Id , 这样服务器就能分辨不同的请求的客户端了.
    

相关Session 的 API

req.getSession(false);  
req.getSession(true);  
session.getId() -> 获取sessionID  
session.isNew -> 获取session 是否是新的  
session.getMaxInactiveInterval() -> session 的非激活时间最大间隔时长 默认1800秒 , 客
户端一直没有操作  
session.setMaxInactiveInterval() -> session 设置非激活时间最大间隔时长 

image.png

image.png

image.png

image.png