Servlet的学习日常

Servlet的学习日常

1.Servlet设置编码问题

tomcat8之前,设置请求编码:

1.get请求方式:

//get方式目前不需要设置编码(基于tomcat8之前)
//如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前)
String fname = request.getParameter("fname");
//1.将字符串打散成字节数组
byte[] bytes = fname.getBytes("ISO-8859-1");
//2.将字节数组按照设定的编码重亲组装成字符串
fname = new String(bytes,"UTF-8");

2.post请求方式:

request.setCharacterEncoding("UTF-8");

tomcat8开始,设置编码,只需要针对post方式

request.setCharacterEncoding("UTF-8");

注意:需要注意的是,设置编码(post)这一句代码必须在所有获取参数动作之前

request.setCharacterEncoding("UTF-8");//之前
String fname = request.getParameter("fname");
String remark = request.getParameter("remark");

2.Servlet的继承关系

1.继承关系:HttpServlet -> GenericServlet -> Servlet接口

2.Servlet中的核心方法: init() , service() , destroy()

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

3.Servlet的生命周期

1.生命周期:从出生到死亡的过程叫做生命周期。对应的Servlet中的 init() , service() , destroy()

2.默认情况下Servlet的生命周期:
第一次接受请求时,这个Servlet会进行实例化(调用构造方法),初始化(调用init()方法),然后调用服务(调用service()方法)

从第二次请求开始,每一次请求都是服务(调用service()方法)
当容器关闭(idea 结束tomcat服务)时,其中的所有servlet实例才会被销毁,调用销毁方法(调用destroy()方法)

3.通过案例我们发现:

  • tomcat只会创建一个Servlet实例,所有请求都是这个实例去响应。
  • 默认情况下,第一次请求时,tomcat才会去实例化,初始化,然后再服务。好处是提高系统的启动速度。缺点是第一次请求时,耗时较长。
  • 因此得出结论:如果需要提高系统的启动速度。当前默认的情况就是这样。如果需要提高响应速度,我们应该设置初始化时机
  • servlet在容器中是单例的,是线程不安全的。
  • 因为servlet是线程不安全的,给我们的启发是:尽量不要在servlet中定义成员变量。如果不得不定义成员变量。
  • 1.不要去修改成员变量的值
  • 2.不要根据成员变量的值做一些逻辑判断。

servlet线程不安全解释:一个线程需要根据这个实例中的某个成员变量去做逻辑判断。但是在中间的某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化。
因为是单例模式,多线程时都会进入service()方法,此时如果存在成员变量,多线程进行抢占。
如图:线程2在线程1进入if判断之前对变量进行赋值操作,则会改变线程1的路线。
在这里插入图片描述

4.Servlet的初始化时机

  • 默认是第一次接收请求时,实例化,初始化
  • 我们可以通过来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值0
<servlet>
        <servlet-name>Demo02Servlet</servlet-name>
        <servlet-class>com.Demo02Servlet</servlet-class>
        <!-- 启动时机参数:数字越小启动的时间越靠前-->
        <load-on-startup>1</load-on-startup>
</servlet>

在这里插入图片描述

4.Http协议

https://heavy_code_industry.gitee.io/code_heavy_industry/pro001-javaweb/lecture/chapter06/

1.Http 称之为 超文本传输协议

2.Http是无状态的

3.Http请求响应包含两个部分:请求和响应
请求:
请求包含三个部分:1.请求行 ;2.请求消息头 ;3.请求主体
1.请求行包含三个信息:1.请求的方式;2.请求的URL;3.请求的协议(一般都是HTTP1.1)
2.请求消息头中包含了很多客户端需要服务器的信息。比如:我的浏览器型号、版本、我能接收的内容的类型、发送的类型,长度等等
3.请求体,分为三种情况
get方式,没有请求体,但是有一个queryString
post方式,有请求体,form data
json方式,有请求体,request payload

响应:
响应也包含三个部分:1.响应行;2.响应行;3.响应体
1.响应行包含三个信息:1.协议 2.响应状态码(200) 3.响应状态(ok)
2.响应头:包含了服务器信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容的长度等)
3.响应体:响应的实际内容(比如请求的add.html页面时,响应的内容就是…)

5.会话

1.Http是无状态的

  • HTTP无状态:服务器无法判断这两次请求时同一个客户端发过来的,还是不同的客户端发过来的

  • 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱。

  • 通过会话跟踪技术解决这个问题。

    在这里插入图片描述

2.会话跟踪技术

  • 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端

  • 下次客户端给服务器端发送请求时,会把session 带给服务器,那么服务器就能获取到了,那么服务器就判断这次请求和上次某次请求是同一个客户端,从而能够区分开客户端。

  • 常用的API:

    request.getSession() -> 获取当前的会话,没有则创建新的
    request.getSession(true) -> 效果和没有参数的相同
    request.getSession(false) -> 获取当前的会话,没有则返回null,不会创建新的

    session.getId() ->获取sessionID
    session.isNew() -> 判断当前session是否是新的
    session.getMaxInactiveInterval() -> session的非激活间隔时长 默认1800秒
    session.invalidate() ->让回话强制失效

3.Session保存作用域

  • session保存作用域是个具体的某一个session对应的
  • 常用的API:
    void session.setAttribute(k,v);
    Object session.getAttribute(k);
    void removeAttribute(k);

下面那个请求来自不同浏览器session是不同的 所以拿不到uname的值在这里插入图片描述

6.服务器内部转发以及客户端重定向

1.服务器内部转发:request.getRequestDispatcher(“…”).forward(request,response);
一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
地址栏没有变化

在这里插入图片描述

2.客户端重定向:response.sendRedirect(“…”)
两次请求响应的过程。客户端肯定知道URL的变化
地址栏有变化

在这里插入图片描述

7.Thymeleaf 视图模板技术

1.添加thymeleaf的jar包

2.新建一个Servlet类viewBaseServlet(源代码考出来的)

3.在web.xml文件中添加配置

    <!-- 在上下文参数中配置视图前缀和视图后缀 -->
    <context-param>
        <param-name>view-prefix</param-name>
        <param-value>/</param-value>
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>

4.使得我们的Servlet继承ViewBaseServlet

5.根据逻辑视图名称 得到 物理视图名称

//此处的视图名称是index
//那么thymeleaf会将这个 逻辑视图名称 对应到物理视图名称上去
//逻辑视图名称 : index
//物理视图名称: view-prefix + 逻辑视图名称 + view-suffix
//所以真实的视图名称是:/         index         .html
super.processTemplate("index",request,response);

6.使用thymeleaf的标签
th:if , th:unless , th:each , th:text

8.保存作用域

1.保存作用域
原始情况下,保存作用域我们可以认为有四个:page(页面级别,现在基本不用) , request(一次请求响应级别) , session(一次会话范围) , application(一次应用程序范围)

request作用域 现象:第一个过程请求不到因为不同请求,第二个过程可以是因为同一个请求。
在这里插入图片描述

session作用域 现象:因为客户端不同产生的session也不同,所以第二次是null

在这里插入图片描述

application作用域 现象除非tomcat停止否则都可以请求到

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值