Servlet
-
中文乱码问题
// post方式下 设置编码,防止中文乱码
// get 方式目前不需要设置编码
// 需要注意的是,设置编码这一句代码必须在所有的获取参数动作之前
request.setCharacterEncoding("UTF-8");
-
servlet的继承关系
-
继承关系
- javax.servlet.Servlet接口
- javax.servlet.GenericServlet抽象类
- javax.servlet.http.HttpServlet抽象子类
-
相关方法
-
javax.servlet.Servlet接口:
- void init(config) - 初始方法
- void service(request, response) - 服务方法
- void destory - 销毁方法
-
javax.servlet.GenericServlet抽象类
- void service(request,response) - 仍然是抽象的
-
javax.servlet.http.HttpServlet抽象子类
-
void service(request,response) - 不是抽象的
-
String method = req.getMethod 获取请求的方式
-
各种if判断,根据请求方式不同,决定去调用不同的do方法
-
在HttpServlet这个抽象类中,do方法都差不多
-
-
-
小结:
- 继承关系:HttpServlet -> GenericServlet -> Servlet
- Servlet中的核心方法:init(), service(), destory()
- 服务方法:当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)
在HttpServlet中我们会去分析请求的方式:到底是get、post、head、还是delete等等
然后再决定调用哪个do开头的方法
那么再HttpServlet中这些do方法默认都是405的实现风格-要我们子类去实现对应的方法,否则就会报405错误
-
因此,我们新建Servlet时,我们才会考虑请求方法,从而决定重写哪个do方法
-
Demo01Servlet.java
public class Demo01Servlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
<servlet> <servlet-name>Demo01Servlet</servlet-name> <servlet-class>com.atguigu.servlets.Demo01Servlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Demo01Servlet</servlet-name> <url-pattern>/Demo01</url-pattern> </servlet-mapping>
-
-
Servlet的生命周期
-
生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init、service 、 destory
-
默认情况下:
- 第一次接受请求时,这个Servlet会进行实例化,初始化,然后服务
- 从第二次请求开始,每一次都是服务
- 当容器关闭时,其中的所有servlet都会被销毁
- 通过案例发现,tomcat只会创建一个servlet实例,所有的请求都是这个实例去响应。
- Servlet初始化时机:可以通过设置来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值为0
- Servlet在容器中是:单例的、线程不安全的
- 单例:所有请求都是个实例去响应
- 线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了成员变量的值,导致第一个发生了变化
- 我们已经知道了Servlet线程是不安全的,所以尽量不要在servlet中定义成员变量,即使定义了也不修改,不根据成员变量的值进行判断。
-
//演示Servlet的生命周期
public class Demo02Servlet 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>
<servlet-name>Demo02Servlet</servlet-name>
<servlet-class>com.atguigu.servlets.Demo02Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Demo02Servlet</servlet-name>
<url-pattern>/demo02</url-pattern>
</servlet-mapping>
-
HTTP协议
- HTTP:Hyper Text Transfer Protocol超文本传输协议。HTTP最大的作用就是确定了请求和响应数据的格式。浏览器发送给服务器的数据:请求报文;服务器返回给浏览器的数据:响应报文。
- Http是无状态的
- Http请求响应包含两个部分:请求和响应
- 请求:
- 请求包含三部分:1.请求行 2. 请求消息头 3. 请求主体
- 请求行包含三个信息:1.请求的方式;2.请求的URL;3. 请求的协议(一般都是HTTP1.1)
- 请求消息头包含了很多客户端需要告诉服务器的信息,比如:我的浏览器型号,版本,我能接受的内容的类型,发送的内容的类型,内容的长度等等
- 请求体,三种情况
- get方式,没有请求体,但是有一个queryString
- post方式,有请求体,form data
- json格式,有请求体,request payload
- 响应:
- 响应也包含三部分:1. 响应行 2.响应头 3. 响应体
- 相应行: 1.协议 2. 响应状态码 3. 响应状态
- 响应头: 包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
- 响应体:响应的实际内容(比如请求add.html页面时,响应的内容就是<form…)
-
会话
-
Http是无状态的
-
HTTP无状态:服务器无法判断这两次请求是同一个客户端发送过来的,还是不同客户端发送过来的
-
无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果两次服务器无法区分是同一用户,那么结账就会导致混论。
-
通过会话跟踪技术解决无状态问题。
// 演示session public class Demo03Servlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取session,如果获取不到,则创建一个新的 HttpSession session = req.getSession(); System.out.println("sessionID:"+session.getId()); } }
-
session获取不到,则创建新的,然后响应给客户端
-
sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端。
-
常用的API:
-
request.getSession -> 获取当前会话,没有则创建
-
request.getSession(true) ->同上
-
request.getSession(false) ->没有则返回false 不会创建新的
-
session.getId() - > 获取sessionID
-
session.isNew() -> 判断当前session是否是新的
-
session.getMaxInactiveInterval() -> session的非激活间隔时常,默认1800秒
-
session.invalidate()-> 强制让会话立即失效
…
-
-
- session 保存作用域
- session.setAttribute(“unname”,“lina”);
- session.getAttribute(“name”);
// 演示向HttpSession保存数据 public class Demo04Servlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.setAttribute("uname","lina"); } }
public class Demo05Servlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object unname = req.getSession().getAttribute("uname"); System.out.println(unname); } }
-
-
服务器内部转发以及客户端重定向
- 服务器内部转发:request.getRequestDispatcher("…").forward(request,response);
- 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
- 客户端重定向:response.sendRedirect("…");
- 两次请求响应的过程客户端肯定知道,请求的URL有变化。
- 服务器内部转发:request.getRequestDispatcher("…").forward(request,response);
这里演示的是转发
Demo06Servlet.java
public class Demo06Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo06...");
//服务器内部转发
req.getRequestDispatcher("demo07").forward(req,resp);
}
}
// 演示服务器内部转发以及客户端重定向
public class Demo07Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo07.。。。");
}
}
下面是重定向(URL发生变化,直接改为demo07)
public class Demo06Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo06...");
//服务器内部转发
// req.getRequestDispatcher("demo07").forward(req,resp);
resp.sendRedirect("demo07");
}
}
-
Thymeleaf - 视图模板技术
-
保存作用域
-
原始情况下有四个:page(页面级别,现在几乎不用), request,session,application
-
request:一次请求范围
-
request.setAttribute("name","lili") response.sendRedirect("demo02")
request.getAttribute("name");
-
此时获取不到"lili" 因为重定向之后这属于两次请求了(转发则可以获取到,多次转发也可)
-
session:当前客户端能获取到(getAttribute(“name”))
-
application:最大范围,所有客户的都可以请求到(getAttribute(“name”))
//ServletContext Servlet上下文 ServletContext application = request.getServletContext();
-