Tomcat:由Apache组织提供的一种Web服务器,提供对jsp和Servlet的支持。它是一种轻量级的javaWeb容器(服务器),也是当前应用最广的JavaWeb服务器(免费)
一、Servlet技术
a)什么是Servlet
1、Servlet是JavaEE规范之一。规范就是接口
2、Servlet是JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。
3、Servlet是运行在服务器上的一个java小程序。它可以接收客户端发送过来的请求,并响应数据给客户端。
b)url地址到Servlet程序的访问
c)Servlet生命周期
1、执行Servlet构造器方法(只在创建servlet程序是调用)
2、执行init初始化方法(只在创建servlet程序是调用)
3、执行service方法(每次访问都会调用)
4、执行destroy方法(在web工程停止的时候调用)
以上是20版旧视频,以下是22版新课程(省略前端部分)
一、CS/BS的异同点
CS:客户端服务器架构模式
优点:充分利用客户端机器的资源,减轻服务器的负荷
(一部分安全要求不高的计算任务存储任务放在客户端执行,不需要把所有的计算和存储都在服务器端执行,从而减轻服务器的压力,也能够减轻网络负荷)
缺点:需要安装;升级维护成本较高
BS:浏览器服务器架构模式
优点:客户端不需要安装;维护成本较低
缺点:所有的计算和存储任务都是放在服务器端的,服务器额负荷较重;在服务端计算完成之后把结果再传输给客户端,因此客户端和服务端会进行非常频繁的数据通信,从而网络负荷较重
二、Tomcat
目录结构说明
bin 可执行文件目录
conf 配置文件目录
lib 存放lib的目录
logs 日志文件目录
webapps 项目部署的目录
work 工作目录
temp临时目录
三、servlet
1、servlet-获取参数
2、servlet-处理请求参数中文乱码问题
tomcat8之前
(1)get请求方式:
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");
3、servlet-继承关系
(1)继承关系:HttpServlet -> GenericServlet -> Servlet
(2)Servlet中的核心方法: init(),service(),destroy()
(3)服务方法:当有请求过来时,service方法会自动相应(其实是tomcat容器调用的)
在HttpServlet中我们回去分析请求的方式:到底是get\post\head还是delete等,然后再决定调用的是哪个do开头的方法
那么在HttpServlet中这些do方法默认都是405的实现风格-要我们子类去实现对应的方法,否则默认会报405错误
(4)因此,我们在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法。
4、Servlet的生命周期
(1)生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法: init(),service(),destroy()
(2)默认情况下:
第一次接收请求时,这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())
从第二次请求开始,每一次都是服务
当容器关闭时,其中的所有的Servlet实例会被销毁,调用销毁方法
(3)Servlet实例tomcat只会创建一个,所有的请求都是这个实例取响应。
默认情况下,第一次请求时,tomcat才会实例化,初始化,然后再服务。(以提高系统的启动速度,但第一次请求时会耗时较长)
结论:如果需要提高系统的启动速度,就使用当前默认情况,如果需要提高响应速度,就需要设置Servlet的初始化时机
(4)Servlet初始化时机:
- 默认是第一次请求时,实例化,初始化
- 可以通过来设置Servlet启动的先后顺序,数字越小,启动越靠前,最小值0
(5)Servlet在容器中是:单例的、线程不安全的
- 单例:所有的请求都是同一个实例去响应
- 线程不安全:一个线程需要根据这个实例中的某个成员变量值去逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化。
- 我们已经知道了servlet是线程不安全的,给我们的启发是:尽量不要在servlet中定义成员变量。如果不得不定义成员变量,那么:①不要去修改成员变量的值;②不要根据成员变量的值做一些逻辑判断
5、HTTP协议
HTTP:Hyper Text Transfer Protocol超文本传输协议。HTTP最大的作用就是确定了请求和响应数据的格式。
浏览器发送给服务器的数据:请求报文。
服务器返回给浏览器的数据:响应报文。
(1)请求报文:
①请求行:展示当前请求的最基本信息(请求方式/访问地址/协议版本http1.1)
②请求消息头:通过具体的参数对本次请求进行详细的说明(客户端需要高速服务器的信息,例如浏览器型号、版本等)
③请求体(三种情况):
1)get方式,没有请求体,但是有一个queryString
2)post方式,有请求体,form data
3)json格式,有请求体,request payload
(2)响应报文:
①响应行:包含协议版本、响应状态码(200)、响应状态(ok)
②响应头:包涵服务器信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
③响应体:响应的实际内容(比如请求add.html页面时,响应的内容就是<html><head><body><form>....
)
6、会话
(1)HTTP是无状态的
- HTTP无状态:服务器无法判断这两次请求时同一个客户端发过来的,还是不同客户端发过来的。
- 无状态带来的现实问题:第一次请求时添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么久会导致混乱。
- 通过会话跟踪技术来解决无状态的问题
(2)会话跟踪技术
- 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端
- 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和之前某次请求是同一个客户端,从而能够区分开客户端。
- 常用API:
①request.getSession:获取当前会话,没有则创建一个新的会话。
②request.getSession(true):效果和不带参数相同。
③request.getSession(false):获取当前会话,没有则返回null,不会创建新的。
④session.getId():获取sessionID。
⑤session.isNew():判断当前id是否是新的。
⑥session.getMaxInactiveInterval():session的非激活间隔时长,默认1800秒。
⑦session.setMaxInactiveInterval()
⑧session.invalidate():强制性让会话立即失效
(3)session保存作用域
- session保存作用域是和具体的某一个session对应的
- 常用的API:
①void session.setAttribute(k,v)
②Object seesion.getAttribute(k)
③void removeAttribute(k)
7、服务器内部转发以及客户端重定向
(1)服务器内部转发:request.getRequestDispatcher(“…”).forward(request,response);
① 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的。
②地址栏没有变化
(2)客户端重定向:response.sendRedirect(“…”);
①两次请求响应的过程,客户端肯定知道请求url有变化
②地址栏有变化
8、Thymeleaf - 视图模板技术
(这里看起来是前端部分)
Thymeleaf是一个流行的模板引擎,该模板引擎采用Java语言开发。
①使用步骤
1)添加thymeleaf的jar包
2)在web.wml文件中添加配置
3)新建一个Servlet类viewBaseServlet
4)使得我们的Servlet集成ViewBaseServlet
②部分标签
<th:if>,<th:unless>,<th:each>,<th:text>
9、Servlet保存作用域
①保存作用域:原始情况下,保存作用域我们可以认为有四个:page(页面级别,现在几乎不用),request(一次请求响应范围),session(一次会话范围),application(整个应用程序范围)
1)request:一次请求响应范围
2)session:一次会话范围有效
3)application:整个应用程序范围
②路径问题:
1)相对路径
2)绝对路径
10、MVC
①service引入:
MVC:Model(模型)、View(视图)、Controller(控制层)
视图层:用于做数据展示以及和用户交互的一个界面
控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成
模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件
1)pojo/vo:值对象
2)DAO:数据访问对象
3)BO:业务对象
区分业务对象和数据访问对象:
1)DAO中的方法都是单精度方法或者称之为细粒度方法。什么叫单精度?一个方法只考虑一个操作,比如添加,那就是insert,查询就是select
2)BO中的方法属于业务方法,实际的业务是比较复杂的,因此业务方法的粒度是比较粗的
举例:注册这个功能属于业务功能, 也就是说注册这个方法属于业务方法。
那么这个业务方法中包含了多个DAO方法,也就是说注册这个业务功能需要通过多个DAO方法的组合调用,从而完成注册功能的开发。
②IOC
1)耦合/依赖:
依赖指的是某某某离不开某某某
在软件系统中,层与层是存在依赖的,我们也称之为耦合。
系统架构设计的一个原则:高内聚低耦合。
层内部的组成应该是高度聚合的,层与层之间的关系应该是低耦合的,最理想的情况是0耦合(就是没有耦合)
2)IOC - 控制反转 / DI - 依赖注入
11、过滤器Filter
1)Filter也属于Servlet规范
2)Filter开发步骤:新建类实现Filter接口,然后实现其中的三个方法:init、doFilter、destroy
DemoFilter implements Filter
配置Filter,可以用注解@WebFilter,也可以使用xm文件
3)Filter在配置时,和servlet一样,也可以配置通配符,例如@WebFilter("*.do"表示拦截所有以.do结尾的请求)
4)过滤器链
①执行的顺序依次是: A B C demo C2 B2 A2
②如果采取的是注解的方式进行配置,那么过滤器链的拦截顺序是按照全类名的先后顺序排序的
③如果采取的是xml的方式进行配置,那么按照配置的先后顺序进行排序