注:设置编码必须放在所有的获取参数动作之前
post方式下:
需要设置编码req.setCharacterEncoding(“UTF-8”);
get方式下现在不需要设置编码(基于tomcat8,tomcat8之前的不行)
get方式下:(tomcat8之前,get请求发送的中文数据,转码稍微有点麻烦)
String fname=req.getParameter(“fname”);
1、将字符串打散为字节数组
byte[] bytes=fname.getBytes(“ISO-8859-1”);
2、将字节数组按照设定的编码重新组装成字符串
fname=new String(bytes,“UTF-8”);
例:
package com.atguigu.servlets;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AddServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String fname = req.getParameter("fname");
String pricestr=req.getParameter("price");
Integer price=Integer.parseInt(pricestr);
String fcountstr=req.getParameter("fcount");
Integer fcount=Integer.parseInt(fcountstr);
String remark=req.getParameter("remark");
System.out.println("fname= "+fname);
System.out.println("price= "+price);
System.out.println("fcount= "+fcount);
System.out.println("remark= "+remark);
}
}
1)、继承关系
javax.servlet.Servlet接口
javax.servlet.GenericServlet抽象类
javax.servlet.HttpServlet抽象子类
2)、相关方法
javax.servlet.Servlet接口:
void init(config)-初始化方法
void service(request,response)- 服务方法
void destroy-销毁方法
javax.servlet.GenericServlet抽象类:
void service(request,response)-仍然是抽象类
javax.servlet.HttpServlet抽象子类:
void service(request,response)-不是抽象类
1.String method=req.getMethod();获取请求的方式
2.根据if判断的结果,得出请求的方式、决定调用的不同的do方法
if(method.equals("GET")){
this.doGet(req,resp);
}else if(method.equals("Head")){
this.doHead(req,resp);
}else if(method.equals("POST")){
this.doPost(req,resp);
}else if(method.equals("PUT"){
this.doPut(req,resp);
}
3.在HttpServlet这个抽象类中,do方法都差不多
protected void doGet (HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException{
String protocol = req.getProtocol () ;
String msg = lStrings.getString ("http.method_get_not_supported" );
if (protocol.endsWith ("1.1") ) {
resp.sendError (405,msg);
}else {
resp. sendError ( 400,msg) ;
}
}
3)、小结
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方法
1)、生命周期:从出生到死亡的过程就是生命周期。对应的Servlet中的三个方法:init()、service()、destroy()
2)、默认情况下:
第一次就接受请求时,这个servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())
第二次请求开始时,每一次都是服务
当容器开始时,其中的所有的servlet实例会被销毁,调用销毁方法
3)、
-Servlet案例tomcat只会创建一个,所有的请求都是这个实例去响应的
-默认情况下,第一次请求时tomcat才会实例化,初始化,然后再服务。
好处是:提高系统的启动速度
缺点是:第一次请求时,耗时较长
-因此:如果需要提高系统的启动速度,当前默认情况就是这样。如果需要提高响应速度,我们应该Servlet的初始化时机
4)、Servlet的初始化时机
可以在xml中 中设置值 值可以是0、1、2、3等,尽量不要写负数
设置Servlet启动的先后顺序,数字越小启动越靠前,最小值0
好处是:响应速度变快
缺点是:系统的启动速度变慢
5)、Servlet在容器中是单例的、线程不安全的
-单例:所有的请求都是在同一个实例中去响应
-线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。
但是在中间的某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生改变
-办法:尽量不要在servlet中定义成员变量。如果不得不定义成员变量,
那么不要去:I不要去修改成员变量的值 II不要去根据成员变量的值做一些逻辑判断
6)、总结:1、Servlet接口:init() 、service() 、destroy()
GenericServlet抽象子类:(这个方法没有实现,还是抽象)abstract service();
HttpServlet抽象子类:实现了service方法,在service方法内部通过request.getMethod()来判断请求的方式
然后根据请求的方式调用内部的do方法。每一个do方法进行了简单的实现,主要是如果请求方式不符,
则报405错误,目的是让我们的Servlet子类去重写对应的方法(如果重写的不对,则调用父类的405错误实现)
2、生命周期:实例化(Tomcat帮我们new的)、初始化、服务、销毁
-Tomcat负责维护Servlet实例的生命周期
-每一个Servlet在Tomcat容器中只有一个实例,他是线程不安全的
-启动时机:通过设置
-Servlet3.0开始支持注解:@webServlet
1)、Http 称之为 超文本传输协议
2)、Http 是无状态的:服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的
-无状态带来的现实问题:
例第一次请求添加商品到购物车,第二次请求是结账;如果两次请求服务器无法区分是同一个用户,那么就会导致混乱
-通过会话跟踪技术解决无状态问题
3)、Http请求响应包含两部分:请求和响应
-请求:
请求包含三部分:1、请求行 2、请求消息头 3、请求主题
I、请求行包含的三个信息:1、请求的方式 2、请求的URL 3、请求的协议(一般都是Http1.1)
II、请求消息头包含很多客户端需要告诉服务器的信息,
比如:我的浏览器的版本型号、版本、我能接收的内容的类型、我给你发的内容的类型、内容的长度等等
III、请求体,三种情况
get方式,没有请求体,但是有一个queryString
post方式,有请求体,form data
json方式,有请求体,request payload
-响应:
响应也包含三部分:1、响应状态行 2、响应消息头 3、响应体
I、响应行包含三个信息:1、协议 2、响应状态码(200) 3、响应状态(ok)
II、响应头:包含了服务器的信息,服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)
III、响应体:相应的实际内容(比如请求add.html页面时,响应的内容就是
1)、会话跟踪技术
-客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端
-下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到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()->强制性让会话立即失效
2)、session保存作用域
-session保存作用域是和具体的某一个session对应的
-常用的API:
void session.setAttribute(k,v);
Object session.getAttribute(k);
void removeAttribute(k);
3)、总结:1、HttpSession:表示 会话
2、为什么需要HttpSession:原因是Http协议是无状态的
3、Session保存作用域:一次会话 范围都有效;void session.setAttribute(k,v);Object getAttribute(k)
4、其他API:(获取ID)session.getId();(判断是否是新的) session.isNew();
(获取创建的时间) session.getCreationTime();(强制性让某一个会话失效)session.invalidate() 等等
1)、服务器内部转发:request.getRequestDispatcher("...").forward(request,response);
-一次请求响应的过程。对于客户端,内部经过多少次转发,客户端是不知道的
-地址栏没有变化
2)、客户端重定向:response.sendRedirect("...");
-两次请求响应的过程。客户端肯定知道请求URL有变化
-地址栏有变化
3)、总结:1、服务器端转发:request.getRequestDispatcher("index.html").forward(request,response);
2、客户端重定向:response.sendRedirect("index.html");
1)、添加thymeleaf的jar包
2)、新建一个Servlet类ViewBaseServlet
3)、在web.xml文件中添加配置
-配置前缀 view-prefix
-配置后缀 view-suffix
4)、使得我们的Servlet继承ViewBaseServlet
5)、根据逻辑视图名称 得到 物理视图名称
//此处的视图名称是index
//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图名称上去
//逻辑视图名称:index
//物理视图名称:view-prefix+逻辑视图名称+view-suffix
//所以真实的视图名称是:(view-prefix对应的名称) +index +(view-suffix对应的名称)
super.processTemplate("index",request,response);
6)、使用thymeleaf标签
th:if , th:unless , th:each , th:text
7)、总结:
1、使用步骤:添加jar ,新建ViewBaseServlet (有两个方法),配置两个: view-prefix, view-suffix
2、部分标签:
3、
//200:正常响应
//302:重定向
//404:找不到资源
//405:请求方式不支持
//500:服务器内部错误