1. Servlet是什么?
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层
使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
servlet架构:
2. Servlet的继承关系?
javax.servlet.Servlet接口
javax.servlet.GenericServlet抽象类
javax.servlet.http.HttpServlet
javax.servlet.Servlet接口的相关方法:
void init(config) - 初始化方法
void service(request,response) - 服务方法
void destroy() - 销毁方法
javax.servlet.GenericServlet抽象类的相关方法:
void service(request,response) - 仍然是抽象的
javax.servlet.http.HttpServlet抽象子类的相关方法:
void servcie(request,response) - 不是抽象的
String method = req.getMethod(); 获取请求的方式
总结
1.继承关系:HttpServlet -> GenericServlet -> Servlet
2.Service中的核心方法:init(),service(),destroy()
3.服务方法:当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)
在HttpServlet中会分析请求的方式:到底是get、post、head还是delete等等
然后决定调用是哪个do开头的方法(这里是例子用的servlet的注解是以do结尾的)
那么在HttpServlet中这些do方法默认都是405的实现风格-要我们子类去实现对应的方法,否则默认会报405错误
4.所有在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法
3.Servlet的生命周期
1)生命周期:从创建到销毁的过程就是生命周期。对应Servlet中的三个方法:init()、service() 、destroy()。
public class ServeletTest extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("初始化......");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("正在服务......");
}
@Override
public void destroy() {
System.out.println("正在销毁.......");
}
}
- 默认情况下:
第一次接收请求时,这个servlet会进行实例化(调用构造方法)、初始化(调用init()方法)、然后服务(service()方法)
当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法。
3)通过案例发现,servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应。
默认情况下,第一次请求时tomcat才会去实例化,初始化然后再服务。这样做的好处?缺点?
好处:提高系统的启动速度
缺点:第一次请求时耗时较长
因此得出结论:如果需要提高系统的启动速度,默认情况就这样
如果需要提高响应速度,我们需要设置servlet的初始化时机。
4)servlet的初始化时机:
默认是第一次接收到请求时,实例化、初始化
我们可以通过来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值为0。
5)servlet在容器中是:单例的、线程不安全的
单例:所有的请求都是同一个实例去响应
线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了改变
所以尽量的不要在servlet中定义成员变量,如果不得不定义成员变量,那么不要去修改成员变量的值,不要去根据成员变量的值去做一些逻辑判断。
4.HTTP协议
①Http称之为超文本传输协议
②Http是无状态的
③Http请求响应包含两个部分:请求和响应
请求
请求包含三个部分:
1.请求行:展示当前请求的最基本的信息:请求的方式、请求的URL、请求的协议版本(一般都是Http1.1)
2.请求头:包含了很对客户端需要告诉服务器的信息,比如:我的服务器型号、版本、我能接收的内容的类型…
3.请求体:三种情况
get方式,没有请求体,但是有一个queryString
post方式,有请求体,form data
json格式,有请求体,request payload
响应
1.响应行:包含三个信息:①协议 ②响应状态码(200) ③响应状态(ok)
2.响应头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
3.响应体:响应的实际内容(比如请求的页面)
5.会话(Session)
1)Http是无状态的
Http无状态:服务器无法判断这两次的请求是同一个客户端发过来的,还是不同的客户端发送过来的
无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么会带来问题
通过会话跟踪技术来解决Http无状态问题
2)会话跟踪技术
客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端
下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这次请求和上次请求是同一个客户端,从而能够区分开客户端
常用的API:
request.getSession() -> 获取当前的会话,没有则创建一个新的会话
request.getSession(true) -> 效果和不带参数相同
request.getSession(false) -> 获取当前会话,没有则返回null,不会创建新的
session.getId() -> 获取sessionID
session.isNew() -> 判断当前session是否是新的
session.getMaxInactiveInterval() -> session的非激活间隔时长,默认1800秒
session.setMaxInactiveInterval()
session.invalidate() -> 强制让会话失效
…
3)session保存作用域
session保存作用域是和具体的某一个session对应的
常用的API:
void session.setAttribute(k,v)
void session.getAttribute(k)
void removeAttribute(k)
6.服务器内部转发和重定向
1)服务器内部转发:
request.getRequestDispatcher("...").forward(request,response);
- 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
- 地址栏没有变化。
2)客户端重定向:
response.sendRedirect(".....");
- 两次请求响应的过程。客户端肯定知道请求URL有变化
- 地址栏有变化
7. Thymeleaf - 视图模板技术
配置的过程
1)添加thymeleaf的jar包
2)新建一个Servlet类ViewBaseServlet
3)在web.xml文件中添加配置
配置前缀 view-prefix
配置后缀 view-suffix
4)使得我们的Servlet继承ViewBaseServlet
使用的过程:
使用thymeleaf的标签
th:if th:unless th:each th:text
8.Servlet配置
1)注解
2)web.xml文件
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
9.设置编码问题
post方式下的设置编码,防止中文乱码
request.setCharacterEncoding("UTF-8")
get提交方式,tomcat8开始,编码不需要设置
tomcat8之前,get方式设置比较麻烦
9.报错信息
报错信息:
200:正常响应
302:重定向
404:找不到资源
405:请求方式不支持
500:服务器内部错误