JavaWeb-Servlet(1)
Web-Servlet(1)
获取参数
大致流程
- 在WEB-INF同级下新建一个html文件,写一个表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<form action="add" method="post">
名称<input type="text" name="fname"/><br>
价格<input type="text" name="price"/><br>
库存<input type="text" name="fcount"/><br>
备注<input type="text" name="remake"/><br>
<input type="submit" value="添加"/><br>
</form>
</body>
</html>
- 在src下新建一个类(AddSevlet)
注:要导入一个包:servlet-api,jar或是点击项目结构
找到自己建额项目
再这样
找到红线画的
//这里要添一点包哦
public class AddServlet extends HttpServlst{
@Override
public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOExcepton,ServletExcption{
String fname = request.getParameter("fname");
String priceSrc = request.getParameter("price");
Integer price = Integer.parseInt(priceSrc); //强转一下
String fcountSrc = request.getParameter("fcount");
Integer fcount = Integer.parseInt(fcountSrc);
String remake = request.getParameter("remake");
System.out.println("fanme="+fname);
System.out.println("price="+price);
System.out.println("fcount="+fcount);
System.out.println("remake="+remake);
}
}
- 再在WEB-INF下新建xml配置文件
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>AddServlet</servlet-name>
<servlet-class>com.servlet.AddServlet</servlet-class> <!--要写全哦-->
</servlet>
<servlet-mapping>
<servlet-name>AddServlet</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>
</web-app>
基本流程/步骤
<!--
1.用户发请求,action = add
2.服务器(tomcat)/项目,中web.xml中找到url-pattern = /add
3.找到第11行的servlet-name = AddServlet
4.找和servlet-mapping中servlet-name一致的servlet
5.找到第八行的servlet-class = com.servlet.AddServlet
6.用户发送的post请求(method = post) 因此tomcat会执行AddServlet中的doPost方法
-->
然后执行,如果看了上一篇的视频,并跟的做了的话可能会出现,404
没有关系将之前的Demo01改成自己html文件的名字就可以啦
再点击添加后,就可以再控制台看到这个了
Servlet的小基础
设置编码问题
- 案例:
在上个项目中的水果表单添加中文时会出现乱码
- 解决方法
在AddServlet中添加(tomcat8之后)
request.setCharacterEncoding("UTF-8");
注:这句代码要在获取参数之前来填写
解决啦
Servlet的继承关系
继承关系(重点查看服务方法)
java.servlet.Servlet接口
java.servlet.GenericServlet抽象类
java.servlet.http.HttpServlet抽象子类
相关方法
- java.servlet.Servlet接口
void init(config) --初始化方法
void service(request,response) --服务方法
void destory() -- 销毁方法
- java.servlet.GenericServlet抽象类
void service(request,response) -- 仍然是抽象的
- java.servlet.http.HttpServlet抽象子类
void service(request,response) --不是抽象的
1.String method = req.getMethood() -- 获取请求的方式
2.各种if判断,根据请求方式的不同,决定去调用不同的do方法
3.在HttpServlet这个抽象类中,do方法都差不多
小结
- 继承关系:HttpServlet->GrnericsServlet->Servlet
- Servlet中的核心方法:init(),service(),destory()
- 服务方法:当有请求过来时,service方法会自动响应(其实时tomcat容器调用的)
- 在HttpServlet中我们会分析请求的方式,是get,post,head...然后决定调用那个方法(默认405实现风格--要我们子类去实现对应的方法,否则报405错误)
- 新建Servlet时,我们要考虑请求方法,从而决定重写哪个do方法
Servlet的生命周期
- 生命周期的概念:从出生到死亡的过程,对应Servlet中3个方法init(),service(),destory()
来个小例子
- html中
//演示Servlet的生命周期
public class Servlet02 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("正在销毁");
}
}
- web.xml中
<servlet>
<servlet-name>Servlet02</servlet-name>
<servlet-class>src.com.servlets.Servlet02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet02</servlet-name>
<url-pattern>/Demo02</url-pattern>
</servlet-mapping>
看看效果:
-
默认情况下:
- 第一次接收请求时,这个Servlet会进行实例化(调用构造方法),初始化(调用init()),然后服务(调用service()) *提高 服务器的启动速度,第一次请求耗时较长* - 从第二次请求开始,每一次都是服务(点一下刷新,服务一次) - 当容器关闭时,其中的所有的Servlet实例化会被销毁,调用销毁方法
-
Servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应
因此:如果要提高系统的启动速度,当前默认情况就是这样;如果需要提高响应速度,我们应该设置Servlet的初始化时机
-
Servlet在容器中是,单例的,线程不安全的(共用一个实例)
-单例:所有请求都是同一个实例去响应
-线程不安全:一个线程需要根据这个实例中的某个成员变量的值去做逻辑判断,但是在中间某个时机,另一个线程 改变了这个成员变量的值,导致第一个线程的执行路径发生了变化
-尽量不要在Servlet中定义成员变量,如果要定义,不要去根据成员便改良的值去做逻辑判断 / 修改成员变量的值
Servlet的初始化时机
默认是第一次接收请求时,实例化,初始化
我们可以通过
修改之后
Http协议
介绍
-
Http:Hyper Text transfer Protocol超文本传输协议。确定了请求和响应的数据格式
-
Http是无状态的
-
Http请求响应包含两个部分:请求和响应
-请求:请求包含3个部分:1.请求行 2.请求(消息)头 3.请求体 -响应:响应也含3个部分:1.响应行 2.响应(消息)头 3.响应体
请求
请求行
作用:展现当前请求的最基本信息
- 请求方式
- 访问地址
- HTTP协议的版本
在我刚才的页面上可以查看(F12)
请求(消息)头
作用:通过具体的参数对本次请求进行详细说明(包含很多客户端需要告诉服务器的信息,eg:我的浏览器型号、版本...)
格式:键值对,键和值之间只用""隔开
请求体
作用:作为请求的主体,发送数据给服务器,具体来说其实就是POS请求方法下的请求参数
格式:
- get方式,没有请求体,但是有一个queryString
- post方式,有请求体,form data
- josn格式,有请求体,request payload
响应
响应行
- 协议
- 响应状态码
- 响应状态
响应(消息)头
包含服务器信息:服务器发送给浏览器的信息(内容的媒体类型、编码...)
响应体
响应的实际内容(eg:请求html的内容)
会话
解释Http无状态:服务器无法判断两次(或多次)请求是否是同一个客户端发来的
-实际问题:第一次请求时添加商品到购物车,第二次时结账,若无法区分是否时同一用户发的请求,会导致混乱
-通过会话跟踪技术来解决
会话跟踪技术
- 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建一个新的,然后响应给客户端
- 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,服务器就判断这一次和某次请求时同分异构客户端发出的,来区分客户端
- 常用的API
request.getSessin() -> 获取当前的会话,没有创一个新的
request.getSession(true) -> 同上
request.getSession(false) -> 获取当前会话,没有则返回null,不会创建新的
session.getId() -> 获取sessionID
session。isNew -> 判断当前session是否是新的
session.getMaxInactiveIntervsl() -> session的非激活间隔时长(默认1800s)
session.setMaxInactiveIntervsl()
session.invalidata() -> 强制让会话立即失效
session.get
小例子(web.xml就不写了,都一样)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取session,如果获取不到,则创键一个新的
HttpSession session = req.getSession();
System.out.println("sessionID:"+session.getId());
}
session保存作用域
1.session保存作用域是和具体的某一个session对应的
2.常用的API
//可以有多个key,但不要重复,一旦重复,会覆盖之前的value
void session.setAttribute(k,v);
Object session.getAttribute(k);
void removeAttribute(k);
大家如果不想实验代码就先跳过下面这一段
两个不同的类哦
//session保存作用域:存储
public class Servlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().setAttribute("uname","lina");
}
//session保存作用域:获取(它是Demo05)
public class Servlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object unameObj = request.getSession().getAttribute("uname");
System.out.println("unameObj:"+unameObj);
}
同上web.xml就不写了
最后会在控制台输出 lina(可以尝试换一个浏览器搜索Demo05,结果是null哦)
服务器内部转发和客户端重定向
- 服务器内部转发:req.getRequestDispatcher("...").forward(req,resp);
-是一次请求响应的过程,对于客户端,内部经历了多少次转发,客户端时不知道的
-地址栏没有变化
例子:(注意看红色的线)
- 客户端重定向:resp.sendRedirect("...");
-两次请求响应的过程,客户端知道URL有变化
-地址栏有变化
例子: